Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
authorDavid S. Miller <davem@davemloft.net>
Thu, 5 Feb 2009 00:51:58 +0000 (16:51 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 5 Feb 2009 00:51:58 +0000 (16:51 -0800)
532 files changed:
Documentation/DocBook/mac80211.tmpl
Documentation/feature-removal-schedule.txt
Documentation/networking/dccp.txt
Documentation/networking/ip-sysctl.txt
Documentation/powerpc/dts-bindings/fsl/tsec.txt
drivers/char/pcmcia/synclink_cs.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/iwch.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/net/3c501.c
drivers/net/3c505.c
drivers/net/3c507.c
drivers/net/3c509.c
drivers/net/3c515.c
drivers/net/3c523.c
drivers/net/3c527.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/82596.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/amd8111e.c
drivers/net/arcnet/arc-rawmode.c
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/capmode.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com20020-pci.c
drivers/net/arcnet/com20020.c
drivers/net/arcnet/rfc1051.c
drivers/net/arcnet/rfc1201.c
drivers/net/arm/ep93xx_eth.c
drivers/net/arm/ixp4xx_eth.c
drivers/net/arm/ks8695net.c
drivers/net/atl1e/atl1e_main.c
drivers/net/au1000_eth.c
drivers/net/b44.c
drivers/net/bfin_mac.c
drivers/net/bmac.c
drivers/net/bnx2.c
drivers/net/bnx2x_main.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/cassini.c
drivers/net/chelsio/sge.c
drivers/net/cpmac.c
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/cxgb3_offload.h
drivers/net/cxgb3/sge.c
drivers/net/declance.c
drivers/net/depca.c
drivers/net/e100.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/ehea/ehea_qmr.c
drivers/net/enic/enic_main.c
drivers/net/epic100.c
drivers/net/fec.c
drivers/net/fec.h
drivers/net/forcedeth.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fsl_pq_mdio.c [new file with mode: 0644]
drivers/net/fsl_pq_mdio.h [new file with mode: 0644]
drivers/net/gianfar.c
drivers/net/gianfar.h
drivers/net/gianfar_ethtool.c
drivers/net/gianfar_mii.c
drivers/net/gianfar_mii.h [deleted file]
drivers/net/gianfar_sysfs.c
drivers/net/hamachi.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/ibmveth.c
drivers/net/igb/e1000_82575.c
drivers/net/igb/igb.h
drivers/net/igb/igb_ethtool.c
drivers/net/igb/igb_main.c
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgbe/Makefile
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_82598.c
drivers/net/ixgbe/ixgbe_common.c
drivers/net/ixgbe/ixgbe_common.h
drivers/net/ixgbe/ixgbe_dcb.c
drivers/net/ixgbe/ixgbe_dcb.h
drivers/net/ixgbe/ixgbe_dcb_82598.c
drivers/net/ixgbe/ixgbe_dcb_82598.h
drivers/net/ixgbe/ixgbe_dcb_nl.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/ixgbe/ixgbe_phy.h
drivers/net/ixgbe/ixgbe_type.h
drivers/net/ixp2000/ixpdev.c
drivers/net/jazzsonic.c
drivers/net/jme.h
drivers/net/korina.c
drivers/net/macb.c
drivers/net/macsonic.c
drivers/net/mlx4/en_rx.c
drivers/net/mv643xx_eth.c
drivers/net/myri10ge/myri10ge.c
drivers/net/myri_sbus.c
drivers/net/natsemi.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/niu.c
drivers/net/pasemi_mac.c
drivers/net/pcnet32.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mdio_bus.c
drivers/net/ppp_generic.c
drivers/net/pppoe.c
drivers/net/pppol2tp.c
drivers/net/pppox.c
drivers/net/ps3_gelic_net.c
drivers/net/ps3_gelic_wireless.c
drivers/net/qla3xxx.c
drivers/net/qlge/qlge_main.c
drivers/net/r6040.c
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/sb1250-mac.c
drivers/net/sc92031.c
drivers/net/sfc/Kconfig
drivers/net/sfc/bitfield.h
drivers/net/sfc/efx.c
drivers/net/sfc/efx.h
drivers/net/sfc/net_driver.h
drivers/net/sfc/rx.c
drivers/net/sfc/rx.h
drivers/net/sfc/sfe4001.c
drivers/net/sfc/tenxpress.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/smc911x.c
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/net/smsc911x.c
drivers/net/smsc9420.c
drivers/net/spider_net.c
drivers/net/starfire.c
drivers/net/sungem.c
drivers/net/tc35815.c
drivers/net/tehuti.c
drivers/net/tg3.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/abyss.c
drivers/net/tokenring/ibmtr.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.h
drivers/net/tokenring/olympic.c
drivers/net/tokenring/olympic.h
drivers/net/tokenring/tms380tr.c
drivers/net/tokenring/tms380tr.h
drivers/net/tokenring/tmspci.c
drivers/net/tsi108_eth.c
drivers/net/tulip/interrupt.c
drivers/net/tun.c
drivers/net/typhoon.c
drivers/net/typhoon.h
drivers/net/ucc_geth.c
drivers/net/ucc_geth.h
drivers/net/ucc_geth_ethtool.c
drivers/net/ucc_geth_mii.c [deleted file]
drivers/net/ucc_geth_mii.h [deleted file]
drivers/net/usb/hso.c
drivers/net/usb/smsc95xx.c
drivers/net/via-rhine.c
drivers/net/via-velocity.h
drivers/net/virtio_net.c
drivers/net/wan/c101.c
drivers/net/wan/cosa.c
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/hd64572.c
drivers/net/wan/hdlc.c
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/hdlc_raw.c
drivers/net/wan/hdlc_raw_eth.c
drivers/net/wan/hdlc_x25.c
drivers/net/wan/hostess_sv11.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wan/lapbether.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/lmc/lmc_proto.c
drivers/net/wan/n2.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wan/sealevel.c
drivers/net/wan/wanxl.c
drivers/net/wimax/i2400m/fw.c
drivers/net/wimax/i2400m/i2400m.h
drivers/net/wimax/i2400m/netdev.c
drivers/net/wimax/i2400m/sdio.c
drivers/net/wimax/i2400m/usb.c
drivers/net/wireless/Kconfig
drivers/net/wireless/airo.c
drivers/net/wireless/ath5k/ath5k.h
drivers/net/wireless/ath5k/base.c
drivers/net/wireless/ath5k/base.h
drivers/net/wireless/ath5k/caps.c
drivers/net/wireless/ath5k/debug.c
drivers/net/wireless/ath5k/debug.h
drivers/net/wireless/ath5k/eeprom.c
drivers/net/wireless/ath5k/gpio.c
drivers/net/wireless/ath5k/pcu.c
drivers/net/wireless/ath5k/qcu.c
drivers/net/wireless/ath9k/Makefile
drivers/net/wireless/ath9k/ahb.c [new file with mode: 0644]
drivers/net/wireless/ath9k/ani.c
drivers/net/wireless/ath9k/ath9k.h
drivers/net/wireless/ath9k/beacon.c
drivers/net/wireless/ath9k/calib.c
drivers/net/wireless/ath9k/core.h
drivers/net/wireless/ath9k/debug.c
drivers/net/wireless/ath9k/eeprom.c
drivers/net/wireless/ath9k/hw.c
drivers/net/wireless/ath9k/hw.h
drivers/net/wireless/ath9k/initvals.h
drivers/net/wireless/ath9k/mac.c
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/ath9k/pci.c [new file with mode: 0644]
drivers/net/wireless/ath9k/rc.c
drivers/net/wireless/ath9k/rc.h
drivers/net/wireless/ath9k/recv.c
drivers/net/wireless/ath9k/reg.h
drivers/net/wireless/ath9k/regd.c
drivers/net/wireless/ath9k/regd.h
drivers/net/wireless/ath9k/regd_common.h
drivers/net/wireless/ath9k/xmit.c
drivers/net/wireless/atmel.c
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/debugfs.c
drivers/net/wireless/b43/debugfs.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/main.h
drivers/net/wireless/b43/phy_g.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/iwl-100.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-3945-commands.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-3945-debug.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-3945-fh.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-3945-hw.h
drivers/net/wireless/iwlwifi/iwl-3945-io.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-3945-led.c
drivers/net/wireless/iwlwifi/iwl-3945-led.h
drivers/net/wireless/iwlwifi/iwl-3945-rs.c
drivers/net/wireless/iwlwifi/iwl-3945-rs.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-3945.h
drivers/net/wireless/iwlwifi/iwl-4965-hw.h
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000-hw.h
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000-hw.h [moved from drivers/net/wireless/iwlwifi/iwl-3945-core.h with 64% similarity]
drivers/net/wireless/iwlwifi/iwl-6000.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.h
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-calib.c
drivers/net/wireless/iwlwifi/iwl-calib.h
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-helpers.h
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-led.h
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-power.h
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-rfkill.c
drivers/net/wireless/iwlwifi/iwl-rfkill.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-spectrum.c
drivers/net/wireless/iwlwifi/iwl-spectrum.h
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-sta.h
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/Makefile
drivers/net/wireless/libertas/debugfs.c
drivers/net/wireless/libertas/defs.h
drivers/net/wireless/libertas/host.h
drivers/net/wireless/libertas/hostcmd.h
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/libertas/if_spi.c [new file with mode: 0644]
drivers/net/wireless/libertas/if_spi.h [new file with mode: 0644]
drivers/net/wireless/libertas/main.c
drivers/net/wireless/libertas_tf/cmd.c
drivers/net/wireless/libertas_tf/libertas_tf.h
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/orinoco/Kconfig [new file with mode: 0644]
drivers/net/wireless/orinoco/orinoco.c
drivers/net/wireless/orinoco/orinoco.h
drivers/net/wireless/p54/Kconfig
drivers/net/wireless/p54/Makefile
drivers/net/wireless/p54/p54.h
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/p54/p54common.h
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/p54spi.c [new file with mode: 0644]
drivers/net/wireless/p54/p54spi.h [new file with mode: 0644]
drivers/net/wireless/p54/p54spi_eeprom.h [new file with mode: 0644]
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/p54/p54usb.h
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_mgt.h
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/Makefile
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500pci.h
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00crypto.c
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rt2x00/rt2x00debug.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00dump.h
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rt2x00/rt2x00leds.c
drivers/net/wireless/rt2x00/rt2x00leds.h
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00link.c [new file with mode: 0644]
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00reg.h
drivers/net/wireless/rt2x00/rt2x00rfkill.c
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rt2x00/rt2x00usb.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h
drivers/net/wireless/rtl818x/rtl8187.h
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/net/wireless/strip.c
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zd1201.c
drivers/net/xen-netfront.c
drivers/net/xtsonic.c
drivers/net/znet.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/scsi/cxgb3i/cxgb3i_ddp.h
drivers/ssb/b43_pci_bridge.c
drivers/ssb/pci.c
include/linux/arcdevice.h
include/linux/ath9k_platform.h [new file with mode: 0644]
include/linux/com20020.h
include/linux/connector.h
include/linux/dccp.h
include/linux/hdlc.h
include/linux/hdlcdrv.h
include/linux/ibmtr.h
include/linux/ieee80211.h
include/linux/if.h
include/linux/inetdevice.h
include/linux/mroute.h
include/linux/netdevice.h
include/linux/nl80211.h
include/linux/pci_ids.h
include/linux/ppp_channel.h
include/linux/skbuff.h
include/linux/smsc911x.h
include/linux/spi/libertas_spi.h [new file with mode: 0644]
include/linux/ssb/ssb_regs.h
include/linux/sysctl.h
include/linux/virtio_net.h
include/linux/wireless.h
include/net/atmclip.h
include/net/cfg80211.h
include/net/inet_hashtables.h
include/net/mac80211.h
include/net/netns/ipv4.h
include/net/netrom.h
include/net/phonet/phonet.h
include/net/phonet/pn_dev.h
include/net/pkt_sched.h
include/net/sch_generic.h
include/net/wireless.h
kernel/sysctl_check.c
net/802/psnap.c
net/8021q/vlan.c
net/8021q/vlan_core.c
net/Kconfig
net/appletalk/ddp.c
net/appletalk/dev.c
net/atm/br2684.c
net/atm/clip.c
net/atm/lec.c
net/atm/lec.h
net/ax25/af_ax25.c
net/bridge/br_netfilter.c
net/can/af_can.c
net/core/dev.c
net/core/skbuff.c
net/dccp/dccp.h
net/dccp/feat.c
net/dccp/feat.h
net/dccp/minisocks.c
net/dccp/options.c
net/dccp/proto.c
net/dccp/sysctl.c
net/decnet/af_decnet.c
net/decnet/dn_route.c
net/dsa/mv88e6123_61_65.c
net/dsa/mv88e6131.c
net/dsa/tag_dsa.c
net/dsa/tag_edsa.c
net/dsa/tag_trailer.c
net/econet/af_econet.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ipconfig.c
net/ipv4/ipmr.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/xfrm4_policy.c
net/ipv6/af_inet6.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_policy.c
net/ipx/af_ipx.c
net/irda/irmod.c
net/llc/llc_core.c
net/mac80211/Makefile
net/mac80211/aes_cmac.c [new file with mode: 0644]
net/mac80211/aes_cmac.h [new file with mode: 0644]
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/debugfs_key.c
net/mac80211/debugfs_key.h
net/mac80211/debugfs_sta.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/pm.c [new file with mode: 0644]
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/spectmgmt.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wext.c
net/mac80211/wpa.c
net/mac80211/wpa.h
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_amanda.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_netbios_ns.c
net/netfilter/nf_conntrack_pptp.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/phonet/af_phonet.c
net/phonet/pn_dev.c
net/phonet/pn_netlink.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/sched/sch_api.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/sm_make_chunk.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/reg.h
net/wireless/sysfs.c
net/wireless/util.c
net/x25/af_x25.c

index 77c3c202991b4ded85f4795ef33e3e73186dd784..8af6d9626878e0459c02052081c41bbc33c5d20d 100644 (file)
@@ -17,8 +17,7 @@
     </authorgroup>
 
     <copyright>
-      <year>2007</year>
-      <year>2008</year>
+      <year>2007-2009</year>
       <holder>Johannes Berg</holder>
     </copyright>
 
@@ -165,8 +164,8 @@ usage should require reading the full document.
 !Pinclude/net/mac80211.h Frame format
       </sect1>
       <sect1>
-        <title>Alignment issues</title>
-        <para>TBD</para>
+        <title>Packet alignment</title>
+!Pnet/mac80211/rx.c Packet alignment
       </sect1>
       <sect1>
         <title>Calling into mac80211 from interrupts</title>
@@ -223,6 +222,11 @@ usage should require reading the full document.
 !Finclude/net/mac80211.h ieee80211_key_flags
     </chapter>
 
+    <chapter id="powersave">
+      <title>Powersave support</title>
+!Pinclude/net/mac80211.h Powersave support
+    </chapter>
+
     <chapter id="qos">
       <title>Multiple queues and QoS support</title>
       <para>TBD</para>
index 5ddbe350487acad3a92bc70b057da477901cdc1c..ac98851f7a0cb815043e9ccb355cd40ff9fb89de 100644 (file)
@@ -229,7 +229,9 @@ Who:        Jan Engelhardt <jengelh@computergmbh.de>
 ---------------------------
 
 What:  b43 support for firmware revision < 410
-When:  July 2008
+When:  The schedule was July 2008, but it was decided that we are going to keep the
+        code as long as there are no major maintanance headaches.
+       So it _could_ be removed _any_ time now, if it conflicts with something new.
 Why:   The support code for the old firmware hurts code readability/maintainability
        and slightly hurts runtime performance. Bugfixes for the old firmware
        are not provided by Broadcom anymore.
index 7a3bb1abb8304a1fe7222e354e43164a7a7635bb..b132e4a3cf0f137b7e8d6a18f67b01b5c44a95c2 100644 (file)
@@ -141,7 +141,8 @@ rx_ccid = 2
        Default CCID for the receiver-sender half-connection; see tx_ccid.
 
 seq_window = 100
-       The initial sequence window (sec. 7.5.2).
+       The initial sequence window (sec. 7.5.2) of the sender. This influences
+       the local ackno validity and the remote seqno validity windows (7.5.1).
 
 tx_qlen = 5
        The size of the transmit buffer in packets. A value of 0 corresponds
index c7712787933c1734c98a0191db23d9cb2886d0f8..ff3f219ee4d7bc590ecea9a9144c094f78f07dbd 100644 (file)
@@ -782,6 +782,12 @@ arp_ignore - INTEGER
        The max value from conf/{all,interface}/arp_ignore is used
        when ARP request is received on the {interface}
 
+arp_notify - BOOLEAN
+       Define mode for notification of address and device changes.
+       0 - (default): do nothing
+       1 - Generate gratuitous arp replies when device is brought up
+           or hardware address changes.
+
 arp_accept - BOOLEAN
        Define behavior when gratuitous arp replies are received:
        0 - drop gratuitous arp frames
index 7fa4b27574b5f54aabb1c9839e61fcf9f053c0ad..edb7ae19e868a2166c8c93e977a0d4064e95dfc2 100644 (file)
@@ -56,6 +56,12 @@ Properties:
     hardware.
   - fsl,magic-packet : If present, indicates that the hardware supports
     waking up via magic packet.
+  - bd-stash : If present, indicates that the hardware supports stashing
+    buffer descriptors in the L2.
+  - rx-stash-len : Denotes the number of bytes of a received buffer to stash
+    in the L2.
+  - rx-stash-idx : Denotes the index of the first byte from the received
+    buffer to stash in the L2.
 
 Example:
        ethernet@24000 {
index dc073e167abc68ed14f3dc67332568a845aac429..5608a1e5a3b3416fa44e44e504c9a2817d1c3c2c 100644 (file)
@@ -4311,10 +4311,17 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
        dev->stats.rx_bytes += size;
 
        netif_rx(skb);
-
-       dev->last_rx = jiffies;
 }
 
+static const struct net_device_ops hdlcdev_ops = {
+       .ndo_open       = hdlcdev_open,
+       .ndo_stop       = hdlcdev_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hdlcdev_ioctl,
+       .ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
 /**
  * called by device driver when adding device instance
  * do generic HDLC initialization
@@ -4341,11 +4348,8 @@ static int hdlcdev_init(MGSLPC_INFO *info)
        dev->irq       = info->irq_level;
 
        /* network layer callbacks and settings */
-       dev->do_ioctl       = hdlcdev_ioctl;
-       dev->open           = hdlcdev_open;
-       dev->stop           = hdlcdev_close;
-       dev->tx_timeout     = hdlcdev_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
+       dev->netdev_ops     = &hdlcdev_ops;
+       dev->watchdog_timeo = 10 * HZ;
        dev->tx_queue_len   = 50;
 
        /* generic HDLC layer callbacks and settings */
index b8063d4cad32ce9c122b051f9560656046864205..0057a8f58cb1261c71b48db67f1562d74282ee59 100644 (file)
@@ -8007,10 +8007,17 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
        dev->stats.rx_bytes += size;
 
        netif_rx(skb);
-
-       dev->last_rx = jiffies;
 }
 
+static const struct net_device_ops hdlcdev_ops = {
+       .ndo_open       = hdlcdev_open,
+       .ndo_stop       = hdlcdev_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hdlcdev_ioctl,
+       .ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
 /**
  * called by device driver when adding device instance
  * do generic HDLC initialization
@@ -8038,11 +8045,8 @@ static int hdlcdev_init(struct mgsl_struct *info)
        dev->dma       = info->dma_level;
 
        /* network layer callbacks and settings */
-       dev->do_ioctl       = hdlcdev_ioctl;
-       dev->open           = hdlcdev_open;
-       dev->stop           = hdlcdev_close;
-       dev->tx_timeout     = hdlcdev_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
+       dev->netdev_ops     = &hdlcdev_ops;
+       dev->watchdog_timeo = 10 * HZ;
        dev->tx_queue_len   = 50;
 
        /* generic HDLC layer callbacks and settings */
index f329f459817cb41bb4cb1ffb0c2ac6b08278ea3c..efb3dc928a43a7b6fe26bcfc551511f84d601772 100644 (file)
@@ -1763,10 +1763,17 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
        dev->stats.rx_bytes += size;
 
        netif_rx(skb);
-
-       dev->last_rx = jiffies;
 }
 
+static const struct net_device_ops hdlcdev_ops = {
+       .ndo_open       = hdlcdev_open,
+       .ndo_stop       = hdlcdev_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hdlcdev_ioctl,
+       .ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
 /**
  * called by device driver when adding device instance
  * do generic HDLC initialization
@@ -1794,11 +1801,8 @@ static int hdlcdev_init(struct slgt_info *info)
        dev->irq       = info->irq_level;
 
        /* network layer callbacks and settings */
-       dev->do_ioctl       = hdlcdev_ioctl;
-       dev->open           = hdlcdev_open;
-       dev->stop           = hdlcdev_close;
-       dev->tx_timeout     = hdlcdev_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
+       dev->netdev_ops     = &hdlcdev_ops;
+       dev->watchdog_timeo = 10 * HZ;
        dev->tx_queue_len   = 50;
 
        /* generic HDLC layer callbacks and settings */
index 7b0c5b2dd2635cbefbb9a919158aba8d5cef9a0b..8eb6c89a980ec1cb674eef7fe83e42142ea4d5cf 100644 (file)
@@ -1907,10 +1907,17 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
        dev->stats.rx_bytes += size;
 
        netif_rx(skb);
-
-       dev->last_rx = jiffies;
 }
 
+static const struct net_device_ops hdlcdev_ops = {
+       .ndo_open       = hdlcdev_open,
+       .ndo_stop       = hdlcdev_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hdlcdev_ioctl,
+       .ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
 /**
  * called by device driver when adding device instance
  * do generic HDLC initialization
@@ -1938,11 +1945,8 @@ static int hdlcdev_init(SLMP_INFO *info)
        dev->irq       = info->irq_level;
 
        /* network layer callbacks and settings */
-       dev->do_ioctl       = hdlcdev_ioctl;
-       dev->open           = hdlcdev_open;
-       dev->stop           = hdlcdev_close;
-       dev->tx_timeout     = hdlcdev_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
+       dev->netdev_ops     = &hdlcdev_ops;
+       dev->watchdog_timeo = 10 * HZ;
        dev->tx_queue_len   = 50;
 
        /* generic HDLC layer callbacks and settings */
index b6fe7e7a2c2fd71e6818a850fd6b8adbfd613bf5..c769ef269fb5833e96b3ac32ece432c4ce1de564 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *     cn_queue.c
- * 
+ *
  * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
  * All rights reserved.
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
 #include <linux/connector.h>
 #include <linux/delay.h>
 
+
+/*
+ * This job is sent to the kevent workqueue.
+ * While no event is once sent to any callback, the connector workqueue
+ * is not created to avoid a useless waiting kernel task.
+ * Once the first event is received, we create this dedicated workqueue which
+ * is necessary because the flow of data can be high and we don't want
+ * to encumber keventd with that.
+ */
+static void cn_queue_create(struct work_struct *work)
+{
+       struct cn_queue_dev *dev;
+
+       dev = container_of(work, struct cn_queue_dev, wq_creation);
+
+       dev->cn_queue = create_singlethread_workqueue(dev->name);
+       /* If we fail, we will use keventd for all following connector jobs */
+       WARN_ON(!dev->cn_queue);
+}
+
+/*
+ * Queue a data sent to a callback.
+ * If the connector workqueue is already created, we queue the job on it.
+ * Otherwise, we queue the job to kevent and queue the connector workqueue
+ * creation too.
+ */
+int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work)
+{
+       struct cn_queue_dev *pdev = cbq->pdev;
+
+       if (likely(pdev->cn_queue))
+               return queue_work(pdev->cn_queue, work);
+
+       /* Don't create the connector workqueue twice */
+       if (atomic_inc_return(&pdev->wq_requested) == 1)
+               schedule_work(&pdev->wq_creation);
+       else
+               atomic_dec(&pdev->wq_requested);
+
+       return schedule_work(work);
+}
+
 void cn_queue_wrapper(struct work_struct *work)
 {
        struct cn_callback_entry *cbq =
@@ -58,14 +100,17 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc
        snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
        memcpy(&cbq->id.id, id, sizeof(struct cb_id));
        cbq->data.callback = callback;
-       
+
        INIT_WORK(&cbq->work, &cn_queue_wrapper);
        return cbq;
 }
 
 static void cn_queue_free_callback(struct cn_callback_entry *cbq)
 {
-       flush_workqueue(cbq->pdev->cn_queue);
+       /* The first jobs have been sent to kevent, flush them too */
+       flush_scheduled_work();
+       if (cbq->pdev->cn_queue)
+               flush_workqueue(cbq->pdev->cn_queue);
 
        kfree(cbq);
 }
@@ -143,14 +188,11 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
        atomic_set(&dev->refcnt, 0);
        INIT_LIST_HEAD(&dev->queue_list);
        spin_lock_init(&dev->queue_lock);
+       init_waitqueue_head(&dev->wq_created);
 
        dev->nls = nls;
 
-       dev->cn_queue = create_singlethread_workqueue(dev->name);
-       if (!dev->cn_queue) {
-               kfree(dev);
-               return NULL;
-       }
+       INIT_WORK(&dev->wq_creation, cn_queue_create);
 
        return dev;
 }
@@ -158,9 +200,25 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
 void cn_queue_free_dev(struct cn_queue_dev *dev)
 {
        struct cn_callback_entry *cbq, *n;
+       long timeout;
+       DEFINE_WAIT(wait);
+
+       /* Flush the first pending jobs queued on kevent */
+       flush_scheduled_work();
+
+       /* If the connector workqueue creation is still pending, wait for it */
+       prepare_to_wait(&dev->wq_created, &wait, TASK_UNINTERRUPTIBLE);
+       if (atomic_read(&dev->wq_requested) && !dev->cn_queue) {
+               timeout = schedule_timeout(HZ * 2);
+               if (!timeout && !dev->cn_queue)
+                       WARN_ON(1);
+       }
+       finish_wait(&dev->wq_created, &wait);
 
-       flush_workqueue(dev->cn_queue);
-       destroy_workqueue(dev->cn_queue);
+       if (dev->cn_queue) {
+               flush_workqueue(dev->cn_queue);
+               destroy_workqueue(dev->cn_queue);
+       }
 
        spin_lock_bh(&dev->queue_lock);
        list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)
index bf4830082a135e126d9f35f1a72a7bf5b18fbecf..fd336c5a9057a8da729ebd2d3961cbb7b6a4c271 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *     connector.c
- * 
+ *
  * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
  * All rights reserved.
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -145,14 +145,13 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
                                __cbq->data.ddata = data;
                                __cbq->data.destruct_data = destruct_data;
 
-                               if (queue_work(dev->cbdev->cn_queue,
-                                                       &__cbq->work))
+                               if (queue_cn_work(__cbq, &__cbq->work))
                                        err = 0;
                                else
                                        err = -EINVAL;
                        } else {
                                struct cn_callback_data *d;
-                               
+
                                err = -ENOMEM;
                                __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
                                if (__new_cbq) {
@@ -163,10 +162,12 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
                                        d->destruct_data = destruct_data;
                                        d->free = __new_cbq;
 
+                                       __new_cbq->pdev = __cbq->pdev;
+
                                        INIT_WORK(&__new_cbq->work,
                                                        &cn_queue_wrapper);
 
-                                       if (queue_work(dev->cbdev->cn_queue,
+                                       if (queue_cn_work(__new_cbq,
                                                    &__new_cbq->work))
                                                err = 0;
                                        else {
@@ -237,7 +238,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
 
                req = (struct cn_notify_req *)ctl->data;
                for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
-                       if (id->idx >= req->first && 
+                       if (id->idx >= req->first &&
                                        id->idx < req->first + req->range) {
                                idx_found = 1;
                                break;
@@ -245,7 +246,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
                }
 
                for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
-                       if (id->val >= req->first && 
+                       if (id->val >= req->first &&
                                        id->val < req->first + req->range) {
                                val_found = 1;
                                break;
@@ -459,7 +460,7 @@ static int __devinit cn_init(void)
                netlink_kernel_release(dev->nls);
                return -EINVAL;
        }
-       
+
        cn_already_initialized = 1;
 
        err = cn_add_callback(&dev->id, "connector", &cn_callback);
index 4dcf08b3fd832dd12d96a5a5ce3c9dcc1c8a5058..11efd3528ce4e8e9943153c3914d45de3467e02e 100644 (file)
@@ -701,6 +701,9 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
        u32 stag_idx;
        u32 wptr;
 
+       if (rdev_p->flags)
+               return -EIO;
+
        stag_state = stag_state > 0;
        stag_idx = (*stag) >> 8;
 
index 656fe47bc84f94ea2d1af60e2d916be85a69cd47..9ed65b055171e331fda71fc32302de55106682c8 100644 (file)
@@ -108,6 +108,8 @@ struct cxio_rdev {
        struct gen_pool *pbl_pool;
        struct gen_pool *rqt_pool;
        struct list_head entry;
+       u32     flags;
+#define        CXIO_ERROR_FATAL        1
 };
 
 static inline int cxio_num_stags(struct cxio_rdev *rdev_p)
index 4489c89d6710c6b22c478f4b7742ff0ff4688576..37a4fc264a07a10bc34ff8e7f92b34869153e640 100644 (file)
@@ -51,13 +51,15 @@ cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
 
 static void open_rnic_dev(struct t3cdev *);
 static void close_rnic_dev(struct t3cdev *);
+static void iwch_err_handler(struct t3cdev *, u32, u32);
 
 struct cxgb3_client t3c_client = {
        .name = "iw_cxgb3",
        .add = open_rnic_dev,
        .remove = close_rnic_dev,
        .handlers = t3c_handlers,
-       .redirect = iwch_ep_redirect
+       .redirect = iwch_ep_redirect,
+       .err_handler = iwch_err_handler
 };
 
 static LIST_HEAD(dev_list);
@@ -160,6 +162,17 @@ static void close_rnic_dev(struct t3cdev *tdev)
        mutex_unlock(&dev_mutex);
 }
 
+static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error)
+{
+       struct cxio_rdev *rdev = tdev->ulp;
+
+       if (status == OFFLOAD_STATUS_DOWN)
+               rdev->flags = CXIO_ERROR_FATAL;
+
+       return;
+
+}
+
 static int __init iwch_init_module(void)
 {
        int err;
index 5d139db1b771e745e9c248df0536c3bbdbc5d01e..53df9de23423bdcb9a96a7d4ea0992e6694bde43 100644 (file)
@@ -2541,7 +2541,7 @@ static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic
 {
        struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
 
-       netif_rx_schedule(&nesvnic->napi);
+       napi_schedule(&nesvnic->napi);
 }
 
 
index 57a47cf7e513ca60d86a1a108454f36248bcd16a..f5484ad1279bd2110a253870b482b7de5fc8b537 100644 (file)
@@ -111,7 +111,7 @@ static int nes_netdev_poll(struct napi_struct *napi, int budget)
        nes_nic_ce_handler(nesdev, nescq);
 
        if (nescq->cqes_pending == 0) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                /* clear out completed cqes and arm */
                nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
                                nescq->cq_number | (nescq->cqe_allocs_pending << 16));
index a1925810be3cb23f8e768b030c60d68944267b5f..da6082739839968ed3c64cc402a3bb438b28b8eb 100644 (file)
@@ -446,11 +446,11 @@ poll_more:
                if (dev->features & NETIF_F_LRO)
                        lro_flush_all(&priv->lro.lro_mgr);
 
-               netif_rx_complete(napi);
+               napi_complete(napi);
                if (unlikely(ib_req_notify_cq(priv->recv_cq,
                                              IB_CQ_NEXT_COMP |
                                              IB_CQ_REPORT_MISSED_EVENTS)) &&
-                   netif_rx_reschedule(napi))
+                   napi_reschedule(napi))
                        goto poll_more;
        }
 
@@ -462,7 +462,7 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
        struct net_device *dev = dev_ptr;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       netif_rx_schedule(&priv->napi);
+       napi_schedule(&priv->napi);
 }
 
 static void drain_tx_cq(struct net_device *dev)
index 3d1318a3e6885901a5f1e4efab65b0964a5dc48e..1c5344aa57cc32473a0b019d7ab1205e3df2b9e0 100644 (file)
@@ -197,6 +197,17 @@ out:
        return ERR_PTR(err);
 }
 
+static const struct net_device_ops el_netdev_ops = {
+       .ndo_open               = el_open,
+       .ndo_stop               = el1_close,
+       .ndo_start_xmit         = el_start_xmit,
+       .ndo_tx_timeout         = el_timeout,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 /**
  *     el1_probe1:
  *     @dev: The device structure to use
@@ -305,12 +316,8 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
         *      The EL1-specific entries in the device structure.
         */
 
-       dev->open = &el_open;
-       dev->hard_start_xmit = &el_start_xmit;
-       dev->tx_timeout = &el_timeout;
+       dev->netdev_ops = &el_netdev_ops;
        dev->watchdog_timeo = HZ;
-       dev->stop = &el1_close;
-       dev->set_multicast_list = &set_multicast_list;
        dev->ethtool_ops = &netdev_ethtool_ops;
        return 0;
 }
index 6124605bef05404bb2dee77114d5f8fcd1a1aff8..ea1ad8ce883640cf73e9ddfcbcff00e491c6f670 100644 (file)
@@ -1348,6 +1348,17 @@ static int __init elp_autodetect(struct net_device *dev)
        return 0;               /* Because of this, the layer above will return -ENODEV */
 }
 
+static const struct net_device_ops elp_netdev_ops = {
+       .ndo_open               = elp_open,
+       .ndo_stop               = elp_close,
+       .ndo_get_stats          = elp_get_stats,
+       .ndo_start_xmit         = elp_start_xmit,
+       .ndo_tx_timeout         = elp_timeout,
+       .ndo_set_multicast_list = elp_set_mc_list,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
 
 /******************************************************
  *
@@ -1552,13 +1563,8 @@ static int __init elplus_setup(struct net_device *dev)
                printk(KERN_ERR "%s: adapter configuration failed\n", dev->name);
        }
 
-       dev->open = elp_open;                           /* local */
-       dev->stop = elp_close;                          /* local */
-       dev->get_stats = elp_get_stats;                 /* local */
-       dev->hard_start_xmit = elp_start_xmit;          /* local */
-       dev->tx_timeout = elp_timeout;                  /* local */
+       dev->netdev_ops = &elp_netdev_ops;
        dev->watchdog_timeo = 10*HZ;
-       dev->set_multicast_list = elp_set_mc_list;      /* local */
        dev->ethtool_ops = &netdev_ethtool_ops;         /* local */
 
        dev->mem_start = dev->mem_end = 0;
index 423e65d0ba737740091fa9488f5305776475200b..fbbaf826deff829531a6dddaac7d652146df030b 100644 (file)
@@ -352,6 +352,16 @@ out:
        return ERR_PTR(err);
 }
 
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = el16_open,
+       .ndo_stop               = el16_close,
+       .ndo_start_xmit         = el16_send_packet,
+       .ndo_tx_timeout         = el16_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 static int __init el16_probe1(struct net_device *dev, int ioaddr)
 {
        static unsigned char init_ID_done, version_printed;
@@ -449,10 +459,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
                goto out1;
        }
 
-       dev->open = el16_open;
-       dev->stop = el16_close;
-       dev->hard_start_xmit = el16_send_packet;
-       dev->tx_timeout = el16_tx_timeout;
+       dev->netdev_ops = &netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->ethtool_ops = &netdev_ethtool_ops;
        dev->flags &= ~IFF_MULTICAST;   /* Multicast doesn't work */
index 535c234286ea80c27f8a2ca8170b88b1b9c87208..d58919c7032ea17cf6aa5ac83dd2154975afdd32 100644 (file)
@@ -537,6 +537,21 @@ static struct mca_driver el3_mca_driver = {
 static int mca_registered;
 #endif /* CONFIG_MCA */
 
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = el3_open,
+       .ndo_stop               = el3_close,
+       .ndo_start_xmit         = el3_start_xmit,
+       .ndo_get_stats          = el3_get_stats,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_tx_timeout         = el3_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = el3_poll_controller,
+#endif
+};
+
 static int __devinit el3_common_init(struct net_device *dev)
 {
        struct el3_private *lp = netdev_priv(dev);
@@ -553,16 +568,8 @@ static int __devinit el3_common_init(struct net_device *dev)
        }
 
        /* The EL3-specific entries in the device structure. */
-       dev->open = &el3_open;
-       dev->hard_start_xmit = &el3_start_xmit;
-       dev->stop = &el3_close;
-       dev->get_stats = &el3_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
-       dev->tx_timeout = el3_tx_timeout;
+       dev->netdev_ops = &netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = el3_poll_controller;
-#endif
        SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
        err = register_netdev(dev);
index 39ac12233aa72778362d0e00eee37830f7d387ce..167bf23066eab6e5e376d4356acde830f2e06aaf 100644 (file)
@@ -563,6 +563,20 @@ no_pnp:
        return NULL;
 }
 
+
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = corkscrew_open,
+       .ndo_stop               = corkscrew_close,
+       .ndo_start_xmit         = corkscrew_start_xmit,
+       .ndo_tx_timeout         = corkscrew_timeout,
+       .ndo_get_stats          = corkscrew_get_stats,
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+
 static int corkscrew_setup(struct net_device *dev, int ioaddr,
                            struct pnp_dev *idev, int card_number)
 {
@@ -681,13 +695,8 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
        vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
 
        /* The 3c51x-specific entries in the device structure. */
-       dev->open = &corkscrew_open;
-       dev->hard_start_xmit = &corkscrew_start_xmit;
-       dev->tx_timeout = &corkscrew_timeout;
+       dev->netdev_ops = &netdev_ops;
        dev->watchdog_timeo = (400 * HZ) / 1000;
-       dev->stop = &corkscrew_close;
-       dev->get_stats = &corkscrew_get_stats;
-       dev->set_multicast_list = &set_rx_mode;
        dev->ethtool_ops = &netdev_ethtool_ops;
 
        return register_netdev(dev);
index ff41e1ff56031876862db4a387c45a0dedb5d0b9..8f734d74b513f66b33e3c89b7c8779125e832246 100644 (file)
@@ -403,6 +403,20 @@ static int elmc_getinfo(char *buf, int slot, void *d)
        return len;
 }                              /* elmc_getinfo() */
 
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = elmc_open,
+       .ndo_stop               = elmc_close,
+       .ndo_get_stats          = elmc_get_stats,
+       .ndo_start_xmit         = elmc_send_packet,
+       .ndo_tx_timeout         = elmc_timeout,
+#ifdef ELMC_MULTICAST
+       .ndo_set_multicast_list = set_multicast_list,
+#endif
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 /*****************************************************************/
 
 static int __init do_elmc_probe(struct net_device *dev)
@@ -544,17 +558,8 @@ static int __init do_elmc_probe(struct net_device *dev)
        printk(KERN_INFO "%s: hardware address %pM\n",
               dev->name, dev->dev_addr);
 
-       dev->open = &elmc_open;
-       dev->stop = &elmc_close;
-       dev->get_stats = &elmc_get_stats;
-       dev->hard_start_xmit = &elmc_send_packet;
-       dev->tx_timeout = &elmc_timeout;
+       dev->netdev_ops = &netdev_ops;
        dev->watchdog_timeo = HZ;
-#ifdef ELMC_MULTICAST
-       dev->set_multicast_list = &set_multicast_list;
-#else
-       dev->set_multicast_list = NULL;
-#endif
        dev->ethtool_ops = &netdev_ethtool_ops;
 
        /* note that we haven't actually requested the IRQ from the kernel.
index 2df3af3b9b20130ead927f93db05730029430d9c..b61073c42bf8641b1623243e5fa30d19299b79aa 100644 (file)
@@ -288,6 +288,18 @@ struct net_device *__init mc32_probe(int unit)
        return ERR_PTR(-ENODEV);
 }
 
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = mc32_open,
+       .ndo_stop               = mc32_close,
+       .ndo_start_xmit         = mc32_send_packet,
+       .ndo_get_stats          = mc32_get_stats,
+       .ndo_set_multicast_list = mc32_set_multicast_list,
+       .ndo_tx_timeout         = mc32_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 /**
  * mc32_probe1 -       Check a given slot for a board and test the card
  * @dev:  Device structure to fill in
@@ -518,12 +530,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
        printk("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
                dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base);
 
-       dev->open               = mc32_open;
-       dev->stop               = mc32_close;
-       dev->hard_start_xmit    = mc32_send_packet;
-       dev->get_stats          = mc32_get_stats;
-       dev->set_multicast_list = mc32_set_multicast_list;
-       dev->tx_timeout         = mc32_timeout;
+       dev->netdev_ops         = &netdev_ops;
        dev->watchdog_timeo     = HZ*5; /* Board does all the work */
        dev->ethtool_ops        = &netdev_ethtool_ops;
 
index cdbbb6226fc598d3fd5bb5b072fd5ffba7ef1c9d..b2563d384cf2998a8b763cf9767146716b718b86 100644 (file)
@@ -992,6 +992,42 @@ out:
        return rc;
 }
 
+static const struct net_device_ops boomrang_netdev_ops = {
+       .ndo_open               = vortex_open,
+       .ndo_stop               = vortex_close,
+       .ndo_start_xmit         = boomerang_start_xmit,
+       .ndo_tx_timeout         = vortex_tx_timeout,
+       .ndo_get_stats          = vortex_get_stats,
+#ifdef CONFIG_PCI
+       .ndo_do_ioctl           = vortex_ioctl,
+#endif
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = poll_vortex,
+#endif
+};
+
+static const struct net_device_ops vortex_netdev_ops = {
+       .ndo_open               = vortex_open,
+       .ndo_stop               = vortex_close,
+       .ndo_start_xmit         = vortex_start_xmit,
+       .ndo_tx_timeout         = vortex_tx_timeout,
+       .ndo_get_stats          = vortex_get_stats,
+#ifdef CONFIG_PCI
+       .ndo_do_ioctl           = vortex_ioctl,
+#endif
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = poll_vortex,
+#endif
+};
+
 /*
  * Start up the PCI/EISA device which is described by *gendev.
  * Return 0 on success.
@@ -1366,18 +1402,16 @@ static int __devinit vortex_probe1(struct device *gendev,
        }
 
        /* The 3c59x-specific entries in the device structure. */
-       dev->open = vortex_open;
        if (vp->full_bus_master_tx) {
-               dev->hard_start_xmit = boomerang_start_xmit;
+               dev->netdev_ops = &boomrang_netdev_ops;
                /* Actually, it still should work with iommu. */
                if (card_idx < MAX_UNITS &&
                    ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
                                hw_checksums[card_idx] == 1)) {
                        dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                }
-       } else {
-               dev->hard_start_xmit = vortex_start_xmit;
-       }
+       } else
+               dev->netdev_ops =  &vortex_netdev_ops;
 
        if (print_info) {
                printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n",
@@ -1386,18 +1420,9 @@ static int __devinit vortex_probe1(struct device *gendev,
                                (dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
        }
 
-       dev->stop = vortex_close;
-       dev->get_stats = vortex_get_stats;
-#ifdef CONFIG_PCI
-       dev->do_ioctl = vortex_ioctl;
-#endif
        dev->ethtool_ops = &vortex_ethtool_ops;
-       dev->set_multicast_list = set_rx_mode;
-       dev->tx_timeout = vortex_tx_timeout;
        dev->watchdog_timeo = (watchdog * HZ) / 1000;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = poll_vortex;
-#endif
+
        if (pdev) {
                vp->pm_state_valid = 1;
                pci_save_state(VORTEX_PCI(vp));
index 4e19ae3ce6bef0d2f10b9c4225974ee6e088754a..35517b06ec3ff39901f8eeba255146e84ea8e7b0 100644 (file)
@@ -604,7 +604,7 @@ rx_next:
 
                spin_lock_irqsave(&cp->lock, flags);
                cpw16_f(IntrMask, cp_intr_mask);
-               __netif_rx_complete(napi);
+               __napi_complete(napi);
                spin_unlock_irqrestore(&cp->lock, flags);
        }
 
@@ -641,9 +641,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
        }
 
        if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
-               if (netif_rx_schedule_prep(&cp->napi)) {
+               if (napi_schedule_prep(&cp->napi)) {
                        cpw16_f(IntrMask, cp_norx_intr_mask);
-                       __netif_rx_schedule(&cp->napi);
+                       __napi_schedule(&cp->napi);
                }
 
        if (status & (TxOK | TxErr | TxEmpty | SWInt))
index a5b24202d5649e5c292e5267701d39f0699bae9a..5341da604e8465df4aafedf5ebba6404db627ee6 100644 (file)
@@ -2128,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(napi);
+               __napi_complete(napi);
                spin_unlock_irqrestore(&tp->lock, flags);
        }
        spin_unlock(&tp->rx_lock);
@@ -2178,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(&tp->napi)) {
+               if (napi_schedule_prep(&tp->napi)) {
                        RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
-                       __netif_rx_schedule(&tp->napi);
+                       __napi_schedule(&tp->napi);
                }
        }
 
index b273596368e36d9c2a99e1143b673e518f93aeed..cca94b9c08ae5360428554fcff302620009488b4 100644 (file)
@@ -1122,6 +1122,17 @@ static void print_eth(unsigned char *add, char *str)
 static int io = 0x300;
 static int irq = 10;
 
+static const struct net_device_ops i596_netdev_ops = {
+       .ndo_open               = i596_open,
+       .ndo_stop               = i596_close,
+       .ndo_start_xmit         = i596_start_xmit,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_tx_timeout         = i596_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 struct net_device * __init i82596_probe(int unit)
 {
        struct net_device *dev;
@@ -1232,11 +1243,7 @@ found:
        DEB(DEB_PROBE,printk(KERN_INFO "%s", version));
 
        /* The 82596-specific entries in the device structure. */
-       dev->open = i596_open;
-       dev->stop = i596_close;
-       dev->hard_start_xmit = i596_start_xmit;
-       dev->set_multicast_list = set_multicast_list;
-       dev->tx_timeout = i596_tx_timeout;
+       dev->netdev_ops = &i596_netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
 
        dev->ml_priv = (void *)(dev->mem_start);
index 6bdfd47d679d9425d777ac68cc7b6b22d13e46f0..62bc0223a8edf6ff7af9aebcae63ce14e7eca0e6 100644 (file)
@@ -1829,10 +1829,10 @@ config 68360_ENET
 
 config FEC
        bool "FEC ethernet controller (of ColdFire CPUs)"
-       depends on M523x || M527x || M5272 || M528x || M520x || M532x
+       depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27
        help
          Say Y here if you want to use the built-in 10/100 Fast ethernet
-         controller on some Motorola ColdFire processors.
+         controller on some Motorola ColdFire and Freescale i.MX processors.
 
 config FEC2
        bool "Second FEC ethernet controller (on some ColdFire CPUs)"
@@ -2022,7 +2022,6 @@ config IGB
 config IGB_LRO 
        bool "Use software LRO"
        depends on IGB && INET
-       select INET_LRO
        ---help---
          Say Y here if you want to use large receive offload. 
 
@@ -2273,9 +2272,17 @@ config GELIC_WIRELESS_OLD_PSK_INTERFACE
 
           If unsure, say N.
 
+config FSL_PQ_MDIO
+       tristate "Freescale PQ MDIO"
+       depends on FSL_SOC
+       select PHYLIB
+       help
+         This driver supports the MDIO bus used by the gianfar and UCC drivers.
+
 config GIANFAR
        tristate "Gianfar Ethernet"
        depends on FSL_SOC
+       select FSL_PQ_MDIO
        select PHYLIB
        select CRC32
        help
@@ -2285,6 +2292,7 @@ config GIANFAR
 config UCC_GETH
        tristate "Freescale QE Gigabit Ethernet"
        depends on QUICC_ENGINE
+       select FSL_PQ_MDIO
        select PHYLIB
        help
          This driver supports the Gigabit Ethernet mode of the QUICC Engine,
@@ -2408,7 +2416,6 @@ config CHELSIO_T3
        tristate "Chelsio Communications T3 10Gb Ethernet support"
        depends on CHELSIO_T3_DEPENDS
        select FW_LOADER
-       select INET_LRO
        help
          This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
          adapters.
@@ -2444,7 +2451,6 @@ config ENIC
 config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
        depends on PCI && INET
-       select INET_LRO
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
          adapters.  For more information on how to identify your adapter, go
index a3c5c002f224343ad30343b0ffc485b358075c77..ad87ba72cf1fc5f6014c0890e2863f4b325ad494 100644 (file)
@@ -24,11 +24,12 @@ obj-$(CONFIG_JME) += jme.o
 
 gianfar_driver-objs := gianfar.o \
                gianfar_ethtool.o \
-               gianfar_mii.o \
                gianfar_sysfs.o
 
 obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
-ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
+
+obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
 
 #
 # link order important here
index 7709992bb6bf21d5e85814c65dc63305412586d8..cb9c95d3ed0ab45854da0e1b1e8e0240c6c044d6 100644 (file)
@@ -831,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(napi);
+               __napi_complete(napi);
                writel(VAL0|RINTEN0, mmio + INTEN0);
                writel(VAL2 | RDMD0, mmio + CMD0);
                spin_unlock_irqrestore(&lp->lock, flags);
@@ -1170,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(&lp->napi)) {
+               if (napi_schedule_prep(&lp->napi)) {
                        /* Disable receive interupts */
                        writel(RINTEN0, mmio + INTEN0);
                        /* Schedule a polling routine */
-                       __netif_rx_schedule(&lp->napi);
+                       __napi_schedule(&lp->napi);
                } else if (intren0 & RINTEN0) {
                        printk("************Driver bug! \
                                interrupt while in poll\n");
index 3ff9affb1a914e212de008728985598e8e724bf8..646dfc5f50c9827014f343ba3c62bc7960b85f4e 100644 (file)
@@ -102,7 +102,7 @@ static void rx(struct net_device *dev, int bufnum,
        skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
        if (skb == NULL) {
                BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
-               lp->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        skb_put(skb, length + ARC_HDR_SIZE);
@@ -122,7 +122,7 @@ static void rx(struct net_device *dev, int bufnum,
 
        BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
 
-       skb->protocol = __constant_htons(ETH_P_ARCNET);
+       skb->protocol = cpu_to_be16(ETH_P_ARCNET);
 ;
        netif_rx(skb);
 }
index 6b53e5ed125cfbb10c2be5f34edca1a04fe36097..a80d4a30a4643ae18f5902f05b8e4fc89c6fb99d 100644 (file)
@@ -95,17 +95,16 @@ EXPORT_SYMBOL(arcnet_unregister_proto);
 EXPORT_SYMBOL(arcnet_debug);
 EXPORT_SYMBOL(alloc_arcdev);
 EXPORT_SYMBOL(arcnet_interrupt);
+EXPORT_SYMBOL(arcnet_open);
+EXPORT_SYMBOL(arcnet_close);
+EXPORT_SYMBOL(arcnet_send_packet);
+EXPORT_SYMBOL(arcnet_timeout);
 
 /* Internal function prototypes */
-static int arcnet_open(struct net_device *dev);
-static int arcnet_close(struct net_device *dev);
-static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnet_timeout(struct net_device *dev);
 static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
                         unsigned short type, const void *daddr,
                         const void *saddr, unsigned len);
 static int arcnet_rebuild_header(struct sk_buff *skb);
-static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
 static int go_tx(struct net_device *dev);
 
 static int debug = ARCNET_DEBUG;
@@ -322,11 +321,18 @@ static const struct header_ops arcnet_header_ops = {
        .rebuild = arcnet_rebuild_header,
 };
 
+static const struct net_device_ops arcnet_netdev_ops = {
+       .ndo_open       = arcnet_open,
+       .ndo_stop       = arcnet_close,
+       .ndo_start_xmit = arcnet_send_packet,
+       .ndo_tx_timeout = arcnet_timeout,
+};
 
 /* Setup a struct device for ARCnet. */
 static void arcdev_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_ARCNET;
+       dev->netdev_ops = &arcnet_netdev_ops;
        dev->header_ops = &arcnet_header_ops;
        dev->hard_header_len = sizeof(struct archdr);
        dev->mtu = choose_mtu();
@@ -339,18 +345,9 @@ static void arcdev_setup(struct net_device *dev)
        /* New-style flags. */
        dev->flags = IFF_BROADCAST;
 
-       /*
-        * Put in this stuff here, so we don't have to export the symbols to
-        * the chipset drivers.
-        */
-       dev->open = arcnet_open;
-       dev->stop = arcnet_close;
-       dev->hard_start_xmit = arcnet_send_packet;
-       dev->tx_timeout = arcnet_timeout;
-       dev->get_stats = arcnet_get_stats;
 }
 
-struct net_device *alloc_arcdev(char *name)
+struct net_device *alloc_arcdev(const char *name)
 {
        struct net_device *dev;
 
@@ -372,7 +369,7 @@ struct net_device *alloc_arcdev(char *name)
  * that "should" only need to be set once at boot, so that there is
  * non-reboot way to recover if something goes wrong.
  */
-static int arcnet_open(struct net_device *dev)
+int arcnet_open(struct net_device *dev)
 {
        struct arcnet_local *lp = netdev_priv(dev);
        int count, newmtu, error;
@@ -472,7 +469,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)
+int arcnet_close(struct net_device *dev)
 {
        struct arcnet_local *lp = netdev_priv(dev);
 
@@ -583,8 +580,8 @@ static int arcnet_rebuild_header(struct sk_buff *skb)
        } else {
                BUGMSG(D_NORMAL,
                       "I don't understand ethernet protocol %Xh addresses!\n", type);
-               lp->stats.tx_errors++;
-               lp->stats.tx_aborted_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
        }
 
        /* if we couldn't resolve the address... give up. */
@@ -601,7 +598,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)
+int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
        struct arcnet_local *lp = netdev_priv(dev);
        struct archdr *pkt;
@@ -645,7 +642,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
                    !proto->ack_tx) {
                        /* done right away and we don't want to acknowledge
                           the package later - forget about it now */
-                       lp->stats.tx_bytes += skb->len;
+                       dev->stats.tx_bytes += skb->len;
                        freeskb = 1;
                } else {
                        /* do it the 'split' way */
@@ -709,7 +706,7 @@ static int go_tx(struct net_device *dev)
        /* start sending */
        ACOMMAND(TXcmd | (lp->cur_tx << 3));
 
-       lp->stats.tx_packets++;
+       dev->stats.tx_packets++;
        lp->lasttrans_dest = lp->lastload_dest;
        lp->lastload_dest = 0;
        lp->excnak_pending = 0;
@@ -720,7 +717,7 @@ static int go_tx(struct net_device *dev)
 
 
 /* Called by the kernel when transmit times out */
-static void arcnet_timeout(struct net_device *dev)
+void arcnet_timeout(struct net_device *dev)
 {
        unsigned long flags;
        struct arcnet_local *lp = netdev_priv(dev);
@@ -732,11 +729,11 @@ static void arcnet_timeout(struct net_device *dev)
                msg = " - missed IRQ?";
        } else {
                msg = "";
-               lp->stats.tx_aborted_errors++;
+               dev->stats.tx_aborted_errors++;
                lp->timed_out = 1;
                ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
        }
-       lp->stats.tx_errors++;
+       dev->stats.tx_errors++;
 
        /* make sure we didn't miss a TX or a EXC NAK IRQ */
        AINTMASK(0);
@@ -865,8 +862,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
                                                       "transmit was not acknowledged! "
                                                       "(status=%Xh, dest=%02Xh)\n",
                                                       status, lp->lasttrans_dest);
-                                               lp->stats.tx_errors++;
-                                               lp->stats.tx_carrier_errors++;
+                                               dev->stats.tx_errors++;
+                                               dev->stats.tx_carrier_errors++;
                                        } else {
                                                BUGMSG(D_DURING,
                                                       "broadcast was not acknowledged; that's normal "
@@ -905,7 +902,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
                                if (txbuf != -1) {
                                        if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
                                                /* that was the last segment */
-                                               lp->stats.tx_bytes += lp->outgoing.skb->len;
+                                               dev->stats.tx_bytes += lp->outgoing.skb->len;
                                                if(!lp->outgoing.proto->ack_tx)
                                                  {
                                                    dev_kfree_skb_irq(lp->outgoing.skb);
@@ -930,7 +927,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
                }
                if (status & lp->intmask & RECONflag) {
                        ACOMMAND(CFLAGScmd | CONFIGclear);
-                       lp->stats.tx_carrier_errors++;
+                       dev->stats.tx_carrier_errors++;
 
                        BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
                               status);
@@ -1038,8 +1035,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
               "(%d+4 bytes)\n",
               bufnum, pkt.hard.source, pkt.hard.dest, length);
 
-       lp->stats.rx_packets++;
-       lp->stats.rx_bytes += length + ARC_HDR_SIZE;
+       dev->stats.rx_packets++;
+       dev->stats.rx_bytes += length + ARC_HDR_SIZE;
 
        /* call the right receiver for the protocol */
        if (arc_proto_map[soft->proto]->is_ip) {
@@ -1067,18 +1064,6 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
 }
 
 
-
-/* 
- * Get the current statistics.  This may be called with the card open or
- * closed.
- */
-static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
-{
-       struct arcnet_local *lp = netdev_priv(dev);
-       return &lp->stats;
-}
-
-
 static void null_rx(struct net_device *dev, int bufnum,
                    struct archdr *pkthdr, int length)
 {
index 30580bbe252d4ff11a346d0d7bbc0db1a0a2bef5..083e21094b20d69ae6fba917bef34485a5cd5766 100644 (file)
@@ -119,7 +119,7 @@ static void rx(struct net_device *dev, int bufnum,
        skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC);
        if (skb == NULL) {
                BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
-               lp->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        skb_put(skb, length + ARC_HDR_SIZE + sizeof(int));
@@ -148,7 +148,7 @@ static void rx(struct net_device *dev, int bufnum,
 
        BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
 
-       skb->protocol = __constant_htons(ETH_P_ARCNET);
+       skb->protocol = cpu_to_be16(ETH_P_ARCNET);
 ;
        netif_rx(skb);
 }
@@ -282,7 +282,7 @@ static int ack_tx(struct net_device *dev, int acked)
   BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n",
         *((int*)&ackpkt->soft.cap.cookie[0]));
 
-  ackskb->protocol = __constant_htons(ETH_P_ARCNET);
+  ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
 
   BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
   netif_rx(ackskb);
index ea53a940272f1172ec4b51070d608becbf71e134..db08fc24047a5b569a3f0e411b1cafea435cd5e2 100644 (file)
@@ -151,6 +151,8 @@ static int __init com20020_init(void)
        if (node && node != 0xff)
                dev->dev_addr[0] = node;
 
+       dev->netdev_ops = &com20020_netdev_ops;
+
        lp = netdev_priv(dev);
        lp->backplane = backplane;
        lp->clockp = clockp & 7;
index 8b51f632581d1810f2f712e2b3b63ae942b33ed3..dbf4de39754d1f4009edfdb02f4bfa1e80e56baa 100644 (file)
@@ -72,6 +72,9 @@ static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_de
        dev = alloc_arcdev(device);
        if (!dev)
                return -ENOMEM;
+
+       dev->netdev_ops = &com20020_netdev_ops;
+
        lp = netdev_priv(dev);
 
        pci_set_drvdata(pdev, dev);
index 103688358fb84721af7568c9a4f14a90ba81659c..651275a5f3d27020022d1682930c89a7db6ace3b 100644 (file)
@@ -149,6 +149,14 @@ int com20020_check(struct net_device *dev)
        return 0;
 }
 
+const struct net_device_ops com20020_netdev_ops = {
+       .ndo_open       = arcnet_open,
+       .ndo_stop       = arcnet_close,
+       .ndo_start_xmit = arcnet_send_packet,
+       .ndo_tx_timeout = arcnet_timeout,
+       .ndo_set_multicast_list = com20020_set_mc_list,
+};
+
 /* Set up the struct net_device associated with this card.  Called after
  * probing succeeds.
  */
@@ -170,8 +178,6 @@ int com20020_found(struct net_device *dev, int shared)
        lp->hw.copy_from_card = com20020_copy_from_card;
        lp->hw.close = com20020_close;
 
-       dev->set_multicast_list = com20020_set_mc_list;
-
        if (!dev->dev_addr[0])
                dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8);   /* FIXME: do this some other way! */
 
@@ -342,6 +348,7 @@ static void com20020_set_mc_list(struct net_device *dev)
     defined(CONFIG_ARCNET_COM20020_CS_MODULE)
 EXPORT_SYMBOL(com20020_check);
 EXPORT_SYMBOL(com20020_found);
+EXPORT_SYMBOL(com20020_netdev_ops);
 #endif
 
 MODULE_LICENSE("GPL");
index 49d39a9cb696331052f7a590cb72b71e4dab2452..06f8fa2f8f2fb90b0317bf02cdacb3476a2823c7 100644 (file)
@@ -88,7 +88,6 @@ MODULE_LICENSE("GPL");
  */
 static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-       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;
@@ -112,8 +111,8 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
                return htons(ETH_P_ARP);
 
        default:
-               lp->stats.rx_errors++;
-               lp->stats.rx_crc_errors++;
+               dev->stats.rx_errors++;
+               dev->stats.rx_crc_errors++;
                return 0;
        }
 
@@ -140,7 +139,7 @@ static void rx(struct net_device *dev, int bufnum,
        skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
        if (skb == NULL) {
                BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
-               lp->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        skb_put(skb, length + ARC_HDR_SIZE);
@@ -168,7 +167,6 @@ 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 = 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;
@@ -184,8 +182,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
        default:
                BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
                       type, type);
-               lp->stats.tx_errors++;
-               lp->stats.tx_aborted_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
                return 0;
        }
 
index 2303d3a1f4b63d512aea87ef1287fb39e54b10d9..745530651c454c3fd25ab85313e90e40b69624a9 100644 (file)
@@ -92,7 +92,6 @@ 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 = netdev_priv(dev);
        int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
 
        /* Pull off the arcnet header. */
@@ -121,8 +120,8 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
        case ARC_P_NOVELL_EC:
                return htons(ETH_P_802_3);
        default:
-               lp->stats.rx_errors++;
-               lp->stats.rx_crc_errors++;
+               dev->stats.rx_errors++;
+               dev->stats.rx_crc_errors++;
                return 0;
        }
 
@@ -172,8 +171,8 @@ static void rx(struct net_device *dev, int bufnum,
                         in->sequence, soft->split_flag, soft->sequence);
                        lp->rfc1201.aborted_seq = soft->sequence;
                        dev_kfree_skb_irq(in->skb);
-                       lp->stats.rx_errors++;
-                       lp->stats.rx_missed_errors++;
+                       dev->stats.rx_errors++;
+                       dev->stats.rx_missed_errors++;
                        in->skb = NULL;
                }
                in->sequence = soft->sequence;
@@ -181,7 +180,7 @@ static void rx(struct net_device *dev, int bufnum,
                skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
                if (skb == NULL) {
                        BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
-                       lp->stats.rx_dropped++;
+                       dev->stats.rx_dropped++;
                        return;
                }
                skb_put(skb, length + ARC_HDR_SIZE);
@@ -213,7 +212,7 @@ static void rx(struct net_device *dev, int bufnum,
                                        BUGMSG(D_EXTRA,
                                               "ARP source address was 00h, set to %02Xh.\n",
                                               saddr);
-                                       lp->stats.rx_crc_errors++;
+                                       dev->stats.rx_crc_errors++;
                                        *cptr = saddr;
                                } else {
                                        BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n",
@@ -222,8 +221,8 @@ static void rx(struct net_device *dev, int bufnum,
                        } else {
                                BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n",
                                       arp->ar_hln, arp->ar_pln);
-                               lp->stats.rx_errors++;
-                               lp->stats.rx_crc_errors++;
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_crc_errors++;
                        }
                }
                BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
@@ -257,8 +256,8 @@ static void rx(struct net_device *dev, int bufnum,
                               soft->split_flag);
                        dev_kfree_skb_irq(in->skb);
                        in->skb = NULL;
-                       lp->stats.rx_errors++;
-                       lp->stats.rx_missed_errors++;
+                       dev->stats.rx_errors++;
+                       dev->stats.rx_missed_errors++;
                        in->lastpacket = in->numpackets = 0;
                }
                if (soft->split_flag & 1) {     /* first packet in split */
@@ -269,8 +268,8 @@ static void rx(struct net_device *dev, int bufnum,
                                       "(splitflag=%d, seq=%d)\n",
                                       in->sequence, soft->split_flag,
                                       soft->sequence);
-                               lp->stats.rx_errors++;
-                               lp->stats.rx_missed_errors++;
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_missed_errors++;
                                dev_kfree_skb_irq(in->skb);
                        }
                        in->sequence = soft->sequence;
@@ -281,8 +280,8 @@ static void rx(struct net_device *dev, int bufnum,
                                BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
                                       soft->split_flag);
                                lp->rfc1201.aborted_seq = soft->sequence;
-                               lp->stats.rx_errors++;
-                               lp->stats.rx_length_errors++;
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_length_errors++;
                                return;
                        }
                        in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE,
@@ -290,7 +289,7 @@ static void rx(struct net_device *dev, int bufnum,
                        if (skb == NULL) {
                                BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
                                lp->rfc1201.aborted_seq = soft->sequence;
-                               lp->stats.rx_dropped++;
+                               dev->stats.rx_dropped++;
                                return;
                        }
                        skb->dev = dev;
@@ -314,8 +313,8 @@ static void rx(struct net_device *dev, int bufnum,
                                               "first! (splitflag=%d, seq=%d, aborted=%d)\n",
                                        soft->split_flag, soft->sequence,
                                               lp->rfc1201.aborted_seq);
-                                       lp->stats.rx_errors++;
-                                       lp->stats.rx_missed_errors++;
+                                       dev->stats.rx_errors++;
+                                       dev->stats.rx_missed_errors++;
                                }
                                return;
                        }
@@ -325,8 +324,8 @@ static void rx(struct net_device *dev, int bufnum,
                                if (packetnum <= in->lastpacket - 1) {
                                        BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n",
                                               soft->split_flag);
-                                       lp->stats.rx_errors++;
-                                       lp->stats.rx_frame_errors++;
+                                       dev->stats.rx_errors++;
+                                       dev->stats.rx_frame_errors++;
                                        return;
                                }
                                /* "bad" duplicate, kill reassembly */
@@ -336,8 +335,8 @@ static void rx(struct net_device *dev, int bufnum,
                                lp->rfc1201.aborted_seq = soft->sequence;
                                dev_kfree_skb_irq(in->skb);
                                in->skb = NULL;
-                               lp->stats.rx_errors++;
-                               lp->stats.rx_missed_errors++;
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_missed_errors++;
                                in->lastpacket = in->numpackets = 0;
                                return;
                        }
@@ -404,8 +403,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
        default:
                BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n",
                       type, type);
-               lp->stats.tx_errors++;
-               lp->stats.tx_aborted_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
                return 0;
        }
 
index 3ec20cc18b0cb397524f5108cd257086b48f871e..cc7708775da0c91e4e86a713a13ed17b781a1cc6 100644 (file)
@@ -298,7 +298,7 @@ poll_some_more:
                int more = 0;
 
                spin_lock_irq(&ep->rx_lock);
-               __netif_rx_complete(napi);
+               __napi_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);
@@ -307,7 +307,7 @@ poll_some_more:
                }
                spin_unlock_irq(&ep->rx_lock);
 
-               if (more && netif_rx_reschedule(napi))
+               if (more && napi_reschedule(napi))
                        goto poll_some_more;
        }
 
@@ -415,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(&ep->napi))) {
+               if (likely(napi_schedule_prep(&ep->napi))) {
                        wrl(ep, REG_INTEN, REG_INTEN_TX);
-                       __netif_rx_schedule(&ep->napi);
+                       __napi_schedule(&ep->napi);
                }
                spin_unlock(&ep->rx_lock);
        }
index 5fce1d5c1a1a6cf273bc25b9983a10f620201df3..5fe17d5eaa5440a4ea81a3f439ba0bbd40603f13 100644 (file)
@@ -473,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(&port->napi);
+       napi_schedule(&port->napi);
 }
 
 static int eth_poll(struct napi_struct *napi, int budget)
@@ -498,16 +498,16 @@ static int eth_poll(struct napi_struct *napi, int budget)
 
                if ((n = queue_get_desc(rxq, port, 0)) < 0) {
 #if DEBUG_RX
-                       printk(KERN_DEBUG "%s: eth_poll netif_rx_complete\n",
+                       printk(KERN_DEBUG "%s: eth_poll napi_complete\n",
                               dev->name);
 #endif
-                       netif_rx_complete(napi);
+                       napi_complete(napi);
                        qmgr_enable_irq(rxq);
                        if (!qmgr_stat_empty(rxq) &&
-                           netif_rx_reschedule(napi)) {
+                           napi_reschedule(napi)) {
 #if DEBUG_RX
                                printk(KERN_DEBUG "%s: eth_poll"
-                                      " netif_rx_reschedule successed\n",
+                                      " napi_reschedule successed\n",
                                       dev->name);
 #endif
                                qmgr_disable_irq(rxq);
@@ -1036,7 +1036,7 @@ static int eth_open(struct net_device *dev)
        }
        ports_open++;
        /* we may already have RX data, enables IRQ */
-       netif_rx_schedule(&port->napi);
+       napi_schedule(&port->napi);
        return 0;
 }
 
index 1cf2f949c0b4d3f60c75b63399a64aa39f9c5f3d..b39210cf4fb39fd3f16e6831ad8cf7e095f58e11 100644 (file)
@@ -1059,7 +1059,7 @@ 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,
+       strlcpy(info->bus_info, dev_name(ndev->dev.parent),
                sizeof(info->bus_info));
 }
 
index bb9094d4cbc9014f2686033162cfde22fcc0d972..c758884728a53ee545879d61cc5b128de2bbe219 100644 (file)
@@ -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(
+                       if (likely(napi_schedule_prep(
                                   &adapter->napi)))
-                               __netif_rx_schedule(&adapter->napi);
+                               __napi_schedule(&adapter->napi);
                }
        } while (--max_ints > 0);
        /* re-enable Interrupt*/
@@ -1514,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(napi);
+               napi_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 */
index 9c875bb3f76c642f93203f9096942af72a0e3e53..4274e4ac963b10467e2a683d343d7f00720794aa 100644 (file)
@@ -81,24 +81,6 @@ MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_LICENSE("GPL");
 
-// prototypes
-static void hard_stop(struct net_device *);
-static void enable_rx_tx(struct net_device *dev);
-static struct net_device * au1000_probe(int port_num);
-static int au1000_init(struct net_device *);
-static int au1000_open(struct net_device *);
-static int au1000_close(struct net_device *);
-static int au1000_tx(struct sk_buff *, struct net_device *);
-static int au1000_rx(struct net_device *);
-static irqreturn_t au1000_interrupt(int, void *);
-static void au1000_tx_timeout(struct net_device *);
-static void set_rx_mode(struct net_device *);
-static int au1000_ioctl(struct net_device *, struct ifreq *, int);
-static int au1000_mdio_read(struct net_device *, int, int);
-static void au1000_mdio_write(struct net_device *, int, int, u16);
-static void au1000_adjust_link(struct net_device *);
-static void enable_mac(struct net_device *, int);
-
 /*
  * Theory of operation
  *
@@ -188,6 +170,26 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 # error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
 #endif
 
+static void enable_mac(struct net_device *dev, int force_reset)
+{
+       unsigned long flags;
+       struct au1000_private *aup = netdev_priv(dev);
+
+       spin_lock_irqsave(&aup->lock, flags);
+
+       if(force_reset || (!aup->mac_enabled)) {
+               *aup->enable = MAC_EN_CLOCK_ENABLE;
+               au_sync_delay(2);
+               *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+                               | MAC_EN_CLOCK_ENABLE);
+               au_sync_delay(2);
+
+               aup->mac_enabled = 1;
+       }
+
+       spin_unlock_irqrestore(&aup->lock, flags);
+}
+
 /*
  * MII operations
  */
@@ -281,6 +283,107 @@ static int au1000_mdiobus_reset(struct mii_bus *bus)
        return 0;
 }
 
+static void hard_stop(struct net_device *dev)
+{
+       struct au1000_private *aup = netdev_priv(dev);
+
+       if (au1000_debug > 4)
+               printk(KERN_INFO "%s: hard stop\n", dev->name);
+
+       aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+       au_sync_delay(10);
+}
+
+static void enable_rx_tx(struct net_device *dev)
+{
+       struct au1000_private *aup = netdev_priv(dev);
+
+       if (au1000_debug > 4)
+               printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
+
+       aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+       au_sync_delay(10);
+}
+
+static void
+au1000_adjust_link(struct net_device *dev)
+{
+       struct au1000_private *aup = netdev_priv(dev);
+       struct phy_device *phydev = aup->phy_dev;
+       unsigned long flags;
+
+       int status_change = 0;
+
+       BUG_ON(!aup->phy_dev);
+
+       spin_lock_irqsave(&aup->lock, flags);
+
+       if (phydev->link && (aup->old_speed != phydev->speed)) {
+               // speed changed
+
+               switch(phydev->speed) {
+               case SPEED_10:
+               case SPEED_100:
+                       break;
+               default:
+                       printk(KERN_WARNING
+                              "%s: Speed (%d) is not 10/100 ???\n",
+                              dev->name, phydev->speed);
+                       break;
+               }
+
+               aup->old_speed = phydev->speed;
+
+               status_change = 1;
+       }
+
+       if (phydev->link && (aup->old_duplex != phydev->duplex)) {
+               // duplex mode changed
+
+               /* switching duplex mode requires to disable rx and tx! */
+               hard_stop(dev);
+
+               if (DUPLEX_FULL == phydev->duplex)
+                       aup->mac->control = ((aup->mac->control
+                                            | MAC_FULL_DUPLEX)
+                                            & ~MAC_DISABLE_RX_OWN);
+               else
+                       aup->mac->control = ((aup->mac->control
+                                             & ~MAC_FULL_DUPLEX)
+                                            | MAC_DISABLE_RX_OWN);
+               au_sync_delay(1);
+
+               enable_rx_tx(dev);
+               aup->old_duplex = phydev->duplex;
+
+               status_change = 1;
+       }
+
+       if(phydev->link != aup->old_link) {
+               // link state changed
+
+               if (!phydev->link) {
+                       /* link went down */
+                       aup->old_speed = 0;
+                       aup->old_duplex = -1;
+               }
+
+               aup->old_link = phydev->link;
+               status_change = 1;
+       }
+
+       spin_unlock_irqrestore(&aup->lock, flags);
+
+       if (status_change) {
+               if (phydev->link)
+                       printk(KERN_INFO "%s: link up (%d/%s)\n",
+                              dev->name, phydev->speed,
+                              DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+               else
+                       printk(KERN_INFO "%s: link down\n", dev->name);
+       }
+}
+
 static int mii_probe (struct net_device *dev)
 {
        struct au1000_private *const aup = netdev_priv(dev);
@@ -355,8 +458,8 @@ static int mii_probe (struct net_device *dev)
        /* now we are supposed to have a proper phydev, to attach to... */
        BUG_ON(phydev->attached_dev);
 
-       phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0,
-                       PHY_INTERFACE_MODE_MII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link,
+                       0, PHY_INTERFACE_MODE_MII);
 
        if (IS_ERR(phydev)) {
                printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -381,8 +484,8 @@ static int mii_probe (struct net_device *dev)
        aup->phy_dev = phydev;
 
        printk(KERN_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);
+              "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+              phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        return 0;
 }
@@ -412,48 +515,6 @@ void ReleaseDB(struct au1000_private *aup, db_dest_t *pDB)
        aup->pDBfree = pDB;
 }
 
-static void enable_rx_tx(struct net_device *dev)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-
-       if (au1000_debug > 4)
-               printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
-
-       aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
-       au_sync_delay(10);
-}
-
-static void hard_stop(struct net_device *dev)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-
-       if (au1000_debug > 4)
-               printk(KERN_INFO "%s: hard stop\n", dev->name);
-
-       aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
-       au_sync_delay(10);
-}
-
-static void enable_mac(struct net_device *dev, int force_reset)
-{
-       unsigned long flags;
-       struct au1000_private *aup = netdev_priv(dev);
-
-       spin_lock_irqsave(&aup->lock, flags);
-
-       if(force_reset || (!aup->mac_enabled)) {
-               *aup->enable = MAC_EN_CLOCK_ENABLE;
-               au_sync_delay(2);
-               *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
-                               | MAC_EN_CLOCK_ENABLE);
-               au_sync_delay(2);
-
-               aup->mac_enabled = 1;
-       }
-
-       spin_unlock_irqrestore(&aup->lock, flags);
-}
-
 static void reset_mac_unlocked(struct net_device *dev)
 {
        struct au1000_private *const aup = netdev_priv(dev);
@@ -541,30 +602,6 @@ static struct {
 
 static int num_ifs;
 
-/*
- * Setup the base address and interrupt of the Au1xxx ethernet macs
- * based on cpu type and whether the interface is enabled in sys_pinfunc
- * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
- */
-static int __init au1000_init_module(void)
-{
-       int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
-       struct net_device *dev;
-       int i, found_one = 0;
-
-       num_ifs = NUM_ETH_INTERFACES - ni;
-
-       for(i = 0; i < num_ifs; i++) {
-               dev = au1000_probe(i);
-               iflist[i].dev = dev;
-               if (dev)
-                       found_one++;
-       }
-       if (!found_one)
-               return -ENODEV;
-       return 0;
-}
-
 /*
  * ethtool operations
  */
@@ -611,336 +648,230 @@ static const struct ethtool_ops au1000_ethtool_ops = {
        .get_link = ethtool_op_get_link,
 };
 
-static struct net_device * au1000_probe(int port_num)
+
+/*
+ * Initialize the interface.
+ *
+ * When the device powers up, the clocks are disabled and the
+ * mac is in reset state.  When the interface is closed, we
+ * do the same -- reset the device and disable the clocks to
+ * conserve power. Thus, whenever au1000_init() is called,
+ * the device should already be in reset state.
+ */
+static int au1000_init(struct net_device *dev)
 {
-       static unsigned version_printed = 0;
-       struct au1000_private *aup = NULL;
-       struct net_device *dev = NULL;
-       db_dest_t *pDB, *pDBfree;
-       char ethaddr[6];
-       int irq, i, err;
-       u32 base, macen;
+       struct au1000_private *aup = netdev_priv(dev);
+       unsigned long flags;
+       int i;
+       u32 control;
 
-       if (port_num >= NUM_ETH_INTERFACES)
-               return NULL;
+       if (au1000_debug > 4)
+               printk("%s: au1000_init\n", dev->name);
 
-       base  = CPHYSADDR(iflist[port_num].base_addr );
-       macen = CPHYSADDR(iflist[port_num].macen_addr);
-       irq = iflist[port_num].irq;
+       /* bring the device out of reset */
+       enable_mac(dev, 1);
 
-       if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
-           !request_mem_region(macen, 4, "Au1x00 ENET"))
-               return NULL;
+       spin_lock_irqsave(&aup->lock, flags);
 
-       if (version_printed++ == 0)
-               printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+       aup->mac->control = 0;
+       aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
+       aup->tx_tail = aup->tx_head;
+       aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
 
-       dev = alloc_etherdev(sizeof(struct au1000_private));
-       if (!dev) {
-               printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
-               return NULL;
+       aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4];
+       aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
+               dev->dev_addr[1]<<8 | dev->dev_addr[0];
+
+       for (i = 0; i < NUM_RX_DMA; i++) {
+               aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
        }
+       au_sync();
 
-       if ((err = register_netdev(dev)) != 0) {
-               printk(KERN_ERR "%s: Cannot register net device, error %d\n",
-                               DRV_NAME, err);
-               free_netdev(dev);
-               return NULL;
+       control = MAC_RX_ENABLE | MAC_TX_ENABLE;
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+       control |= MAC_BIG_ENDIAN;
+#endif
+       if (aup->phy_dev) {
+               if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
+                       control |= MAC_FULL_DUPLEX;
+               else
+                       control |= MAC_DISABLE_RX_OWN;
+       } else { /* PHY-less op, assume full-duplex */
+               control |= MAC_FULL_DUPLEX;
        }
 
-       printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
-               dev->name, base, irq);
-
-       aup = netdev_priv(dev);
-
-       spin_lock_init(&aup->lock);
-
-       /* Allocate the data buffers */
-       /* Snooping works fine with eth on all au1xxx */
-       aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
-                                               (NUM_TX_BUFFS + NUM_RX_BUFFS),
-                                               &aup->dma_addr, 0);
-       if (!aup->vaddr) {
-               free_netdev(dev);
-               release_mem_region( base, MAC_IOSIZE);
-               release_mem_region(macen, 4);
-               return NULL;
-       }
-
-       /* aup->mac is the base address of the MAC's registers */
-       aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
-
-       /* Setup some variables for quick register address access */
-       aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
-       aup->mac_id = port_num;
-       au_macs[port_num] = aup;
-
-       if (port_num == 0) {
-               if (prom_get_ethernet_addr(ethaddr) == 0)
-                       memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
-               else {
-                       printk(KERN_INFO "%s: No MAC address found\n",
-                                        dev->name);
-                               /* Use the hard coded MAC addresses */
-               }
-
-               setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-       } else if (port_num == 1)
-               setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-
-       /*
-        * Assign to the Ethernet ports two consecutive MAC addresses
-        * to match those that are printed on their stickers
-        */
-       memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-       dev->dev_addr[5] += port_num;
-
-       *aup->enable = 0;
-       aup->mac_enabled = 0;
-
-       aup->mii_bus = mdiobus_alloc();
-       if (aup->mii_bus == NULL)
-               goto err_out;
-
-       aup->mii_bus->priv = dev;
-       aup->mii_bus->read = au1000_mdiobus_read;
-       aup->mii_bus->write = au1000_mdiobus_write;
-       aup->mii_bus->reset = au1000_mdiobus_reset;
-       aup->mii_bus->name = "au1000_eth_mii";
-       snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
-       aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-       for(i = 0; i < PHY_MAX_ADDR; ++i)
-               aup->mii_bus->irq[i] = PHY_POLL;
-
-       /* if known, set corresponding PHY IRQs */
-#if defined(AU1XXX_PHY_STATIC_CONFIG)
-# if defined(AU1XXX_PHY0_IRQ)
-       if (AU1XXX_PHY0_BUSID == aup->mac_id)
-               aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
-# endif
-# if defined(AU1XXX_PHY1_IRQ)
-       if (AU1XXX_PHY1_BUSID == aup->mac_id)
-               aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
-# endif
-#endif
-       mdiobus_register(aup->mii_bus);
-
-       if (mii_probe(dev) != 0) {
-               goto err_out;
-       }
-
-       pDBfree = NULL;
-       /* setup the data buffer descriptors and attach a buffer to each one */
-       pDB = aup->db;
-       for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
-               pDB->pnext = pDBfree;
-               pDBfree = pDB;
-               pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
-               pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
-               pDB++;
-       }
-       aup->pDBfree = pDBfree;
-
-       for (i = 0; i < NUM_RX_DMA; i++) {
-               pDB = GetFreeDB(aup);
-               if (!pDB) {
-                       goto err_out;
-               }
-               aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
-               aup->rx_db_inuse[i] = pDB;
-       }
-       for (i = 0; i < NUM_TX_DMA; i++) {
-               pDB = GetFreeDB(aup);
-               if (!pDB) {
-                       goto err_out;
-               }
-               aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
-               aup->tx_dma_ring[i]->len = 0;
-               aup->tx_db_inuse[i] = pDB;
-       }
+       aup->mac->control = control;
+       aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
+       au_sync();
 
-       dev->base_addr = base;
-       dev->irq = irq;
-       dev->open = au1000_open;
-       dev->hard_start_xmit = au1000_tx;
-       dev->stop = au1000_close;
-       dev->set_multicast_list = &set_rx_mode;
-       dev->do_ioctl = &au1000_ioctl;
-       SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
-       dev->tx_timeout = au1000_tx_timeout;
-       dev->watchdog_timeo = ETH_TX_TIMEOUT;
+       spin_unlock_irqrestore(&aup->lock, flags);
+       return 0;
+}
 
-       /*
-        * The boot code uses the ethernet controller, so reset it to start
-        * fresh.  au1000_init() expects that the device is in reset state.
-        */
-       reset_mac(dev);
+static inline void update_rx_stats(struct net_device *dev, u32 status)
+{
+       struct au1000_private *aup = netdev_priv(dev);
+       struct net_device_stats *ps = &dev->stats;
 
-       return dev;
+       ps->rx_packets++;
+       if (status & RX_MCAST_FRAME)
+               ps->multicast++;
 
-err_out:
-       if (aup->mii_bus != NULL) {
-               mdiobus_unregister(aup->mii_bus);
-               mdiobus_free(aup->mii_bus);
+       if (status & RX_ERROR) {
+               ps->rx_errors++;
+               if (status & RX_MISSED_FRAME)
+                       ps->rx_missed_errors++;
+               if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR))
+                       ps->rx_length_errors++;
+               if (status & RX_CRC_ERROR)
+                       ps->rx_crc_errors++;
+               if (status & RX_COLL)
+                       ps->collisions++;
        }
+       else
+               ps->rx_bytes += status & RX_FRAME_LEN_MASK;
 
-       /* here we should have a valid dev plus aup-> register addresses
-        * so we can reset the mac properly.*/
-       reset_mac(dev);
-
-       for (i = 0; i < NUM_RX_DMA; i++) {
-               if (aup->rx_db_inuse[i])
-                       ReleaseDB(aup, aup->rx_db_inuse[i]);
-       }
-       for (i = 0; i < NUM_TX_DMA; i++) {
-               if (aup->tx_db_inuse[i])
-                       ReleaseDB(aup, aup->tx_db_inuse[i]);
-       }
-       dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
-                            (void *)aup->vaddr, aup->dma_addr);
-       unregister_netdev(dev);
-       free_netdev(dev);
-       release_mem_region( base, MAC_IOSIZE);
-       release_mem_region(macen, 4);
-       return NULL;
 }
 
 /*
- * Initialize the interface.
- *
- * When the device powers up, the clocks are disabled and the
- * mac is in reset state.  When the interface is closed, we
- * do the same -- reset the device and disable the clocks to
- * conserve power. Thus, whenever au1000_init() is called,
- * the device should already be in reset state.
+ * Au1000 receive routine.
  */
-static int au1000_init(struct net_device *dev)
+static int au1000_rx(struct net_device *dev)
 {
        struct au1000_private *aup = netdev_priv(dev);
-       unsigned long flags;
-       int i;
-       u32 control;
-
-       if (au1000_debug > 4)
-               printk("%s: au1000_init\n", dev->name);
-
-       /* bring the device out of reset */
-       enable_mac(dev, 1);
-
-       spin_lock_irqsave(&aup->lock, flags);
+       struct sk_buff *skb;
+       volatile rx_dma_t *prxd;
+       u32 buff_stat, status;
+       db_dest_t *pDB;
+       u32     frmlen;
 
-       aup->mac->control = 0;
-       aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
-       aup->tx_tail = aup->tx_head;
-       aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
+       if (au1000_debug > 5)
+               printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head);
 
-       aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4];
-       aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
-               dev->dev_addr[1]<<8 | dev->dev_addr[0];
+       prxd = aup->rx_dma_ring[aup->rx_head];
+       buff_stat = prxd->buff_stat;
+       while (buff_stat & RX_T_DONE)  {
+               status = prxd->status;
+               pDB = aup->rx_db_inuse[aup->rx_head];
+               update_rx_stats(dev, status);
+               if (!(status & RX_ERROR))  {
 
-       for (i = 0; i < NUM_RX_DMA; i++) {
-               aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
-       }
-       au_sync();
+                       /* good frame */
+                       frmlen = (status & RX_FRAME_LEN_MASK);
+                       frmlen -= 4; /* Remove FCS */
+                       skb = dev_alloc_skb(frmlen + 2);
+                       if (skb == NULL) {
+                               printk(KERN_ERR
+                                      "%s: Memory squeeze, dropping packet.\n",
+                                      dev->name);
+                               dev->stats.rx_dropped++;
+                               continue;
+                       }
+                       skb_reserve(skb, 2);    /* 16 byte IP header align */
+                       skb_copy_to_linear_data(skb,
+                               (unsigned char *)pDB->vaddr, frmlen);
+                       skb_put(skb, frmlen);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);  /* pass the packet to upper layers */
+               }
+               else {
+                       if (au1000_debug > 4) {
+                               if (status & RX_MISSED_FRAME)
+                                       printk("rx miss\n");
+                               if (status & RX_WDOG_TIMER)
+                                       printk("rx wdog\n");
+                               if (status & RX_RUNT)
+                                       printk("rx runt\n");
+                               if (status & RX_OVERLEN)
+                                       printk("rx overlen\n");
+                               if (status & RX_COLL)
+                                       printk("rx coll\n");
+                               if (status & RX_MII_ERROR)
+                                       printk("rx mii error\n");
+                               if (status & RX_CRC_ERROR)
+                                       printk("rx crc error\n");
+                               if (status & RX_LEN_ERROR)
+                                       printk("rx len error\n");
+                               if (status & RX_U_CNTRL_FRAME)
+                                       printk("rx u control frame\n");
+                               if (status & RX_MISSED_FRAME)
+                                       printk("rx miss\n");
+                       }
+               }
+               prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
+               aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
+               au_sync();
 
-       control = MAC_RX_ENABLE | MAC_TX_ENABLE;
-#ifndef CONFIG_CPU_LITTLE_ENDIAN
-       control |= MAC_BIG_ENDIAN;
-#endif
-       if (aup->phy_dev) {
-               if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
-                       control |= MAC_FULL_DUPLEX;
-               else
-                       control |= MAC_DISABLE_RX_OWN;
-       } else { /* PHY-less op, assume full-duplex */
-               control |= MAC_FULL_DUPLEX;
+               /* next descriptor */
+               prxd = aup->rx_dma_ring[aup->rx_head];
+               buff_stat = prxd->buff_stat;
        }
-
-       aup->mac->control = control;
-       aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
-       au_sync();
-
-       spin_unlock_irqrestore(&aup->lock, flags);
        return 0;
 }
 
-static void
-au1000_adjust_link(struct net_device *dev)
+static void update_tx_stats(struct net_device *dev, u32 status)
 {
        struct au1000_private *aup = netdev_priv(dev);
-       struct phy_device *phydev = aup->phy_dev;
-       unsigned long flags;
-
-       int status_change = 0;
-
-       BUG_ON(!aup->phy_dev);
-
-       spin_lock_irqsave(&aup->lock, flags);
-
-       if (phydev->link && (aup->old_speed != phydev->speed)) {
-               // speed changed
+       struct net_device_stats *ps = &dev->stats;
 
-               switch(phydev->speed) {
-               case SPEED_10:
-               case SPEED_100:
-                       break;
-               default:
-                       printk(KERN_WARNING
-                              "%s: Speed (%d) is not 10/100 ???\n",
-                              dev->name, phydev->speed);
-                       break;
+       if (status & TX_FRAME_ABORTED) {
+               if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
+                       if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
+                               /* any other tx errors are only valid
+                                * in half duplex mode */
+                               ps->tx_errors++;
+                               ps->tx_aborted_errors++;
+                       }
                }
+               else {
+                       ps->tx_errors++;
+                       ps->tx_aborted_errors++;
+                       if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
+                               ps->tx_carrier_errors++;
+               }
+       }
+}
 
-               aup->old_speed = phydev->speed;
-
-               status_change = 1;
-       }
-
-       if (phydev->link && (aup->old_duplex != phydev->duplex)) {
-               // duplex mode changed
-
-               /* switching duplex mode requires to disable rx and tx! */
-               hard_stop(dev);
-
-               if (DUPLEX_FULL == phydev->duplex)
-                       aup->mac->control = ((aup->mac->control
-                                            | MAC_FULL_DUPLEX)
-                                            & ~MAC_DISABLE_RX_OWN);
-               else
-                       aup->mac->control = ((aup->mac->control
-                                             & ~MAC_FULL_DUPLEX)
-                                            | MAC_DISABLE_RX_OWN);
-               au_sync_delay(1);
-
-               enable_rx_tx(dev);
-               aup->old_duplex = phydev->duplex;
+/*
+ * Called from the interrupt service routine to acknowledge
+ * the TX DONE bits.  This is a must if the irq is setup as
+ * edge triggered.
+ */
+static void au1000_tx_ack(struct net_device *dev)
+{
+       struct au1000_private *aup = netdev_priv(dev);
+       volatile tx_dma_t *ptxd;
 
-               status_change = 1;
-       }
+       ptxd = aup->tx_dma_ring[aup->tx_tail];
 
-       if(phydev->link != aup->old_link) {
-               // link state changed
+       while (ptxd->buff_stat & TX_T_DONE) {
+               update_tx_stats(dev, ptxd->status);
+               ptxd->buff_stat &= ~TX_T_DONE;
+               ptxd->len = 0;
+               au_sync();
 
-               if (!phydev->link) {
-                       /* link went down */
-                       aup->old_speed = 0;
-                       aup->old_duplex = -1;
-               }
+               aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
+               ptxd = aup->tx_dma_ring[aup->tx_tail];
 
-               aup->old_link = phydev->link;
-               status_change = 1;
+               if (aup->tx_full) {
+                       aup->tx_full = 0;
+                       netif_wake_queue(dev);
+               }
        }
+}
 
-       spin_unlock_irqrestore(&aup->lock, flags);
+/*
+ * Au1000 interrupt service routine.
+ */
+static irqreturn_t au1000_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
 
-       if (status_change) {
-               if (phydev->link)
-                       printk(KERN_INFO "%s: link up (%d/%s)\n",
-                              dev->name, phydev->speed,
-                              DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
-               else
-                       printk(KERN_INFO "%s: link down\n", dev->name);
-       }
+       /* Handle RX interrupts first to minimize chance of overrun */
+
+       au1000_rx(dev);
+       au1000_tx_ack(dev);
+       return IRQ_RETVAL(1);
 }
 
 static int au1000_open(struct net_device *dev)
@@ -1003,88 +934,6 @@ static int au1000_close(struct net_device *dev)
        return 0;
 }
 
-static void __exit au1000_cleanup_module(void)
-{
-       int i, j;
-       struct net_device *dev;
-       struct au1000_private *aup;
-
-       for (i = 0; i < num_ifs; i++) {
-               dev = iflist[i].dev;
-               if (dev) {
-                       aup = netdev_priv(dev);
-                       unregister_netdev(dev);
-                       mdiobus_unregister(aup->mii_bus);
-                       mdiobus_free(aup->mii_bus);
-                       for (j = 0; j < NUM_RX_DMA; j++)
-                               if (aup->rx_db_inuse[j])
-                                       ReleaseDB(aup, aup->rx_db_inuse[j]);
-                       for (j = 0; j < NUM_TX_DMA; j++)
-                               if (aup->tx_db_inuse[j])
-                                       ReleaseDB(aup, aup->tx_db_inuse[j]);
-                       dma_free_noncoherent(NULL, MAX_BUF_SIZE *
-                                            (NUM_TX_BUFFS + NUM_RX_BUFFS),
-                                            (void *)aup->vaddr, aup->dma_addr);
-                       release_mem_region(dev->base_addr, MAC_IOSIZE);
-                       release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
-                       free_netdev(dev);
-               }
-       }
-}
-
-static void update_tx_stats(struct net_device *dev, u32 status)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-       struct net_device_stats *ps = &dev->stats;
-
-       if (status & TX_FRAME_ABORTED) {
-               if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
-                       if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
-                               /* any other tx errors are only valid
-                                * in half duplex mode */
-                               ps->tx_errors++;
-                               ps->tx_aborted_errors++;
-                       }
-               }
-               else {
-                       ps->tx_errors++;
-                       ps->tx_aborted_errors++;
-                       if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
-                               ps->tx_carrier_errors++;
-               }
-       }
-}
-
-
-/*
- * Called from the interrupt service routine to acknowledge
- * the TX DONE bits.  This is a must if the irq is setup as
- * edge triggered.
- */
-static void au1000_tx_ack(struct net_device *dev)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-       volatile tx_dma_t *ptxd;
-
-       ptxd = aup->tx_dma_ring[aup->tx_tail];
-
-       while (ptxd->buff_stat & TX_T_DONE) {
-               update_tx_stats(dev, ptxd->status);
-               ptxd->buff_stat &= ~TX_T_DONE;
-               ptxd->len = 0;
-               au_sync();
-
-               aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
-               ptxd = aup->tx_dma_ring[aup->tx_tail];
-
-               if (aup->tx_full) {
-                       aup->tx_full = 0;
-                       netif_wake_queue(dev);
-               }
-       }
-}
-
-
 /*
  * Au1000 transmit routine.
  */
@@ -1129,136 +978,19 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
                ptxd->len = ETH_ZLEN;
        }
        else
-               ptxd->len = skb->len;
-
-       ps->tx_packets++;
-       ps->tx_bytes += ptxd->len;
-
-       ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-       au_sync();
-       dev_kfree_skb(skb);
-       aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
-       dev->trans_start = jiffies;
-       return 0;
-}
-
-static inline void update_rx_stats(struct net_device *dev, u32 status)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-       struct net_device_stats *ps = &dev->stats;
-
-       ps->rx_packets++;
-       if (status & RX_MCAST_FRAME)
-               ps->multicast++;
-
-       if (status & RX_ERROR) {
-               ps->rx_errors++;
-               if (status & RX_MISSED_FRAME)
-                       ps->rx_missed_errors++;
-               if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR))
-                       ps->rx_length_errors++;
-               if (status & RX_CRC_ERROR)
-                       ps->rx_crc_errors++;
-               if (status & RX_COLL)
-                       ps->collisions++;
-       }
-       else
-               ps->rx_bytes += status & RX_FRAME_LEN_MASK;
-
-}
-
-/*
- * Au1000 receive routine.
- */
-static int au1000_rx(struct net_device *dev)
-{
-       struct au1000_private *aup = netdev_priv(dev);
-       struct sk_buff *skb;
-       volatile rx_dma_t *prxd;
-       u32 buff_stat, status;
-       db_dest_t *pDB;
-       u32     frmlen;
-
-       if (au1000_debug > 5)
-               printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head);
-
-       prxd = aup->rx_dma_ring[aup->rx_head];
-       buff_stat = prxd->buff_stat;
-       while (buff_stat & RX_T_DONE)  {
-               status = prxd->status;
-               pDB = aup->rx_db_inuse[aup->rx_head];
-               update_rx_stats(dev, status);
-               if (!(status & RX_ERROR))  {
-
-                       /* good frame */
-                       frmlen = (status & RX_FRAME_LEN_MASK);
-                       frmlen -= 4; /* Remove FCS */
-                       skb = dev_alloc_skb(frmlen + 2);
-                       if (skb == NULL) {
-                               printk(KERN_ERR
-                                      "%s: Memory squeeze, dropping packet.\n",
-                                      dev->name);
-                               dev->stats.rx_dropped++;
-                               continue;
-                       }
-                       skb_reserve(skb, 2);    /* 16 byte IP header align */
-                       skb_copy_to_linear_data(skb,
-                               (unsigned char *)pDB->vaddr, frmlen);
-                       skb_put(skb, frmlen);
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);  /* pass the packet to upper layers */
-               }
-               else {
-                       if (au1000_debug > 4) {
-                               if (status & RX_MISSED_FRAME)
-                                       printk("rx miss\n");
-                               if (status & RX_WDOG_TIMER)
-                                       printk("rx wdog\n");
-                               if (status & RX_RUNT)
-                                       printk("rx runt\n");
-                               if (status & RX_OVERLEN)
-                                       printk("rx overlen\n");
-                               if (status & RX_COLL)
-                                       printk("rx coll\n");
-                               if (status & RX_MII_ERROR)
-                                       printk("rx mii error\n");
-                               if (status & RX_CRC_ERROR)
-                                       printk("rx crc error\n");
-                               if (status & RX_LEN_ERROR)
-                                       printk("rx len error\n");
-                               if (status & RX_U_CNTRL_FRAME)
-                                       printk("rx u control frame\n");
-                               if (status & RX_MISSED_FRAME)
-                                       printk("rx miss\n");
-                       }
-               }
-               prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
-               aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-               au_sync();
-
-               /* next descriptor */
-               prxd = aup->rx_dma_ring[aup->rx_head];
-               buff_stat = prxd->buff_stat;
-       }
-       return 0;
-}
-
-
-/*
- * Au1000 interrupt service routine.
- */
-static irqreturn_t au1000_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
+               ptxd->len = skb->len;
 
-       /* Handle RX interrupts first to minimize chance of overrun */
+       ps->tx_packets++;
+       ps->tx_bytes += ptxd->len;
 
-       au1000_rx(dev);
-       au1000_tx_ack(dev);
-       return IRQ_RETVAL(1);
+       ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
+       au_sync();
+       dev_kfree_skb(skb);
+       aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
+       dev->trans_start = jiffies;
+       return 0;
 }
 
-
 /*
  * The Tx ring has been full longer than the watchdog timeout
  * value. The transmitter must be hung?
@@ -1315,5 +1047,252 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd);
 }
 
+static struct net_device * au1000_probe(int port_num)
+{
+       static unsigned version_printed = 0;
+       struct au1000_private *aup = NULL;
+       struct net_device *dev = NULL;
+       db_dest_t *pDB, *pDBfree;
+       char ethaddr[6];
+       int irq, i, err;
+       u32 base, macen;
+
+       if (port_num >= NUM_ETH_INTERFACES)
+               return NULL;
+
+       base  = CPHYSADDR(iflist[port_num].base_addr );
+       macen = CPHYSADDR(iflist[port_num].macen_addr);
+       irq = iflist[port_num].irq;
+
+       if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
+           !request_mem_region(macen, 4, "Au1x00 ENET"))
+               return NULL;
+
+       if (version_printed++ == 0)
+               printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+
+       dev = alloc_etherdev(sizeof(struct au1000_private));
+       if (!dev) {
+               printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
+               return NULL;
+       }
+
+       if ((err = register_netdev(dev)) != 0) {
+               printk(KERN_ERR "%s: Cannot register net device, error %d\n",
+                               DRV_NAME, err);
+               free_netdev(dev);
+               return NULL;
+       }
+
+       printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+               dev->name, base, irq);
+
+       aup = netdev_priv(dev);
+
+       spin_lock_init(&aup->lock);
+
+       /* Allocate the data buffers */
+       /* Snooping works fine with eth on all au1xxx */
+       aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+                                               (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                               &aup->dma_addr, 0);
+       if (!aup->vaddr) {
+               free_netdev(dev);
+               release_mem_region( base, MAC_IOSIZE);
+               release_mem_region(macen, 4);
+               return NULL;
+       }
+
+       /* aup->mac is the base address of the MAC's registers */
+       aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+
+       /* Setup some variables for quick register address access */
+       aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
+       aup->mac_id = port_num;
+       au_macs[port_num] = aup;
+
+       if (port_num == 0) {
+               if (prom_get_ethernet_addr(ethaddr) == 0)
+                       memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
+               else {
+                       printk(KERN_INFO "%s: No MAC address found\n",
+                                        dev->name);
+                               /* Use the hard coded MAC addresses */
+               }
+
+               setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
+       } else if (port_num == 1)
+               setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
+
+       /*
+        * Assign to the Ethernet ports two consecutive MAC addresses
+        * to match those that are printed on their stickers
+        */
+       memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+       dev->dev_addr[5] += port_num;
+
+       *aup->enable = 0;
+       aup->mac_enabled = 0;
+
+       aup->mii_bus = mdiobus_alloc();
+       if (aup->mii_bus == NULL)
+               goto err_out;
+
+       aup->mii_bus->priv = dev;
+       aup->mii_bus->read = au1000_mdiobus_read;
+       aup->mii_bus->write = au1000_mdiobus_write;
+       aup->mii_bus->reset = au1000_mdiobus_reset;
+       aup->mii_bus->name = "au1000_eth_mii";
+       snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+       aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+       for(i = 0; i < PHY_MAX_ADDR; ++i)
+               aup->mii_bus->irq[i] = PHY_POLL;
+
+       /* if known, set corresponding PHY IRQs */
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+# if defined(AU1XXX_PHY0_IRQ)
+       if (AU1XXX_PHY0_BUSID == aup->mac_id)
+               aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+# endif
+# if defined(AU1XXX_PHY1_IRQ)
+       if (AU1XXX_PHY1_BUSID == aup->mac_id)
+               aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+# endif
+#endif
+       mdiobus_register(aup->mii_bus);
+
+       if (mii_probe(dev) != 0) {
+               goto err_out;
+       }
+
+       pDBfree = NULL;
+       /* setup the data buffer descriptors and attach a buffer to each one */
+       pDB = aup->db;
+       for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
+               pDB->pnext = pDBfree;
+               pDBfree = pDB;
+               pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
+               pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
+               pDB++;
+       }
+       aup->pDBfree = pDBfree;
+
+       for (i = 0; i < NUM_RX_DMA; i++) {
+               pDB = GetFreeDB(aup);
+               if (!pDB) {
+                       goto err_out;
+               }
+               aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
+               aup->rx_db_inuse[i] = pDB;
+       }
+       for (i = 0; i < NUM_TX_DMA; i++) {
+               pDB = GetFreeDB(aup);
+               if (!pDB) {
+                       goto err_out;
+               }
+               aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
+               aup->tx_dma_ring[i]->len = 0;
+               aup->tx_db_inuse[i] = pDB;
+       }
+
+       dev->base_addr = base;
+       dev->irq = irq;
+       dev->open = au1000_open;
+       dev->hard_start_xmit = au1000_tx;
+       dev->stop = au1000_close;
+       dev->set_multicast_list = &set_rx_mode;
+       dev->do_ioctl = &au1000_ioctl;
+       SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
+       dev->tx_timeout = au1000_tx_timeout;
+       dev->watchdog_timeo = ETH_TX_TIMEOUT;
+
+       /*
+        * The boot code uses the ethernet controller, so reset it to start
+        * fresh.  au1000_init() expects that the device is in reset state.
+        */
+       reset_mac(dev);
+
+       return dev;
+
+err_out:
+       if (aup->mii_bus != NULL) {
+               mdiobus_unregister(aup->mii_bus);
+               mdiobus_free(aup->mii_bus);
+       }
+
+       /* here we should have a valid dev plus aup-> register addresses
+        * so we can reset the mac properly.*/
+       reset_mac(dev);
+
+       for (i = 0; i < NUM_RX_DMA; i++) {
+               if (aup->rx_db_inuse[i])
+                       ReleaseDB(aup, aup->rx_db_inuse[i]);
+       }
+       for (i = 0; i < NUM_TX_DMA; i++) {
+               if (aup->tx_db_inuse[i])
+                       ReleaseDB(aup, aup->tx_db_inuse[i]);
+       }
+       dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                            (void *)aup->vaddr, aup->dma_addr);
+       unregister_netdev(dev);
+       free_netdev(dev);
+       release_mem_region( base, MAC_IOSIZE);
+       release_mem_region(macen, 4);
+       return NULL;
+}
+
+/*
+ * Setup the base address and interrupt of the Au1xxx ethernet macs
+ * based on cpu type and whether the interface is enabled in sys_pinfunc
+ * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
+ */
+static int __init au1000_init_module(void)
+{
+       int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
+       struct net_device *dev;
+       int i, found_one = 0;
+
+       num_ifs = NUM_ETH_INTERFACES - ni;
+
+       for(i = 0; i < num_ifs; i++) {
+               dev = au1000_probe(i);
+               iflist[i].dev = dev;
+               if (dev)
+                       found_one++;
+       }
+       if (!found_one)
+               return -ENODEV;
+       return 0;
+}
+
+static void __exit au1000_cleanup_module(void)
+{
+       int i, j;
+       struct net_device *dev;
+       struct au1000_private *aup;
+
+       for (i = 0; i < num_ifs; i++) {
+               dev = iflist[i].dev;
+               if (dev) {
+                       aup = netdev_priv(dev);
+                       unregister_netdev(dev);
+                       mdiobus_unregister(aup->mii_bus);
+                       mdiobus_free(aup->mii_bus);
+                       for (j = 0; j < NUM_RX_DMA; j++)
+                               if (aup->rx_db_inuse[j])
+                                       ReleaseDB(aup, aup->rx_db_inuse[j]);
+                       for (j = 0; j < NUM_TX_DMA; j++)
+                               if (aup->tx_db_inuse[j])
+                                       ReleaseDB(aup, aup->tx_db_inuse[j]);
+                       dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+                                            (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                            (void *)aup->vaddr, aup->dma_addr);
+                       release_mem_region(dev->base_addr, MAC_IOSIZE);
+                       release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
+                       free_netdev(dev);
+               }
+       }
+}
+
 module_init(au1000_init_module);
 module_exit(au1000_cleanup_module);
index c38512ebcea65fd0408ae0821d3be177b2854e26..92aaaa1ee9f1cbd01a45f820b1a685e8569d582c 100644 (file)
@@ -874,7 +874,7 @@ static int b44_poll(struct napi_struct *napi, int budget)
        }
 
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                b44_enable_ints(bp);
        }
 
@@ -906,13 +906,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
                        goto irq_ack;
                }
 
-               if (netif_rx_schedule_prep(&bp->napi)) {
+               if (napi_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(&bp->napi);
+                       __napi_schedule(&bp->napi);
                } else {
                        printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
                               dev->name);
index 78e31aa861e020e461336e2323cea4647d7cb9c8..9afe8092dfc4c9f3b8fe04d1a915d2040206d794 100644 (file)
@@ -415,11 +415,11 @@ static int mii_probe(struct net_device *dev)
        }
 
 #if defined(CONFIG_BFIN_MAC_RMII)
-       phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
-                       PHY_INTERFACE_MODE_RMII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+                       0, PHY_INTERFACE_MODE_RMII);
 #else
-       phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
-                       PHY_INTERFACE_MODE_MII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+                       0, PHY_INTERFACE_MODE_MII);
 #endif
 
        if (IS_ERR(phydev)) {
@@ -447,7 +447,7 @@ static int mii_probe(struct net_device *dev)
        printk(KERN_INFO "%s: attached PHY driver [%s] "
               "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)"
               "@sclk=%dMHz)\n",
-              DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq,
+              DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
               MDC_CLK, mdc_div, sclk/1000000);
 
        return 0;
@@ -488,7 +488,7 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
        strcpy(info->driver, DRV_NAME);
        strcpy(info->version, DRV_VERSION);
        strcpy(info->fw_version, "N/A");
-       strcpy(info->bus_info, dev->dev.bus_id);
+       strcpy(info->bus_info, dev_name(&dev->dev));
 }
 
 static struct ethtool_ops bfin_mac_ethtool_ops = {
index 8a546a33d58124fb39cf67ff673e305f7a7fd418..1ab58375d0617039cfdf658d7ee8c56f0f6bbf09 100644 (file)
@@ -1240,7 +1240,7 @@ static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf
 {
        struct bmac_data *bp = netdev_priv(dev);
        strcpy(info->driver, "bmac");
-       strcpy(info->bus_info, bp->mdev->ofdev.dev.bus_id);
+       strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev));
 }
 
 static const struct ethtool_ops bmac_ethtool_ops = {
index d4a3dac21dcfb83fdc7e6c2835705ac66433ec3c..49e0e51a9dfc5655bbaaab14b3ca6096ed7445cb 100644 (file)
@@ -1497,6 +1497,8 @@ static int bnx2_fw_sync(struct bnx2 *, u32, int, int);
 
 static int
 bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
+__releases(&bp->phy_lock)
+__acquires(&bp->phy_lock)
 {
        u32 speed_arg = 0, pause_adv;
 
@@ -1554,6 +1556,8 @@ bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
 
 static int
 bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
+__releases(&bp->phy_lock)
+__acquires(&bp->phy_lock)
 {
        u32 adv, bmcr;
        u32 new_adv = 0;
@@ -1866,6 +1870,8 @@ bnx2_set_remote_link(struct bnx2 *bp)
 
 static int
 bnx2_setup_copper_phy(struct bnx2 *bp)
+__releases(&bp->phy_lock)
+__acquires(&bp->phy_lock)
 {
        u32 bmcr;
        u32 new_bmcr;
@@ -1963,6 +1969,8 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
 
 static int
 bnx2_setup_phy(struct bnx2 *bp, u8 port)
+__releases(&bp->phy_lock)
+__acquires(&bp->phy_lock)
 {
        if (bp->loopback == MAC_LOOPBACK)
                return 0;
@@ -2176,6 +2184,8 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
 
 static int
 bnx2_init_phy(struct bnx2 *bp, int reset_phy)
+__releases(&bp->phy_lock)
+__acquires(&bp->phy_lock)
 {
        u32 val;
        int rc = 0;
@@ -2997,6 +3007,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
                }
 
+               skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
+
 #ifdef BCM_VLAN
                if (hw_vlan)
                        vlan_hwaccel_receive_skb(skb, bp->vlgrp, vtag);
@@ -3053,7 +3065,7 @@ bnx2_msi(int irq, void *dev_instance)
        if (unlikely(atomic_read(&bp->intr_sem) != 0))
                return IRQ_HANDLED;
 
-       netif_rx_schedule(&bnapi->napi);
+       napi_schedule(&bnapi->napi);
 
        return IRQ_HANDLED;
 }
@@ -3070,7 +3082,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
        if (unlikely(atomic_read(&bp->intr_sem) != 0))
                return IRQ_HANDLED;
 
-       netif_rx_schedule(&bnapi->napi);
+       napi_schedule(&bnapi->napi);
 
        return IRQ_HANDLED;
 }
@@ -3106,9 +3118,9 @@ bnx2_interrupt(int irq, void *dev_instance)
        if (unlikely(atomic_read(&bp->intr_sem) != 0))
                return IRQ_HANDLED;
 
-       if (netif_rx_schedule_prep(&bnapi->napi)) {
+       if (napi_schedule_prep(&bnapi->napi)) {
                bnapi->last_status_idx = sblk->status_idx;
-               __netif_rx_schedule(&bnapi->napi);
+               __napi_schedule(&bnapi->napi);
        }
 
        return IRQ_HANDLED;
@@ -3218,7 +3230,7 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget)
                rmb();
                if (likely(!bnx2_has_fast_work(bnapi))) {
 
-                       netif_rx_complete(napi);
+                       napi_complete(napi);
                        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
                               bnapi->last_status_idx);
@@ -3251,7 +3263,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
 
                rmb();
                if (likely(!bnx2_has_work(bnapi))) {
-                       netif_rx_complete(napi);
+                       napi_complete(napi);
                        if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
                                REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
index d3e7775a9ccfaa2cc262c28ff4ba6c60b4a1ab6e..88da14c141f451c609963e492fb54c721eee38b7 100644 (file)
@@ -1325,6 +1325,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
                skb->protocol = eth_type_trans(skb, bp->dev);
                skb->ip_summed = CHECKSUM_UNNECESSARY;
+               skb_record_rx_queue(skb, queue);
 
                {
                        struct iphdr *iph;
@@ -1654,7 +1655,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(&bnx2x_fp(bp, index, napi));
+       napi_schedule(&bnx2x_fp(bp, index, napi));
 
        return IRQ_HANDLED;
 }
@@ -1693,7 +1694,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(&bnx2x_fp(bp, 0, napi));
+               napi_schedule(&bnx2x_fp(bp, 0, napi));
 
                status &= ~mask;
        }
@@ -9374,7 +9375,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
 #ifdef BNX2X_STOP_ON_ERROR
 poll_panic:
 #endif
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
                bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID,
                             le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
index 8a83eb283c21c8abecb64047be80a72faaa611b5..a306230381c8f69c0ba83523430a16cfb1bef8a3 100644 (file)
@@ -29,7 +29,7 @@
 
 // General definitions
 #define BOND_ETH_P_LACPDU       0x8809
-#define PKT_TYPE_LACPDU         __constant_htons(BOND_ETH_P_LACPDU)
+#define PKT_TYPE_LACPDU         cpu_to_be16(BOND_ETH_P_LACPDU)
 #define AD_TIMER_INTERVAL       100 /*msec*/
 
 #define MULTICAST_LACPDU_ADDR    {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
index 27fb7f5c21cf57029b62d830ada44b6f26904dac..409b140742754cb61e0d60f649d6355a254979d5 100644 (file)
@@ -822,7 +822,7 @@ static int rlb_initialize(struct bonding *bond)
        _unlock_rx_hashtbl(bond);
 
        /*initialize packet type*/
-       pk_type->type = __constant_htons(ETH_P_ARP);
+       pk_type->type = cpu_to_be16(ETH_P_ARP);
        pk_type->dev = NULL;
        pk_type->func = rlb_arp_recv;
 
@@ -892,7 +892,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
        memset(&pkt, 0, size);
        memcpy(pkt.mac_dst, mac_addr, ETH_ALEN);
        memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
-       pkt.type = __constant_htons(ETH_P_LOOP);
+       pkt.type = cpu_to_be16(ETH_P_LOOP);
 
        for (i = 0; i < MAX_LP_BURST; i++) {
                struct sk_buff *skb;
index 9fb388388fb72e6990e697843ac68158fb565bf0..21bce2c0fde22af42e1927d5da172d754e592732 100644 (file)
@@ -3369,7 +3369,7 @@ static int bond_info_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations bond_info_seq_ops = {
+static const struct seq_operations bond_info_seq_ops = {
        .start = bond_info_seq_start,
        .next  = bond_info_seq_next,
        .stop  = bond_info_seq_stop,
index bbbc3bb08aa54a2bcb52e80b7c9df860d1a42f16..0effefa1b882036813a3b5e2401ed4b4fc126888 100644 (file)
@@ -2506,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(&cp->napi);
+               napi_schedule(&cp->napi);
 #else
                cas_rx_ringN(cp, ring, 0);
 #endif
@@ -2557,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(&cp->napi);
+               napi_schedule(&cp->napi);
 #else
                cas_rx_ringN(cp, 1, 0);
 #endif
@@ -2613,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(&cp->napi);
+               napi_schedule(&cp->napi);
 #else
                cas_rx_ringN(cp, 0, 0);
 #endif
@@ -2691,7 +2691,7 @@ rx_comp:
 #endif
        spin_unlock_irqrestore(&cp->lock, flags);
        if (enable_intr) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                cas_unmask_intr(cp);
        }
        return credits;
index d984b799576373f1c7a7064d8180f476f8870f48..840da83fb3cf46669515ba8b6d849aa942d14374 100644 (file)
@@ -1612,7 +1612,7 @@ int t1_poll(struct napi_struct *napi, int budget)
        int work_done = process_responses(adapter, budget);
 
        if (likely(work_done < budget)) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                writel(adapter->sge->respQ.cidx,
                       adapter->regs + A_SG_SLEEPING);
        }
@@ -1630,7 +1630,7 @@ irqreturn_t t1_interrupt(int irq, void *data)
 
                if (napi_schedule_prep(&adapter->napi)) {
                        if (process_pure_responses(adapter))
-                               __netif_rx_schedule(&adapter->napi);
+                               __napi_schedule(&adapter->napi);
                        else {
                                /* no data, no NAPI needed */
                                writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
index f66548751c384c1bf111f69b995dd701aa60b713..3f476c7c07365ab0d2bfcda55d0a86435d9096d8 100644 (file)
@@ -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(napi);
+               napi_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(napi);
+               napi_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(napi);
+       napi_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(&priv->napi)) {
+               if (napi_schedule_prep(&priv->napi)) {
                        cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue);
-                       __netif_rx_schedule(&priv->napi);
+                       __napi_schedule(&priv->napi);
                }
        }
 
@@ -1161,7 +1161,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
        priv->msg_enable = netif_msg_init(debug_level, 0xff);
        memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
 
-       priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id,
+       priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev),
                                &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
        if (IS_ERR(priv->phy)) {
                if (netif_msg_drv(priv))
index a89d8cc512059001870ff122a9da174834041a1e..fbe15699584e537d6715a17d849acdb639296d7f 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/cache.h>
 #include <linux/mutex.h>
 #include <linux/bitops.h>
-#include <linux/inet_lro.h>
 #include "t3cdev.h"
 #include <asm/io.h>
 
@@ -178,15 +177,11 @@ enum {                            /* per port SGE statistics */
        SGE_PSTAT_TX_CSUM,      /* # of TX checksum offloads */
        SGE_PSTAT_VLANEX,       /* # of VLAN tag extractions */
        SGE_PSTAT_VLANINS,      /* # of VLAN tag insertions */
-       SGE_PSTAT_LRO_AGGR,     /* # of page chunks added to LRO sessions */
-       SGE_PSTAT_LRO_FLUSHED,  /* # of flushed LRO sessions */
-       SGE_PSTAT_LRO_NO_DESC,  /* # of overflown LRO sessions */
 
        SGE_PSTAT_MAX           /* must be last */
 };
 
-#define T3_MAX_LRO_SES 8
-#define T3_MAX_LRO_MAX_PKTS 64
+struct napi_gro_fraginfo;
 
 struct sge_qset {              /* an SGE queue set */
        struct adapter *adap;
@@ -194,12 +189,8 @@ struct sge_qset {          /* an SGE queue set */
        struct sge_rspq rspq;
        struct sge_fl fl[SGE_RXQ_PER_SET];
        struct sge_txq txq[SGE_TXQ_PER_SET];
-       struct net_lro_mgr lro_mgr;
-       struct net_lro_desc lro_desc[T3_MAX_LRO_SES];
-       struct skb_frag_struct *lro_frag_tbl;
-       int lro_nfrags;
+       struct napi_gro_fraginfo lro_frag_tbl;
        int lro_enabled;
-       int lro_frag_len;
        void *lro_va;
        struct net_device *netdev;
        struct netdev_queue *tx_q;      /* associated netdev TX queue */
@@ -230,6 +221,7 @@ struct adapter {
        unsigned int slow_intr_mask;
        unsigned long irq_stats[IRQ_NUM_STATS];
 
+       int msix_nvectors;
        struct {
                unsigned short vec;
                char desc[22];
index 0089746b8d026ba8acdcd0911cab91075110a84a..f2c7cc3e263afffade80281415ff1f560bf7d6a2 100644 (file)
@@ -338,7 +338,7 @@ static void free_irq_resources(struct adapter *adapter)
 
                free_irq(adapter->msix_info[0].vec, adapter);
                for_each_port(adapter, i)
-                   n += adap2pinfo(adapter, i)->nqsets;
+                       n += adap2pinfo(adapter, i)->nqsets;
 
                for (i = 0; i < n; ++i)
                        free_irq(adapter->msix_info[i + 1].vec,
@@ -508,19 +508,9 @@ 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;
 }
 
 /**
@@ -1433,9 +1423,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
        *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS);
        *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
        *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
-       *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_AGGR);
-       *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_FLUSHED);
-       *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_NO_DESC);
+       *data++ = 0;
+       *data++ = 0;
+       *data++ = 0;
        *data++ = s->rx_cong_drops;
 
        *data++ = s->num_toggled;
@@ -1826,28 +1816,6 @@ 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_offload & T3_RX_CSUM))
-                       return -EINVAL;
-
-               pi->rx_offload |= T3_LRO;
-               for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
-                       set_qset_lro(dev, i, 1);
-
-       } else {
-               pi->rx_offload &= ~T3_LRO;
-               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,
@@ -1877,8 +1845,6 @@ 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)
@@ -2576,6 +2542,12 @@ static int t3_adapter_error(struct adapter *adapter, int reset)
 {
        int i, ret = 0;
 
+       if (is_offload(adapter) &&
+           test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
+               cxgb3_err_notify(&adapter->tdev, OFFLOAD_STATUS_DOWN, 0);
+               offload_close(&adapter->tdev);
+       }
+
        /* Stop all ports */
        for_each_port(adapter, i) {
                struct net_device *netdev = adapter->port[i];
@@ -2584,10 +2556,6 @@ static int t3_adapter_error(struct adapter *adapter, int reset)
                        cxgb_close(netdev);
        }
 
-       if (is_offload(adapter) &&
-           test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
-               offload_close(&adapter->tdev);
-
        /* Stop SGE timers */
        t3_stop_sge_timers(adapter);
 
@@ -2639,6 +2607,9 @@ static void t3_resume_ports(struct adapter *adapter)
                        }
                }
        }
+
+       if (is_offload(adapter) && !ofld_disable)
+               cxgb3_err_notify(&adapter->tdev, OFFLOAD_STATUS_UP, 0);
 }
 
 /*
@@ -2752,7 +2723,7 @@ static void set_nqsets(struct adapter *adap)
        int i, j = 0;
        int num_cpus = num_online_cpus();
        int hwports = adap->params.nports;
-       int nqsets = SGE_QSETS;
+       int nqsets = adap->msix_nvectors - 1;
 
        if (adap->params.rev > 0 && adap->flags & USING_MSIX) {
                if (hwports == 2 &&
@@ -2781,18 +2752,25 @@ static void set_nqsets(struct adapter *adap)
 static int __devinit cxgb_enable_msix(struct adapter *adap)
 {
        struct msix_entry entries[SGE_QSETS + 1];
+       int vectors;
        int i, err;
 
-       for (i = 0; i < ARRAY_SIZE(entries); ++i)
+       vectors = ARRAY_SIZE(entries);
+       for (i = 0; i < vectors; ++i)
                entries[i].entry = i;
 
-       err = pci_enable_msix(adap->pdev, entries, ARRAY_SIZE(entries));
+       while ((err = pci_enable_msix(adap->pdev, entries, vectors)) > 0)
+               vectors = err;
+
+       if (!err && vectors < (adap->params.nports + 1))
+               err = -1;
+
        if (!err) {
-               for (i = 0; i < ARRAY_SIZE(entries); ++i)
+               for (i = 0; i < vectors; ++i)
                        adap->msix_info[i].vec = entries[i].vector;
-       } else if (err > 0)
-               dev_info(&adap->pdev->dev,
-                      "only %d MSI-X vectors left, not using MSI-X\n", err);
+               adap->msix_nvectors = vectors;
+       }
+
        return err;
 }
 
@@ -2960,7 +2938,7 @@ static int __devinit init_one(struct pci_dev *pdev,
                netdev->mem_end = mmio_start + mmio_len - 1;
                netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
                netdev->features |= NETIF_F_LLTX;
-               netdev->features |= NETIF_F_LRO;
+               netdev->features |= NETIF_F_GRO;
                if (pci_using_dac)
                        netdev->features |= NETIF_F_HIGHDMA;
 
index 2d7f69aff1d949a47e952997932800593444338e..620d80be6aacb1d3806d3f42f786c9f5b52bc6a3 100644 (file)
@@ -153,6 +153,18 @@ void cxgb3_remove_clients(struct t3cdev *tdev)
        mutex_unlock(&cxgb3_db_lock);
 }
 
+void cxgb3_err_notify(struct t3cdev *tdev, u32 status, u32 error)
+{
+       struct cxgb3_client *client;
+
+       mutex_lock(&cxgb3_db_lock);
+       list_for_each_entry(client, &client_list, client_list) {
+               if (client->err_handler)
+                       client->err_handler(tdev, status, error);
+       }
+       mutex_unlock(&cxgb3_db_lock);
+}
+
 static struct net_device *get_iff_from_mac(struct adapter *adapter,
                                           const unsigned char *mac,
                                           unsigned int vlan)
index d514e5019dfc36b0935bace2be32056b0ee4f272..a8e8e5fcdf84d55c5daa3aafd0f4d1081cab4f5a 100644 (file)
@@ -64,10 +64,16 @@ void cxgb3_register_client(struct cxgb3_client *client);
 void cxgb3_unregister_client(struct cxgb3_client *client);
 void cxgb3_add_clients(struct t3cdev *tdev);
 void cxgb3_remove_clients(struct t3cdev *tdev);
+void cxgb3_err_notify(struct t3cdev *tdev, u32 status, u32 error);
 
 typedef int (*cxgb3_cpl_handler_func)(struct t3cdev *dev,
                                      struct sk_buff *skb, void *ctx);
 
+enum {
+       OFFLOAD_STATUS_UP,
+       OFFLOAD_STATUS_DOWN
+};
+
 struct cxgb3_client {
        char *name;
        void (*add) (struct t3cdev *);
@@ -76,6 +82,7 @@ struct cxgb3_client {
        int (*redirect)(void *ctx, struct dst_entry *old,
                        struct dst_entry *new, struct l2t_entry *l2t);
        struct list_head client_list;
+       void (*err_handler)(struct t3cdev *tdev, u32 status, u32 error);
 };
 
 /*
index 379a1324db4e9c0709e1f56207b10d4567fdd9c7..272a0168f3e9ffb32d3f4c2b40529e3a1d1c38bc 100644 (file)
@@ -585,8 +585,7 @@ static void t3_reset_qset(struct sge_qset *q)
        memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
        q->txq_stopped = 0;
        q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
-       kfree(q->lro_frag_tbl);
-       q->lro_nfrags = q->lro_frag_len = 0;
+       q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0;
 }
 
 
@@ -1938,6 +1937,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        } else
                skb->ip_summed = CHECKSUM_NONE;
+       skb_record_rx_queue(skb, qs - &adap->sge.qs[0]);
 
        if (unlikely(p->vlan_valid)) {
                struct vlan_group *grp = pi->vlan_grp;
@@ -1945,10 +1945,8 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
                qs->port_stats[SGE_PSTAT_VLANEX]++;
                if (likely(grp))
                        if (lro)
-                               lro_vlan_hwaccel_receive_skb(&qs->lro_mgr, skb,
-                                                            grp,
-                                                            ntohs(p->vlan),
-                                                            p);
+                               vlan_gro_receive(&qs->napi, grp,
+                                                ntohs(p->vlan), skb);
                        else {
                                if (unlikely(pi->iscsi_ipv4addr &&
                                    is_arp(skb))) {
@@ -1965,7 +1963,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
                        dev_kfree_skb_any(skb);
        } else if (rq->polling) {
                if (lro)
-                       lro_receive_skb(&qs->lro_mgr, skb, p);
+                       napi_gro_receive(&qs->napi, skb);
                else {
                        if (unlikely(pi->iscsi_ipv4addr && is_arp(skb)))
                                cxgb3_arp_process(adap, skb);
@@ -1980,59 +1978,6 @@ static inline int is_eth_tcp(u32 rss)
        return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE;
 }
 
-/**
- *     lro_frame_ok - check if an ingress packet is eligible for LRO
- *     @p: the CPL header of the packet
- *
- *     Returns true if a received packet is eligible for LRO.
- *     The following conditions must be true:
- *     - packet is TCP/IP Ethernet II (checked elsewhere)
- *     - not an IP fragment
- *     - no IP options
- *     - TCP/IP checksums are correct
- *     - the packet is for this host
- */
-static inline int lro_frame_ok(const struct cpl_rx_pkt *p)
-{
-       const struct ethhdr *eh = (struct ethhdr *)(p + 1);
-       const struct iphdr *ih = (struct iphdr *)(eh + 1);
-
-       return (*((u8 *)p + 1) & 0x90) == 0x10 && p->csum == htons(0xffff) &&
-               eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2);
-}
-
-static int t3_get_lro_header(void **eh,  void **iph, void **tcph,
-                            u64 *hdr_flags, void *priv)
-{
-       const struct cpl_rx_pkt *cpl = priv;
-
-       if (!lro_frame_ok(cpl))
-               return -1;
-
-       *eh = (struct ethhdr *)(cpl + 1);
-       *iph = (struct iphdr *)((struct ethhdr *)*eh + 1);
-       *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1);
-
-       *hdr_flags = LRO_IPV4 | LRO_TCP;
-       return 0;
-}
-
-static int t3_get_skb_header(struct sk_buff *skb,
-                             void **iph, void **tcph, u64 *hdr_flags,
-                             void *priv)
-{
-       void *eh;
-
-       return t3_get_lro_header(&eh, iph, tcph, hdr_flags, priv);
-}
-
-static int t3_get_frag_header(struct skb_frag_struct *frag, void **eh,
-                             void **iph, void **tcph, u64 *hdr_flags,
-                             void *priv)
-{
-       return t3_get_lro_header(eh, iph, tcph, hdr_flags, priv);
-}
-
 /**
  *     lro_add_page - add a page chunk to an LRO session
  *     @adap: the adapter
@@ -2049,8 +1994,9 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
 {
        struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
        struct cpl_rx_pkt *cpl;
-       struct skb_frag_struct *rx_frag = qs->lro_frag_tbl;
-       int nr_frags = qs->lro_nfrags, frag_len = qs->lro_frag_len;
+       struct skb_frag_struct *rx_frag = qs->lro_frag_tbl.frags;
+       int nr_frags = qs->lro_frag_tbl.nr_frags;
+       int frag_len = qs->lro_frag_tbl.len;
        int offset = 0;
 
        if (!nr_frags) {
@@ -2069,13 +2015,13 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
        rx_frag->page_offset = sd->pg_chunk.offset + offset;
        rx_frag->size = len;
        frag_len += len;
-       qs->lro_nfrags++;
-       qs->lro_frag_len = frag_len;
+       qs->lro_frag_tbl.nr_frags++;
+       qs->lro_frag_tbl.len = frag_len;
 
        if (!complete)
                return;
 
-       qs->lro_nfrags = qs->lro_frag_len = 0;
+       qs->lro_frag_tbl.ip_summed = CHECKSUM_UNNECESSARY;
        cpl = qs->lro_va;
 
        if (unlikely(cpl->vlan_valid)) {
@@ -2084,36 +2030,15 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
                struct vlan_group *grp = pi->vlan_grp;
 
                if (likely(grp != NULL)) {
-                       lro_vlan_hwaccel_receive_frags(&qs->lro_mgr,
-                                                      qs->lro_frag_tbl,
-                                                      frag_len, frag_len,
-                                                      grp, ntohs(cpl->vlan),
-                                                      cpl, 0);
-                       return;
+                       vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan),
+                                      &qs->lro_frag_tbl);
+                       goto out;
                }
        }
-       lro_receive_frags(&qs->lro_mgr, qs->lro_frag_tbl,
-                         frag_len, frag_len, cpl, 0);
-}
+       napi_gro_frags(&qs->napi, &qs->lro_frag_tbl);
 
-/**
- *     init_lro_mgr - initialize a LRO manager object
- *     @lro_mgr: the LRO manager object
- */
-static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr)
-{
-       lro_mgr->dev = qs->netdev;
-       lro_mgr->features = LRO_F_NAPI;
-       lro_mgr->frag_align_pad = NET_IP_ALIGN;
-       lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
-       lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
-       lro_mgr->max_desc = T3_MAX_LRO_SES;
-       lro_mgr->lro_arr = qs->lro_desc;
-       lro_mgr->get_frag_header = t3_get_frag_header;
-       lro_mgr->get_skb_header = t3_get_skb_header;
-       lro_mgr->max_aggr = T3_MAX_LRO_MAX_PKTS;
-       if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
-               lro_mgr->max_aggr = MAX_SKB_FRAGS;
+out:
+       qs->lro_frag_tbl.nr_frags = qs->lro_frag_tbl.len = 0;
 }
 
 /**
@@ -2357,10 +2282,6 @@ next_fl:
        }
 
        deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
-       lro_flush_all(&qs->lro_mgr);
-       qs->port_stats[SGE_PSTAT_LRO_AGGR] = qs->lro_mgr.stats.aggregated;
-       qs->port_stats[SGE_PSTAT_LRO_FLUSHED] = qs->lro_mgr.stats.flushed;
-       qs->port_stats[SGE_PSTAT_LRO_NO_DESC] = qs->lro_mgr.stats.no_desc;
 
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
@@ -2907,7 +2828,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
 {
        int i, avail, ret = -ENOMEM;
        struct sge_qset *q = &adapter->sge.qs[id];
-       struct net_lro_mgr *lro_mgr = &q->lro_mgr;
 
        init_qset_cntxt(q, id);
        setup_timer(&q->tx_reclaim_timer, sge_timer_cb, (unsigned long)q);
@@ -2987,10 +2907,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
        q->fl[0].order = FL0_PG_ORDER;
        q->fl[1].order = FL1_PG_ORDER;
 
-       q->lro_frag_tbl = kcalloc(MAX_FRAME_SIZE / FL1_PG_CHUNK_SIZE + 1,
-                                 sizeof(struct skb_frag_struct),
-                                 GFP_KERNEL);
-       q->lro_nfrags = q->lro_frag_len = 0;
        spin_lock_irq(&adapter->sge.reg_lock);
 
        /* FL threshold comparison uses < */
@@ -3042,8 +2958,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
        q->tx_q = netdevq;
        t3_update_qset_coalesce(q, p);
 
-       init_lro_mgr(q, lro_mgr);
-
        avail = refill_fl(adapter, &q->fl[0], q->fl[0].size,
                          GFP_KERNEL | __GFP_COMP);
        if (!avail) {
index 7ce3053530f9c62279f38dd17340e89167b6044b..861c867fca879a181095b23fef81c17056018d6c 100644 (file)
@@ -1027,7 +1027,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type)
                printk(version);
 
        if (bdev)
-               snprintf(name, sizeof(name), "%s", bdev->bus_id);
+               snprintf(name, sizeof(name), "%s", dev_name(bdev));
        else {
                i = 0;
                dev = root_lance_dev;
@@ -1105,10 +1105,10 @@ static int __init dec_lance_probe(struct device *bdev, const int type)
 
                start = to_tc_dev(bdev)->resource.start;
                len = to_tc_dev(bdev)->resource.end - start + 1;
-               if (!request_mem_region(start, len, bdev->bus_id)) {
+               if (!request_mem_region(start, len, dev_name(bdev))) {
                        printk(KERN_ERR
                               "%s: Unable to reserve MMIO resource\n",
-                              bdev->bus_id);
+                              dev_name(bdev));
                        ret = -EBUSY;
                        goto err_out_dev;
                }
index e4cef491dc73fc8d6486b98976d9b937b12399ad..55625dbbae5a8f8bf96415e8466f246c471f3585 100644 (file)
@@ -606,8 +606,8 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
        if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
                return -ENXIO;
 
-       printk ("%s: %s at 0x%04lx",
-               device->bus_id, depca_signature[lp->adapter], ioaddr);
+       printk("%s: %s at 0x%04lx",
+              dev_name(device), depca_signature[lp->adapter], ioaddr);
 
        switch (lp->depca_bus) {
 #ifdef CONFIG_MCA
@@ -669,7 +669,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
 
        spin_lock_init(&lp->lock);
        sprintf(lp->adapter_name, "%s (%s)",
-               depca_signature[lp->adapter], device->bus_id);
+               depca_signature[lp->adapter], dev_name(device));
        status = -EBUSY;
 
        /* Initialisation Block */
index 86bb876fb123a312088b7d3edae3e4f91c2771e4..861d2eeaa43c1bd34deaeefc956d5d3f62a1788e 100644 (file)
@@ -1944,9 +1944,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(&nic->napi))) {
+       if (likely(napi_schedule_prep(&nic->napi))) {
                e100_disable_irq(nic);
-               __netif_rx_schedule(&nic->napi);
+               __napi_schedule(&nic->napi);
        }
 
        return IRQ_HANDLED;
@@ -1962,7 +1962,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(napi);
+               napi_complete(napi);
                e100_enable_irq(nic);
        }
 
index f5581de04757701df1c0205980018361459da7a0..e9a416f4016299b4dd5a09c15001efc9ff067bcd 100644 (file)
@@ -182,7 +182,6 @@ struct e1000_tx_ring {
        /* array of buffer information structs */
        struct e1000_buffer *buffer_info;
 
-       spinlock_t tx_lock;
        u16 tdh;
        u16 tdt;
        bool last_tx_tso;
@@ -238,7 +237,6 @@ struct e1000_adapter {
        u16 link_speed;
        u16 link_duplex;
        spinlock_t stats_lock;
-       spinlock_t tx_queue_lock;
        unsigned int total_tx_bytes;
        unsigned int total_tx_packets;
        unsigned int total_rx_bytes;
index 6bd63cc67b3ec37eec06275368b5685300cd9b79..ca7cd7e2bf23c7ccb2ee6329a91638b451331b8e 100644 (file)
@@ -1048,8 +1048,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       netdev->features |= NETIF_F_LLTX;
-
        netdev->vlan_features |= NETIF_F_TSO;
        netdev->vlan_features |= NETIF_F_TSO6;
        netdev->vlan_features |= NETIF_F_HW_CSUM;
@@ -1368,8 +1366,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
                return -ENOMEM;
        }
 
-       spin_lock_init(&adapter->tx_queue_lock);
-
        /* Explicitly disable IRQ since the NIC can be in any state. */
        e1000_irq_disable(adapter);
 
@@ -1624,7 +1620,6 @@ setup_tx_desc_die:
 
        txdr->next_to_use = 0;
        txdr->next_to_clean = 0;
-       spin_lock_init(&txdr->tx_lock);
 
        return 0;
 }
@@ -2865,11 +2860,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter,
                return false;
 
        switch (skb->protocol) {
-       case __constant_htons(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IP):
                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
                        cmd_len |= E1000_TXD_CMD_TCP;
                break;
-       case __constant_htons(ETH_P_IPV6):
+       case cpu_to_be16(ETH_P_IPV6):
                /* XXX not handling all IPV6 headers */
                if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
                        cmd_len |= E1000_TXD_CMD_TCP;
@@ -3185,7 +3180,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
        unsigned int tx_flags = 0;
        unsigned int len = skb->len - skb->data_len;
-       unsigned long flags;
        unsigned int nr_frags;
        unsigned int mss;
        int count = 0;
@@ -3290,22 +3284,15 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
            (hw->mac_type == e1000_82573))
                e1000_transfer_dhcp_info(adapter, skb);
 
-       if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags))
-               /* Collision - tell upper layer to requeue */
-               return NETDEV_TX_LOCKED;
-
        /* need: count + 2 desc gap to keep tail from touching
         * head, otherwise try next time */
-       if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) {
-               spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+       if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
                return NETDEV_TX_BUSY;
-       }
 
        if (unlikely(hw->mac_type == e1000_82547)) {
                if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
                        netif_stop_queue(netdev);
                        mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
-                       spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
                        return NETDEV_TX_BUSY;
                }
        }
@@ -3320,7 +3307,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        tso = e1000_tso(adapter, tx_ring, skb);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
-               spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
                return NETDEV_TX_OK;
        }
 
@@ -3345,7 +3331,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* Make sure there is space in the ring for the next send. */
        e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
 
-       spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
        return NETDEV_TX_OK;
 }
 
@@ -3687,12 +3672,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-       if (likely(netif_rx_schedule_prep(&adapter->napi))) {
+       if (likely(napi_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(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        } else
                e1000_irq_enable(adapter);
 
@@ -3747,12 +3732,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
                ew32(IMC, ~0);
                E1000_WRITE_FLUSH();
        }
-       if (likely(netif_rx_schedule_prep(&adapter->napi))) {
+       if (likely(napi_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(&adapter->napi);
+               __napi_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 */
@@ -3773,15 +3758,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
 
        adapter = netdev_priv(poll_dev);
 
-       /* e1000_clean is called per-cpu.  This lock protects
-        * tx_ring[0] from being cleaned by multiple cpus
-        * simultaneously.  A failure obtaining the lock means
-        * tx_ring[0] is currently being cleaned anyway. */
-       if (spin_trylock(&adapter->tx_queue_lock)) {
-               tx_cleaned = e1000_clean_tx_irq(adapter,
-                                               &adapter->tx_ring[0]);
-               spin_unlock(&adapter->tx_queue_lock);
-       }
+       tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
 
        adapter->clean_rx(adapter, &adapter->rx_ring[0],
                          &work_done, budget);
@@ -3793,7 +3770,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(napi);
+               napi_complete(napi);
                e1000_irq_enable(adapter);
        }
 
index 37bcb190eef80856c89caa08e3e93df1380b38e7..28bf9a51346f57511107680a0a2633d56c7ad243 100644 (file)
@@ -195,8 +195,6 @@ struct e1000_adapter {
        u16 link_duplex;
        u16 eeprom_vers;
 
-       spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
-
        /* track device up/down/testing state */
        unsigned long state;
 
index 91817d0afcaf15a14db138a611160de81cd4fdf3..c425b19e33629d84c992c0b1bfb0dcb1ac67dedf 100644 (file)
@@ -47,7 +47,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "0.3.3.3-k6"
+#define DRV_VERSION "0.3.3.4-k2"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -99,8 +99,8 @@ static void e1000_receive_skb(struct e1000_adapter *adapter,
        skb->protocol = eth_type_trans(skb, netdev);
 
        if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
-               vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-                                        le16_to_cpu(vlan));
+               vlan_gro_receive(&adapter->napi, adapter->vlgrp,
+                                le16_to_cpu(vlan), skb);
        else
                napi_gro_receive(&adapter->napi, skb);
 }
@@ -1179,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(&adapter->napi)) {
+       if (napi_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(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        }
 
        return IRQ_HANDLED;
@@ -1246,12 +1246,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-       if (netif_rx_schedule_prep(&adapter->napi)) {
+       if (napi_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(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        }
 
        return IRQ_HANDLED;
@@ -1320,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(&adapter->napi)) {
+       if (napi_schedule_prep(&adapter->napi)) {
                adapter->total_rx_bytes = 0;
                adapter->total_rx_packets = 0;
-               __netif_rx_schedule(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        }
        return IRQ_HANDLED;
 }
@@ -1698,7 +1698,6 @@ int e1000e_setup_tx_resources(struct e1000_adapter *adapter)
 
        tx_ring->next_to_use = 0;
        tx_ring->next_to_clean = 0;
-       spin_lock_init(&adapter->tx_queue_lock);
 
        return 0;
 err:
@@ -2007,16 +2006,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
            !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
                goto clean_rx;
 
-       /*
-        * e1000_clean is called per-cpu.  This lock protects
-        * tx_ring from being cleaned by multiple cpus
-        * simultaneously.  A failure obtaining the lock means
-        * tx_ring is currently being cleaned anyway.
-        */
-       if (spin_trylock(&adapter->tx_queue_lock)) {
-               tx_cleaned = e1000_clean_tx_irq(adapter);
-               spin_unlock(&adapter->tx_queue_lock);
-       }
+       tx_cleaned = e1000_clean_tx_irq(adapter);
 
 clean_rx:
        adapter->clean_rx(adapter, &work_done, budget);
@@ -2028,7 +2018,7 @@ clean_rx:
        if (work_done < budget) {
                if (adapter->itr_setting & 3)
                        e1000_set_itr(adapter);
-               netif_rx_complete(napi);
+               napi_complete(napi);
                if (adapter->msix_entries)
                        ew32(IMS, adapter->rx_ring->ims_val);
                else
@@ -2922,8 +2912,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
        if (e1000_alloc_queues(adapter))
                return -ENOMEM;
 
-       spin_lock_init(&adapter->tx_queue_lock);
-
        /* Explicitly disable IRQ since the NIC can be in any state. */
        e1000_irq_disable(adapter);
 
@@ -3782,11 +3770,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
                return 0;
 
        switch (skb->protocol) {
-       case __constant_htons(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IP):
                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
                        cmd_len |= E1000_TXD_CMD_TCP;
                break;
-       case __constant_htons(ETH_P_IPV6):
+       case cpu_to_be16(ETH_P_IPV6):
                /* XXX not handling all IPV6 headers */
                if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
                        cmd_len |= E1000_TXD_CMD_TCP;
@@ -4069,7 +4057,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
        unsigned int tx_flags = 0;
        unsigned int len = skb->len - skb->data_len;
-       unsigned long irq_flags;
        unsigned int nr_frags;
        unsigned int mss;
        int count = 0;
@@ -4138,18 +4125,12 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if (adapter->hw.mac.tx_pkt_filtering)
                e1000_transfer_dhcp_info(adapter, skb);
 
-       if (!spin_trylock_irqsave(&adapter->tx_queue_lock, irq_flags))
-               /* Collision - tell upper layer to requeue */
-               return NETDEV_TX_LOCKED;
-
        /*
         * need: count + 2 desc gap to keep tail from touching
         * head, otherwise try next time
         */
-       if (e1000_maybe_stop_tx(netdev, count + 2)) {
-               spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
+       if (e1000_maybe_stop_tx(netdev, count + 2))
                return NETDEV_TX_BUSY;
-       }
 
        if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
                tx_flags |= E1000_TX_FLAGS_VLAN;
@@ -4161,7 +4142,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        tso = e1000_tso(adapter, skb);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
-               spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
                return NETDEV_TX_OK;
        }
 
@@ -4182,7 +4162,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if (count < 0) {
                /* handle pci_map_single() error in e1000_tx_map */
                dev_kfree_skb_any(skb);
-               spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
                return NETDEV_TX_OK;
        }
 
@@ -4193,7 +4172,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* Make sure there is space in the ring for the next send. */
        e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2);
 
-       spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
        return NETDEV_TX_OK;
 }
 
@@ -4922,12 +4900,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       /*
-        * We should not be using LLTX anymore, but we are still Tx faster with
-        * it.
-        */
-       netdev->features |= NETIF_F_LLTX;
-
        if (e1000e_enable_mng_pass_thru(&adapter->hw))
                adapter->flags |= FLAG_MNG_PT_ENABLED;
 
index 6271b9411ccf08c079046059a00d4584746a9d83..f7e2ccfd3e8cfe73c2f23467ca905f29d5445bc0 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0096"
+#define DRV_VERSION    "EHEA_0097"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
index dfe92264e8252978d5719dc81f5b08dfff6d5f25..489fdb90f7647ac1524b4be6c8545b1cd2a25cc9 100644 (file)
@@ -308,7 +308,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
 
        memset(stats, 0, sizeof(*stats));
 
-       cb2 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+       cb2 = (void *)get_zeroed_page(GFP_ATOMIC);
        if (!cb2) {
                ehea_error("no mem for cb2");
                goto out;
@@ -341,7 +341,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
        stats->rx_packets = rx_packets;
 
 out_herr:
-       kfree(cb2);
+       free_page((unsigned long)cb2);
 out:
        return stats;
 }
@@ -370,8 +370,6 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
                                                              EHEA_L_PKT_SIZE);
                        if (!skb_arr_rq1[index]) {
                                pr->rq1_skba.os_skbs = fill_wqes - i;
-                               ehea_error("%s: no mem for skb/%d wqes filled",
-                                          dev->name, i);
                                break;
                        }
                }
@@ -387,26 +385,19 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
        ehea_update_rq1a(pr->qp, adder);
 }
 
-static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
+static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
 {
-       int ret = 0;
        struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
        struct net_device *dev = pr->port->netdev;
        int i;
 
        for (i = 0; i < pr->rq1_skba.len; i++) {
                skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-               if (!skb_arr_rq1[i]) {
-                       ehea_error("%s: no mem for skb/%d wqes filled",
-                                  dev->name, i);
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               if (!skb_arr_rq1[i])
+                       break;
        }
        /* Ring doorbell */
        ehea_update_rq1a(pr->qp, nr_rq1a);
-out:
-       return ret;
 }
 
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
@@ -435,10 +426,12 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
                u64 tmp_addr;
                struct sk_buff *skb = netdev_alloc_skb(dev, packet_size);
                if (!skb) {
-                       ehea_error("%s: no mem for skb/%d wqes filled",
-                                  pr->port->netdev->name, i);
                        q_skba->os_skbs = fill_wqes - i;
-                       ret = -ENOMEM;
+                       if (q_skba->os_skbs == q_skba->len - 2) {
+                               ehea_info("%s: rq%i ran dry - no mem for skb",
+                                         pr->port->netdev->name, rq_nr);
+                               ret = -ENOMEM;
+                       }
                        break;
                }
                skb_reserve(skb, NET_IP_ALIGN);
@@ -830,7 +823,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(napi);
+               napi_complete(napi);
                ehea_reset_cq_ep(pr->recv_cq);
                ehea_reset_cq_ep(pr->send_cq);
                ehea_reset_cq_n1(pr->recv_cq);
@@ -841,7 +834,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
                if (!cqe && !cqe_skb)
                        return rx;
 
-               if (!netif_rx_reschedule(napi))
+               if (!napi_reschedule(napi))
                        return rx;
 
                cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
@@ -859,7 +852,7 @@ static void ehea_netpoll(struct net_device *dev)
        int i;
 
        for (i = 0; i < port->num_def_qps; i++)
-               netif_rx_schedule(&port->port_res[i].napi);
+               napi_schedule(&port->port_res[i].napi);
 }
 #endif
 
@@ -867,7 +860,7 @@ static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
 {
        struct ehea_port_res *pr = param;
 
-       netif_rx_schedule(&pr->napi);
+       napi_schedule(&pr->napi);
 
        return IRQ_HANDLED;
 }
@@ -915,7 +908,7 @@ int ehea_sense_port_attr(struct ehea_port *port)
        struct hcp_ehea_port_cb0 *cb0;
 
        /* may be called via ehea_neq_tasklet() */
-       cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+       cb0 = (void *)get_zeroed_page(GFP_ATOMIC);
        if (!cb0) {
                ehea_error("no mem for cb0");
                ret = -ENOMEM;
@@ -996,7 +989,7 @@ int ehea_sense_port_attr(struct ehea_port *port)
 out_free:
        if (ret || netif_msg_probe(port))
                ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr");
-       kfree(cb0);
+       free_page((unsigned long)cb0);
 out:
        return ret;
 }
@@ -1007,7 +1000,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
        u64 hret;
        int ret = 0;
 
-       cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb4 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb4) {
                ehea_error("no mem for cb4");
                ret = -ENOMEM;
@@ -1075,7 +1068,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
        if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
                netif_carrier_on(port->netdev);
 
-       kfree(cb4);
+       free_page((unsigned long)cb4);
 out:
        return ret;
 }
@@ -1201,11 +1194,11 @@ static int ehea_fill_port_res(struct ehea_port_res *pr)
        int ret;
        struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
 
-       ret = ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1
-                                    - init_attr->act_nr_rwqes_rq2
-                                    - init_attr->act_nr_rwqes_rq3 - 1);
+       ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1
+                              - init_attr->act_nr_rwqes_rq2
+                              - init_attr->act_nr_rwqes_rq3 - 1);
 
-       ret |= ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
+       ret = ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
 
        ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1);
 
@@ -1302,7 +1295,7 @@ static int ehea_configure_port(struct ehea_port *port)
        struct hcp_ehea_port_cb0 *cb0;
 
        ret = -ENOMEM;
-       cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb0 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb0)
                goto out;
 
@@ -1338,7 +1331,7 @@ static int ehea_configure_port(struct ehea_port *port)
        ret = 0;
 
 out_free:
-       kfree(cb0);
+       free_page((unsigned long)cb0);
 out:
        return ret;
 }
@@ -1748,7 +1741,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
                goto out;
        }
 
-       cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb0 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb0) {
                ehea_error("no mem for cb0");
                ret = -ENOMEM;
@@ -1793,7 +1786,7 @@ out_upregs:
        ehea_update_bcmc_registrations();
        spin_unlock(&ehea_bcmc_regs.lock);
 out_free:
-       kfree(cb0);
+       free_page((unsigned long)cb0);
 out:
        return ret;
 }
@@ -1817,7 +1810,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable)
        if ((enable && port->promisc) || (!enable && !port->promisc))
                return;
 
-       cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+       cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
        if (!cb7) {
                ehea_error("no mem for cb7");
                goto out;
@@ -1836,7 +1829,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable)
 
        port->promisc = enable;
 out:
-       kfree(cb7);
+       free_page((unsigned long)cb7);
        return;
 }
 
@@ -2217,7 +2210,7 @@ static void ehea_vlan_rx_register(struct net_device *dev,
 
        port->vgrp = grp;
 
-       cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb1 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb1) {
                ehea_error("no mem for cb1");
                goto out;
@@ -2228,7 +2221,7 @@ static void ehea_vlan_rx_register(struct net_device *dev,
        if (hret != H_SUCCESS)
                ehea_error("modify_ehea_port failed");
 
-       kfree(cb1);
+       free_page((unsigned long)cb1);
 out:
        return;
 }
@@ -2241,7 +2234,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
        int index;
        u64 hret;
 
-       cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb1 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb1) {
                ehea_error("no mem for cb1");
                goto out;
@@ -2262,7 +2255,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
        if (hret != H_SUCCESS)
                ehea_error("modify_ehea_port failed");
 out:
-       kfree(cb1);
+       free_page((unsigned long)cb1);
        return;
 }
 
@@ -2276,7 +2269,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
        vlan_group_set_device(port->vgrp, vid, NULL);
 
-       cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb1 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb1) {
                ehea_error("no mem for cb1");
                goto out;
@@ -2297,7 +2290,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        if (hret != H_SUCCESS)
                ehea_error("modify_ehea_port failed");
 out:
-       kfree(cb1);
+       free_page((unsigned long)cb1);
        return;
 }
 
@@ -2309,7 +2302,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
        u64 dummy64 = 0;
        struct hcp_modify_qp_cb0 *cb0;
 
-       cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb0 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb0) {
                ret = -ENOMEM;
                goto out;
@@ -2372,7 +2365,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
 
        ret = 0;
 out:
-       kfree(cb0);
+       free_page((unsigned long)cb0);
        return ret;
 }
 
@@ -2664,7 +2657,7 @@ int ehea_stop_qps(struct net_device *dev)
        u64 dummy64 = 0;
        u16 dummy16 = 0;
 
-       cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb0 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb0) {
                ret = -ENOMEM;
                goto out;
@@ -2716,7 +2709,7 @@ int ehea_stop_qps(struct net_device *dev)
 
        ret = 0;
 out:
-       kfree(cb0);
+       free_page((unsigned long)cb0);
 
        return ret;
 }
@@ -2766,7 +2759,7 @@ int ehea_restart_qps(struct net_device *dev)
        u64 dummy64 = 0;
        u16 dummy16 = 0;
 
-       cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb0 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb0) {
                ret = -ENOMEM;
                goto out;
@@ -2819,7 +2812,7 @@ int ehea_restart_qps(struct net_device *dev)
                ehea_refill_rq3(pr, 0);
        }
 out:
-       kfree(cb0);
+       free_page((unsigned long)cb0);
 
        return ret;
 }
@@ -2950,7 +2943,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
        u64 hret;
        int ret;
 
-       cb = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb) {
                ret = -ENOMEM;
                goto out;
@@ -2967,7 +2960,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
        ret = 0;
 
 out_herr:
-       kfree(cb);
+       free_page((unsigned long)cb);
 out:
        return ret;
 }
@@ -2981,7 +2974,7 @@ int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
        *jumbo = 0;
 
        /* (Try to) enable *jumbo frames */
-       cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb4 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb4) {
                ehea_error("no mem for cb4");
                ret = -ENOMEM;
@@ -3009,7 +3002,7 @@ int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
                } else
                        ret = -EINVAL;
 
-               kfree(cb4);
+               free_page((unsigned long)cb4);
        }
 out:
        return ret;
@@ -3040,7 +3033,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
        port->ofdev.dev.parent = &port->adapter->ofdev->dev;
        port->ofdev.dev.bus = &ibmebus_bus_type;
 
-       sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
+       dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++);
        port->ofdev.dev.release = logical_port_release;
 
        ret = of_device_register(&port->ofdev);
@@ -3069,6 +3062,22 @@ static void ehea_unregister_port(struct ehea_port *port)
        of_device_unregister(&port->ofdev);
 }
 
+static const struct net_device_ops ehea_netdev_ops = {
+       .ndo_open               = ehea_open,
+       .ndo_stop               = ehea_stop,
+       .ndo_start_xmit         = ehea_start_xmit,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ehea_netpoll,
+#endif
+       .ndo_get_stats          = ehea_get_stats,
+       .ndo_set_mac_address    = ehea_set_mac_addr,
+       .ndo_set_multicast_list = ehea_set_multicast_list,
+       .ndo_change_mtu         = ehea_change_mtu,
+       .ndo_vlan_rx_register   = ehea_vlan_rx_register,
+       .ndo_vlan_rx_add_vid    = ehea_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid   = ehea_vlan_rx_kill_vid
+};
+
 struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                                         u32 logical_port_id,
                                         struct device_node *dn)
@@ -3121,19 +3130,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
        /* initialize net_device structure */
        memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
 
-       dev->open = ehea_open;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = ehea_netpoll;
-#endif
-       dev->stop = ehea_stop;
-       dev->hard_start_xmit = ehea_start_xmit;
-       dev->get_stats = ehea_get_stats;
-       dev->set_multicast_list = ehea_set_multicast_list;
-       dev->set_mac_address = ehea_set_mac_addr;
-       dev->change_mtu = ehea_change_mtu;
-       dev->vlan_rx_register = ehea_vlan_rx_register;
-       dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid;
-       dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
+       dev->netdev_ops = &ehea_netdev_ops;
+       ehea_set_ethtool_ops(dev);
+
        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
                      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
                      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
@@ -3142,7 +3141,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
        INIT_WORK(&port->reset_task, ehea_reset_port);
-       ehea_set_ethtool_ops(dev);
 
        ret = register_netdev(dev);
        if (ret) {
index 49d766ebbcf4e630d91cf8c245e50e96322be360..3747457f5e69441a14d91932b3ac3aca18a5c879 100644 (file)
@@ -1005,7 +1005,7 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
        unsigned long ret;
        u64 *rblock;
 
-       rblock = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       rblock = (void *)get_zeroed_page(GFP_KERNEL);
        if (!rblock) {
                ehea_error("Cannot allocate rblock memory.");
                return;
@@ -1022,5 +1022,5 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
        else
                ehea_error("Error data could not be fetched: %llX", res_handle);
 
-       kfree(rblock);
+       free_page((unsigned long)rblock);
 }
index 7d60551d538fccae67b2638ac8b85f985938a8b4..5dd11563553eefea854faceec0eda746811d6ab7 100644 (file)
@@ -411,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(&enic->napi))
-                       __netif_rx_schedule(&enic->napi);
+               if (napi_schedule_prep(&enic->napi))
+                       __napi_schedule(&enic->napi);
        } else {
                vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
        }
@@ -440,7 +440,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
         * writes).
         */
 
-       netif_rx_schedule(&enic->napi);
+       napi_schedule(&enic->napi);
 
        return IRQ_HANDLED;
 }
@@ -450,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->napi);
+       napi_schedule(&enic->napi);
 
        return IRQ_HANDLED;
 }
@@ -570,11 +570,11 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic,
         * to each TCP segment resulting from the TSO.
         */
 
-       if (skb->protocol == __constant_htons(ETH_P_IP)) {
+       if (skb->protocol == cpu_to_be16(ETH_P_IP)) {
                ip_hdr(skb)->check = 0;
                tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
                        ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
-       } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+       } else if (skb->protocol == cpu_to_be16(ETH_P_IPV6)) {
                tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                        &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
        }
@@ -1068,7 +1068,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
                if (netdev->features & NETIF_F_LRO)
                        lro_flush_all(&enic->lro_mgr);
 
-               netif_rx_complete(napi);
+               napi_complete(napi);
                vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
        }
 
@@ -1112,7 +1112,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
                if (netdev->features & NETIF_F_LRO)
                        lro_flush_all(&enic->lro_mgr);
 
-               netif_rx_complete(napi);
+               napi_complete(napi);
                vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
        }
 
index a539bc3163cf07548479422c633b1ebb1f87681e..b60e27dfcfa7c24a3c576ca1f5713e30befb4d60 100644 (file)
@@ -1114,9 +1114,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(&ep->napi)) {
+               if (napi_schedule_prep(&ep->napi)) {
                        epic_napi_irq_off(dev, ep);
-                       __netif_rx_schedule(&ep->napi);
+                       __napi_schedule(&ep->napi);
                } else
                        ep->reschedule_in_poll++;
                spin_unlock(&ep->napi_lock);
@@ -1293,7 +1293,7 @@ rx_action:
 
                more = ep->reschedule_in_poll;
                if (!more) {
-                       __netif_rx_complete(napi);
+                       __napi_complete(napi);
                        outl(EpicNapiEvent, ioaddr + INTSTAT);
                        epic_napi_irq_on(dev, ep);
                } else
index 2769083bfe83a27265925e46e00462127885b739..fe2650237e349a407b8bc22c5bf0af5c7dbddb11 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
 
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
+#ifndef CONFIG_ARCH_MXC
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#endif
+
 #include "fec.h"
 
-#if defined(CONFIG_FEC2)
-#define        FEC_MAX_PORTS   2
+#ifdef CONFIG_ARCH_MXC
+#include <mach/hardware.h>
+#define FEC_ALIGNMENT  0xf
 #else
-#define        FEC_MAX_PORTS   1
+#define FEC_ALIGNMENT  0x3
 #endif
 
+#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \
+       || defined CONFIG_M528x || defined CONFIG_M532x || defined CONFIG_M520x
+#define FEC_LEGACY
+/*
+ * Define the fixed address of the FEC hardware.
+ */
 #if defined(CONFIG_M5272)
 #define HAVE_mii_link_interrupt
 #endif
 
-/*
- * Define the fixed address of the FEC hardware.
- */
+#if defined(CONFIG_FEC2)
+#define        FEC_MAX_PORTS   2
+#else
+#define        FEC_MAX_PORTS   1
+#endif
+
 static unsigned int fec_hw[] = {
 #if defined(CONFIG_M5272)
        (MCF_MBAR + 0x840),
@@ -72,8 +85,6 @@ static unsigned int fec_hw[] = {
        (MCF_MBAR+0x30000),
 #elif defined(CONFIG_M532x)
        (MCF_MBAR+0xfc030000),
-#else
-       &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
 #endif
 };
 
@@ -99,6 +110,8 @@ static unsigned char fec_mac_default[] = {
 #define        FEC_FLASHMAC    0
 #endif
 
+#endif /* FEC_LEGACY */
+
 /* Forward declarations of some structures to support different PHYs
 */
 
@@ -162,7 +175,7 @@ typedef struct {
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
 #define        OPT_FRAME_SIZE  (PKT_MAXBUF_SIZE << 16)
 #else
 #define        OPT_FRAME_SIZE  0
@@ -182,6 +195,8 @@ struct fec_enet_private {
 
        struct net_device *netdev;
 
+       struct clk *clk;
+
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        unsigned char *tx_bounce[TX_RING_SIZE];
        struct  sk_buff* tx_skbuff[TX_RING_SIZE];
@@ -190,6 +205,7 @@ struct fec_enet_private {
 
        /* CPM dual port RAM relative addresses.
        */
+       dma_addr_t      bd_dma;
        cbd_t   *rx_bd_base;            /* Address of Rx and Tx buffers. */
        cbd_t   *tx_bd_base;
        cbd_t   *cur_rx, *cur_tx;               /* The next free ring entry */
@@ -342,10 +358,10 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
         *      4-byte boundaries. Use bounce buffers to copy data
         *      and get it aligned. Ugh.
         */
-       if (bdp->cbd_bufaddr & 0x3) {
+       if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
                unsigned int index;
                index = bdp - fep->tx_bd_base;
-               memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen);
+               memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
                bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
        }
 
@@ -359,8 +375,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Push the data cache so the CPM does not get stale memory
         * data.
         */
-       flush_dcache_range((unsigned long)skb->data,
-                          (unsigned long)skb->data + skb->len);
+       dma_sync_single(NULL, bdp->cbd_bufaddr,
+                       bdp->cbd_datlen, DMA_TO_DEVICE);
 
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
@@ -633,6 +649,9 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
        dev->stats.rx_bytes += pkt_len;
        data = (__u8*)__va(bdp->cbd_bufaddr);
 
+       dma_sync_single(NULL, (unsigned long)__pa(data),
+                       pkt_len - 4, DMA_FROM_DEVICE);
+
        /* This does 16 byte alignment, exactly what we need.
         * The packet length includes FCS, but we don't want to
         * include that when passing upstream as it messes up
@@ -1114,7 +1133,7 @@ static phy_info_t const phy_info_am79c874 = {
 /* register definitions for the 8721 */
 
 #define MII_KS8721BL_RXERCR    21
-#define MII_KS8721BL_ICSR      22
+#define MII_KS8721BL_ICSR      27
 #define        MII_KS8721BL_PHYCR      31
 
 static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
@@ -1308,10 +1327,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
-static void __inline__ fec_enable_phy_intr(void)
-{
-}
-
 static void __inline__ fec_disable_phy_intr(void)
 {
        volatile unsigned long *icrp;
@@ -1327,17 +1342,6 @@ static void __inline__ fec_phy_ack_intr(void)
        *icrp = 0x0d000000;
 }
 
-static void __inline__ fec_localhw_setup(void)
-{
-}
-
-/*
- *     Do not need to make region uncached on 5272.
- */
-static void __inline__ fec_uncache(unsigned long addr)
-{
-}
-
 /* ------------------------------------------------------------------------- */
 
 #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
@@ -1477,10 +1481,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
-static void __inline__ fec_enable_phy_intr(void)
-{
-}
-
 static void __inline__ fec_disable_phy_intr(void)
 {
 }
@@ -1489,17 +1489,6 @@ static void __inline__ fec_phy_ack_intr(void)
 {
 }
 
-static void __inline__ fec_localhw_setup(void)
-{
-}
-
-/*
- *     Do not need to make region uncached on 5272.
- */
-static void __inline__ fec_uncache(unsigned long addr)
-{
-}
-
 /* ------------------------------------------------------------------------- */
 
 #elif defined(CONFIG_M520x)
@@ -1598,10 +1587,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
-static void __inline__ fec_enable_phy_intr(void)
-{
-}
-
 static void __inline__ fec_disable_phy_intr(void)
 {
 }
@@ -1610,14 +1595,6 @@ static void __inline__ fec_phy_ack_intr(void)
 {
 }
 
-static void __inline__ fec_localhw_setup(void)
-{
-}
-
-static void __inline__ fec_uncache(unsigned long addr)
-{
-}
-
 /* ------------------------------------------------------------------------- */
 
 #elif defined(CONFIG_M532x)
@@ -1737,10 +1714,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
-static void __inline__ fec_enable_phy_intr(void)
-{
-}
-
 static void __inline__ fec_disable_phy_intr(void)
 {
 }
@@ -1749,107 +1722,6 @@ static void __inline__ fec_phy_ack_intr(void)
 {
 }
 
-static void __inline__ fec_localhw_setup(void)
-{
-}
-
-/*
- *     Do not need to make region uncached on 532x.
- */
-static void __inline__ fec_uncache(unsigned long addr)
-{
-}
-
-/* ------------------------------------------------------------------------- */
-
-
-#else
-
-/*
- *     Code specific to the MPC860T setup.
- */
-static void __inline__ fec_request_intrs(struct net_device *dev)
-{
-       volatile immap_t *immap;
-
-       immap = (immap_t *)IMAP_ADDR;   /* pointer to internal registers */
-
-       if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
-               panic("Could not allocate FEC IRQ!");
-}
-
-static void __inline__ fec_get_mac(struct net_device *dev)
-{
-       bd_t *bd;
-
-       bd = (bd_t *)__res;
-       memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
-}
-
-static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
-{
-       extern uint _get_IMMR(void);
-       volatile immap_t *immap;
-       volatile fec_t *fecp;
-
-       fecp = fep->hwp;
-       immap = (immap_t *)IMAP_ADDR;   /* pointer to internal registers */
-
-       /* Configure all of port D for MII.
-       */
-       immap->im_ioport.iop_pdpar = 0x1fff;
-
-       /* Bits moved from Rev. D onward.
-       */
-       if ((_get_IMMR() & 0xffff) < 0x0501)
-               immap->im_ioport.iop_pddir = 0x1c58;    /* Pre rev. D */
-       else
-               immap->im_ioport.iop_pddir = 0x1fff;    /* Rev. D and later */
-
-       /* Set MII speed to 2.5 MHz
-       */
-       fecp->fec_mii_speed = fep->phy_speed =
-               ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e;
-}
-
-static void __inline__ fec_enable_phy_intr(void)
-{
-       volatile fec_t *fecp;
-
-       fecp = fep->hwp;
-
-       /* Enable MII command finished interrupt
-       */
-       fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
-}
-
-static void __inline__ fec_disable_phy_intr(void)
-{
-}
-
-static void __inline__ fec_phy_ack_intr(void)
-{
-}
-
-static void __inline__ fec_localhw_setup(void)
-{
-       volatile fec_t *fecp;
-
-       fecp = fep->hwp;
-       fecp->fec_r_hash = PKT_MAXBUF_SIZE;
-       /* Enable big endian and don't care about SDMA FC.
-       */
-       fecp->fec_fun_code = 0x78000000;
-}
-
-static void __inline__ fec_uncache(unsigned long addr)
-{
-       pte_t *pte;
-       pte = va_to_pte(mem_addr);
-       pte_val(*pte) |= _PAGE_NO_CACHE;
-       flush_tlb_page(init_mm.mmap, mem_addr);
-}
-
 #endif
 
 /* ------------------------------------------------------------------------- */
@@ -2055,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
                printk("FEC: No PHY device found.\n");
                /* Disable external MII interface */
                fecp->fec_mii_speed = fep->phy_speed = 0;
+#ifdef FREC_LEGACY
                fec_disable_phy_intr();
+#endif
        }
 }
 
@@ -2237,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev)
 
 }
 
-/* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
- */
  /*
   * XXX:  We need to clean up on failure exits here.
+  *
+  * index is only used in legacy code
   */
-int __init fec_enet_init(struct net_device *dev)
+int __init fec_enet_init(struct net_device *dev, int index)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        unsigned long   mem_addr;
@@ -2250,15 +2124,11 @@ int __init fec_enet_init(struct net_device *dev)
        cbd_t           *cbd_base;
        volatile fec_t  *fecp;
        int             i, j;
-       static int      index = 0;
-
-       /* Only allow us to be probed once. */
-       if (index >= FEC_MAX_PORTS)
-               return -ENXIO;
 
        /* Allocate memory for buffer descriptors.
        */
-       mem_addr = __get_free_page(GFP_KERNEL);
+       mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE,
+                       &fep->bd_dma, GFP_KERNEL);
        if (mem_addr == 0) {
                printk("FEC: allocate descriptor memory failed?\n");
                return -ENOMEM;
@@ -2269,7 +2139,7 @@ int __init fec_enet_init(struct net_device *dev)
 
        /* Create an Ethernet device instance.
        */
-       fecp = (volatile fec_t *) fec_hw[index];
+       fecp = (volatile fec_t *)dev->base_addr;
 
        fep->index = index;
        fep->hwp = fecp;
@@ -2280,18 +2150,24 @@ int __init fec_enet_init(struct net_device *dev)
        fecp->fec_ecntrl = 1;
        udelay(10);
 
-       /* Set the Ethernet address.  If using multiple Enets on the 8xx,
-        * this needs some work to get unique addresses.
-        *
-        * This is our default MAC address unless the user changes
-        * it via eth_mac_addr (our dev->set_mac_addr handler).
-        */
+       /* Set the Ethernet address */
+#ifdef FEC_LEGACY
        fec_get_mac(dev);
+#else
+       {
+               unsigned long l;
+               l = fecp->fec_addr_low;
+               dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
+               dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
+               dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
+               dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
+               l = fecp->fec_addr_high;
+               dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
+               dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
+       }
+#endif
 
        cbd_base = (cbd_t *)mem_addr;
-       /* XXX: missing check for allocation failure */
-
-       fec_uncache(mem_addr);
 
        /* Set receive and transmit descriptor base.
        */
@@ -2313,8 +2189,6 @@ int __init fec_enet_init(struct net_device *dev)
                mem_addr = __get_free_page(GFP_KERNEL);
                /* XXX: missing check for allocation failure */
 
-               fec_uncache(mem_addr);
-
                /* Initialize the BD for every fragment in the page.
                */
                for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
@@ -2357,13 +2231,16 @@ int __init fec_enet_init(struct net_device *dev)
 
        /* Set receive and transmit descriptor base.
        */
-       fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
-       fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
+       fecp->fec_r_des_start = fep->bd_dma;
+       fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
+                               * RX_RING_SIZE;
 
+#ifdef FEC_LEGACY
        /* Install our interrupt handlers. This varies depending on
         * the architecture.
        */
        fec_request_intrs(dev);
+#endif
 
        fecp->fec_grp_hash_table_high = 0;
        fecp->fec_grp_hash_table_low = 0;
@@ -2375,8 +2252,6 @@ int __init fec_enet_init(struct net_device *dev)
        fecp->fec_hash_table_low = 0;
 #endif
 
-       dev->base_addr = (unsigned long)fecp;
-
        /* The FEC Ethernet specific entries in the device structure. */
        dev->open = fec_enet_open;
        dev->hard_start_xmit = fec_enet_start_xmit;
@@ -2390,7 +2265,20 @@ int __init fec_enet_init(struct net_device *dev)
        mii_free = mii_cmds;
 
        /* setup MII interface */
+#ifdef FEC_LEGACY
        fec_set_mii(dev, fep);
+#else
+       fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
+       fecp->fec_x_cntrl = 0x00;
+
+       /*
+        * Set MII speed to 2.5 MHz
+        */
+       fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
+                                       / 2500000) / 2) & 0x3F) << 1;
+       fecp->fec_mii_speed = fep->phy_speed;
+       fec_restart(dev, 0);
+#endif
 
        /* Clear and enable interrupts */
        fecp->fec_ievent = 0xffc00000;
@@ -2403,7 +2291,6 @@ int __init fec_enet_init(struct net_device *dev)
        fep->phy_addr = 0;
        mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
 
-       index++;
        return 0;
 }
 
@@ -2430,7 +2317,6 @@ fec_restart(struct net_device *dev, int duplex)
        /* Clear any outstanding interrupt.
        */
        fecp->fec_ievent = 0xffc00000;
-       fec_enable_phy_intr();
 
        /* Set station address.
        */
@@ -2445,12 +2331,11 @@ fec_restart(struct net_device *dev, int duplex)
        */
        fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
 
-       fec_localhw_setup();
-
        /* Set receive and transmit descriptor base.
        */
-       fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
-       fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
+       fecp->fec_r_des_start = fep->bd_dma;
+       fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
+                               * RX_RING_SIZE;
 
        fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
        fep->cur_rx = fep->rx_bd_base;
@@ -2552,12 +2437,12 @@ fec_stop(struct net_device *dev)
        /* Clear outstanding MII command interrupts.
        */
        fecp->fec_ievent = FEC_ENET_MII;
-       fec_enable_phy_intr();
 
        fecp->fec_imask = FEC_ENET_MII;
        fecp->fec_mii_speed = fep->phy_speed;
 }
 
+#ifdef FEC_LEGACY
 static int __init fec_enet_module_init(void)
 {
        struct net_device *dev;
@@ -2569,7 +2454,8 @@ static int __init fec_enet_module_init(void)
                dev = alloc_etherdev(sizeof(struct fec_enet_private));
                if (!dev)
                        return -ENOMEM;
-               err = fec_enet_init(dev);
+               dev->base_addr = (unsigned long)fec_hw[i];
+               err = fec_enet_init(dev, i);
                if (err) {
                        free_netdev(dev);
                        continue;
@@ -2584,6 +2470,170 @@ static int __init fec_enet_module_init(void)
        }
        return 0;
 }
+#else
+
+static int __devinit
+fec_probe(struct platform_device *pdev)
+{
+       struct fec_enet_private *fep;
+       struct net_device *ndev;
+       int i, irq, ret = 0;
+       struct resource *r;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r)
+               return -ENXIO;
+
+       r = request_mem_region(r->start, resource_size(r), pdev->name);
+       if (!r)
+               return -EBUSY;
+
+       /* Init network device */
+       ndev = alloc_etherdev(sizeof(struct fec_enet_private));
+       if (!ndev)
+               return -ENOMEM;
+
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       /* setup board info structure */
+       fep = netdev_priv(ndev);
+       memset(fep, 0, sizeof(*fep));
+
+       ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
+
+       if (!ndev->base_addr) {
+               ret = -ENOMEM;
+               goto failed_ioremap;
+       }
+
+       platform_set_drvdata(pdev, ndev);
+
+       /* This device has up to three irqs on some platforms */
+       for (i = 0; i < 3; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (i && irq < 0)
+                       break;
+               ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
+               if (ret) {
+                       while (i >= 0) {
+                               irq = platform_get_irq(pdev, i);
+                               free_irq(irq, ndev);
+                               i--;
+                       }
+                       goto failed_irq;
+               }
+       }
+
+       fep->clk = clk_get(&pdev->dev, "fec_clk");
+       if (IS_ERR(fep->clk)) {
+               ret = PTR_ERR(fep->clk);
+               goto failed_clk;
+       }
+       clk_enable(fep->clk);
+
+       ret = fec_enet_init(ndev, 0);
+       if (ret)
+               goto failed_init;
+
+       ret = register_netdev(ndev);
+       if (ret)
+               goto failed_register;
+
+       return 0;
+
+failed_register:
+failed_init:
+       clk_disable(fep->clk);
+       clk_put(fep->clk);
+failed_clk:
+       for (i = 0; i < 3; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (irq > 0)
+                       free_irq(irq, ndev);
+       }
+failed_irq:
+       iounmap((void __iomem *)ndev->base_addr);
+failed_ioremap:
+       free_netdev(ndev);
+
+       return ret;
+}
+
+static int __devexit
+fec_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       fec_stop(ndev);
+       clk_disable(fep->clk);
+       clk_put(fep->clk);
+       iounmap((void __iomem *)ndev->base_addr);
+       unregister_netdev(ndev);
+       free_netdev(ndev);
+       return 0;
+}
+
+static int
+fec_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+       struct fec_enet_private *fep;
+
+       if (ndev) {
+               fep = netdev_priv(ndev);
+               if (netif_running(ndev)) {
+                       netif_device_detach(ndev);
+                       fec_stop(ndev);
+               }
+       }
+       return 0;
+}
+
+static int
+fec_resume(struct platform_device *dev)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+
+       if (ndev) {
+               if (netif_running(ndev)) {
+                       fec_enet_init(ndev, 0);
+                       netif_device_attach(ndev);
+               }
+       }
+       return 0;
+}
+
+static struct platform_driver fec_driver = {
+       .driver = {
+               .name    = "fec",
+               .owner   = THIS_MODULE,
+       },
+       .probe   = fec_probe,
+       .remove  = __devexit_p(fec_drv_remove),
+       .suspend = fec_suspend,
+       .resume  = fec_resume,
+};
+
+static int __init
+fec_enet_module_init(void)
+{
+       printk(KERN_INFO "FEC Ethernet Driver\n");
+
+       return platform_driver_register(&fec_driver);
+}
+
+static void __exit
+fec_enet_cleanup(void)
+{
+       platform_driver_unregister(&fec_driver);
+}
+
+module_exit(fec_enet_cleanup);
+
+#endif /* FEC_LEGACY */
 
 module_init(fec_enet_module_init);
 
index 292719daceff0e8060aa7ae6ddef7fda0a0bcf31..76c64c92e190980ef5a5d8451412882e410ff722 100644 (file)
@@ -14,7 +14,7 @@
 /****************************************************************************/
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
 /*
  *     Just figures, Motorola would have to change the offsets for
  *     registers in the same peripheral device on different models
@@ -103,12 +103,19 @@ typedef struct fec {
 /*
  *     Define the buffer descriptor structure.
  */
+#ifdef CONFIG_ARCH_MXC
+typedef struct bufdesc {
+       unsigned short cbd_datlen;      /* Data length */
+       unsigned short cbd_sc;  /* Control and status info */
+       unsigned long cbd_bufaddr;      /* Buffer address */
+} cbd_t;
+#else
 typedef struct bufdesc {
        unsigned short  cbd_sc;                 /* Control and status info */
        unsigned short  cbd_datlen;             /* Data length */
        unsigned long   cbd_bufaddr;            /* Buffer address */
 } cbd_t;
-
+#endif
 
 /*
  *     The following definitions courtesy of commproc.h, which where
index 5b910cf63740877416f8a25f1b91f94da7b783d8..875509d7d86bd773b53e522c87c07309a1cd768e 100644 (file)
@@ -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(&np->napi);
+       napi_schedule(&np->napi);
 }
 #else
 static void nv_do_rx_refill(unsigned long data)
@@ -3406,7 +3406,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
 #ifdef CONFIG_FORCEDETH_NAPI
                if (events & NVREG_IRQ_RX_ALL) {
                        spin_lock(&np->lock);
-                       netif_rx_schedule(&np->napi);
+                       napi_schedule(&np->napi);
 
                        /* Disable furthur receive irq's */
                        np->irqmask &= ~NVREG_IRQ_RX_ALL;
@@ -3523,7 +3523,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
 #ifdef CONFIG_FORCEDETH_NAPI
                if (events & NVREG_IRQ_RX_ALL) {
                        spin_lock(&np->lock);
-                       netif_rx_schedule(&np->napi);
+                       napi_schedule(&np->napi);
 
                        /* Disable furthur receive irq's */
                        np->irqmask &= ~NVREG_IRQ_RX_ALL;
@@ -3680,7 +3680,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(napi);
+               __napi_complete(napi);
 
                np->irqmask |= NVREG_IRQ_RX_ALL;
                if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -3706,7 +3706,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
        writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
 
        if (events) {
-               netif_rx_schedule(&np->napi);
+               napi_schedule(&np->napi);
                /* disable receive interrupts on the nic */
                writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
                pci_push(base);
index ce900e54d8d1dfa7db79e016472c7ce4996631c1..b037ce9857bf57e325a664adc0d6063bca993536 100644 (file)
@@ -209,7 +209,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
 
        if (received < budget) {
                /* done */
-               netif_rx_complete(napi);
+               napi_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(&fep->napi);
+                                       __napi_schedule(&fep->napi);
                        }
                }
 
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
new file mode 100644 (file)
index 0000000..c434a15
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Freescale PowerQUICC Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming <afleming@freescale.com>
+ *
+ * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc.
+ *
+ * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips)
+ *
+ * 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/platform_device.h>
+#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>
+#include <asm/uaccess.h>
+#include <asm/ucc.h>
+
+#include "gianfar.h"
+#include "fsl_pq_mdio.h"
+
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id,
+               int regnum, u16 value)
+{
+       /* Set the PHY address and the register address we want to write */
+       out_be32(&regs->miimadd, (mii_id << 8) | regnum);
+
+       /* Write out the value we want */
+       out_be32(&regs->miimcon, value);
+
+       /* Wait for the transaction to finish */
+       while (in_be32(&regs->miimind) & MIIMIND_BUSY)
+               cpu_relax();
+
+       return 0;
+}
+
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, in turn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs,
+               int mii_id, int regnum)
+{
+       u16 value;
+
+       /* Set the PHY address and the register address we want to read */
+       out_be32(&regs->miimadd, (mii_id << 8) | regnum);
+
+       /* Clear miimcom, and then initiate a read */
+       out_be32(&regs->miimcom, 0);
+       out_be32(&regs->miimcom, MII_READ_COMMAND);
+
+       /* Wait for the transaction to finish */
+       while (in_be32(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+               cpu_relax();
+
+       /* Grab the value of the register from miimstat */
+       value = in_be32(&regs->miimstat);
+
+       return value;
+}
+
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ */
+int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+       struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
+
+       /* Write to the local MII regs */
+       return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.
+ */
+int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+       struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
+
+       /* Read the local MII regs */
+       return(fsl_pq_local_mdio_read(regs, mii_id, regnum));
+}
+
+/* Reset the MIIM registers, and wait for the bus to free */
+static int fsl_pq_mdio_reset(struct mii_bus *bus)
+{
+       struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv;
+       unsigned int timeout = PHY_INIT_TIMEOUT;
+
+       mutex_lock(&bus->mdio_lock);
+
+       /* Reset the management interface */
+       out_be32(&regs->miimcfg, MIIMCFG_RESET);
+
+       /* Setup the MII Mgmt clock speed */
+       out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+       /* Wait until the bus is free */
+       while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
+               cpu_relax();
+
+       mutex_unlock(&bus->mdio_lock);
+
+       if(timeout == 0) {
+               printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+                               bus->name);
+               return -EBUSY;
+       }
+
+       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 fsl_pq_mdio_bus_name(char *name, struct device_node *np)
+{
+       const u32 *reg;
+
+       reg = of_get_property(np, "reg", NULL);
+
+       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 fsl_pq_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;
+}
+
+
+#ifdef CONFIG_GIANFAR
+static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
+{
+       struct gfar __iomem *enet_regs;
+
+       /*
+        * This is mildly evil, but so is our hardware for doing this.
+        * Also, we have to cast back to struct gfar because of
+        * definition weirdness done in gianfar.h.
+        */
+       enet_regs = (struct gfar __iomem *)
+               ((char __iomem *)regs - offsetof(struct gfar, gfar_mii_regs));
+
+       return &enet_regs->tbipa;
+}
+#endif
+
+
+#ifdef CONFIG_UCC_GETH
+static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
+{
+       struct device_node *np = NULL;
+       int err = 0;
+
+       for_each_compatible_node(np, NULL, "ucc_geth") {
+               struct resource tempres;
+
+               err = of_address_to_resource(np, 0, &tempres);
+               if (err)
+                       continue;
+
+               /* if our mdio regs fall within this UCC regs range */
+               if ((start >= tempres.start) && (end <= tempres.end)) {
+                       /* Find the id of the UCC */
+                       const u32 *id;
+
+                       id = of_get_property(np, "cell-index", NULL);
+                       if (!id) {
+                               id = of_get_property(np, "device-id", NULL);
+                               if (!id)
+                                       continue;
+                       }
+
+                       *ucc_id = *id;
+
+                       return 0;
+               }
+       }
+
+       if (err)
+               return err;
+       else
+               return -EINVAL;
+}
+#endif
+
+
+static int fsl_pq_mdio_probe(struct of_device *ofdev,
+               const struct of_device_id *match)
+{
+       struct device_node *np = ofdev->node;
+       struct device_node *tbi;
+       struct fsl_pq_mdio __iomem *regs;
+       u32 __iomem *tbipa;
+       struct mii_bus *new_bus;
+       int tbiaddr = -1;
+       u64 addr, size;
+       int err = 0;
+
+       new_bus = mdiobus_alloc();
+       if (NULL == new_bus)
+               return -ENOMEM;
+
+       new_bus->name = "Freescale PowerQUICC MII Bus",
+       new_bus->read = &fsl_pq_mdio_read,
+       new_bus->write = &fsl_pq_mdio_write,
+       new_bus->reset = &fsl_pq_mdio_reset,
+       fsl_pq_mdio_bus_name(new_bus->id, np);
+
+       /* Set the PHY base address */
+       addr = of_translate_address(np, of_get_address(np, 0, &size, NULL));
+       regs = ioremap(addr, size);
+
+       if (NULL == regs) {
+               err = -ENOMEM;
+               goto err_free_bus;
+       }
+
+       new_bus->priv = (void __force *)regs;
+
+       new_bus->irq = create_irq_map(np);
+
+       if (NULL == new_bus->irq) {
+               err = -ENOMEM;
+               goto err_unmap_regs;
+       }
+
+       new_bus->parent = &ofdev->dev;
+       dev_set_drvdata(&ofdev->dev, new_bus);
+
+       if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
+                       of_device_is_compatible(np, "gianfar")) {
+#ifdef CONFIG_GIANFAR
+               tbipa = get_gfar_tbipa(regs);
+#else
+               err = -ENODEV;
+               goto err_free_irqs;
+#endif
+       } else if (of_device_is_compatible(np, "fsl,ucc-mdio") ||
+                       of_device_is_compatible(np, "ucc_geth_phy")) {
+#ifdef CONFIG_UCC_GETH
+               u32 id;
+
+               tbipa = &regs->utbipar;
+
+               if ((err = get_ucc_id_for_range(addr, addr + size, &id)))
+                       goto err_free_irqs;
+
+               ucc_set_qe_mux_mii_mng(id - 1);
+#else
+               err = -ENODEV;
+               goto err_free_irqs;
+#endif
+       } else {
+               err = -ENODEV;
+               goto err_free_irqs;
+       }
+
+       for_each_child_of_node(np, tbi) {
+               if (!strncmp(tbi->type, "tbi-phy", 8))
+                       break;
+       }
+
+       if (tbi) {
+               const u32 *prop = of_get_property(tbi, "reg", NULL);
+
+               if (prop)
+                       tbiaddr = *prop;
+       }
+
+       if (tbiaddr == -1) {
+               out_be32(tbipa, 0);
+
+               tbiaddr = fsl_pq_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 err_free_irqs;
+       }
+
+       out_be32(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 (err) {
+               printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+                               new_bus->name);
+               goto err_free_irqs;
+       }
+
+       return 0;
+
+err_free_irqs:
+       kfree(new_bus->irq);
+err_unmap_regs:
+       iounmap(regs);
+err_free_bus:
+       kfree(new_bus);
+
+       return err;
+}
+
+
+static int fsl_pq_mdio_remove(struct of_device *ofdev)
+{
+       struct device *device = &ofdev->dev;
+       struct mii_bus *bus = dev_get_drvdata(device);
+
+       mdiobus_unregister(bus);
+
+       dev_set_drvdata(device, NULL);
+
+       iounmap((void __iomem *)bus->priv);
+       bus->priv = NULL;
+       mdiobus_free(bus);
+
+       return 0;
+}
+
+static struct of_device_id fsl_pq_mdio_match[] = {
+       {
+               .type = "mdio",
+               .compatible = "ucc_geth_phy",
+       },
+       {
+               .type = "mdio",
+               .compatible = "gianfar",
+       },
+       {
+               .compatible = "fsl,ucc-mdio",
+       },
+       {
+               .compatible = "fsl,gianfar-tbi",
+       },
+       {
+               .compatible = "fsl,gianfar-mdio",
+       },
+       {},
+};
+
+static struct of_platform_driver fsl_pq_mdio_driver = {
+       .name = "fsl-pq_mdio",
+       .probe = fsl_pq_mdio_probe,
+       .remove = fsl_pq_mdio_remove,
+       .match_table = fsl_pq_mdio_match,
+};
+
+int __init fsl_pq_mdio_init(void)
+{
+       return of_register_platform_driver(&fsl_pq_mdio_driver);
+}
+
+void fsl_pq_mdio_exit(void)
+{
+       of_unregister_platform_driver(&fsl_pq_mdio_driver);
+}
+subsys_initcall_sync(fsl_pq_mdio_init);
+module_exit(fsl_pq_mdio_exit);
diff --git a/drivers/net/fsl_pq_mdio.h b/drivers/net/fsl_pq_mdio.h
new file mode 100644 (file)
index 0000000..36dad52
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Freescale PowerQUICC MDIO Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller on Freescale PowerQUICC processors
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __FSL_PQ_MDIO_H
+#define __FSL_PQ_MDIO_H
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+#define MIIMCFG_INIT_VALUE     0x00000007
+#define MIIMCFG_RESET           0x80000000
+
+#define MII_READ_COMMAND       0x00000001
+
+struct fsl_pq_mdio {
+       u32 miimcfg;            /* MII management configuration reg */
+       u32 miimcom;            /* MII management command reg */
+       u32 miimadd;            /* MII management address reg */
+       u32 miimcon;            /* MII management control reg */
+       u32 miimstat;           /* MII management status reg */
+       u32 miimind;            /* MII management indication reg */
+       u8 reserved[28];        /* Space holder */
+       u32 utbipar;            /* TBI phy address reg (only on UCC) */
+} __attribute__ ((packed));
+
+
+int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id,
+                         int regnum, u16 value);
+int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum);
+int __init fsl_pq_mdio_init(void);
+void fsl_pq_mdio_exit(void);
+void fsl_pq_mdio_bus_name(char *name, struct device_node *np);
+#endif /* FSL_PQ_MDIO_H */
index 3f7eab42aef12b14e10c8e874894d3c1b1490093..dadd08cd801b5fdebe4d39be9ef12c0bcac27d58 100644 (file)
@@ -93,7 +93,7 @@
 #include <linux/of.h>
 
 #include "gianfar.h"
-#include "gianfar_mii.h"
+#include "fsl_pq_mdio.h"
 
 #define TX_TIMEOUT      (1*HZ)
 #undef BRIEF_GFAR_ERRORS
@@ -141,8 +141,6 @@ void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
 
-extern const struct ethtool_ops gfar_ethtool_ops;
-
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
 MODULE_LICENSE("GPL");
@@ -166,6 +164,9 @@ static int gfar_of_init(struct net_device *dev)
        struct gfar_private *priv = netdev_priv(dev);
        struct device_node *np = priv->node;
        char bus_name[MII_BUS_ID_SIZE];
+       const u32 *stash;
+       const u32 *stash_len;
+       const u32 *stash_idx;
 
        if (!np || !of_device_is_available(np))
                return -ENODEV;
@@ -195,6 +196,26 @@ static int gfar_of_init(struct net_device *dev)
                }
        }
 
+       stash = of_get_property(np, "bd-stash", NULL);
+
+       if(stash) {
+               priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING;
+               priv->bd_stash_en = 1;
+       }
+
+       stash_len = of_get_property(np, "rx-stash-len", NULL);
+
+       if (stash_len)
+               priv->rx_stash_size = *stash_len;
+
+       stash_idx = of_get_property(np, "rx-stash-idx", NULL);
+
+       if (stash_idx)
+               priv->rx_stash_index = *stash_idx;
+
+       if (stash_len || stash_idx)
+               priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;
+
        mac_addr = of_get_mac_address(np);
        if (mac_addr)
                memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN);
@@ -255,7 +276,7 @@ static int gfar_of_init(struct net_device *dev)
                of_node_put(phy);
                of_node_put(mdio);
 
-               gfar_mdio_bus_name(bus_name, mdio);
+               fsl_pq_mdio_bus_name(bus_name, mdio);
                snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x",
                                bus_name, *id);
        }
@@ -422,7 +443,7 @@ static int gfar_probe(struct of_device *ofdev,
                priv->hash_width = 8;
 
                priv->hash_regs[0] = &priv->regs->gaddr0;
-                priv->hash_regs[1] = &priv->regs->gaddr1;
+               priv->hash_regs[1] = &priv->regs->gaddr1;
                priv->hash_regs[2] = &priv->regs->gaddr2;
                priv->hash_regs[3] = &priv->regs->gaddr3;
                priv->hash_regs[4] = &priv->regs->gaddr4;
@@ -463,6 +484,9 @@ static int gfar_probe(struct of_device *ofdev,
                goto register_fail;
        }
 
+       device_init_wakeup(&dev->dev,
+               priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
        /* fill out IRQ number and name fields */
        len_devname = strlen(dev->name);
        strncpy(&priv->int_name_tx[0], dev->name, len_devname);
@@ -835,7 +859,7 @@ void stop_gfar(struct net_device *dev)
                free_irq(priv->interruptTransmit, dev);
                free_irq(priv->interruptReceive, dev);
        } else {
-               free_irq(priv->interruptTransmit, dev);
+               free_irq(priv->interruptTransmit, dev);
        }
 
        free_skb_resources(priv);
@@ -1180,6 +1204,8 @@ static int gfar_enet_open(struct net_device *dev)
 
        napi_enable(&priv->napi);
 
+       skb_queue_head_init(&priv->rx_recycle);
+
        /* Initialize a bunch of registers */
        init_registers(dev);
 
@@ -1200,6 +1226,8 @@ static int gfar_enet_open(struct net_device *dev)
 
        netif_start_queue(dev);
 
+       device_set_wakeup_enable(&dev->dev, priv->wol_en);
+
        return err;
 }
 
@@ -1396,6 +1424,7 @@ static int gfar_close(struct net_device *dev)
 
        napi_disable(&priv->napi);
 
+       skb_queue_purge(&priv->rx_recycle);
        cancel_work_sync(&priv->reset_task);
        stop_gfar(dev);
 
@@ -1592,7 +1621,17 @@ static int gfar_clean_tx_ring(struct net_device *dev)
                        bdp = next_txbd(bdp, base, tx_ring_size);
                }
 
-               dev_kfree_skb_any(skb);
+               /*
+                * If there's room in the queue (limit it to rx_buffer_size)
+                * we add this skb back into the pool, if it's the right size
+                */
+               if (skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size &&
+                               skb_recycle_check(skb, priv->rx_buffer_size +
+                                       RXBUF_ALIGNMENT))
+                       __skb_queue_head(&priv->rx_recycle, skb);
+               else
+                       dev_kfree_skb_any(skb);
+
                priv->tx_skbuff[skb_dirtytx] = NULL;
 
                skb_dirtytx = (skb_dirtytx + 1) &
@@ -1623,9 +1662,9 @@ static void gfar_schedule_cleanup(struct net_device *dev)
        spin_lock_irqsave(&priv->txlock, flags);
        spin_lock(&priv->rxlock);
 
-       if (netif_rx_schedule_prep(&priv->napi)) {
+       if (napi_schedule_prep(&priv->napi)) {
                gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED);
-               __netif_rx_schedule(&priv->napi);
+               __napi_schedule(&priv->napi);
        }
 
        spin_unlock(&priv->rxlock);
@@ -1665,8 +1704,10 @@ struct sk_buff * gfar_new_skb(struct net_device *dev)
        struct gfar_private *priv = netdev_priv(dev);
        struct sk_buff *skb = NULL;
 
-       /* We have to allocate the skb, so keep trying till we succeed */
-       skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+       skb = __skb_dequeue(&priv->rx_recycle);
+       if (!skb)
+               skb = netdev_alloc_skb(dev,
+                               priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
        if (!skb)
                return NULL;
@@ -1814,7 +1855,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
                        if (unlikely(!newskb))
                                newskb = skb;
                        else if (skb)
-                               dev_kfree_skb_any(skb);
+                               __skb_queue_head(&priv->rx_recycle, skb);
                } else {
                        /* Increment the number of packets */
                        dev->stats.rx_packets++;
@@ -1826,6 +1867,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
                                skb_put(skb, pkt_len);
                                dev->stats.rx_bytes += pkt_len;
 
+                               if (in_irq() || irqs_disabled())
+                                       printk("Interrupt problem!\n");
                                gfar_process_frame(dev, skb, amount_pull);
 
                        } else {
@@ -1882,7 +1925,7 @@ static int gfar_poll(struct napi_struct *napi, int budget)
                return budget;
 
        if (rx_cleaned < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
                /* Clear the halt bit in RSTAT */
                gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
@@ -2299,23 +2342,12 @@ static struct of_platform_driver gfar_driver = {
 
 static int __init gfar_init(void)
 {
-       int err = gfar_mdio_init();
-
-       if (err)
-               return err;
-
-       err = of_register_platform_driver(&gfar_driver);
-
-       if (err)
-               gfar_mdio_exit();
-
-       return err;
+       return of_register_platform_driver(&gfar_driver);
 }
 
 static void __exit gfar_exit(void)
 {
        of_unregister_platform_driver(&gfar_driver);
-       gfar_mdio_exit();
 }
 
 module_init(gfar_init);
index b1a83344acc75de952a5b4ed3345448595875d33..811855bc42312607e5545b0de1b1e995bd7a1369 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/workqueue.h>
 #include <linux/ethtool.h>
 #include <linux/fsl_devices.h>
-#include "gianfar_mii.h"
 
 /* The maximum number of packets to be handled in one call of gfar_poll */
 #define GFAR_DEV_WEIGHT 64
@@ -126,9 +125,12 @@ extern const char gfar_driver_version[];
 #define DEFAULT_RX_COALESCE 0
 #define DEFAULT_RXCOUNT        0
 
-#define MIIMCFG_INIT_VALUE     0x00000007
-#define MIIMCFG_RESET           0x80000000
-#define MIIMIND_BUSY            0x00000001
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+               | SUPPORTED_10baseT_Full \
+               | SUPPORTED_100baseT_Half \
+               | SUPPORTED_100baseT_Full \
+               | SUPPORTED_Autoneg \
+               | SUPPORTED_MII)
 
 /* TBI register addresses */
 #define MII_TBICON             0x11
@@ -756,6 +758,8 @@ struct gfar_private {
        unsigned int rx_stash_size;
        unsigned int rx_stash_index;
 
+       struct sk_buff_head rx_recycle;
+
        struct vlan_group *vlgrp;
 
        /* Unprotected fields */
@@ -826,8 +830,7 @@ extern void gfar_halt(struct net_device *dev);
 extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
                int enable, u32 regnum, u32 read);
 void gfar_init_sysfs(struct net_device *dev);
-int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
-                         int regnum, u16 value);
-int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
+
+extern const struct ethtool_ops gfar_ethtool_ops;
 
 #endif /* __GIANFAR_H */
index 59b3b5d98efe5bcc746e687b766301e5c6b52720..dbf06e9313cc27750362aa59ab6bb779051f81b8 100644 (file)
@@ -600,6 +600,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 
        spin_lock_irqsave(&priv->bflock, flags);
        priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+       device_set_wakeup_enable(&dev->dev, priv->wol_en);
        spin_unlock_irqrestore(&priv->bflock, flags);
 
        return 0;
index f49a426ad681c1996f7675f8e993eb784e4981af..64e4679b3279e8f93e65265c5e709cbc7c5c92f5 100644 (file)
@@ -105,7 +105,7 @@ int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum)
  * All PHY configuration is done through the TSEC1 MIIM regs */
 int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
 {
-       struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+       struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv;
 
        /* Write to the local MII regs */
        return(gfar_local_mdio_write(regs, mii_id, regnum, value));
@@ -116,7 +116,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
  * configuration has to be done through the TSEC1 MIIM regs */
 int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
-       struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+       struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv;
 
        /* Read the local MII regs */
        return(gfar_local_mdio_read(regs, mii_id, regnum));
@@ -125,7 +125,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 /* Reset the MIIM registers, and wait for the bus to free */
 static int gfar_mdio_reset(struct mii_bus *bus)
 {
-       struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+       struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv;
        unsigned int timeout = PHY_INIT_TIMEOUT;
 
        mutex_lock(&bus->mdio_lock);
@@ -268,8 +268,8 @@ static int gfar_mdio_probe(struct of_device *ofdev,
         * Also, we have to cast back to struct gfar_mii because of
         * definition weirdness done in gianfar.h.
         */
-       enet_regs = (struct gfar __iomem *)
-               ((char *)regs - offsetof(struct gfar, gfar_mii_regs));
+       enet_regs = (struct gfar __force __iomem *)
+               ((char __force *)regs - offsetof(struct gfar, gfar_mii_regs));
 
        for_each_child_of_node(np, tbi) {
                if (!strncmp(tbi->type, "tbi-phy", 8))
@@ -337,7 +337,7 @@ static int gfar_mdio_remove(struct of_device *ofdev)
 
        dev_set_drvdata(&ofdev->dev, NULL);
 
-       iounmap((void __iomem *)bus->priv);
+       iounmap((void __force __iomem *)bus->priv);
        bus->priv = NULL;
        kfree(bus->irq);
        mdiobus_free(bus);
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
deleted file mode 100644 (file)
index 65c242c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * drivers/net/gianfar_mii.h
- *
- * Gianfar Ethernet Driver -- MII Management Bus Implementation
- * Driver for the MDIO bus controller in the Gianfar register space
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#ifndef __GIANFAR_MII_H
-#define __GIANFAR_MII_H
-
-struct gfar_private; /* forward ref */
-
-#define MIIMIND_BUSY            0x00000001
-#define MIIMIND_NOTVALID        0x00000004
-
-#define MII_READ_COMMAND       0x00000001
-
-#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
-               | SUPPORTED_10baseT_Full \
-               | SUPPORTED_100baseT_Half \
-               | SUPPORTED_100baseT_Full \
-               | SUPPORTED_Autoneg \
-               | SUPPORTED_MII)
-
-struct gfar_mii {
-       u32     miimcfg;        /* 0x.520 - MII Management Config Register */
-       u32     miimcom;        /* 0x.524 - MII Management Command Register */
-       u32     miimadd;        /* 0x.528 - MII Management Address Register */
-       u32     miimcon;        /* 0x.52c - MII Management Control Register */
-       u32     miimstat;       /* 0x.530 - MII Management Status Register */
-       u32     miimind;        /* 0x.534 - MII Management Indicator Register */
-};
-
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
-int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
-                         int regnum, u16 value);
-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 */
index 782c201700820c45abb1cddfd1dba606ba6c38ae..dd26da74f27a0e0ba808bdbb5c42c89dec3cbf65 100644 (file)
@@ -53,6 +53,9 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
        u32 temp;
        unsigned long flags;
 
+       if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
+               return count;
+
        /* Find out the new setting */
        if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
                new_setting = 1;
@@ -81,7 +84,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
        return count;
 }
 
-DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
+static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
 
 static ssize_t gfar_show_rx_stash_size(struct device *dev,
                                       struct device_attribute *attr, char *buf)
@@ -100,6 +103,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
        u32 temp;
        unsigned long flags;
 
+       if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
+               return count;
+
        spin_lock_irqsave(&priv->rxlock, flags);
        if (length > priv->rx_buffer_size)
                goto out;
@@ -130,8 +136,8 @@ out:
        return count;
 }
 
-DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
-           gfar_set_rx_stash_size);
+static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
+                  gfar_set_rx_stash_size);
 
 /* Stashing will only be enabled when rx_stash_size != 0 */
 static ssize_t gfar_show_rx_stash_index(struct device *dev,
@@ -152,6 +158,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
        u32 temp;
        unsigned long flags;
 
+       if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
+               return count;
+
        spin_lock_irqsave(&priv->rxlock, flags);
        if (index > priv->rx_stash_size)
                goto out;
@@ -172,8 +181,8 @@ out:
        return count;
 }
 
-DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
-           gfar_set_rx_stash_index);
+static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
+                  gfar_set_rx_stash_index);
 
 static ssize_t gfar_show_fifo_threshold(struct device *dev,
                                        struct device_attribute *attr,
@@ -210,8 +219,8 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
        return count;
 }
 
-DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
-           gfar_set_fifo_threshold);
+static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
+                  gfar_set_fifo_threshold);
 
 static ssize_t gfar_show_fifo_starve(struct device *dev,
                                     struct device_attribute *attr, char *buf)
@@ -247,7 +256,8 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
        return count;
 }
 
-DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, gfar_set_fifo_starve);
+static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve,
+                  gfar_set_fifo_starve);
 
 static ssize_t gfar_show_fifo_starve_off(struct device *dev,
                                         struct device_attribute *attr,
@@ -284,8 +294,8 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
        return count;
 }
 
-DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
-           gfar_set_fifo_starve_off);
+static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
+                  gfar_set_fifo_starve_off);
 
 void gfar_init_sysfs(struct net_device *dev)
 {
@@ -293,12 +303,9 @@ void gfar_init_sysfs(struct net_device *dev)
        int rc;
 
        /* Initialize the default values */
-       priv->rx_stash_size = DEFAULT_STASH_LENGTH;
-       priv->rx_stash_index = DEFAULT_STASH_INDEX;
        priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
        priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
        priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
-       priv->bd_stash_en = DEFAULT_BD_STASH;
 
        /* Create our sysfs files */
        rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
index 7e8b3c59a7d6ca1f2613e2d3028b3f3b18f7d952..455641f8677e6be6e523b2f7b2230b34662d6d59 100644 (file)
@@ -1244,7 +1244,7 @@ do { \
     csum_add(sum, (ih)->saddr & 0xffff); \
     csum_add(sum, (ih)->daddr >> 16); \
     csum_add(sum, (ih)->daddr & 0xffff); \
-    csum_add(sum, __constant_htons(IPPROTO_UDP)); \
+    csum_add(sum, cpu_to_be16(IPPROTO_UDP)); \
     csum_add(sum, (uh)->len); \
 } while (0)
 
@@ -1255,7 +1255,7 @@ do { \
     csum_add(sum, (ih)->saddr & 0xffff); \
     csum_add(sum, (ih)->daddr >> 16); \
     csum_add(sum, (ih)->daddr & 0xffff); \
-    csum_add(sum, __constant_htons(IPPROTO_TCP)); \
+    csum_add(sum, cpu_to_be16(IPPROTO_TCP)); \
     csum_add(sum, htons(len)); \
 } while (0)
 #endif
@@ -1296,7 +1296,7 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
            /* tack on checksum tag */
            u32 tagval = 0;
            struct ethhdr *eh = (struct ethhdr *)skb->data;
-           if (eh->h_proto == __constant_htons(ETH_P_IP)) {
+           if (eh->h_proto == cpu_to_be16(ETH_P_IP)) {
                struct iphdr *ih = (struct iphdr *)((char *)eh + ETH_HLEN);
                if (ih->protocol == IPPROTO_UDP) {
                    struct udphdr *uh
@@ -1605,7 +1605,7 @@ static int hamachi_rx(struct net_device *dev)
                                 */
                                if (ntohs(ih->tot_len) >= 46){
                                        /* don't worry about frags */
-                                       if (!(ih->frag_off & __constant_htons(IP_MF|IP_OFFSET))) {
+                                       if (!(ih->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) {
                                                u32 inv = *(u32 *) &buf_addr[data_size - 16];
                                                u32 *p = (u32 *) &buf_addr[data_size - 20];
                                                register u32 crc, p_r, p_r1;
index 2d4089894ec7b13c61f7626c95b8fa991ca104a5..3da9f394b4c6d6616868d53ad3e8f6d528c7905a 100644 (file)
@@ -322,23 +322,25 @@ static const struct header_ops sp_header_ops = {
        .rebuild        = sp_rebuild_header,
 };
 
+static const struct net_device_ops sp_netdev_ops = {
+       .ndo_open               = sp_open_dev,
+       .ndo_stop               = sp_close,
+       .ndo_start_xmit         = sp_xmit,
+       .ndo_set_mac_address    = sp_set_mac_address,
+};
+
 static void sp_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
-       dev->mtu                = SIXP_MTU;
-       dev->hard_start_xmit    = sp_xmit;
-       dev->open               = sp_open_dev;
+       dev->netdev_ops         = &sp_netdev_ops;
        dev->destructor         = free_netdev;
-       dev->stop               = sp_close;
-
-       dev->set_mac_address    = sp_set_mac_address;
+       dev->mtu                = SIXP_MTU;
        dev->hard_header_len    = AX25_MAX_HEADER_LEN;
        dev->header_ops         = &sp_header_ops;
 
        dev->addr_len           = AX25_ADDR_LEN;
        dev->type               = ARPHRD_AX25;
        dev->tx_queue_len       = 10;
-       dev->tx_timeout         = NULL;
 
        /* Only activated in AX.25 mode */
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
index 81a65e3a1c053fe070e9a3c8985ef6f909439801..bb78c11559cd2cd9cb0876cbe2630816b539aea3 100644 (file)
@@ -203,7 +203,6 @@ struct baycom_state {
                unsigned char buf[TXBUFFER_SIZE];
         } hdlctx;
 
-        struct net_device_stats stats;
        unsigned int ptt_keyed;
        struct sk_buff *skb;  /* next transmit packet  */
 
@@ -423,7 +422,7 @@ static void encode_hdlc(struct baycom_state *bc)
        bc->hdlctx.bufptr = bc->hdlctx.buf;
        bc->hdlctx.bufcnt = wp - bc->hdlctx.buf;
        dev_kfree_skb(skb);
-       bc->stats.tx_packets++;
+       bc->dev->stats.tx_packets++;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -547,7 +546,7 @@ static void do_rxpacket(struct net_device *dev)
        pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */
        if (!(skb = dev_alloc_skb(pktlen))) {
                printk("%s: memory squeeze, dropping packet\n", dev->name);
-               bc->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        cp = skb_put(skb, pktlen);
@@ -555,7 +554,7 @@ 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);
-       bc->stats.rx_packets++;
+       dev->stats.rx_packets++;
 }
 
 static int receive(struct net_device *dev, int cnt)
@@ -802,19 +801,6 @@ static int baycom_set_mac_address(struct net_device *dev, void *addr)
 
 /* --------------------------------------------------------------------- */
 
-static struct net_device_stats *baycom_get_stats(struct net_device *dev)
-{
-       struct baycom_state *bc = netdev_priv(dev);
-
-       /* 
-        * Get the current statistics.  This may be called with the
-        * card open or closed. 
-        */
-       return &bc->stats;
-}
-
-/* --------------------------------------------------------------------- */
-
 static void epp_wakeup(void *handle)
 {
         struct net_device *dev = (struct net_device *)handle;
@@ -1065,10 +1051,10 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                hi.data.cs.ptt = !!(bc->stat & EPP_PTTBIT);
                hi.data.cs.dcd = !(bc->stat & EPP_DCDBIT);
                hi.data.cs.ptt_keyed = bc->ptt_keyed;
-               hi.data.cs.tx_packets = bc->stats.tx_packets;
-               hi.data.cs.tx_errors = bc->stats.tx_errors;
-               hi.data.cs.rx_packets = bc->stats.rx_packets;
-               hi.data.cs.rx_errors = bc->stats.rx_errors;
+               hi.data.cs.tx_packets = dev->stats.tx_packets;
+               hi.data.cs.tx_errors = dev->stats.tx_errors;
+               hi.data.cs.rx_packets = dev->stats.rx_packets;
+               hi.data.cs.rx_errors = dev->stats.rx_errors;
                break;          
 
        case HDLCDRVCTL_OLDGETSTAT:
@@ -1116,6 +1102,14 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 /* --------------------------------------------------------------------- */
 
+static const struct net_device_ops baycom_netdev_ops = {
+       .ndo_open            = epp_open,
+       .ndo_stop            = epp_close,
+       .ndo_do_ioctl        = baycom_ioctl,
+       .ndo_start_xmit      = baycom_send_packet,
+       .ndo_set_mac_address = baycom_set_mac_address,
+};
+
 /*
  * Check for a network adaptor of this type, and return '0' if one exists.
  * If dev->base_addr == 0, probe all likely locations.
@@ -1143,17 +1137,12 @@ static void baycom_probe(struct net_device *dev)
        /*
         * initialize the device struct
         */
-       dev->open = epp_open;
-       dev->stop = epp_close;
-       dev->do_ioctl = baycom_ioctl;
-       dev->hard_start_xmit = baycom_send_packet;
-       dev->get_stats = baycom_get_stats;
 
        /* Fill in the fields of the device structure */
        bc->skb = NULL;
        
+       dev->netdev_ops = &baycom_netdev_ops;
        dev->header_ops = &ax25_header_ops;
-       dev->set_mac_address = baycom_set_mac_address;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
index 46f8f3390e7d1806c038f791f0f103c744c09830..2c619bc99ae79fc9ea58ff565a7751fccd5032c0 100644 (file)
@@ -97,7 +97,7 @@ static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
 static int bpq_device_event(struct notifier_block *, unsigned long, void *);
 
 static struct packet_type bpq_packet_type = {
-       .type   = __constant_htons(ETH_P_BPQ),
+       .type   = cpu_to_be16(ETH_P_BPQ),
        .func   = bpq_rcv,
 };
 
@@ -110,7 +110,6 @@ struct bpqdev {
        struct list_head bpq_list;      /* list of bpq devices chain */
        struct net_device *ethdev;      /* link to ethernet device */
        struct net_device *axdev;       /* bpq device (bpq#) */
-       struct net_device_stats stats;  /* some statistics */
        char   dest_addr[6];            /* ether destination address */
        char   acpt_addr[6];            /* accept ether frames from this address only */
 };
@@ -222,8 +221,8 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        skb_pull(skb, 2);       /* Remove the length bytes */
        skb_trim(skb, len);     /* Set the length of the data */
 
-       bpq->stats.rx_packets++;
-       bpq->stats.rx_bytes += len;
+       dev->stats.rx_packets++;
+       dev->stats.rx_bytes += len;
 
        ptr = skb_push(skb, 1);
        *ptr = 0;
@@ -292,7 +291,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
        bpq = netdev_priv(dev);
 
        if ((dev = bpq_get_ether_dev(dev)) == NULL) {
-               bpq->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                kfree_skb(skb);
                return -ENODEV;
        }
@@ -300,24 +299,14 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
        skb->protocol = ax25_type_trans(skb, dev);
        skb_reset_network_header(skb);
        dev_hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
-       bpq->stats.tx_packets++;
-       bpq->stats.tx_bytes+=skb->len;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes+=skb->len;
   
        dev_queue_xmit(skb);
        netif_wake_queue(dev);
        return 0;
 }
 
-/*
- *     Statistics
- */
-static struct net_device_stats *bpq_get_stats(struct net_device *dev)
-{
-       struct bpqdev *bpq = netdev_priv(dev);
-
-       return &bpq->stats;
-}
-
 /*
  *     Set AX.25 callsign
  */
@@ -454,7 +443,7 @@ static int bpq_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations bpq_seqops = {
+static const struct seq_operations bpq_seqops = {
        .start = bpq_seq_start,
        .next = bpq_seq_next,
        .stop = bpq_seq_stop,
@@ -477,16 +466,17 @@ static const struct file_operations bpq_info_fops = {
 
 /* ------------------------------------------------------------------------ */
 
+static const struct net_device_ops bpq_netdev_ops = {
+       .ndo_open            = bpq_open,
+       .ndo_stop            = bpq_close,
+       .ndo_start_xmit      = bpq_xmit,
+       .ndo_set_mac_address = bpq_set_mac_address,
+       .ndo_do_ioctl        = bpq_ioctl,
+};
 
 static void bpq_setup(struct net_device *dev)
 {
-
-       dev->hard_start_xmit = bpq_xmit;
-       dev->open            = bpq_open;
-       dev->stop            = bpq_close;
-       dev->set_mac_address = bpq_set_mac_address;
-       dev->get_stats       = bpq_get_stats;
-       dev->do_ioctl        = bpq_ioctl;
+       dev->netdev_ops      = &bpq_netdev_ops;
        dev->destructor      = free_netdev;
 
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
index e67103396ed7649b32a331e7f4d9fc341f6dc206..881bf818bb48aac8a71672b4cd2677b2588613a4 100644 (file)
@@ -195,7 +195,7 @@ struct scc_priv {
        int chip;
        struct net_device *dev;
        struct scc_info *info;
-       struct net_device_stats stats;
+
        int channel;
        int card_base, scc_cmd, scc_data;
        int tmr_cnt, tmr_ctrl, tmr_mode;
@@ -239,7 +239,6 @@ static int scc_open(struct net_device *dev);
 static int scc_close(struct net_device *dev);
 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);
-static struct net_device_stats *scc_get_stats(struct net_device *dev);
 static int scc_set_mac_address(struct net_device *dev, void *sa);
 
 static inline void tx_on(struct scc_priv *priv);
@@ -441,6 +440,13 @@ static void __init dev_setup(struct net_device *dev)
        memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 }
 
+static const struct net_device_ops scc_netdev_ops = {
+       .ndo_open = scc_open,
+       .ndo_stop = scc_close,
+       .ndo_start_xmit = scc_send_packet,
+       .ndo_do_ioctl = scc_ioctl,
+};
+
 static int __init setup_adapter(int card_base, int type, int n)
 {
        int i, irq, chip;
@@ -576,11 +582,7 @@ static int __init setup_adapter(int card_base, int type, int n)
                sprintf(dev->name, "dmascc%i", 2 * n + i);
                dev->base_addr = card_base;
                dev->irq = irq;
-               dev->open = scc_open;
-               dev->stop = scc_close;
-               dev->do_ioctl = scc_ioctl;
-               dev->hard_start_xmit = scc_send_packet;
-               dev->get_stats = scc_get_stats;
+               dev->netdev_ops = &scc_netdev_ops;
                dev->header_ops = &ax25_header_ops;
                dev->set_mac_address = scc_set_mac_address;
        }
@@ -961,14 +963,6 @@ 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->ml_priv;
-
-       return &priv->stats;
-}
-
-
 static int scc_set_mac_address(struct net_device *dev, void *sa)
 {
        memcpy(dev->dev_addr, ((struct sockaddr *) sa)->sa_data,
@@ -1216,17 +1210,17 @@ static void special_condition(struct scc_priv *priv, int rc)
                }
                if (priv->rx_over) {
                        /* We had an overrun */
-                       priv->stats.rx_errors++;
+                       priv->dev->stats.rx_errors++;
                        if (priv->rx_over == 2)
-                               priv->stats.rx_length_errors++;
+                               priv->dev->stats.rx_length_errors++;
                        else
-                               priv->stats.rx_fifo_errors++;
+                               priv->dev->stats.rx_fifo_errors++;
                        priv->rx_over = 0;
                } else if (rc & CRC_ERR) {
                        /* Count invalid CRC only if packet length >= minimum */
                        if (cb >= 15) {
-                               priv->stats.rx_errors++;
-                               priv->stats.rx_crc_errors++;
+                               priv->dev->stats.rx_errors++;
+                               priv->dev->stats.rx_crc_errors++;
                        }
                } else {
                        if (cb >= 15) {
@@ -1239,8 +1233,8 @@ static void special_condition(struct scc_priv *priv, int rc)
                                        priv->rx_count++;
                                        schedule_work(&priv->rx_work);
                                } else {
-                                       priv->stats.rx_errors++;
-                                       priv->stats.rx_over_errors++;
+                                       priv->dev->stats.rx_errors++;
+                                       priv->dev->stats.rx_over_errors++;
                                }
                        }
                }
@@ -1275,7 +1269,7 @@ static void rx_bh(struct work_struct *ugli_api)
                skb = dev_alloc_skb(cb + 1);
                if (skb == NULL) {
                        /* Drop packet */
-                       priv->stats.rx_dropped++;
+                       priv->dev->stats.rx_dropped++;
                } else {
                        /* Fill buffer */
                        data = skb_put(skb, cb + 1);
@@ -1283,8 +1277,8 @@ 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->stats.rx_packets++;
-                       priv->stats.rx_bytes += cb;
+                       priv->dev->stats.rx_packets++;
+                       priv->dev->stats.rx_bytes += cb;
                }
                spin_lock_irqsave(&priv->ring_lock, flags);
                /* Move tail */
@@ -1351,15 +1345,15 @@ static void es_isr(struct scc_priv *priv)
                        write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
                if (res) {
                        /* Update packet statistics */
-                       priv->stats.tx_errors++;
-                       priv->stats.tx_fifo_errors++;
+                       priv->dev->stats.tx_errors++;
+                       priv->dev->stats.tx_fifo_errors++;
                        /* Other underrun interrupts may already be waiting */
                        write_scc(priv, R0, RES_EXT_INT);
                        write_scc(priv, R0, RES_EXT_INT);
                } else {
                        /* Update packet statistics */
-                       priv->stats.tx_packets++;
-                       priv->stats.tx_bytes += priv->tx_len[i];
+                       priv->dev->stats.tx_packets++;
+                       priv->dev->stats.tx_bytes += priv->tx_len[i];
                        /* Remove frame from FIFO */
                        priv->tx_tail = (i + 1) % NUM_TX_BUF;
                        priv->tx_count--;
@@ -1425,7 +1419,7 @@ static void tm_isr(struct scc_priv *priv)
                write_scc(priv, R15, DCDIE);
                priv->rr0 = read_scc(priv, R0);
                if (priv->rr0 & DCD) {
-                       priv->stats.collisions++;
+                       priv->dev->stats.collisions++;
                        rx_on(priv);
                        priv->state = RX_ON;
                } else {
index 8eba61a1d4abc3ff7365b08d33f4d70c2d368819..61de56e45eedb509bc33bca2ed120b4868ab5c7f 100644 (file)
@@ -154,7 +154,7 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
        pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */
        if (!(skb = dev_alloc_skb(pkt_len))) {
                printk("%s: memory squeeze, dropping packet\n", dev->name);
-               s->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                return;
        }
        cp = skb_put(skb, pkt_len);
@@ -162,7 +162,7 @@ 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);
-       s->stats.rx_packets++;
+       dev->stats.rx_packets++;
 }
 
 void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)
@@ -326,7 +326,7 @@ void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)
                        s->hdlctx.len = pkt_len+2; /* the appended CRC */
                        s->hdlctx.tx_state = 2;
                        s->hdlctx.bitstream = 0;
-                       s->stats.tx_packets++;
+                       dev->stats.tx_packets++;
                        break;
                case 2:
                        if (!s->hdlctx.len) {
@@ -426,19 +426,6 @@ static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)
        return 0;                                         
 }
 
-/* --------------------------------------------------------------------- */
-
-static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
-{
-       struct hdlcdrv_state *sm = netdev_priv(dev);
-
-       /* 
-        * Get the current statistics.  This may be called with the
-        * card open or closed. 
-        */
-       return &sm->stats;
-}
-
 /* --------------------------------------------------------------------- */
 /*
  * Open/initialize the board. This is called (in the current kernel)
@@ -568,10 +555,10 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                bi.data.cs.ptt = hdlcdrv_ptt(s);
                bi.data.cs.dcd = s->hdlcrx.dcd;
                bi.data.cs.ptt_keyed = s->ptt_keyed;
-               bi.data.cs.tx_packets = s->stats.tx_packets;
-               bi.data.cs.tx_errors = s->stats.tx_errors;
-               bi.data.cs.rx_packets = s->stats.rx_packets;
-               bi.data.cs.rx_errors = s->stats.rx_errors;
+               bi.data.cs.tx_packets = dev->stats.tx_packets;
+               bi.data.cs.tx_errors = dev->stats.tx_errors;
+               bi.data.cs.rx_packets = dev->stats.rx_packets;
+               bi.data.cs.rx_errors = dev->stats.rx_errors;
                break;          
 
        case HDLCDRVCTL_OLDGETSTAT:
@@ -630,6 +617,14 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 /* --------------------------------------------------------------------- */
 
+static const struct net_device_ops hdlcdrv_netdev = {
+       .ndo_open       = hdlcdrv_open,
+       .ndo_stop       = hdlcdrv_close,
+       .ndo_start_xmit = hdlcdrv_send_packet,
+       .ndo_do_ioctl   = hdlcdrv_ioctl,
+       .ndo_set_mac_address = hdlcdrv_set_mac_address,
+};
+
 /*
  * Initialize fields in hdlcdrv
  */
@@ -669,21 +664,13 @@ static void hdlcdrv_setup(struct net_device *dev)
        s->bitbuf_hdlc.shreg = 0x80;
 #endif /* HDLCDRV_DEBUG */
 
-       /*
-        * initialize the device struct
-        */
-       dev->open = hdlcdrv_open;
-       dev->stop = hdlcdrv_close;
-       dev->do_ioctl = hdlcdrv_ioctl;
-       dev->hard_start_xmit = hdlcdrv_send_packet;
-       dev->get_stats = hdlcdrv_get_stats;
 
        /* Fill in the fields of the device structure */
 
        s->skb = NULL;
        
+       dev->netdev_ops = &hdlcdrv_netdev;
        dev->header_ops = &ax25_header_ops;
-       dev->set_mac_address = hdlcdrv_set_mac_address;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
index bbdb311b8420c6cd500a60d8293132d7e67b3059..ed5b37d43334577ad76c728805a7cf722cf0aacf 100644 (file)
@@ -59,8 +59,6 @@ struct mkiss {
        unsigned char           *xhead; /* pointer to next byte to XMIT */
        int                     xleft;  /* bytes left in XMIT queue     */
 
-       struct net_device_stats stats;
-
        /* Detailed SLIP statistics. */
        int             mtu;            /* Our mtu (to spot changes!)   */
        int             buffsize;       /* Max buffers sizes            */
@@ -253,7 +251,7 @@ static void ax_bump(struct mkiss *ax)
        if (ax->rbuff[0] > 0x0f) {
                if (ax->rbuff[0] & 0x80) {
                        if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                                spin_unlock_bh(&ax->buflock);
 
                                return;
@@ -268,7 +266,7 @@ static void ax_bump(struct mkiss *ax)
                        *ax->rbuff &= ~0x80;
                } else if (ax->rbuff[0] & 0x20)  {
                        if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                                spin_unlock_bh(&ax->buflock);
                                return;
                        }
@@ -295,7 +293,7 @@ static void ax_bump(struct mkiss *ax)
        if ((skb = dev_alloc_skb(count)) == NULL) {
                printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
                       ax->dev->name);
-               ax->stats.rx_dropped++;
+               ax->dev->stats.rx_dropped++;
                spin_unlock_bh(&ax->buflock);
                return;
        }
@@ -303,8 +301,8 @@ 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->stats.rx_packets++;
-       ax->stats.rx_bytes += count;
+       ax->dev->stats.rx_packets++;
+       ax->dev->stats.rx_bytes += count;
        spin_unlock_bh(&ax->buflock);
 }
 
@@ -344,7 +342,7 @@ static void kiss_unesc(struct mkiss *ax, unsigned char s)
                        return;
                }
 
-               ax->stats.rx_over_errors++;
+               ax->dev->stats.rx_over_errors++;
                set_bit(AXF_ERROR, &ax->flags);
        }
        spin_unlock_bh(&ax->buflock);
@@ -406,7 +404,7 @@ static void ax_changedmtu(struct mkiss *ax)
                        memcpy(ax->xbuff, ax->xhead, ax->xleft);
                } else  {
                        ax->xleft = 0;
-                       ax->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                }
        }
 
@@ -417,7 +415,7 @@ static void ax_changedmtu(struct mkiss *ax)
                        memcpy(ax->rbuff, orbuff, ax->rcount);
                } else  {
                        ax->rcount = 0;
-                       ax->stats.rx_over_errors++;
+                       dev->stats.rx_over_errors++;
                        set_bit(AXF_ERROR, &ax->flags);
                }
        }
@@ -444,7 +442,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
        if (len > ax->mtu) {            /* Sigh, shouldn't occur BUT ... */
                len = ax->mtu;
                printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
-               ax->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                netif_start_queue(dev);
                return;
        }
@@ -518,8 +516,8 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
 
        set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
        actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
-       ax->stats.tx_packets++;
-       ax->stats.tx_bytes += actual;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += actual;
 
        ax->dev->trans_start = jiffies;
        ax->xleft = count - actual;
@@ -664,32 +662,28 @@ static int ax_close(struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *ax_get_stats(struct net_device *dev)
-{
-       struct mkiss *ax = netdev_priv(dev);
-
-       return &ax->stats;
-}
-
 static const struct header_ops ax_header_ops = {
        .create    = ax_header,
        .rebuild   = ax_rebuild_header,
 };
 
+static const struct net_device_ops ax_netdev_ops = {
+       .ndo_open            = ax_open_dev,
+       .ndo_stop            = ax_close,
+       .ndo_start_xmit      = ax_xmit,
+       .ndo_set_mac_address = ax_set_mac_address,
+};
+
 static void ax_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
        dev->mtu             = AX_MTU;
-       dev->hard_start_xmit = ax_xmit;
-       dev->open            = ax_open_dev;
-       dev->stop            = ax_close;
-       dev->get_stats       = ax_get_stats;
-       dev->set_mac_address = ax_set_mac_address;
        dev->hard_header_len = 0;
        dev->addr_len        = 0;
        dev->type            = ARPHRD_AX25;
        dev->tx_queue_len    = 10;
        dev->header_ops      = &ax_header_ops;
+       dev->netdev_ops      = &ax_netdev_ops;
 
 
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
@@ -929,7 +923,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        while (count--) {
                if (fp != NULL && *fp++) {
                        if (!test_and_set_bit(AXF_ERROR, &ax->flags))
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                        cp++;
                        continue;
                }
index c011af7088ea41cfb06325c02b6847addafed2bd..2acb18f0697298d22a8be3ef8d6313a4f5f7ec64 100644 (file)
@@ -1542,23 +1542,24 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
 /* *                       Network driver methods                    * */
 /* ******************************************************************** */
 
+static const struct net_device_ops scc_netdev_ops = {
+       .ndo_open            = scc_net_open,
+       .ndo_stop            = scc_net_close,
+       .ndo_start_xmit      = scc_net_tx,
+       .ndo_set_mac_address = scc_net_set_mac_address,
+       .ndo_get_stats       = scc_net_get_stats,
+       .ndo_do_ioctl        = scc_net_ioctl,
+};
+
 /* ----> Initialize device <----- */
 
 static void scc_net_setup(struct net_device *dev)
 {
        dev->tx_queue_len    = 16;      /* should be enough... */
 
-       dev->open            = scc_net_open;
-       dev->stop            = scc_net_close;
-
-       dev->hard_start_xmit = scc_net_tx;
+       dev->netdev_ops      = &scc_netdev_ops;
        dev->header_ops      = &ax25_header_ops;
 
-       dev->set_mac_address = scc_net_set_mac_address;
-       dev->get_stats       = scc_net_get_stats;
-       dev->do_ioctl        = scc_net_ioctl;
-       dev->tx_timeout      = NULL;
-
        memcpy(dev->broadcast, &ax25_bcast,  AX25_ADDR_LEN);
        memcpy(dev->dev_addr,  &ax25_defaddr, AX25_ADDR_LEN);
  
@@ -2073,7 +2074,7 @@ static int scc_net_seq_show(struct seq_file *seq, void *v)
         return 0;
 }
 
-static struct seq_operations scc_net_seq_ops = {
+static const struct seq_operations scc_net_seq_ops = {
        .start  = scc_net_seq_start,
        .next   = scc_net_seq_next,
        .stop   = scc_net_seq_stop,
index 5407f7486c9c00cdc310962e237284897eac9113..82a8be7613d63a92381d5ef5e87166902dd7492d 100644 (file)
@@ -115,10 +115,6 @@ struct yam_port {
 
        struct net_device *dev;
 
-       /* Stats section */
-
-       struct net_device_stats stats;
-
        int nb_rxint;
        int nb_mdint;
 
@@ -507,7 +503,7 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)
                } else {
                        if (!(skb = dev_alloc_skb(pkt_len))) {
                                printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);
-                               ++yp->stats.rx_dropped;
+                               ++dev->stats.rx_dropped;
                        } else {
                                unsigned char *cp;
                                cp = skb_put(skb, pkt_len);
@@ -515,7 +511,7 @@ 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);
-                               ++yp->stats.rx_packets;
+                               ++dev->stats.rx_packets;
                        }
                }
        }
@@ -677,7 +673,7 @@ static void yam_tx_byte(struct net_device *dev, struct yam_port *yp)
                        yp->tx_count = 1;
                        yp->tx_state = TX_HEAD;
                }
-               ++yp->stats.tx_packets;
+               ++dev->stats.tx_packets;
                break;
        case TX_TAIL:
                if (--yp->tx_count <= 0) {
@@ -716,7 +712,7 @@ static irqreturn_t yam_interrupt(int irq, void *dev_id)
                        handled = 1;
 
                        if (lsr & LSR_OE)
-                               ++yp->stats.rx_fifo_errors;
+                               ++dev->stats.rx_fifo_errors;
 
                        yp->dcd = (msr & RX_DCD) ? 1 : 0;
 
@@ -778,16 +774,16 @@ static int yam_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "  TxTail   %u\n", yp->txtail);
        seq_printf(seq, "  SlotTime %u\n", yp->slot);
        seq_printf(seq, "  Persist  %u\n", yp->pers);
-       seq_printf(seq, "  TxFrames %lu\n", yp->stats.tx_packets);
-       seq_printf(seq, "  RxFrames %lu\n", yp->stats.rx_packets);
+       seq_printf(seq, "  TxFrames %lu\n", dev->stats.tx_packets);
+       seq_printf(seq, "  RxFrames %lu\n", dev->stats.rx_packets);
        seq_printf(seq, "  TxInt    %u\n", yp->nb_mdint);
        seq_printf(seq, "  RxInt    %u\n", yp->nb_rxint);
-       seq_printf(seq, "  RxOver   %lu\n", yp->stats.rx_fifo_errors);
+       seq_printf(seq, "  RxOver   %lu\n", dev->stats.rx_fifo_errors);
        seq_printf(seq, "\n");
        return 0;
 }
 
-static struct seq_operations yam_seqops = {
+static const struct seq_operations yam_seqops = {
        .start = yam_seq_start,
        .next = yam_seq_next,
        .stop = yam_seq_stop,
@@ -810,26 +806,6 @@ static const struct file_operations yam_info_fops = {
 #endif
 
 
-/* --------------------------------------------------------------------- */
-
-static struct net_device_stats *yam_get_stats(struct net_device *dev)
-{
-       struct yam_port *yp;
-
-       if (!dev)
-               return NULL;
-
-       yp = netdev_priv(dev);
-       if (yp->magic != YAM_MAGIC)
-               return NULL;
-
-       /* 
-        * Get the current statistics.  This may be called with the
-        * card open or closed. 
-        */
-       return &yp->stats;
-}
-
 /* --------------------------------------------------------------------- */
 
 static int yam_open(struct net_device *dev)
@@ -878,9 +854,9 @@ static int yam_open(struct net_device *dev)
        /* Reset overruns for all ports - FPGA programming makes overruns */
        for (i = 0; i < NR_PORTS; i++) {
                struct net_device *dev = yam_devs[i];
-               struct yam_port *yp = netdev_priv(dev);
+
                inb(LSR(dev->base_addr));
-               yp->stats.rx_fifo_errors = 0;
+               dev->stats.rx_fifo_errors = 0;
        }
 
        printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq,
@@ -1068,6 +1044,14 @@ static int yam_set_mac_address(struct net_device *dev, void *addr)
 
 /* --------------------------------------------------------------------- */
 
+static const struct net_device_ops yam_netdev_ops = {
+       .ndo_open            = yam_open,
+       .ndo_stop            = yam_close,
+       .ndo_start_xmit      = yam_send_packet,
+       .ndo_do_ioctl        = yam_ioctl,
+       .ndo_set_mac_address = yam_set_mac_address,
+};
+
 static void yam_setup(struct net_device *dev)
 {
        struct yam_port *yp = netdev_priv(dev);
@@ -1088,18 +1072,11 @@ static void yam_setup(struct net_device *dev)
        dev->base_addr = yp->iobase;
        dev->irq = yp->irq;
 
-       dev->open = yam_open;
-       dev->stop = yam_close;
-       dev->do_ioctl = yam_ioctl;
-       dev->hard_start_xmit = yam_send_packet;
-       dev->get_stats = yam_get_stats;
-
        skb_queue_head_init(&yp->send_queue);
 
+       dev->netdev_ops = &yam_netdev_ops;
        dev->header_ops = &ax25_header_ops;
 
-       dev->set_mac_address = yam_set_mac_address;
-
        dev->type = ARPHRD_AX25;
        dev->hard_header_len = AX25_MAX_HEADER_LEN;
        dev->mtu = AX25_MTU;
index dfa6348ac1dcbdad7e556de869149b6a81f154a6..5c6315df86b98ae29c7e8306fd3a803dc45f2ca4 100644 (file)
@@ -1028,10 +1028,10 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
 
                ibmveth_assert(lpar_rc == H_SUCCESS);
 
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
                if (ibmveth_rxq_pending_buffer(adapter) &&
-                   netif_rx_reschedule(napi)) {
+                   napi_reschedule(napi)) {
                        lpar_rc = h_vio_signal(adapter->vdev->unit_address,
                                               VIO_IRQ_DISABLE);
                        goto restart_poll;
@@ -1047,11 +1047,11 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
        unsigned long lpar_rc;
 
-       if (netif_rx_schedule_prep(&adapter->napi)) {
+       if (napi_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(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        }
        return IRQ_HANDLED;
 }
index 13ca73f96ec6e397971ab9b7dbb42924430e8408..f5e4cad7971a3aa8fb78abd1d7ba97d26e54c2a1 100644 (file)
@@ -1110,6 +1110,13 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
               E1000_CTRL_SWDPIN1;
        wr32(E1000_CTRL, reg);
 
+       /* Power on phy for 82576 fiber adapters */
+       if (hw->mac.type == e1000_82576) {
+               reg = rd32(E1000_CTRL_EXT);
+               reg &= ~E1000_CTRL_EXT_SDP7_DATA;
+               wr32(E1000_CTRL_EXT, reg);
+       }
+
        /* Set switch control to serdes energy detect */
        reg = rd32(E1000_CONNSW);
        reg |= E1000_CONNSW_ENRGSRC;
index aebef8e48e76ebd80d6cd22e7fd5468f7bf6e181..30657ddf48425a81ea1bc4ed68ab3d8042acddfe 100644 (file)
 
 struct igb_adapter;
 
-#ifdef CONFIG_IGB_LRO
-#include <linux/inet_lro.h>
-#define MAX_LRO_AGGR                      32
-#define MAX_LRO_DESCRIPTORS                8
-#endif
-
 /* Interrupt defines */
 #define IGB_MIN_DYN_ITR 3000
 #define IGB_MAX_DYN_ITR 96000
@@ -176,10 +170,6 @@ struct igb_ring {
                        struct napi_struct napi;
                        int set_itr;
                        struct igb_ring *buddy;
-#ifdef CONFIG_IGB_LRO
-                       struct net_lro_mgr lro_mgr;
-                       bool lro_used;
-#endif
                };
        };
 
@@ -288,12 +278,6 @@ struct igb_adapter {
        int need_ioport;
 
        struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES];
-#ifdef CONFIG_IGB_LRO
-       unsigned int lro_max_aggr;
-       unsigned int lro_aggregated;
-       unsigned int lro_flushed;
-       unsigned int lro_no_desc;
-#endif
        unsigned int tx_ring_count;
        unsigned int rx_ring_count;
 };
index 3c831f1472adcbb6608f258e33900c8d6e91088a..4606e63fc6f56cc30dbd4ba04725846f601dc72b 100644 (file)
@@ -93,11 +93,6 @@ static const struct igb_stats igb_gstrings_stats[] = {
        { "tx_smbus", IGB_STAT(stats.mgptc) },
        { "rx_smbus", IGB_STAT(stats.mgprc) },
        { "dropped_smbus", IGB_STAT(stats.mgpdc) },
-#ifdef CONFIG_IGB_LRO
-       { "lro_aggregated", IGB_STAT(lro_aggregated) },
-       { "lro_flushed", IGB_STAT(lro_flushed) },
-       { "lro_no_desc", IGB_STAT(lro_no_desc) },
-#endif
 };
 
 #define IGB_QUEUE_STATS_LEN \
@@ -1921,18 +1916,6 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64);
        int j;
        int i;
-#ifdef CONFIG_IGB_LRO
-       int aggregated = 0, flushed = 0, no_desc = 0;
-
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated;
-               flushed += adapter->rx_ring[i].lro_mgr.stats.flushed;
-               no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc;
-       }
-       adapter->lro_aggregated = aggregated;
-       adapter->lro_flushed = flushed;
-       adapter->lro_no_desc = no_desc;
-#endif
 
        igb_update_stats(adapter);
        for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
index a50db5398fa52a297c07b78dddc5c6502c406f39..8b80fe3434352ce1835cb3097c68a9b32f1fe78a 100644 (file)
@@ -115,9 +115,6 @@ static bool igb_clean_tx_irq(struct igb_ring *);
 static int igb_poll(struct napi_struct *, int);
 static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int);
 static void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
-#ifdef CONFIG_IGB_LRO
-static int igb_get_skb_hdr(struct sk_buff *skb, void **, void **, u64 *, void *);
-#endif
 static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void igb_tx_timeout(struct net_device *);
 static void igb_reset_task(struct work_struct *);
@@ -1189,7 +1186,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
        netdev->features |= NETIF_F_TSO6;
 
 #ifdef CONFIG_IGB_LRO
-       netdev->features |= NETIF_F_LRO;
+       netdev->features |= NETIF_F_GRO;
 #endif
 
        netdev->vlan_features |= NETIF_F_TSO;
@@ -1200,7 +1197,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       netdev->features |= NETIF_F_LLTX;
        adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw);
 
        /* before reading the NVM, reset the controller to put the device in a
@@ -1738,14 +1734,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
        struct pci_dev *pdev = adapter->pdev;
        int size, desc_len;
 
-#ifdef CONFIG_IGB_LRO
-       size = sizeof(struct net_lro_desc) * MAX_LRO_DESCRIPTORS;
-       rx_ring->lro_mgr.lro_arr = vmalloc(size);
-       if (!rx_ring->lro_mgr.lro_arr)
-               goto err;
-       memset(rx_ring->lro_mgr.lro_arr, 0, size);
-#endif
-
        size = sizeof(struct igb_buffer) * rx_ring->count;
        rx_ring->buffer_info = vmalloc(size);
        if (!rx_ring->buffer_info)
@@ -1772,10 +1760,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
        return 0;
 
 err:
-#ifdef CONFIG_IGB_LRO
-       vfree(rx_ring->lro_mgr.lro_arr);
-       rx_ring->lro_mgr.lro_arr = NULL;
-#endif
        vfree(rx_ring->buffer_info);
        dev_err(&adapter->pdev->dev, "Unable to allocate memory for "
                "the receive descriptor ring\n");
@@ -1929,16 +1913,6 @@ static void igb_configure_rx(struct igb_adapter *adapter)
                rxdctl |= IGB_RX_HTHRESH << 8;
                rxdctl |= IGB_RX_WTHRESH << 16;
                wr32(E1000_RXDCTL(j), rxdctl);
-#ifdef CONFIG_IGB_LRO
-               /* Intitial LRO Settings */
-               ring->lro_mgr.max_aggr = MAX_LRO_AGGR;
-               ring->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
-               ring->lro_mgr.get_skb_header = igb_get_skb_hdr;
-               ring->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
-               ring->lro_mgr.dev = adapter->netdev;
-               ring->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
-               ring->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-#endif
        }
 
        if (adapter->num_rx_queues > 1) {
@@ -2127,11 +2101,6 @@ void igb_free_rx_resources(struct igb_ring *rx_ring)
        vfree(rx_ring->buffer_info);
        rx_ring->buffer_info = NULL;
 
-#ifdef CONFIG_IGB_LRO
-       vfree(rx_ring->lro_mgr.lro_arr);
-       rx_ring->lro_mgr.lro_arr = NULL;
-#endif 
-
        pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
 
        rx_ring->desc = NULL;
@@ -2779,12 +2748,12 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
 
                if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        switch (skb->protocol) {
-                       case __constant_htons(ETH_P_IP):
+                       case cpu_to_be16(ETH_P_IP):
                                tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
                                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
                                        tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
                                break;
-                       case __constant_htons(ETH_P_IPV6):
+                       case cpu_to_be16(ETH_P_IPV6):
                                /* XXX what about other V6 headers?? */
                                if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
                                        tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
@@ -3385,8 +3354,8 @@ static irqreturn_t igb_msix_rx(int irq, void *data)
 
        igb_write_itr(rx_ring);
 
-       if (netif_rx_schedule_prep(&rx_ring->napi))
-               __netif_rx_schedule(&rx_ring->napi);
+       if (napi_schedule_prep(&rx_ring->napi))
+               __napi_schedule(&rx_ring->napi);
 
 #ifdef CONFIG_IGB_DCA
        if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
@@ -3535,7 +3504,7 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-       netif_rx_schedule(&adapter->rx_ring[0].napi);
+       napi_schedule(&adapter->rx_ring[0].napi);
 
        return IRQ_HANDLED;
 }
@@ -3573,7 +3542,7 @@ static irqreturn_t igb_intr(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-       netif_rx_schedule(&adapter->rx_ring[0].napi);
+       napi_schedule(&adapter->rx_ring[0].napi);
 
        return IRQ_HANDLED;
 }
@@ -3608,7 +3577,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(napi);
+               napi_complete(napi);
                if (!test_bit(__IGB_DOWN, &adapter->state))
                        igb_irq_enable(adapter);
                return 0;
@@ -3634,7 +3603,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(napi);
+               napi_complete(napi);
 
                if (adapter->itr_setting & 3) {
                        if (adapter->num_rx_queues == 1)
@@ -3764,39 +3733,6 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
        return (count < tx_ring->count);
 }
 
-#ifdef CONFIG_IGB_LRO
- /**
- * igb_get_skb_hdr - helper function for LRO header processing
- * @skb: pointer to sk_buff to be added to LRO packet
- * @iphdr: pointer to ip header structure
- * @tcph: pointer to tcp header structure
- * @hdr_flags: pointer to header flags
- * @priv: pointer to the receive descriptor for the current sk_buff
- **/
-static int igb_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
-                           u64 *hdr_flags, void *priv)
-{
-       union e1000_adv_rx_desc *rx_desc = priv;
-       u16 pkt_type = rx_desc->wb.lower.lo_dword.pkt_info &
-                      (E1000_RXDADV_PKTTYPE_IPV4 | E1000_RXDADV_PKTTYPE_TCP);
-
-       /* Verify that this is a valid IPv4 TCP packet */
-       if (pkt_type != (E1000_RXDADV_PKTTYPE_IPV4 |
-                         E1000_RXDADV_PKTTYPE_TCP))
-               return -1;
-
-       /* Set network headers */
-       skb_reset_network_header(skb);
-       skb_set_transport_header(skb, ip_hdrlen(skb));
-       *iphdr = ip_hdr(skb);
-       *tcph = tcp_hdr(skb);
-       *hdr_flags = LRO_IPV4 | LRO_TCP;
-
-       return 0;
-
-}
-#endif /* CONFIG_IGB_LRO */
-
 /**
  * igb_receive_skb - helper function to handle rx indications
  * @ring: pointer to receive ring receving this packet 
@@ -3811,28 +3747,21 @@ static void igb_receive_skb(struct igb_ring *ring, u8 status,
        struct igb_adapter * adapter = ring->adapter;
        bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP));
 
-#ifdef CONFIG_IGB_LRO
-       if (adapter->netdev->features & NETIF_F_LRO &&
-           skb->ip_summed == CHECKSUM_UNNECESSARY) {
+       skb_record_rx_queue(skb, ring->queue_index);
+       if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                if (vlan_extracted)
-                       lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
-                                          adapter->vlgrp,
-                                          le16_to_cpu(rx_desc->wb.upper.vlan),
-                                          rx_desc);
+                       vlan_gro_receive(&ring->napi, adapter->vlgrp,
+                                        le16_to_cpu(rx_desc->wb.upper.vlan),
+                                        skb);
                else
-                       lro_receive_skb(&ring->lro_mgr,skb, rx_desc);
-               ring->lro_used = 1;
+                       napi_gro_receive(&ring->napi, skb);
        } else {
-#endif
                if (vlan_extracted)
                        vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
                                          le16_to_cpu(rx_desc->wb.upper.vlan));
                else
-
                        netif_receive_skb(skb);
-#ifdef CONFIG_IGB_LRO
        }
-#endif
 }
 
 
@@ -3987,13 +3916,6 @@ next_desc:
        rx_ring->next_to_clean = i;
        cleaned_count = IGB_DESC_UNUSED(rx_ring);
 
-#ifdef CONFIG_IGB_LRO
-       if (rx_ring->lro_used) {
-               lro_flush_all(&rx_ring->lro_mgr);
-               rx_ring->lro_used = 0;
-       }
-#endif
-
        if (cleaned_count)
                igb_alloc_rx_buffers_adv(rx_ring, cleaned_count);
 
index eee28d3956827cb8dcb3951df9738ab6c9cd54e6..e2ef16b29700ed0c0d81e258338c978f5f65f1b5 100644 (file)
@@ -1721,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(&adapter->napi)) {
+       if (napi_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(&adapter->napi);
+               __napi_schedule(&adapter->napi);
        }
        return IRQ_HANDLED;
 }
@@ -1749,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(napi);
+               napi_complete(napi);
                if (!test_bit(__IXGB_DOWN, &adapter->flags))
                        ixgb_irq_enable(adapter);
        }
index 6e7ef765bcd882ec2257dcd5c244f0352846f36c..f6061950f5d124b8fd4b128512f4b94a3129abd9 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 10 Gigabit PCI Express Linux driver
-# Copyright(c) 1999 - 2007 Intel Corporation.
+# Copyright(c) 1999 - 2009 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,
index e112008f39c1dc889a73e4b9c0af5a4ceb7b95f1..0ea791ae0d14422791e094f59db7c10759c85d69 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
-#include <linux/inet_lro.h>
 #include <linux/aer.h>
 
 #include "ixgbe_type.h"
@@ -88,9 +87,6 @@
 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
 #define IXGBE_TX_FLAGS_VLAN_SHIFT      16
 
-#define IXGBE_MAX_LRO_DESCRIPTORS       8
-#define IXGBE_MAX_LRO_AGGREGATE         32
-
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
@@ -142,8 +138,6 @@ struct ixgbe_ring {
        /* cpu for tx queue */
        int cpu;
 #endif
-       struct net_lro_mgr lro_mgr;
-       bool lro_used;
        struct ixgbe_queue_stats stats;
        u16 v_idx; /* maps directly to the index for this ring in the hardware
                   * vector array, can also be used for finding the bit in EICR
@@ -210,9 +204,13 @@ struct ixgbe_q_vector {
 #define OTHER_VECTOR 1
 #define NON_Q_VECTORS (OTHER_VECTOR)
 
-#define MAX_MSIX_Q_VECTORS 16
+#define MAX_MSIX_VECTORS_82598 18
+#define MAX_MSIX_Q_VECTORS_82598 16
+
+#define MAX_MSIX_Q_VECTORS MAX_MSIX_Q_VECTORS_82598
+#define MAX_MSIX_COUNT MAX_MSIX_VECTORS_82598
+
 #define MIN_MSIX_Q_VECTORS 2
-#define MAX_MSIX_COUNT (MAX_MSIX_Q_VECTORS + NON_Q_VECTORS)
 #define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS)
 
 /* board specific private data structure */
@@ -250,6 +248,7 @@ struct ixgbe_adapter {
        u64 hw_csum_rx_good;
        u64 non_eop_descs;
        int num_msix_vectors;
+       int max_msix_q_vectors;         /* true count of q_vectors for device */
        struct ixgbe_ring_feature ring_feature[3];
        struct msix_entry *msix_entries;
 
@@ -301,9 +300,6 @@ struct ixgbe_adapter {
 
        unsigned long state;
        u64 tx_busy;
-       u64 lro_aggregated;
-       u64 lro_flushed;
-       u64 lro_no_desc;
        unsigned int tx_ring_count;
        unsigned int rx_ring_count;
 
index ad5699d9ab0dacaaecf5fd6069b1268ff07d5e9c..8e7315e0a7fae5d1661f61d8c61ec541713d55d0 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
@@ -49,6 +49,27 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
 static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
                                        u8 *eeprom_data);
 
+/**
+ *  ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
+ *  @hw: pointer to hardware structure
+ *
+ *  Read PCIe configuration space, and get the MSI-X vector count from
+ *  the capabilities table.
+ **/
+u16 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw)
+{
+       struct ixgbe_adapter *adapter = hw->back;
+       u16 msix_count;
+       pci_read_config_word(adapter->pdev, IXGBE_PCIE_MSIX_82598_CAPS,
+                            &msix_count);
+       msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
+
+       /* MSI-X count is zero-based in HW, so increment to give proper value */
+       msix_count++;
+
+       return msix_count;
+}
+
 /**
  */
 static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
@@ -106,6 +127,7 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
        mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
        mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
        mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
+       mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
 
 out:
        return ret_val;
@@ -213,6 +235,10 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
 
        /* Media type for I82598 is based on device ID */
        switch (hw->device_id) {
+       case IXGBE_DEV_ID_82598:
+       case IXGBE_DEV_ID_82598_BX:
+               media_type = ixgbe_media_type_backplane;
+               break;
        case IXGBE_DEV_ID_82598AF_DUAL_PORT:
        case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
        case IXGBE_DEV_ID_82598EB_CX4:
@@ -1002,6 +1028,13 @@ static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
        s32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
 
        switch (hw->device_id) {
+       case IXGBE_DEV_ID_82598:
+               /* Default device ID is mezzanine card KX/KX4 */
+               physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
+                                 IXGBE_PHYSICAL_LAYER_1000BASE_KX);
+               break;
+       case IXGBE_DEV_ID_82598_BX:
+               physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
        case IXGBE_DEV_ID_82598EB_CX4:
        case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
                physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
index f67c68404bb382462662ea664749b080a280ab6a..05f0e872947f02098ca79cfd9b670cbf68cc38ab 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 192f8d0129111724b25fb52a82cc4a02a02bd4f1..0b5ba57558057b402bcf3c4e9c4b2640e8ed4855 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index e2e28ac63deca37eb752b1da2a8d7f1239d11e12..2a60c89ab3465e1aeec72be9c0ee89ddc94a760a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2007 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 75f6efe1e36920a9fba4c1f4859ec701f0a2549a..0da5c6d5bcafc3207dd8a3dc980a242cd1a610f9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2007 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 2c046b0b5d2806507178e5a2ff948cf9217f4d61..5603211489354d49da1e3e3b4e82598394f31a6d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2007 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 1e6a313719d7e2a0237896aa997c8871b8ee25bf..ebbe53c352a7a3f6ab172bf19e520f5efb60b5d7 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2007 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 4129976953f5609f58c4f442b22f58095c8a54f7..dd9d1d63a59c0fb069cd3d6c5a5b086e8c06bbfe 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 67f87a79154dbff3f88ab64bddaa7ab2577b7099..14e661e0a2504a1899a82bc164ea83afdba3edaf 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
@@ -89,8 +89,6 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
        {"rx_header_split", IXGBE_STAT(rx_hdr_split)},
        {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
        {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
-       {"lro_aggregated", IXGBE_STAT(lro_aggregated)},
-       {"lro_flushed", IXGBE_STAT(lro_flushed)},
 };
 
 #define IXGBE_QUEUE_STATS_LEN \
@@ -132,6 +130,26 @@ static int ixgbe_get_settings(struct net_device *netdev,
                        ecmd->advertising |= ADVERTISED_1000baseT_Full;
 
                ecmd->port = PORT_TP;
+       } else if (hw->phy.media_type == ixgbe_media_type_backplane) {
+               /* Set as FIBRE until SERDES defined in kernel */
+               switch (hw->device_id) {
+               case IXGBE_DEV_ID_82598:
+                       ecmd->supported |= (SUPPORTED_1000baseT_Full |
+                               SUPPORTED_FIBRE);
+                       ecmd->advertising = (ADVERTISED_10000baseT_Full |
+                               ADVERTISED_1000baseT_Full |
+                               ADVERTISED_FIBRE);
+                       ecmd->port = PORT_FIBRE;
+                       break;
+               case IXGBE_DEV_ID_82598_BX:
+                       ecmd->supported = (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_FIBRE);
+                       ecmd->advertising = (ADVERTISED_1000baseT_Full |
+                                            ADVERTISED_FIBRE);
+                       ecmd->port = PORT_FIBRE;
+                       ecmd->autoneg = AUTONEG_DISABLE;
+                       break;
+               }
        } else {
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising = (ADVERTISED_10000baseT_Full |
@@ -808,15 +826,6 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
        int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
        int j, k;
        int i;
-       u64 aggregated = 0, flushed = 0, no_desc = 0;
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated;
-               flushed += adapter->rx_ring[i].lro_mgr.stats.flushed;
-               no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc;
-       }
-       adapter->lro_aggregated = aggregated;
-       adapter->lro_flushed = flushed;
-       adapter->lro_no_desc = no_desc;
 
        ixgbe_update_stats(adapter);
        for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
index d2f4d5f508b75f4283774e445619b5d920029564..ed8d14163c1d6d461e1afa0fba60a70623d6763d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
@@ -47,9 +47,9 @@ char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
                               "Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "1.3.30-k2"
+#define DRV_VERSION "1.3.56-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
-static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation.";
+static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
        [board_82598] = &ixgbe_82598_info,
@@ -64,6 +64,8 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
  *   Class, Class Mask, private data (not used) }
  */
 static struct pci_device_id ixgbe_pci_tbl[] = {
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598),
+        board_82598 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT),
         board_82598 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
@@ -82,6 +84,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
         board_82598 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM),
         board_82598 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX),
+        board_82598 },
 
        /* required last entry */
        {0, }
@@ -403,23 +407,21 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
  * @rx_ring: rx descriptor ring (for a specific queue) to setup
  * @rx_desc: rx descriptor
  **/
-static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
+static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
                               struct sk_buff *skb, u8 status,
-                              struct ixgbe_ring *ring,
                               union ixgbe_adv_rx_desc *rx_desc)
 {
+       struct ixgbe_adapter *adapter = q_vector->adapter;
+       struct napi_struct *napi = &q_vector->napi;
        bool is_vlan = (status & IXGBE_RXD_STAT_VP);
        u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-       if (adapter->netdev->features & NETIF_F_LRO &&
-           skb->ip_summed == CHECKSUM_UNNECESSARY) {
+       skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]);
+       if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                if (adapter->vlgrp && is_vlan && (tag != 0))
-                       lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
-                                                    adapter->vlgrp, tag,
-                                                    rx_desc);
+                       vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
                else
-                       lro_receive_skb(&ring->lro_mgr, skb, rx_desc);
-               ring->lro_used = true;
+                       napi_gro_receive(napi, skb);
        } else {
                if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
                        if (adapter->vlgrp && is_vlan && (tag != 0))
@@ -574,10 +576,11 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc)
        return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
 }
 
-static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
+static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                                struct ixgbe_ring *rx_ring,
                                int *work_done, int work_to_do)
 {
+       struct ixgbe_adapter *adapter = q_vector->adapter;
        struct pci_dev *pdev = adapter->pdev;
        union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
        struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
@@ -678,7 +681,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
                total_rx_packets++;
 
                skb->protocol = eth_type_trans(skb, adapter->netdev);
-               ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
+               ixgbe_receive_skb(q_vector, skb, staterr, rx_desc);
 
 next_desc:
                rx_desc->wb.upper.status_error = 0;
@@ -696,11 +699,6 @@ next_desc:
                staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
        }
 
-       if (rx_ring->lro_used) {
-               lro_flush_all(&rx_ring->lro_mgr);
-               rx_ring->lro_used = false;
-       }
-
        rx_ring->next_to_clean = i;
        cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
 
@@ -1015,7 +1013,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(&q_vector->napi);
+       napi_schedule(&q_vector->napi);
 
        return IRQ_HANDLED;
 }
@@ -1052,11 +1050,11 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
                ixgbe_update_rx_dca(adapter, rx_ring);
 #endif
 
-       ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget);
+       ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
 
        /* If all Rx work done, exit the polling mode */
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                if (adapter->itr_setting & 3)
                        ixgbe_set_itr_msix(q_vector);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -1095,7 +1093,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
                if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                        ixgbe_update_rx_dca(adapter, rx_ring);
 #endif
-               ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget);
+               ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
                enable_mask |= rx_ring->v_idx;
                r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
                                      r_idx + 1);
@@ -1105,7 +1103,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(napi);
+               napi_complete(napi);
                if (adapter->itr_setting & 3)
                        ixgbe_set_itr_msix(q_vector);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -1381,13 +1379,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 
        ixgbe_check_fan_failure(adapter, eicr);
 
-       if (netif_rx_schedule_prep(&adapter->q_vector[0].napi)) {
+       if (napi_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(&adapter->q_vector[0].napi);
+               __napi_schedule(&adapter->q_vector[0].napi);
        }
 
        return IRQ_HANDLED;
@@ -1568,33 +1566,6 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
 }
 
-/**
- * ixgbe_get_skb_hdr - helper function for LRO header processing
- * @skb: pointer to sk_buff to be added to LRO packet
- * @iphdr: pointer to ip header structure
- * @tcph: pointer to tcp header structure
- * @hdr_flags: pointer to header flags
- * @priv: private data
- **/
-static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
-                             u64 *hdr_flags, void *priv)
-{
-       union ixgbe_adv_rx_desc *rx_desc = priv;
-
-       /* Verify that this is a valid IPv4 TCP packet */
-       if (!((ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_IPV4) &&
-            (ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_TCP)))
-               return -1;
-
-       /* Set network headers */
-       skb_reset_network_header(skb);
-       skb_set_transport_header(skb, ip_hdrlen(skb));
-       *iphdr = ip_hdr(skb);
-       *tcph = tcp_hdr(skb);
-       *hdr_flags = LRO_IPV4 | LRO_TCP;
-       return 0;
-}
-
 #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
                            (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
 
@@ -1666,16 +1637,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
                adapter->rx_ring[i].head = IXGBE_RDH(j);
                adapter->rx_ring[i].tail = IXGBE_RDT(j);
                adapter->rx_ring[i].rx_buf_len = rx_buf_len;
-               /* Intitial LRO Settings */
-               adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
-               adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
-               adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
-               adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
-               if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
-                       adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
-               adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
-               adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
-               adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
 
                ixgbe_configure_srrctl(adapter, j);
        }
@@ -2310,14 +2271,14 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
 #endif
 
        tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
-       ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);
+       ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
 
        if (tx_cleaned)
                work_done = budget;
 
        /* If budget not fully consumed, exit the polling mode */
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                if (adapter->itr_setting & 3)
                        ixgbe_set_itr(adapter);
                if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2460,7 +2421,13 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
                ixgbe_set_num_queues(adapter);
        } else {
                adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
-               adapter->num_msix_vectors = vectors;
+               /*
+                * Adjust for only the vectors we'll use, which is minimum
+                * of max_msix_q_vectors + NON_Q_VECTORS, or the number of
+                * vectors we were allocated.
+                */
+               adapter->num_msix_vectors = min(vectors,
+                                  adapter->max_msix_q_vectors + NON_Q_VECTORS);
        }
 }
 
@@ -2785,6 +2752,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
        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;
+       adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
 
 #ifdef CONFIG_IXGBE_DCB
        /* Configure DCB traffic classes */
@@ -2926,12 +2894,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
        struct pci_dev *pdev = adapter->pdev;
        int size;
 
-       size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
-       rx_ring->lro_mgr.lro_arr = vmalloc(size);
-       if (!rx_ring->lro_mgr.lro_arr)
-               return -ENOMEM;
-       memset(rx_ring->lro_mgr.lro_arr, 0, size);
-
        size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
        rx_ring->rx_buffer_info = vmalloc(size);
        if (!rx_ring->rx_buffer_info) {
@@ -2960,8 +2922,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
        return 0;
 
 alloc_failed:
-       vfree(rx_ring->lro_mgr.lro_arr);
-       rx_ring->lro_mgr.lro_arr = NULL;
        return -ENOMEM;
 }
 
@@ -3039,9 +2999,6 @@ void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
 
-       vfree(rx_ring->lro_mgr.lro_arr);
-       rx_ring->lro_mgr.lro_arr = NULL;
-
        ixgbe_clean_rx_ring(adapter, rx_ring);
 
        vfree(rx_ring->rx_buffer_info);
@@ -3619,13 +3576,13 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
 
                if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        switch (skb->protocol) {
-                       case __constant_htons(ETH_P_IP):
+                       case cpu_to_be16(ETH_P_IP):
                                type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
                                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
                                        type_tucmd_mlhl |=
                                                IXGBE_ADVTXD_TUCMD_L4T_TCP;
                                break;
-                       case __constant_htons(ETH_P_IPV6):
+                       case cpu_to_be16(ETH_P_IPV6):
                                /* XXX what about other V6 headers?? */
                                if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
                                        type_tucmd_mlhl |=
@@ -3956,16 +3913,27 @@ static void ixgbe_netpoll(struct net_device *netdev)
  **/
 static int ixgbe_link_config(struct ixgbe_hw *hw)
 {
-       u32 autoneg = IXGBE_LINK_SPEED_10GB_FULL;
+       u32 autoneg;
+       bool link_up = false;
+       u32 ret = IXGBE_ERR_LINK_SETUP;
+
+       if (hw->mac.ops.check_link)
+               ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
 
-       /* must always autoneg for both 1G and 10G link */
-       hw->mac.autoneg = true;
+       if (ret || !link_up)
+               goto link_cfg_out;
 
-       if ((hw->mac.type == ixgbe_mac_82598EB) &&
-           (hw->phy.media_type == ixgbe_media_type_copper))
-               autoneg = IXGBE_LINK_SPEED_82598_AUTONEG;
+       if (hw->mac.ops.get_link_capabilities)
+               ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
+                                                       &hw->mac.autoneg);
+       if (ret)
+               goto link_cfg_out;
 
-       return hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
+       if (hw->mac.ops.setup_link_speed)
+               ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
+
+link_cfg_out:
+       return ret;
 }
 
 static const struct net_device_ops ixgbe_netdev_ops = {
@@ -4141,7 +4109,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        netdev->features |= NETIF_F_IPV6_CSUM;
        netdev->features |= NETIF_F_TSO;
        netdev->features |= NETIF_F_TSO6;
-       netdev->features |= NETIF_F_LRO;
+       netdev->features |= NETIF_F_GRO;
 
        netdev->vlan_features |= NETIF_F_TSO;
        netdev->vlan_features |= NETIF_F_TSO6;
index 5a8669aedf6417a244b0b4908f91e1913b530a11..77ec26f5650ae9808611127308fd72f0b09a9f96 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index 43a97bc420f54c0dbda983bdcbb214aad955f94b..539a3061eb29ac6a16553aedb41a4809cc1002b7 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 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,
index f011c57c92051e419c31914c0639f221d25f1645..c49ba8a17f1b25b1c916113cc2e6f819919d1934 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -34,6 +34,8 @@
 #define IXGBE_INTEL_VENDOR_ID   0x8086
 
 /* Device IDs */
+#define IXGBE_DEV_ID_82598               0x10B6
+#define IXGBE_DEV_ID_82598_BX            0x1508
 #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_FW_PTR            0x0F
 #define IXGBE_PBANUM0_PTR       0x15
 #define IXGBE_PBANUM1_PTR       0x16
+#define IXGBE_PCIE_MSIX_82598_CAPS  0x62
+
+/* MSI-X capability fields masks */
+#define IXGBE_PCIE_MSIX_TBL_SZ_MASK     0x7FF
 
 /* Legacy EEPROM word offsets */
 #define IXGBE_ISCSI_BOOT_CAPS           0x0033
@@ -1449,6 +1455,7 @@ struct ixgbe_mac_info {
        u32                             num_rar_entries;
        u32                             max_tx_queues;
        u32                             max_rx_queues;
+       u32                             max_msix_vectors;
        u32                             link_attach_type;
        u32                             link_mode_select;
        bool                            link_settings_loaded;
index 014745720560df448b6654c0f051093505838e46..d3bf2f017cc27f0507b393a07761b198a15cd123 100644 (file)
@@ -141,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(napi);
+       napi_complete(napi);
        ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
 
        return rx;
@@ -204,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(&ip->napi);
+                       __napi_schedule(&ip->napi);
                } else {
                        printk(KERN_CRIT "ixp2000: irq while polling!!\n");
                }
index 334ff9e12cdd25c5aa131ce98e10fd485a435189..14248cfc3dfd165d74d2656d8a56431460478538 100644 (file)
@@ -131,7 +131,8 @@ static int __init sonic_probe1(struct net_device *dev)
        if (sonic_debug  &&  version_printed++ == 0)
                printk(version);
 
-       printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
+       printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ",
+              dev_name(lp->device), dev->base_addr);
 
        /*
         * Put the sonic into software reset, then
@@ -156,7 +157,8 @@ static int __init sonic_probe1(struct net_device *dev)
        if ((lp->descriptors = dma_alloc_coherent(lp->device,
                                SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
                                &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
-               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
+               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n",
+                      dev_name(lp->device));
                goto out;
        }
 
index 5154411b5e6b0821054cdefef093947bf99a8333..e321c678b11c098f7436a9eb950912c50d6f47f1 100644 (file)
@@ -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(napis)
+#define JME_RX_COMPLETE(dev, napis) napi_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->napi)
+       napi_schedule_prep(&priv->napi)
 #define JME_RX_SCHEDULE(priv) \
-       __netif_rx_schedule(&priv->napi);
+       __napi_schedule(&priv->napi);
 
 /*
  * Jmac Adapter Private data
index 75010cac76ac7e63e4f046322dcd21ec1525c278..38d6649a29c42a491139b2cb882d3a68421c0fc3 100644 (file)
@@ -334,7 +334,7 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
                                DMA_STAT_HALT | DMA_STAT_ERR),
                                &lp->rx_dma_regs->dmasm);
 
-               netif_rx_schedule(&lp->napi);
+               napi_schedule(&lp->napi);
 
                if (dmas & DMA_STAT_ERR)
                        printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
@@ -468,7 +468,7 @@ static int korina_poll(struct napi_struct *napi, int budget)
 
        work_done = korina_rx(dev, budget);
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
                writel(readl(&lp->rx_dma_regs->dmasm) &
                        ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
index f6c4936e2fa8e368ca1f2fdbdb09ad75d990562e..872c1bdf42bd4d211d6f78cb3137067afc72ed58 100644 (file)
@@ -211,10 +211,10 @@ static int macb_mii_probe(struct net_device *dev)
 
        /* attach the mac to the phy */
        if (pdata && pdata->is_rmii) {
-               phydev = phy_connect(dev, phydev->dev.bus_id,
+               phydev = phy_connect(dev, dev_name(&phydev->dev),
                        &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
        } else {
-               phydev = phy_connect(dev, phydev->dev.bus_id,
+               phydev = phy_connect(dev, dev_name(&phydev->dev),
                        &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
        }
 
@@ -527,7 +527,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(napi);
+               napi_complete(napi);
                goto out;
        }
 
@@ -538,13 +538,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(napi);
+               napi_complete(napi);
                goto out;
        }
 
        work_done = macb_rx(bp, budget);
        if (work_done < budget)
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
        /*
         * We've done what we can to clean the buffers. Make sure we
@@ -579,7 +579,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                }
 
                if (status & MACB_RX_INT_FLAGS) {
-                       if (netif_rx_schedule_prep(&bp->napi)) {
+                       if (napi_schedule_prep(&bp->napi)) {
                                /*
                                 * There's no point taking any more interrupts
                                 * until we have processed the buffers
@@ -587,7 +587,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(&bp->napi);
+                               __napi_schedule(&bp->napi);
                        }
                }
 
@@ -1077,7 +1077,7 @@ static void macb_get_drvinfo(struct net_device *dev,
 
        strcpy(info->driver, bp->pdev->dev.driver->name);
        strcpy(info->version, "$Revision: 1.14 $");
-       strcpy(info->bus_info, bp->pdev->dev.bus_id);
+       strcpy(info->bus_info, dev_name(&bp->pdev->dev));
 }
 
 static struct ethtool_ops macb_ethtool_ops = {
@@ -1234,8 +1234,8 @@ static int __init macb_probe(struct platform_device *pdev)
 
        phydev = bp->phy_dev;
        printk(KERN_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);
+               "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+               phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        return 0;
 
index 205bb05c25d6f41a2eec0abfdb958348179d0e93..527166e35d566b11897055e0aabb99911ab17c43 100644 (file)
@@ -176,7 +176,8 @@ static int __init macsonic_init(struct net_device *dev)
        if ((lp->descriptors = dma_alloc_coherent(lp->device,
                    SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
                    &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
-               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
+               printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n",
+                      dev_name(lp->device));
                return -ENOMEM;
        }
 
@@ -337,7 +338,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev)
                sonic_version_printed = 1;
        }
        printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
-              lp->device->bus_id, dev->base_addr);
+              dev_name(lp->device), dev->base_addr);
 
        /* The PowerBook's SONIC is 16 bit always. */
        if (macintosh_config->ident == MAC_MODEL_PB520) {
@@ -370,10 +371,10 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev)
        }
        printk(KERN_INFO
               "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
-              lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset);
+              dev_name(lp->device), sr, lp->dma_bitmode?32:16, lp->reg_offset);
 
 #if 0 /* This is sometimes useful to find out how MacOS configured the card. */
-       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device),
               SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
 #endif
 
@@ -525,12 +526,12 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev)
                sonic_version_printed = 1;
        }
        printk(KERN_INFO "%s: %s in slot %X\n",
-              lp->device->bus_id, ndev->board->name, ndev->board->slot);
+              dev_name(lp->device), ndev->board->name, ndev->board->slot);
        printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
-              lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
+              dev_name(lp->device), SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
 
 #if 0 /* This is sometimes useful to find out how MacOS configured the card. */
-       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+       printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device),
               SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
 #endif
 
index c61b0bdca1a433c33771784d88fb8f6eae3f092d..a4130e764991a79e77a30395c685a2ac5088188e 100644 (file)
@@ -768,6 +768,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 
                skb->ip_summed = ip_summed;
                skb->protocol = eth_type_trans(skb, dev);
+               skb_record_rx_queue(skb, cq->ring);
 
                /* Push it up the stack */
                if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) &
@@ -814,7 +815,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->napi);
+               napi_schedule(&cq->napi);
        else
                mlx4_en_arm_cq(priv, cq);
 }
@@ -834,7 +835,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(napi);
+               napi_complete(napi);
                mlx4_en_arm_cq(priv, cq);
        }
        return done;
index 5f31bbb614aff948703ce58e770cbeb81dcaf6c3..8fab31f631a0e933183c114dd3cfa2a742b06e67 100644 (file)
@@ -2589,7 +2589,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 
        phy_reset(mp);
 
-       phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII);
+       phy_attach(mp->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_GMII);
 
        if (speed == 0) {
                phy->autoneg = AUTONEG_ENABLE;
index e9c1296b267eccecb1eba8d7e9c53ffe7dcceeea..aea9fdaa3cd50db7e9ba983bf7174f0b302eb0f1 100644 (file)
@@ -1324,6 +1324,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
                skb_shinfo(skb)->nr_frags = 0;
        }
        skb->protocol = eth_type_trans(skb, dev);
+       skb_record_rx_queue(skb, ss - &mgp->ss[0]);
 
        if (mgp->csum_flag) {
                if ((skb->protocol == htons(ETH_P_IP)) ||
@@ -1514,7 +1515,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(napi);
+               napi_complete(napi);
                put_be32(htonl(3), ss->irq_claim);
        }
        return work_done;
@@ -1532,7 +1533,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->napi);
+               napi_schedule(&ss->napi);
                return (IRQ_HANDLED);
        }
 
@@ -1543,7 +1544,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->napi);
+               napi_schedule(&ss->napi);
 
        if (!mgp->msi_enabled && !mgp->msix_enabled) {
                put_be32(0, mgp->irq_deassert);
index 899ed065a1478dc7ef4303b445285954776eb282..88b52883acea0705804aa6b7ee04da7c2e963ddf 100644 (file)
@@ -748,7 +748,7 @@ static int myri_rebuild_header(struct sk_buff *skb)
        switch (eth->h_proto)
        {
 #ifdef CONFIG_INET
-       case __constant_htons(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IP):
                return arp_find(eth->h_dest, skb);
 #endif
 
index c5dec54251bf4ad4641d3100e3e8d786e4f8a362..c23a58624a33fc00ea301e57aae28424c41aca6e 100644 (file)
@@ -2198,10 +2198,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(&np->napi)) {
+       if (napi_schedule_prep(&np->napi)) {
                /* Disable interrupts and register for poll */
                natsemi_irq_disable(dev);
-               __netif_rx_schedule(&np->napi);
+               __napi_schedule(&np->napi);
        } else
                printk(KERN_WARNING
                       "%s: Ignoring interrupt, status %#08x, mask %#08x.\n",
@@ -2253,7 +2253,7 @@ static int natsemi_poll(struct napi_struct *napi, int budget)
                np->intr_status = readl(ioaddr + IntrStatus);
        } while (np->intr_status);
 
-       netif_rx_complete(napi);
+       napi_complete(napi);
 
        /* Reenable interrupts providing nothing is trying to shut
         * the chip down. */
index 645d384fe87e67d96b0b60684a734165568bce38..ada462e94c96eadc6b85001fdf5dcaedcdf3e6c2 100644 (file)
@@ -1170,7 +1170,7 @@ static bool netxen_tso_check(struct net_device *netdev,
        __be16 protocol = skb->protocol;
        u16 flags = 0;
 
-       if (protocol == __constant_htons(ETH_P_8021Q)) {
+       if (protocol == cpu_to_be16(ETH_P_8021Q)) {
                struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
                protocol = vh->h_vlan_encapsulated_proto;
                flags = FLAGS_VLAN_TAGGED;
@@ -1183,21 +1183,21 @@ static bool netxen_tso_check(struct net_device *netdev,
                desc->total_hdr_length =
                        skb_transport_offset(skb) + tcp_hdrlen(skb);
 
-               opcode = (protocol == __constant_htons(ETH_P_IPV6)) ?
+               opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
                                TX_TCP_LSO6 : TX_TCP_LSO;
                tso = true;
 
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u8 l4proto;
 
-               if (protocol == __constant_htons(ETH_P_IP)) {
+               if (protocol == cpu_to_be16(ETH_P_IP)) {
                        l4proto = ip_hdr(skb)->protocol;
 
                        if (l4proto == IPPROTO_TCP)
                                opcode = TX_TCP_PKT;
                        else if(l4proto == IPPROTO_UDP)
                                opcode = TX_UDP_PKT;
-               } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               } else if (protocol == cpu_to_be16(ETH_P_IPV6)) {
                        l4proto = ipv6_hdr(skb)->nexthdr;
 
                        if (l4proto == IPPROTO_TCP)
@@ -1640,7 +1640,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
        }
 
        if ((work_done < budget) && tx_complete) {
-               netif_rx_complete(&adapter->napi);
+               napi_complete(&adapter->napi);
                netxen_nic_enable_int(adapter);
        }
 
index 0c0b752315cae844c6944b912d8605032070e93c..c26325ded20e35d821547e9aa3261b6ec96102e3 100644 (file)
@@ -3390,6 +3390,7 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp)
        rp->rx_bytes += skb->len;
 
        skb->protocol = eth_type_trans(skb, np->dev);
+       skb_record_rx_queue(skb, rp->rx_channel);
        netif_receive_skb(skb);
 
        return num_rcr;
@@ -3669,7 +3670,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(napi);
+               napi_complete(napi);
                niu_ldg_rearm(np, lp, 1);
        }
        return work_done;
@@ -4088,12 +4089,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(&lp->napi))) {
+       if (likely(napi_schedule_prep(&lp->napi))) {
                lp->v0 = v0;
                lp->v1 = v1;
                lp->v2 = v2;
                __niu_fastpath_interrupt(np, lp->ldg_num, v0);
-               __netif_rx_schedule(&lp->napi);
+               __napi_schedule(&lp->napi);
        }
 }
 
@@ -6446,11 +6447,11 @@ static u64 niu_compute_tx_flags(struct sk_buff *skb, struct ethhdr *ehdr,
 
        ipv6 = ihl = 0;
        switch (skb->protocol) {
-       case __constant_htons(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IP):
                ip_proto = ip_hdr(skb)->protocol;
                ihl = ip_hdr(skb)->ihl;
                break;
-       case __constant_htons(ETH_P_IPV6):
+       case cpu_to_be16(ETH_P_IPV6):
                ip_proto = ipv6_hdr(skb)->nexthdr;
                ihl = (40 >> 2);
                ipv6 = 1;
index d0349e7d73ea9d873a4ce23afe6ae6e262e55fdb..5eeb5a87b7387ede885f565ea9409da99a704865 100644 (file)
@@ -970,7 +970,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(&mac->napi);
+       napi_schedule(&mac->napi);
 
        write_iob_reg(PAS_IOB_DMA_RXCH_RESET(chan->chno), reg);
 
@@ -1010,7 +1010,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->napi);
+       napi_schedule(&mac->napi);
 
        if (reg)
                write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg);
@@ -1639,7 +1639,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(napi);
+               napi_complete(napi);
 
                pasemi_mac_restart_rx_intr(mac);
                pasemi_mac_restart_tx_intr(mac);
index 665a4286da39dc29de659e03900ad7d89f172ab3..80124fac65fa83682a7b256db5dd11039fb7d445 100644 (file)
@@ -1397,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(napi);
+               __napi_complete(napi);
 
                /* clear interrupt masks */
                val = lp->a.read_csr(ioaddr, CSR3);
@@ -2592,14 +2592,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(&lp->napi)) {
+               if (napi_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(&lp->napi);
+                       __napi_schedule(&lp->napi);
                        break;
                }
                csr0 = lp->a.read_csr(ioaddr, CSR0);
index a439ebeb431926e7bec18d84dcd22a8bc30f5b53..3f460c564927e202bb2c4abf76a34e82a0bc918a 100644 (file)
@@ -200,16 +200,21 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
 {
        struct device_node *np = NULL;
        struct mdio_gpio_platform_data *pdata;
+       int ret;
 
        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)
+       ret = of_get_gpio(ofdev->node, 0);
+       if (ret < 0)
                goto out_free;
+       pdata->mdc = ret;
+
+       ret = of_get_gpio(ofdev->node, 1);
+       if (ret < 0)
+                goto out_free;
+       pdata->mdio = ret;
 
        while ((np = of_get_next_child(ofdev->node, np)))
                if (!strcmp(np->type, "ethernet-phy"))
index 811a637695caf4270247cbace802bca469bc03e0..bb29ae3ff17dc6765fac1db21c532c1c5660b93c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -286,33 +287,58 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
                (phydev->phy_id & phydrv->phy_id_mask));
 }
 
+static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
+{
+       struct device_driver *drv = phydev->dev.driver;
+       struct phy_driver *phydrv = to_phy_driver(drv);
+       struct net_device *netdev = phydev->attached_dev;
+
+       if (!drv || !phydrv->suspend)
+               return false;
+
+       /* PHY not attached? May suspend. */
+       if (!netdev)
+               return true;
+
+       /*
+        * Don't suspend PHY if the attched netdev parent may wakeup.
+        * The parent may point to a PCI device, as in tg3 driver.
+        */
+       if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
+               return false;
+
+       /*
+        * Also don't suspend PHY if the netdev itself may wakeup. This
+        * is the case for devices w/o underlaying pwr. mgmt. aware bus,
+        * e.g. SoC devices.
+        */
+       if (device_may_wakeup(&netdev->dev))
+               return false;
+
+       return true;
+}
+
 /* Suspend and resume.  Copied from platform_suspend and
  * platform_resume
  */
 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_driver *phydrv = to_phy_driver(dev->driver);
        struct phy_device *phydev = to_phy_device(dev);
 
-       if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent))
-               ret = phydrv->suspend(phydev);
-
-       return ret;
+       if (!mdio_bus_phy_may_suspend(phydev))
+               return 0;
+       return phydrv->suspend(phydev);
 }
 
 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_driver *phydrv = to_phy_driver(dev->driver);
        struct phy_device *phydev = to_phy_device(dev);
 
-       if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent))
-               ret = phydrv->resume(phydev);
-
-       return ret;
+       if (!mdio_bus_phy_may_suspend(phydev))
+               return 0;
+       return phydrv->resume(phydev);
 }
 
 struct bus_type mdio_bus_type = {
index 7b2728b8f1b7327e77c92dd4afa93c712af2a36d..4405a76ed3da197344955924ad3a3e7eef10e11e 100644 (file)
 #include <net/slhc_vj.h>
 #include <asm/atomic.h>
 
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #define PPP_VERSION    "2.4.2"
 
 /*
@@ -131,6 +135,7 @@ struct ppp {
        struct sock_filter *active_filter;/* filter for pkts to reset idle */
        unsigned pass_len, active_len;
 #endif /* CONFIG_PPP_FILTER */
+       struct net      *ppp_net;       /* the net we belong to */
 };
 
 /*
@@ -155,6 +160,7 @@ struct channel {
        struct rw_semaphore chan_sem;   /* protects `chan' during chan ioctl */
        spinlock_t      downl;          /* protects `chan', file.xq dequeue */
        struct ppp      *ppp;           /* ppp unit we're connected to */
+       struct net      *chan_net;      /* the net channel belongs to */
        struct list_head clist;         /* link in list of channels per unit */
        rwlock_t        upl;            /* protects `ppp' */
 #ifdef CONFIG_PPP_MULTILINK
@@ -173,26 +179,35 @@ struct channel {
  * channel.downl.
  */
 
-/*
- * 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 atomic_t ppp_unit_count = ATOMIC_INIT(0);
-static DEFINE_IDR(ppp_units_idr);
-
-/*
- * all_channels_lock protects all_channels and last_channel_index,
- * and the atomicity of find a channel and updating its file.refcnt
- * field.
- */
-static DEFINE_SPINLOCK(all_channels_lock);
-static LIST_HEAD(all_channels);
-static LIST_HEAD(new_channels);
-static int last_channel_index;
 static atomic_t channel_count = ATOMIC_INIT(0);
 
+/* per-net private data for this module */
+static unsigned int ppp_net_id;
+struct ppp_net {
+       /* units to ppp mapping */
+       struct idr units_idr;
+
+       /*
+        * all_ppp_mutex protects the units_idr mapping.
+        * It also ensures that finding a ppp unit in the units_idr
+        * map and updating its file.refcnt field is atomic.
+        */
+       struct mutex all_ppp_mutex;
+
+       /* channels */
+       struct list_head all_channels;
+       struct list_head new_channels;
+       int last_channel_index;
+
+       /*
+        * all_channels_lock protects all_channels and
+        * last_channel_index, and the atomicity of find
+        * a channel and updating its file.refcnt field.
+        */
+       spinlock_t all_channels_lock;
+};
+
 /* Get the PPP protocol number from a skb */
 #define PPP_PROTO(skb) (((skb)->data[0] << 8) + (skb)->data[1])
 
@@ -216,8 +231,8 @@ static atomic_t channel_count = ATOMIC_INIT(0);
 #define seq_after(a, b)                ((s32)((a) - (b)) > 0)
 
 /* Prototypes. */
-static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
-                               unsigned int cmd, unsigned long arg);
+static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
+                       struct file *file, unsigned int cmd, unsigned long arg);
 static void ppp_xmit_process(struct ppp *ppp);
 static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
 static void ppp_push(struct ppp *ppp);
@@ -240,12 +255,12 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
 static void ppp_ccp_closed(struct ppp *ppp);
 static struct compressor *find_compressor(int type);
 static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
-static struct ppp *ppp_create_interface(int unit, int *retp);
+static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
 static void init_ppp_file(struct ppp_file *pf, int kind);
 static void ppp_shutdown_interface(struct ppp *ppp);
 static void ppp_destroy_interface(struct ppp *ppp);
-static struct ppp *ppp_find_unit(int unit);
-static struct channel *ppp_find_channel(int unit);
+static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
+static struct channel *ppp_find_channel(struct ppp_net *pn, 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);
@@ -256,6 +271,14 @@ static void *unit_find(struct idr *p, int n);
 
 static struct class *ppp_class;
 
+/* per net-namespace data */
+static inline struct ppp_net *ppp_pernet(struct net *net)
+{
+       BUG_ON(!net);
+
+       return net_generic(net, ppp_net_id);
+}
+
 /* Translates a PPP protocol number to a NP index (NP == network protocol) */
 static inline int proto_to_npindex(int proto)
 {
@@ -544,7 +567,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        int __user *p = argp;
 
        if (!pf)
-               return ppp_unattached_ioctl(pf, file, cmd, arg);
+               return ppp_unattached_ioctl(current->nsproxy->net_ns,
+                                       pf, file, cmd, arg);
 
        if (cmd == PPPIOCDETACH) {
                /*
@@ -763,12 +787,13 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        return err;
 }
 
-static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
-                               unsigned int cmd, unsigned long arg)
+static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
+                       struct file *file, unsigned int cmd, unsigned long arg)
 {
        int unit, err = -EFAULT;
        struct ppp *ppp;
        struct channel *chan;
+       struct ppp_net *pn;
        int __user *p = (int __user *)arg;
 
        lock_kernel();
@@ -777,7 +802,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
                /* Create a new ppp unit */
                if (get_user(unit, p))
                        break;
-               ppp = ppp_create_interface(unit, &err);
+               ppp = ppp_create_interface(net, unit, &err);
                if (!ppp)
                        break;
                file->private_data = &ppp->file;
@@ -792,29 +817,31 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
                /* Attach to an existing ppp unit */
                if (get_user(unit, p))
                        break;
-               mutex_lock(&all_ppp_mutex);
                err = -ENXIO;
-               ppp = ppp_find_unit(unit);
+               pn = ppp_pernet(net);
+               mutex_lock(&pn->all_ppp_mutex);
+               ppp = ppp_find_unit(pn, unit);
                if (ppp) {
                        atomic_inc(&ppp->file.refcnt);
                        file->private_data = &ppp->file;
                        err = 0;
                }
-               mutex_unlock(&all_ppp_mutex);
+               mutex_unlock(&pn->all_ppp_mutex);
                break;
 
        case PPPIOCATTCHAN:
                if (get_user(unit, p))
                        break;
-               spin_lock_bh(&all_channels_lock);
                err = -ENXIO;
-               chan = ppp_find_channel(unit);
+               pn = ppp_pernet(net);
+               spin_lock_bh(&pn->all_channels_lock);
+               chan = ppp_find_channel(pn, unit);
                if (chan) {
                        atomic_inc(&chan->file.refcnt);
                        file->private_data = &chan->file;
                        err = 0;
                }
-               spin_unlock_bh(&all_channels_lock);
+               spin_unlock_bh(&pn->all_channels_lock);
                break;
 
        default:
@@ -834,6 +861,51 @@ static const struct file_operations ppp_device_fops = {
        .release        = ppp_release
 };
 
+static __net_init int ppp_init_net(struct net *net)
+{
+       struct ppp_net *pn;
+       int err;
+
+       pn = kzalloc(sizeof(*pn), GFP_KERNEL);
+       if (!pn)
+               return -ENOMEM;
+
+       idr_init(&pn->units_idr);
+       mutex_init(&pn->all_ppp_mutex);
+
+       INIT_LIST_HEAD(&pn->all_channels);
+       INIT_LIST_HEAD(&pn->new_channels);
+
+       spin_lock_init(&pn->all_channels_lock);
+
+       err = net_assign_generic(net, ppp_net_id, pn);
+       if (err) {
+               kfree(pn);
+               return err;
+       }
+
+       return 0;
+}
+
+static __net_exit void ppp_exit_net(struct net *net)
+{
+       struct ppp_net *pn;
+
+       pn = net_generic(net, ppp_net_id);
+       idr_destroy(&pn->units_idr);
+       /*
+        * if someone has cached our net then
+        * further net_generic call will return NULL
+        */
+       net_assign_generic(net, ppp_net_id, NULL);
+       kfree(pn);
+}
+
+static __net_initdata struct pernet_operations ppp_net_ops = {
+       .init = ppp_init_net,
+       .exit = ppp_exit_net,
+};
+
 #define PPP_MAJOR      108
 
 /* Called at boot time if ppp is compiled into the kernel,
@@ -843,25 +915,36 @@ static int __init ppp_init(void)
        int err;
 
        printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
-       err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
-       if (!err) {
-               ppp_class = class_create(THIS_MODULE, "ppp");
-               if (IS_ERR(ppp_class)) {
-                       err = PTR_ERR(ppp_class);
-                       goto out_chrdev;
-               }
-               device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
-                             "ppp");
+
+       err = register_pernet_gen_device(&ppp_net_id, &ppp_net_ops);
+       if (err) {
+               printk(KERN_ERR "failed to register PPP pernet device (%d)\n", err);
+               goto out;
        }
 
-out:
-       if (err)
+       err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
+       if (err) {
                printk(KERN_ERR "failed to register PPP device (%d)\n", err);
-       return err;
+               goto out_net;
+       }
+
+       ppp_class = class_create(THIS_MODULE, "ppp");
+       if (IS_ERR(ppp_class)) {
+               err = PTR_ERR(ppp_class);
+               goto out_chrdev;
+       }
+
+       /* not a big deal if we fail here :-) */
+       device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+
+       return 0;
 
 out_chrdev:
        unregister_chrdev(PPP_MAJOR, "ppp");
-       goto out;
+out_net:
+       unregister_pernet_gen_device(ppp_net_id, &ppp_net_ops);
+out:
+       return err;
 }
 
 /*
@@ -969,6 +1052,7 @@ static void ppp_setup(struct net_device *dev)
        dev->tx_queue_len = 3;
        dev->type = ARPHRD_PPP;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+       dev->features |= NETIF_F_NETNS_LOCAL;
 }
 
 /*
@@ -1986,19 +2070,27 @@ ppp_mp_reconstruct(struct ppp *ppp)
  * Channel interface.
  */
 
-/*
- * Create a new, unattached ppp channel.
- */
-int
-ppp_register_channel(struct ppp_channel *chan)
+/* Create a new, unattached ppp channel. */
+int ppp_register_channel(struct ppp_channel *chan)
+{
+       return ppp_register_net_channel(current->nsproxy->net_ns, chan);
+}
+
+/* Create a new, unattached ppp channel for specified net. */
+int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
 {
        struct channel *pch;
+       struct ppp_net *pn;
 
        pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
        if (!pch)
                return -ENOMEM;
+
+       pn = ppp_pernet(net);
+
        pch->ppp = NULL;
        pch->chan = chan;
+       pch->chan_net = net;
        chan->ppp = pch;
        init_ppp_file(&pch->file, CHANNEL);
        pch->file.hdrlen = chan->hdrlen;
@@ -2008,11 +2100,13 @@ ppp_register_channel(struct ppp_channel *chan)
        init_rwsem(&pch->chan_sem);
        spin_lock_init(&pch->downl);
        rwlock_init(&pch->upl);
-       spin_lock_bh(&all_channels_lock);
-       pch->file.index = ++last_channel_index;
-       list_add(&pch->list, &new_channels);
+
+       spin_lock_bh(&pn->all_channels_lock);
+       pch->file.index = ++pn->last_channel_index;
+       list_add(&pch->list, &pn->new_channels);
        atomic_inc(&channel_count);
-       spin_unlock_bh(&all_channels_lock);
+       spin_unlock_bh(&pn->all_channels_lock);
+
        return 0;
 }
 
@@ -2053,9 +2147,11 @@ void
 ppp_unregister_channel(struct ppp_channel *chan)
 {
        struct channel *pch = chan->ppp;
+       struct ppp_net *pn;
 
        if (!pch)
                return;         /* should never happen */
+
        chan->ppp = NULL;
 
        /*
@@ -2068,9 +2164,12 @@ ppp_unregister_channel(struct ppp_channel *chan)
        spin_unlock_bh(&pch->downl);
        up_write(&pch->chan_sem);
        ppp_disconnect_channel(pch);
-       spin_lock_bh(&all_channels_lock);
+
+       pn = ppp_pernet(pch->chan_net);
+       spin_lock_bh(&pn->all_channels_lock);
        list_del(&pch->list);
-       spin_unlock_bh(&all_channels_lock);
+       spin_unlock_bh(&pn->all_channels_lock);
+
        pch->file.dead = 1;
        wake_up_interruptible(&pch->file.rwait);
        if (atomic_dec_and_test(&pch->file.refcnt))
@@ -2395,9 +2494,10 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
  * unit == -1 means allocate a new number.
  */
 static struct ppp *
-ppp_create_interface(int unit, int *retp)
+ppp_create_interface(struct net *net, int unit, int *retp)
 {
        struct ppp *ppp;
+       struct ppp_net *pn;
        struct net_device *dev = NULL;
        int ret = -ENOMEM;
        int i;
@@ -2406,6 +2506,8 @@ ppp_create_interface(int unit, int *retp)
        if (!dev)
                goto out1;
 
+       pn = ppp_pernet(net);
+
        ppp = netdev_priv(dev);
        ppp->dev = dev;
        ppp->mru = PPP_MRU;
@@ -2421,17 +2523,23 @@ ppp_create_interface(int unit, int *retp)
        skb_queue_head_init(&ppp->mrq);
 #endif /* CONFIG_PPP_MULTILINK */
 
+       /*
+        * drum roll: don't forget to set
+        * the net device is belong to
+        */
+       dev_net_set(dev, net);
+
        ret = -EEXIST;
-       mutex_lock(&all_ppp_mutex);
+       mutex_lock(&pn->all_ppp_mutex);
 
        if (unit < 0) {
-               unit = unit_get(&ppp_units_idr, ppp);
+               unit = unit_get(&pn->units_idr, ppp);
                if (unit < 0) {
                        *retp = unit;
                        goto out2;
                }
        } else {
-               if (unit_find(&ppp_units_idr, unit))
+               if (unit_find(&pn->units_idr, unit))
                        goto out2; /* unit already exists */
                /*
                 * if caller need a specified unit number
@@ -2442,7 +2550,7 @@ ppp_create_interface(int unit, int *retp)
                 * fair but at least pppd will ask us to allocate
                 * new unit in this case so user is happy :)
                 */
-               unit = unit_set(&ppp_units_idr, ppp, unit);
+               unit = unit_set(&pn->units_idr, ppp, unit);
                if (unit < 0)
                        goto out2;
        }
@@ -2453,20 +2561,22 @@ ppp_create_interface(int unit, int *retp)
 
        ret = register_netdev(dev);
        if (ret != 0) {
-               unit_put(&ppp_units_idr, unit);
+               unit_put(&pn->units_idr, unit);
                printk(KERN_ERR "PPP: couldn't register device %s (%d)\n",
                       dev->name, ret);
                goto out2;
        }
 
+       ppp->ppp_net = net;
+
        atomic_inc(&ppp_unit_count);
-       mutex_unlock(&all_ppp_mutex);
+       mutex_unlock(&pn->all_ppp_mutex);
 
        *retp = 0;
        return ppp;
 
 out2:
-       mutex_unlock(&all_ppp_mutex);
+       mutex_unlock(&pn->all_ppp_mutex);
        free_netdev(dev);
 out1:
        *retp = ret;
@@ -2492,7 +2602,11 @@ init_ppp_file(struct ppp_file *pf, int kind)
  */
 static void ppp_shutdown_interface(struct ppp *ppp)
 {
-       mutex_lock(&all_ppp_mutex);
+       struct ppp_net *pn;
+
+       pn = ppp_pernet(ppp->ppp_net);
+       mutex_lock(&pn->all_ppp_mutex);
+
        /* This will call dev_close() for us. */
        ppp_lock(ppp);
        if (!ppp->closing) {
@@ -2502,11 +2616,12 @@ static void ppp_shutdown_interface(struct ppp *ppp)
        } else
                ppp_unlock(ppp);
 
-       unit_put(&ppp_units_idr, ppp->file.index);
+       unit_put(&pn->units_idr, ppp->file.index);
        ppp->file.dead = 1;
        ppp->owner = NULL;
        wake_up_interruptible(&ppp->file.rwait);
-       mutex_unlock(&all_ppp_mutex);
+
+       mutex_unlock(&pn->all_ppp_mutex);
 }
 
 /*
@@ -2554,9 +2669,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
  * The caller should have locked the all_ppp_mutex.
  */
 static struct ppp *
-ppp_find_unit(int unit)
+ppp_find_unit(struct ppp_net *pn, int unit)
 {
-       return unit_find(&ppp_units_idr, unit);
+       return unit_find(&pn->units_idr, unit);
 }
 
 /*
@@ -2568,20 +2683,22 @@ ppp_find_unit(int unit)
  * when we have a lot of channels in use.
  */
 static struct channel *
-ppp_find_channel(int unit)
+ppp_find_channel(struct ppp_net *pn, int unit)
 {
        struct channel *pch;
 
-       list_for_each_entry(pch, &new_channels, list) {
+       list_for_each_entry(pch, &pn->new_channels, list) {
                if (pch->file.index == unit) {
-                       list_move(&pch->list, &all_channels);
+                       list_move(&pch->list, &pn->all_channels);
                        return pch;
                }
        }
-       list_for_each_entry(pch, &all_channels, list) {
+
+       list_for_each_entry(pch, &pn->all_channels, list) {
                if (pch->file.index == unit)
                        return pch;
        }
+
        return NULL;
 }
 
@@ -2592,11 +2709,14 @@ static int
 ppp_connect_channel(struct channel *pch, int unit)
 {
        struct ppp *ppp;
+       struct ppp_net *pn;
        int ret = -ENXIO;
        int hdrlen;
 
-       mutex_lock(&all_ppp_mutex);
-       ppp = ppp_find_unit(unit);
+       pn = ppp_pernet(pch->chan_net);
+
+       mutex_lock(&pn->all_ppp_mutex);
+       ppp = ppp_find_unit(pn, unit);
        if (!ppp)
                goto out;
        write_lock_bh(&pch->upl);
@@ -2620,7 +2740,7 @@ ppp_connect_channel(struct channel *pch, int unit)
  outl:
        write_unlock_bh(&pch->upl);
  out:
-       mutex_unlock(&all_ppp_mutex);
+       mutex_unlock(&pn->all_ppp_mutex);
        return ret;
 }
 
@@ -2677,7 +2797,7 @@ static void __exit ppp_cleanup(void)
        unregister_chrdev(PPP_MAJOR, "ppp");
        device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
        class_destroy(ppp_class);
-       idr_destroy(&ppp_units_idr);
+       unregister_pernet_gen_device(ppp_net_id, &ppp_net_ops);
 }
 
 /*
@@ -2743,6 +2863,7 @@ static void *unit_find(struct idr *p, int n)
 module_init(ppp_init);
 module_exit(ppp_cleanup);
 
+EXPORT_SYMBOL(ppp_register_net_channel);
 EXPORT_SYMBOL(ppp_register_channel);
 EXPORT_SYMBOL(ppp_unregister_channel);
 EXPORT_SYMBOL(ppp_channel_index);
index c22b30533a14cb89eeeda69a83317f80e8c383b3..1011fd64108b1718500bfc3121545feb8bef59d7 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+#include <linux/nsproxy.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
 #include <net/sock.h>
 
 #include <asm/uaccess.h>
 
 #define PPPOE_HASH_BITS 4
-#define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS)
-
-static struct ppp_channel_ops pppoe_chan_ops;
+#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
+#define PPPOE_HASH_MASK        (PPPOE_HASH_SIZE - 1)
 
 static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
 static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
 
 static const struct proto_ops pppoe_ops;
-static DEFINE_RWLOCK(pppoe_hash_lock);
-
 static struct ppp_channel_ops pppoe_chan_ops;
 
+/* per-net private data for this module */
+static unsigned int pppoe_net_id;
+struct pppoe_net {
+       /*
+        * we could use _single_ hash table for all
+        * nets by injecting net id into the hash but
+        * it would increase hash chains and add
+        * a few additional math comparations messy
+        * as well, moreover in case of SMP less locking
+        * controversy here
+        */
+       struct pppox_sock *hash_table[PPPOE_HASH_SIZE];
+       rwlock_t hash_lock;
+};
+
+/* to eliminate a race btw pppoe_flush_dev and pppoe_release */
+static DEFINE_SPINLOCK(flush_lock);
+
+/*
+ * PPPoE could be in the following stages:
+ * 1) Discovery stage (to obtain remote MAC and Session ID)
+ * 2) Session stage (MAC and SID are known)
+ *
+ * Ethernet frames have a special tag for this but
+ * we use simplier approach based on session id
+ */
+static inline bool stage_session(__be16 sid)
+{
+       return sid != 0;
+}
+
+static inline struct pppoe_net *pppoe_pernet(struct net *net)
+{
+       BUG_ON(!net);
+
+       return net_generic(net, pppoe_net_id);
+}
+
 static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b)
 {
-       return (a->sid == b->sid &&
-               (memcmp(a->remote, b->remote, ETH_ALEN) == 0));
+       return a->sid == b->sid && !memcmp(a->remote, b->remote, ETH_ALEN);
 }
 
 static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr)
 {
-       return (a->sid == sid &&
-               (memcmp(a->remote,addr,ETH_ALEN) == 0));
+       return a->sid == sid && !memcmp(a->remote, addr, ETH_ALEN);
 }
 
-#if 8%PPPOE_HASH_BITS
+#if 8 % PPPOE_HASH_BITS
 #error 8 must be a multiple of PPPOE_HASH_BITS
 #endif
 
@@ -118,69 +153,71 @@ static int hash_item(__be16 sid, unsigned char *addr)
        unsigned char hash = 0;
        unsigned int i;
 
-       for (i = 0 ; i < ETH_ALEN ; i++) {
+       for (i = 0; i < ETH_ALEN; i++)
                hash ^= addr[i];
-       }
-       for (i = 0 ; i < sizeof(sid_t)*8 ; i += 8 ){
-               hash ^= (__force __u32)sid>>i;
-       }
-       for (i = 8 ; (i>>=1) >= PPPOE_HASH_BITS ; ) {
-               hash ^= hash>>i;
-       }
+       for (i = 0; i < sizeof(sid_t) * 8; i += 8)
+               hash ^= (__force __u32)sid >> i;
+       for (i = 8; (i >>= 1) >= PPPOE_HASH_BITS;)
+               hash ^= hash >> i;
 
-       return hash & ( PPPOE_HASH_SIZE - 1 );
+       return hash & PPPOE_HASH_MASK;
 }
 
-/* zeroed because its in .bss */
-static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE];
-
 /**********************************************************************
  *
  *  Set/get/delete/rehash items  (internal versions)
  *
  **********************************************************************/
-static struct pppox_sock *__get_item(__be16 sid, unsigned char *addr, int ifindex)
+static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid,
+                               unsigned char *addr, int ifindex)
 {
        int hash = hash_item(sid, addr);
        struct pppox_sock *ret;
 
-       ret = item_hash_table[hash];
+       ret = pn->hash_table[hash];
+       while (ret) {
+               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
+                   ret->pppoe_ifindex == ifindex)
+                       return ret;
 
-       while (ret && !(cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex))
                ret = ret->next;
+       }
 
-       return ret;
+       return NULL;
 }
 
-static int __set_item(struct pppox_sock *po)
+static int __set_item(struct pppoe_net *pn, struct pppox_sock *po)
 {
        int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
        struct pppox_sock *ret;
 
-       ret = item_hash_table[hash];
+       ret = pn->hash_table[hash];
        while (ret) {
-               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_ifindex == po->pppoe_ifindex)
+               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) &&
+                   ret->pppoe_ifindex == po->pppoe_ifindex)
                        return -EALREADY;
 
                ret = ret->next;
        }
 
-       po->next = item_hash_table[hash];
-       item_hash_table[hash] = po;
+       po->next = pn->hash_table[hash];
+       pn->hash_table[hash] = po;
 
        return 0;
 }
 
-static struct pppox_sock *__delete_item(__be16 sid, char *addr, int ifindex)
+static struct pppox_sock *__delete_item(struct pppoe_net *pn, __be16 sid,
+                                       char *addr, int ifindex)
 {
        int hash = hash_item(sid, addr);
        struct pppox_sock *ret, **src;
 
-       ret = item_hash_table[hash];
-       src = &item_hash_table[hash];
+       ret = pn->hash_table[hash];
+       src = &pn->hash_table[hash];
 
        while (ret) {
-               if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex) {
+               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
+                   ret->pppoe_ifindex == ifindex) {
                        *src = ret->next;
                        break;
                }
@@ -197,46 +234,54 @@ static struct pppox_sock *__delete_item(__be16 sid, char *addr, int ifindex)
  *  Set/get/delete/rehash items
  *
  **********************************************************************/
-static inline struct pppox_sock *get_item(__be16 sid,
-                                        unsigned char *addr, int ifindex)
+static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid,
+                                       unsigned char *addr, int ifindex)
 {
        struct pppox_sock *po;
 
-       read_lock_bh(&pppoe_hash_lock);
-       po = __get_item(sid, addr, ifindex);
+       read_lock_bh(&pn->hash_lock);
+       po = __get_item(pn, sid, addr, ifindex);
        if (po)
                sock_hold(sk_pppox(po));
-       read_unlock_bh(&pppoe_hash_lock);
+       read_unlock_bh(&pn->hash_lock);
 
        return po;
 }
 
-static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp)
+static inline struct pppox_sock *get_item_by_addr(struct net *net,
+                                               struct sockaddr_pppox *sp)
 {
        struct net_device *dev;
+       struct pppoe_net *pn;
+       struct pppox_sock *pppox_sock;
+
        int ifindex;
 
-       dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
-       if(!dev)
+       dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev);
+       if (!dev)
                return NULL;
+
        ifindex = dev->ifindex;
+       pn = net_generic(net, pppoe_net_id);
+       pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid,
+                               sp->sa_addr.pppoe.remote, ifindex);
        dev_put(dev);
-       return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex);
+
+       return pppox_sock;
 }
 
-static inline struct pppox_sock *delete_item(__be16 sid, char *addr, int ifindex)
+static inline struct pppox_sock *delete_item(struct pppoe_net *pn, __be16 sid,
+                                       char *addr, int ifindex)
 {
        struct pppox_sock *ret;
 
-       write_lock_bh(&pppoe_hash_lock);
-       ret = __delete_item(sid, addr, ifindex);
-       write_unlock_bh(&pppoe_hash_lock);
+       write_lock_bh(&pn->hash_lock);
+       ret = __delete_item(pn, sid, addr, ifindex);
+       write_unlock_bh(&pn->hash_lock);
 
        return ret;
 }
 
-
-
 /***************************************************************************
  *
  *  Handler for device events.
@@ -246,25 +291,33 @@ static inline struct pppox_sock *delete_item(__be16 sid, char *addr, int ifindex
 
 static void pppoe_flush_dev(struct net_device *dev)
 {
-       int hash;
+       struct pppoe_net *pn;
+       int i;
+
        BUG_ON(dev == NULL);
 
-       write_lock_bh(&pppoe_hash_lock);
-       for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) {
-               struct pppox_sock *po = item_hash_table[hash];
+       pn = pppoe_pernet(dev_net(dev));
+       if (!pn) /* already freed */
+               return;
+
+       write_lock_bh(&pn->hash_lock);
+       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+               struct pppox_sock *po = pn->hash_table[i];
 
                while (po != NULL) {
-                       struct sock *sk = sk_pppox(po);
+                       struct sock *sk;
                        if (po->pppoe_dev != dev) {
                                po = po->next;
                                continue;
                        }
+                       sk = sk_pppox(po);
+                       spin_lock(&flush_lock);
                        po->pppoe_dev = NULL;
+                       spin_unlock(&flush_lock);
                        dev_put(dev);
 
-
                        /* We always grab the socket lock, followed by the
-                        * pppoe_hash_lock, in that order.  Since we should
+                        * hash_lock, in that order.  Since we should
                         * hold the sock lock while doing any unbinding,
                         * we need to release the lock we're holding.
                         * Hold a reference to the sock so it doesn't disappear
@@ -273,7 +326,7 @@ static void pppoe_flush_dev(struct net_device *dev)
 
                        sock_hold(sk);
 
-                       write_unlock_bh(&pppoe_hash_lock);
+                       write_unlock_bh(&pn->hash_lock);
                        lock_sock(sk);
 
                        if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
@@ -289,20 +342,17 @@ static void pppoe_flush_dev(struct net_device *dev)
                         * While the lock was dropped the chain contents may
                         * have changed.
                         */
-                       write_lock_bh(&pppoe_hash_lock);
-                       po = item_hash_table[hash];
+                       write_lock_bh(&pn->hash_lock);
+                       po = pn->hash_table[i];
                }
        }
-       write_unlock_bh(&pppoe_hash_lock);
+       write_unlock_bh(&pn->hash_lock);
 }
 
 static int pppoe_device_event(struct notifier_block *this,
                              unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *) ptr;
-
-       if (dev_net(dev) != &init_net)
-               return NOTIFY_DONE;
+       struct net_device *dev = (struct net_device *)ptr;
 
        /* Only look at sockets that are using this specific device. */
        switch (event) {
@@ -324,12 +374,10 @@ static int pppoe_device_event(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
-
 static struct notifier_block pppoe_notifier = {
        .notifier_call = pppoe_device_event,
 };
 
-
 /************************************************************************
  *
  * Do the real work of receiving a PPPoE Session frame.
@@ -343,8 +391,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
        if (sk->sk_state & PPPOX_BOUND) {
                ppp_input(&po->chan, skb);
        } else if (sk->sk_state & PPPOX_RELAY) {
-               relay_po = get_item_by_addr(&po->pppoe_relay);
-
+               relay_po = get_item_by_addr(dev_net(po->pppoe_dev),
+                                               &po->pppoe_relay);
                if (relay_po == NULL)
                        goto abort_kfree;
 
@@ -373,22 +421,18 @@ abort_kfree:
  * Receive wrapper called in BH context.
  *
  ***********************************************************************/
-static int pppoe_rcv(struct sk_buff *skb,
-                    struct net_device *dev,
-                    struct packet_type *pt,
-                    struct net_device *orig_dev)
-
+static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
+                    struct packet_type *pt, struct net_device *orig_dev)
 {
        struct pppoe_hdr *ph;
        struct pppox_sock *po;
+       struct pppoe_net *pn;
        int len;
 
-       if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
                goto out;
 
-       if (dev_net(dev) != &init_net)
-               goto drop;
-
        if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
                goto drop;
 
@@ -402,7 +446,8 @@ static int pppoe_rcv(struct sk_buff *skb,
        if (pskb_trim_rcsum(skb, len))
                goto drop;
 
-       po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
+       pn = pppoe_pernet(dev_net(dev));
+       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
        if (!po)
                goto drop;
 
@@ -420,19 +465,16 @@ out:
  * This is solely for detection of PADT frames
  *
  ***********************************************************************/
-static int pppoe_disc_rcv(struct sk_buff *skb,
-                         struct net_device *dev,
-                         struct packet_type *pt,
-                         struct net_device *orig_dev)
+static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
+                         struct packet_type *pt, struct net_device *orig_dev)
 
 {
        struct pppoe_hdr *ph;
        struct pppox_sock *po;
+       struct pppoe_net *pn;
 
-       if (dev_net(dev) != &init_net)
-               goto abort;
-
-       if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
                goto out;
 
        if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
@@ -442,7 +484,8 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
        if (ph->code != PADT_CODE)
                goto abort;
 
-       po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
+       pn = pppoe_pernet(dev_net(dev));
+       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
        if (po) {
                struct sock *sk = sk_pppox(po);
 
@@ -471,12 +514,12 @@ out:
 }
 
 static struct packet_type pppoes_ptype = {
-       .type   = __constant_htons(ETH_P_PPP_SES),
+       .type   = cpu_to_be16(ETH_P_PPP_SES),
        .func   = pppoe_rcv,
 };
 
 static struct packet_type pppoed_ptype = {
-       .type   = __constant_htons(ETH_P_PPP_DISC),
+       .type   = cpu_to_be16(ETH_P_PPP_DISC),
        .func   = pppoe_disc_rcv,
 };
 
@@ -493,38 +536,37 @@ static struct proto pppoe_sk_proto = {
  **********************************************************************/
 static int pppoe_create(struct net *net, struct socket *sock)
 {
-       int error = -ENOMEM;
        struct sock *sk;
 
        sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto);
        if (!sk)
-               goto out;
+               return -ENOMEM;
 
        sock_init_data(sock, sk);
 
-       sock->state = SS_UNCONNECTED;
-       sock->ops   = &pppoe_ops;
+       sock->state     = SS_UNCONNECTED;
+       sock->ops       = &pppoe_ops;
 
-       sk->sk_backlog_rcv = pppoe_rcv_core;
-       sk->sk_state       = PPPOX_NONE;
-       sk->sk_type        = SOCK_STREAM;
-       sk->sk_family      = PF_PPPOX;
-       sk->sk_protocol    = PX_PROTO_OE;
+       sk->sk_backlog_rcv      = pppoe_rcv_core;
+       sk->sk_state            = PPPOX_NONE;
+       sk->sk_type             = SOCK_STREAM;
+       sk->sk_family           = PF_PPPOX;
+       sk->sk_protocol         = PX_PROTO_OE;
 
-       error = 0;
-out:   return error;
+       return 0;
 }
 
 static int pppoe_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
        struct pppox_sock *po;
+       struct pppoe_net *pn;
 
        if (!sk)
                return 0;
 
        lock_sock(sk);
-       if (sock_flag(sk, SOCK_DEAD)){
+       if (sock_flag(sk, SOCK_DEAD)) {
                release_sock(sk);
                return -EBADF;
        }
@@ -534,26 +576,39 @@ static int pppoe_release(struct socket *sock)
        /* Signal the death of the socket. */
        sk->sk_state = PPPOX_DEAD;
 
+       /*
+        * pppoe_flush_dev could lead to a race with
+        * this routine so we use flush_lock to eliminate
+        * such a case (we only need per-net specific data)
+        */
+       spin_lock(&flush_lock);
+       po = pppox_sk(sk);
+       if (!po->pppoe_dev) {
+               spin_unlock(&flush_lock);
+               goto out;
+       }
+       pn = pppoe_pernet(dev_net(po->pppoe_dev));
+       spin_unlock(&flush_lock);
 
-       /* Write lock on hash lock protects the entire "po" struct from
-        * concurrent updates via pppoe_flush_dev. The "po" struct should
-        * be considered part of the hash table contents, thus protected
-        * by the hash table lock */
-       write_lock_bh(&pppoe_hash_lock);
+       /*
+        * protect "po" from concurrent updates
+        * on pppoe_flush_dev
+        */
+       write_lock_bh(&pn->hash_lock);
 
        po = pppox_sk(sk);
-       if (po->pppoe_pa.sid) {
-               __delete_item(po->pppoe_pa.sid,
-                             po->pppoe_pa.remote, po->pppoe_ifindex);
-       }
+       if (stage_session(po->pppoe_pa.sid))
+               __delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
+                               po->pppoe_ifindex);
 
        if (po->pppoe_dev) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }
 
-       write_unlock_bh(&pppoe_hash_lock);
+       write_unlock_bh(&pn->hash_lock);
 
+out:
        sock_orphan(sk);
        sock->sk = NULL;
 
@@ -564,14 +619,14 @@ static int pppoe_release(struct socket *sock)
        return 0;
 }
 
-
 static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                  int sockaddr_len, int flags)
 {
        struct sock *sk = sock->sk;
-       struct net_device *dev;
-       struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+       struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr;
        struct pppox_sock *po = pppox_sk(sk);
+       struct net_device *dev;
+       struct pppoe_net *pn;
        int error;
 
        lock_sock(sk);
@@ -582,44 +637,45 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
 
        /* Check for already bound sockets */
        error = -EBUSY;
-       if ((sk->sk_state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid)
+       if ((sk->sk_state & PPPOX_CONNECTED) &&
+            stage_session(sp->sa_addr.pppoe.sid))
                goto end;
 
        /* Check for already disconnected sockets, on attempts to disconnect */
        error = -EALREADY;
-       if ((sk->sk_state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid )
+       if ((sk->sk_state & PPPOX_DEAD) &&
+            !stage_session(sp->sa_addr.pppoe.sid))
                goto end;
 
        error = 0;
-       if (po->pppoe_pa.sid) {
-               pppox_unbind_sock(sk);
-
-               /* Delete the old binding */
-               delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote,po->pppoe_ifindex);
 
-               if(po->pppoe_dev)
+       /* Delete the old binding */
+       if (stage_session(po->pppoe_pa.sid)) {
+               pppox_unbind_sock(sk);
+               if (po->pppoe_dev) {
+                       pn = pppoe_pernet(dev_net(po->pppoe_dev));
+                       delete_item(pn, po->pppoe_pa.sid,
+                               po->pppoe_pa.remote, po->pppoe_ifindex);
                        dev_put(po->pppoe_dev);
-
+               }
                memset(sk_pppox(po) + 1, 0,
                       sizeof(struct pppox_sock) - sizeof(struct sock));
-
                sk->sk_state = PPPOX_NONE;
        }
 
-       /* Don't re-bind if sid==0 */
-       if (sp->sa_addr.pppoe.sid != 0) {
-               dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
-
+       /* Re-bind in session stage only */
+       if (stage_session(sp->sa_addr.pppoe.sid)) {
                error = -ENODEV;
+               dev = dev_get_by_name(sock_net(sk), sp->sa_addr.pppoe.dev);
                if (!dev)
                        goto end;
 
                po->pppoe_dev = dev;
                po->pppoe_ifindex = dev->ifindex;
-
-               write_lock_bh(&pppoe_hash_lock);
-               if (!(dev->flags & IFF_UP)){
-                       write_unlock_bh(&pppoe_hash_lock);
+               pn = pppoe_pernet(dev_net(dev));
+               write_lock_bh(&pn->hash_lock);
+               if (!(dev->flags & IFF_UP)) {
+                       write_unlock_bh(&pn->hash_lock);
                        goto err_put;
                }
 
@@ -627,8 +683,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                       &sp->sa_addr.pppoe,
                       sizeof(struct pppoe_addr));
 
-               error = __set_item(po);
-               write_unlock_bh(&pppoe_hash_lock);
+               error = __set_item(pn, po);
+               write_unlock_bh(&pn->hash_lock);
                if (error < 0)
                        goto err_put;
 
@@ -639,7 +695,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                po->chan.private = sk;
                po->chan.ops = &pppoe_chan_ops;
 
-               error = ppp_register_channel(&po->chan);
+               error = ppp_register_net_channel(dev_net(dev), &po->chan);
                if (error)
                        goto err_put;
 
@@ -648,7 +704,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
 
        po->num = sp->sa_addr.pppoe.sid;
 
- end:
+end:
        release_sock(sk);
        return error;
 err_put:
@@ -659,7 +715,6 @@ err_put:
        goto end;
 }
 
-
 static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
                  int *usockaddr_len, int peer)
 {
@@ -678,7 +733,6 @@ static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
        return 0;
 }
 
-
 static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
                unsigned long arg)
 {
@@ -690,7 +744,6 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
        switch (cmd) {
        case PPPIOCGMRU:
                err = -ENXIO;
-
                if (!(sk->sk_state & PPPOX_CONNECTED))
                        break;
 
@@ -698,7 +751,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
                if (put_user(po->pppoe_dev->mtu -
                             sizeof(struct pppoe_hdr) -
                             PPP_HDRLEN,
-                            (int __user *) arg))
+                            (int __user *)arg))
                        break;
                err = 0;
                break;
@@ -709,7 +762,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
                        break;
 
                err = -EFAULT;
-               if (get_user(val,(int __user *) arg))
+               if (get_user(val, (int __user *)arg))
                        break;
 
                if (val < (po->pppoe_dev->mtu
@@ -722,7 +775,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
 
        case PPPIOCSFLAGS:
                err = -EFAULT;
-               if (get_user(val, (int __user *) arg))
+               if (get_user(val, (int __user *)arg))
                        break;
                err = 0;
                break;
@@ -749,13 +802,12 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
 
                err = -EINVAL;
                if (po->pppoe_relay.sa_family != AF_PPPOX ||
-                   po->pppoe_relay.sa_protocol!= PX_PROTO_OE)
+                   po->pppoe_relay.sa_protocol != PX_PROTO_OE)
                        break;
 
                /* Check that the socket referenced by the address
                   actually exists. */
-               relay_po = get_item_by_addr(&po->pppoe_relay);
-
+               relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay);
                if (!relay_po)
                        break;
 
@@ -781,7 +833,6 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
        return err;
 }
 
-
 static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
                  struct msghdr *m, size_t total_len)
 {
@@ -808,7 +859,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
        dev = po->pppoe_dev;
 
        error = -EMSGSIZE;
-       if (total_len > (dev->mtu + dev->hard_header_len))
+       if (total_len > (dev->mtu + dev->hard_header_len))
                goto end;
 
 
@@ -826,13 +877,12 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
        skb->dev = dev;
 
        skb->priority = sk->sk_priority;
-       skb->protocol = __constant_htons(ETH_P_PPP_SES);
+       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
 
-       ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr));
-       start = (char *) &ph->tag[0];
+       ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr));
+       start = (char *)&ph->tag[0];
 
        error = memcpy_fromiovec(start, m->msg_iov, total_len);
-
        if (error < 0) {
                kfree_skb(skb);
                goto end;
@@ -853,7 +903,6 @@ end:
        return error;
 }
 
-
 /************************************************************************
  *
  * xmit function for internal use.
@@ -888,7 +937,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
        ph->sid = po->num;
        ph->length = htons(data_len);
 
-       skb->protocol = __constant_htons(ETH_P_PPP_SES);
+       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
        skb->dev = dev;
 
        dev_hard_header(skb, dev, ETH_P_PPP_SES,
@@ -903,7 +952,6 @@ abort:
        return 1;
 }
 
-
 /************************************************************************
  *
  * xmit function called by generic PPP driver
@@ -912,11 +960,10 @@ abort:
  ***********************************************************************/
 static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 {
-       struct sock *sk = (struct sock *) chan->private;
+       struct sock *sk = (struct sock *)chan->private;
        return __pppoe_xmit(sk, skb);
 }
 
-
 static struct ppp_channel_ops pppoe_chan_ops = {
        .start_xmit = pppoe_xmit,
 };
@@ -935,7 +982,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                flags & MSG_DONTWAIT, &error);
-
        if (error < 0)
                goto end;
 
@@ -968,44 +1014,47 @@ static int pppoe_seq_show(struct seq_file *seq, void *v)
        dev_name = po->pppoe_pa.dev;
 
        seq_printf(seq, "%08X %pM %8s\n",
-                  po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
+               po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
 out:
        return 0;
 }
 
-static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos)
+static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos)
 {
        struct pppox_sock *po;
-       int i = 0;
+       int i;
 
-       for (; i < PPPOE_HASH_SIZE; i++) {
-               po = item_hash_table[i];
+       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+               po = pn->hash_table[i];
                while (po) {
                        if (!pos--)
                                goto out;
                        po = po->next;
                }
        }
+
 out:
        return po;
 }
 
 static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(pppoe_hash_lock)
+       __acquires(pn->hash_lock)
 {
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
        loff_t l = *pos;
 
-       read_lock_bh(&pppoe_hash_lock);
-       return l ? pppoe_get_idx(--l) : SEQ_START_TOKEN;
+       read_lock_bh(&pn->hash_lock);
+       return l ? pppoe_get_idx(pn, --l) : SEQ_START_TOKEN;
 }
 
 static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
        struct pppox_sock *po;
 
        ++*pos;
        if (v == SEQ_START_TOKEN) {
-               po = pppoe_get_idx(0);
+               po = pppoe_get_idx(pn, 0);
                goto out;
        }
        po = v;
@@ -1015,22 +1064,24 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
 
                while (++hash < PPPOE_HASH_SIZE) {
-                       po = item_hash_table[hash];
+                       po = pn->hash_table[hash];
                        if (po)
                                break;
                }
        }
+
 out:
        return po;
 }
 
 static void pppoe_seq_stop(struct seq_file *seq, void *v)
-       __releases(pppoe_hash_lock)
+       __releases(pn->hash_lock)
 {
-       read_unlock_bh(&pppoe_hash_lock);
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
+       read_unlock_bh(&pn->hash_lock);
 }
 
-static struct seq_operations pppoe_seq_ops = {
+static const struct seq_operations pppoe_seq_ops = {
        .start          = pppoe_seq_start,
        .next           = pppoe_seq_next,
        .stop           = pppoe_seq_stop,
@@ -1039,7 +1090,8 @@ static struct seq_operations pppoe_seq_ops = {
 
 static int pppoe_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open(file, &pppoe_seq_ops);
+       return seq_open_net(inode, file, &pppoe_seq_ops,
+                       sizeof(struct seq_net_private));
 }
 
 static const struct file_operations pppoe_seq_fops = {
@@ -1047,74 +1099,115 @@ static const struct file_operations pppoe_seq_fops = {
        .open           = pppoe_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_net,
 };
 
-static int __init pppoe_proc_init(void)
-{
-       struct proc_dir_entry *p;
-
-       p = proc_net_fops_create(&init_net, "pppoe", S_IRUGO, &pppoe_seq_fops);
-       if (!p)
-               return -ENOMEM;
-       return 0;
-}
-#else /* CONFIG_PROC_FS */
-static inline int pppoe_proc_init(void) { return 0; }
 #endif /* CONFIG_PROC_FS */
 
 static const struct proto_ops pppoe_ops = {
-    .family            = AF_PPPOX,
-    .owner             = THIS_MODULE,
-    .release           = pppoe_release,
-    .bind              = sock_no_bind,
-    .connect           = pppoe_connect,
-    .socketpair                = sock_no_socketpair,
-    .accept            = sock_no_accept,
-    .getname           = pppoe_getname,
-    .poll              = datagram_poll,
-    .listen            = sock_no_listen,
-    .shutdown          = sock_no_shutdown,
-    .setsockopt                = sock_no_setsockopt,
-    .getsockopt                = sock_no_getsockopt,
-    .sendmsg           = pppoe_sendmsg,
-    .recvmsg           = pppoe_recvmsg,
-    .mmap              = sock_no_mmap,
-    .ioctl             = pppox_ioctl,
+       .family         = AF_PPPOX,
+       .owner          = THIS_MODULE,
+       .release        = pppoe_release,
+       .bind           = sock_no_bind,
+       .connect        = pppoe_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .getname        = pppoe_getname,
+       .poll           = datagram_poll,
+       .listen         = sock_no_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = sock_no_setsockopt,
+       .getsockopt     = sock_no_getsockopt,
+       .sendmsg        = pppoe_sendmsg,
+       .recvmsg        = pppoe_recvmsg,
+       .mmap           = sock_no_mmap,
+       .ioctl          = pppox_ioctl,
 };
 
 static struct pppox_proto pppoe_proto = {
-    .create    = pppoe_create,
-    .ioctl     = pppoe_ioctl,
-    .owner     = THIS_MODULE,
+       .create = pppoe_create,
+       .ioctl  = pppoe_ioctl,
+       .owner  = THIS_MODULE,
 };
 
+static __net_init int pppoe_init_net(struct net *net)
+{
+       struct pppoe_net *pn;
+       struct proc_dir_entry *pde;
+       int err;
+
+       pn = kzalloc(sizeof(*pn), GFP_KERNEL);
+       if (!pn)
+               return -ENOMEM;
+
+       rwlock_init(&pn->hash_lock);
+
+       err = net_assign_generic(net, pppoe_net_id, pn);
+       if (err)
+               goto out;
+
+       pde = proc_net_fops_create(net, "pppoe", S_IRUGO, &pppoe_seq_fops);
+#ifdef CONFIG_PROC_FS
+       if (!pde) {
+               err = -ENOMEM;
+               goto out;
+       }
+#endif
+
+       return 0;
+
+out:
+       kfree(pn);
+       return err;
+}
+
+static __net_exit void pppoe_exit_net(struct net *net)
+{
+       struct pppoe_net *pn;
+
+       proc_net_remove(net, "pppoe");
+       pn = net_generic(net, pppoe_net_id);
+       /*
+        * if someone has cached our net then
+        * further net_generic call will return NULL
+        */
+       net_assign_generic(net, pppoe_net_id, NULL);
+       kfree(pn);
+}
+
+static __net_initdata struct pernet_operations pppoe_net_ops = {
+       .init = pppoe_init_net,
+       .exit = pppoe_exit_net,
+};
 
 static int __init pppoe_init(void)
 {
-       int err = proto_register(&pppoe_sk_proto, 0);
+       int err;
 
+       err = proto_register(&pppoe_sk_proto, 0);
        if (err)
                goto out;
 
-       err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+       err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
        if (err)
                goto out_unregister_pppoe_proto;
 
-       err = pppoe_proc_init();
+       err = register_pernet_gen_device(&pppoe_net_id, &pppoe_net_ops);
        if (err)
                goto out_unregister_pppox_proto;
 
        dev_add_pack(&pppoes_ptype);
        dev_add_pack(&pppoed_ptype);
        register_netdevice_notifier(&pppoe_notifier);
-out:
-       return err;
+
+       return 0;
+
 out_unregister_pppox_proto:
        unregister_pppox_proto(PX_PROTO_OE);
 out_unregister_pppoe_proto:
        proto_unregister(&pppoe_sk_proto);
-       goto out;
+out:
+       return err;
 }
 
 static void __exit pppoe_exit(void)
@@ -1123,7 +1216,7 @@ static void __exit pppoe_exit(void)
        dev_remove_pack(&pppoes_ptype);
        dev_remove_pack(&pppoed_ptype);
        unregister_netdevice_notifier(&pppoe_notifier);
-       remove_proc_entry("pppoe", init_net.proc_net);
+       unregister_pernet_gen_device(pppoe_net_id, &pppoe_net_ops);
        proto_unregister(&pppoe_sk_proto);
 }
 
index f1a946785c6aee3bf580ad6015d9b825318c6566..15f4a43a68901d945d0f3345f9cdf1b274630eeb 100644 (file)
@@ -90,7 +90,9 @@
 #include <linux/hash.h>
 #include <linux/sort.h>
 #include <linux/proc_fs.h>
+#include <linux/nsproxy.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
 #include <net/dst.h>
 #include <net/ip.h>
 #include <net/udp.h>
@@ -204,6 +206,7 @@ struct pppol2tp_tunnel
        struct sock             *sock;          /* Parent socket */
        struct list_head        list;           /* Keep a list of all open
                                                 * prepared sockets */
+       struct net              *pppol2tp_net;  /* the net we belong to */
 
        atomic_t                ref_count;
 };
@@ -227,8 +230,20 @@ static atomic_t pppol2tp_tunnel_count;
 static atomic_t pppol2tp_session_count;
 static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
 static struct proto_ops pppol2tp_ops;
-static LIST_HEAD(pppol2tp_tunnel_list);
-static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock);
+
+/* per-net private data for this module */
+static unsigned int pppol2tp_net_id;
+struct pppol2tp_net {
+       struct list_head pppol2tp_tunnel_list;
+       rwlock_t pppol2tp_tunnel_list_lock;
+};
+
+static inline struct pppol2tp_net *pppol2tp_pernet(struct net *net)
+{
+       BUG_ON(!net);
+
+       return net_generic(net, pppol2tp_net_id);
+}
 
 /* Helpers to obtain tunnel/session contexts from sockets.
  */
@@ -321,18 +336,19 @@ pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id)
 
 /* Lookup a tunnel by id
  */
-static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id)
+static struct pppol2tp_tunnel *pppol2tp_tunnel_find(struct net *net, u16 tunnel_id)
 {
-       struct pppol2tp_tunnel *tunnel = NULL;
+       struct pppol2tp_tunnel *tunnel;
+       struct pppol2tp_net *pn = pppol2tp_pernet(net);
 
-       read_lock_bh(&pppol2tp_tunnel_list_lock);
-       list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) {
+       read_lock_bh(&pn->pppol2tp_tunnel_list_lock);
+       list_for_each_entry(tunnel, &pn->pppol2tp_tunnel_list, list) {
                if (tunnel->stats.tunnel_id == tunnel_id) {
-                       read_unlock_bh(&pppol2tp_tunnel_list_lock);
+                       read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
                        return tunnel;
                }
        }
-       read_unlock_bh(&pppol2tp_tunnel_list_lock);
+       read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
 
        return NULL;
 }
@@ -1287,10 +1303,12 @@ again:
  */
 static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel)
 {
+       struct pppol2tp_net *pn = pppol2tp_pernet(tunnel->pppol2tp_net);
+
        /* Remove from socket list */
-       write_lock_bh(&pppol2tp_tunnel_list_lock);
+       write_lock_bh(&pn->pppol2tp_tunnel_list_lock);
        list_del_init(&tunnel->list);
-       write_unlock_bh(&pppol2tp_tunnel_list_lock);
+       write_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
 
        atomic_dec(&pppol2tp_tunnel_count);
        kfree(tunnel);
@@ -1444,13 +1462,14 @@ error:
 /* Internal function to prepare a tunnel (UDP) socket to have PPPoX
  * sockets attached to it.
  */
-static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
-                                                  int *error)
+static struct sock *pppol2tp_prepare_tunnel_socket(struct net *net,
+                                       int fd, u16 tunnel_id, int *error)
 {
        int err;
        struct socket *sock = NULL;
        struct sock *sk;
        struct pppol2tp_tunnel *tunnel;
+       struct pppol2tp_net *pn;
        struct sock *ret = NULL;
 
        /* Get the tunnel UDP socket from the fd, which was opened by
@@ -1524,11 +1543,15 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
        /* Misc init */
        rwlock_init(&tunnel->hlist_lock);
 
+       /* The net we belong to */
+       tunnel->pppol2tp_net = net;
+       pn = pppol2tp_pernet(net);
+
        /* Add tunnel to our list */
        INIT_LIST_HEAD(&tunnel->list);
-       write_lock_bh(&pppol2tp_tunnel_list_lock);
-       list_add(&tunnel->list, &pppol2tp_tunnel_list);
-       write_unlock_bh(&pppol2tp_tunnel_list_lock);
+       write_lock_bh(&pn->pppol2tp_tunnel_list_lock);
+       list_add(&tunnel->list, &pn->pppol2tp_tunnel_list);
+       write_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
        atomic_inc(&pppol2tp_tunnel_count);
 
        /* Bump the reference count. The tunnel context is deleted
@@ -1629,7 +1652,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
         * tunnel id.
         */
        if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
-               tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd,
+               tunnel_sock = pppol2tp_prepare_tunnel_socket(sock_net(sk),
+                                                            sp->pppol2tp.fd,
                                                             sp->pppol2tp.s_tunnel,
                                                             &error);
                if (tunnel_sock == NULL)
@@ -1637,7 +1661,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
 
                tunnel = tunnel_sock->sk_user_data;
        } else {
-               tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel);
+               tunnel = pppol2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel);
 
                /* Error if we can't find the tunnel */
                error = -ENOENT;
@@ -1725,7 +1749,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
        po->chan.ops     = &pppol2tp_chan_ops;
        po->chan.mtu     = session->mtu;
 
-       error = ppp_register_channel(&po->chan);
+       error = ppp_register_net_channel(sock_net(sk), &po->chan);
        if (error)
                goto end_put_tun;
 
@@ -2347,8 +2371,9 @@ end:
 #include <linux/seq_file.h>
 
 struct pppol2tp_seq_data {
-       struct pppol2tp_tunnel *tunnel; /* current tunnel */
-       struct pppol2tp_session *session; /* NULL means get first session in tunnel */
+       struct seq_net_private p;
+       struct pppol2tp_tunnel *tunnel;         /* current tunnel */
+       struct pppol2tp_session *session;       /* NULL means get first session in tunnel */
 };
 
 static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr)
@@ -2384,17 +2409,18 @@ out:
        return session;
 }
 
-static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr)
+static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_net *pn,
+                                          struct pppol2tp_tunnel *curr)
 {
        struct pppol2tp_tunnel *tunnel = NULL;
 
-       read_lock_bh(&pppol2tp_tunnel_list_lock);
-       if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) {
+       read_lock_bh(&pn->pppol2tp_tunnel_list_lock);
+       if (list_is_last(&curr->list, &pn->pppol2tp_tunnel_list)) {
                goto out;
        }
        tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list);
 out:
-       read_unlock_bh(&pppol2tp_tunnel_list_lock);
+       read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
 
        return tunnel;
 }
@@ -2402,6 +2428,7 @@ out:
 static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
 {
        struct pppol2tp_seq_data *pd = SEQ_START_TOKEN;
+       struct pppol2tp_net *pn;
        loff_t pos = *offs;
 
        if (!pos)
@@ -2409,14 +2436,15 @@ static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
 
        BUG_ON(m->private == NULL);
        pd = m->private;
+       pn = pppol2tp_pernet(seq_file_net(m));
 
        if (pd->tunnel == NULL) {
-               if (!list_empty(&pppol2tp_tunnel_list))
-                       pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
+               if (!list_empty(&pn->pppol2tp_tunnel_list))
+                       pd->tunnel = list_entry(pn->pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
        } else {
                pd->session = next_session(pd->tunnel, pd->session);
                if (pd->session == NULL) {
-                       pd->tunnel = next_tunnel(pd->tunnel);
+                       pd->tunnel = next_tunnel(pn, pd->tunnel);
                }
        }
 
@@ -2517,7 +2545,7 @@ out:
        return 0;
 }
 
-static struct seq_operations pppol2tp_seq_ops = {
+static const struct seq_operations pppol2tp_seq_ops = {
        .start          = pppol2tp_seq_start,
        .next           = pppol2tp_seq_next,
        .stop           = pppol2tp_seq_stop,
@@ -2530,51 +2558,18 @@ static struct seq_operations pppol2tp_seq_ops = {
  */
 static int pppol2tp_proc_open(struct inode *inode, struct file *file)
 {
-       struct seq_file *m;
-       struct pppol2tp_seq_data *pd;
-       int ret = 0;
-
-       ret = seq_open(file, &pppol2tp_seq_ops);
-       if (ret < 0)
-               goto out;
-
-       m = file->private_data;
-
-       /* Allocate and fill our proc_data for access later */
-       ret = -ENOMEM;
-       m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL);
-       if (m->private == NULL)
-               goto out;
-
-       pd = m->private;
-       ret = 0;
-
-out:
-       return ret;
-}
-
-/* Called when /proc file access completes.
- */
-static int pppol2tp_proc_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *m = (struct seq_file *)file->private_data;
-
-       kfree(m->private);
-       m->private = NULL;
-
-       return seq_release(inode, file);
+       return seq_open_net(inode, file, &pppol2tp_seq_ops,
+                           sizeof(struct pppol2tp_seq_data));
 }
 
-static struct file_operations pppol2tp_proc_fops = {
+static const struct file_operations pppol2tp_proc_fops = {
        .owner          = THIS_MODULE,
        .open           = pppol2tp_proc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = pppol2tp_proc_release,
+       .release        = seq_release_net,
 };
 
-static struct proc_dir_entry *pppol2tp_proc;
-
 #endif /* CONFIG_PROC_FS */
 
 /*****************************************************************************
@@ -2606,6 +2601,57 @@ static struct pppox_proto pppol2tp_proto = {
        .ioctl          = pppol2tp_ioctl
 };
 
+static __net_init int pppol2tp_init_net(struct net *net)
+{
+       struct pppol2tp_net *pn;
+       struct proc_dir_entry *pde;
+       int err;
+
+       pn = kzalloc(sizeof(*pn), GFP_KERNEL);
+       if (!pn)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&pn->pppol2tp_tunnel_list);
+       rwlock_init(&pn->pppol2tp_tunnel_list_lock);
+
+       err = net_assign_generic(net, pppol2tp_net_id, pn);
+       if (err)
+               goto out;
+
+       pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops);
+#ifdef CONFIG_PROC_FS
+       if (!pde) {
+               err = -ENOMEM;
+               goto out;
+       }
+#endif
+
+       return 0;
+
+out:
+       kfree(pn);
+       return err;
+}
+
+static __net_exit void pppol2tp_exit_net(struct net *net)
+{
+       struct pppoe_net *pn;
+
+       proc_net_remove(net, "pppol2tp");
+       pn = net_generic(net, pppol2tp_net_id);
+       /*
+        * if someone has cached our net then
+        * further net_generic call will return NULL
+        */
+       net_assign_generic(net, pppol2tp_net_id, NULL);
+       kfree(pn);
+}
+
+static __net_initdata struct pernet_operations pppol2tp_net_ops = {
+       .init = pppol2tp_init_net,
+       .exit = pppol2tp_exit_net,
+};
+
 static int __init pppol2tp_init(void)
 {
        int err;
@@ -2617,23 +2663,17 @@ static int __init pppol2tp_init(void)
        if (err)
                goto out_unregister_pppol2tp_proto;
 
-#ifdef CONFIG_PROC_FS
-       pppol2tp_proc = proc_net_fops_create(&init_net, "pppol2tp", 0,
-                                            &pppol2tp_proc_fops);
-       if (!pppol2tp_proc) {
-               err = -ENOMEM;
+       err = register_pernet_gen_device(&pppol2tp_net_id, &pppol2tp_net_ops);
+       if (err)
                goto out_unregister_pppox_proto;
-       }
-#endif /* CONFIG_PROC_FS */
+
        printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
               PPPOL2TP_DRV_VERSION);
 
 out:
        return err;
-#ifdef CONFIG_PROC_FS
 out_unregister_pppox_proto:
        unregister_pppox_proto(PX_PROTO_OL2TP);
-#endif
 out_unregister_pppol2tp_proto:
        proto_unregister(&pppol2tp_sk_proto);
        goto out;
@@ -2642,10 +2682,6 @@ out_unregister_pppol2tp_proto:
 static void __exit pppol2tp_exit(void)
 {
        unregister_pppox_proto(PX_PROTO_OL2TP);
-
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("pppol2tp", init_net.proc_net);
-#endif
        proto_unregister(&pppol2tp_sk_proto);
 }
 
index 03aecc97fb453d32eefb596dddba3f6286d909df..4f6d33fbc673ccb45a95cc56ebe915b712d3b07e 100644 (file)
@@ -108,9 +108,6 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol)
 {
        int rc = -EPROTOTYPE;
 
-       if (net != &init_net)
-               return -EAFNOSUPPORT;
-
        if (protocol < 0 || protocol > PX_MAX_PROTO)
                goto out;
 
index 4b564eda5bd932ef67f8b850c4b947761da31628..30900b30d532e9dedf2b040a672d47d0921e6203 100644 (file)
@@ -745,7 +745,7 @@ static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb,
        /* Move the mac addresses to the top of buffer */
        memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
 
-       veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
+       veth->h_vlan_proto = cpu_to_be16(ETH_P_8021Q);
        veth->h_vlan_TCI = htons(tag);
 
        return skb;
@@ -1403,6 +1403,19 @@ void gelic_net_tx_timeout(struct net_device *netdev)
                atomic_dec(&card->tx_timeout_task_counter);
 }
 
+static const struct net_device_ops gelic_netdevice_ops = {
+       .ndo_open = gelic_net_open,
+       .ndo_stop = gelic_net_stop,
+       .ndo_start_xmit = gelic_net_xmit,
+       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_change_mtu = gelic_net_change_mtu,
+       .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = gelic_net_poll_controller,
+#endif
+};
+
 /**
  * gelic_ether_setup_netdev_ops - initialization of net_device operations
  * @netdev: net_device structure
@@ -1412,21 +1425,12 @@ void gelic_net_tx_timeout(struct net_device *netdev)
 static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
                                         struct napi_struct *napi)
 {
-       netdev->open = &gelic_net_open;
-       netdev->stop = &gelic_net_stop;
-       netdev->hard_start_xmit = &gelic_net_xmit;
-       netdev->set_multicast_list = &gelic_net_set_multi;
-       netdev->change_mtu = &gelic_net_change_mtu;
-       /* tx watchdog */
-       netdev->tx_timeout = &gelic_net_tx_timeout;
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
        /* NAPI */
        netif_napi_add(netdev, napi,
                       gelic_net_poll, GELIC_NET_NAPI_WEIGHT);
        netdev->ethtool_ops = &gelic_ether_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       netdev->poll_controller = gelic_net_poll_controller;
-#endif
+       netdev->netdev_ops = &gelic_netdevice_ops;
 }
 
 /**
index 335da4831ab3ecfa5d142d572e6374a5b63f1800..a5ac2bd58b5ba0c3113e602a992341bee52d867d 100644 (file)
@@ -2697,6 +2697,19 @@ static int gelic_wl_stop(struct net_device *netdev)
 
 /* -- */
 
+static const struct net_device_ops gelic_wl_netdevice_ops = {
+       .ndo_open = gelic_wl_open,
+       .ndo_stop = gelic_wl_stop,
+       .ndo_start_xmit = gelic_net_xmit,
+       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_change_mtu = gelic_net_change_mtu,
+       .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = gelic_net_poll_controller,
+#endif
+};
+
 static struct ethtool_ops gelic_wl_ethtool_ops = {
        .get_drvinfo    = gelic_net_get_drvinfo,
        .get_link       = gelic_wl_get_link,
@@ -2711,21 +2724,12 @@ static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
        struct gelic_wl_info *wl;
        wl = port_wl(netdev_priv(netdev));
        BUG_ON(!wl);
-       netdev->open = &gelic_wl_open;
-       netdev->stop = &gelic_wl_stop;
-       netdev->hard_start_xmit = &gelic_net_xmit;
-       netdev->set_multicast_list = &gelic_net_set_multi;
-       netdev->change_mtu = &gelic_net_change_mtu;
-       netdev->wireless_data = &wl->wireless_data;
-       netdev->wireless_handlers = &gelic_wl_wext_handler_def;
-       /* tx watchdog */
-       netdev->tx_timeout = &gelic_net_tx_timeout;
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
 
        netdev->ethtool_ops = &gelic_wl_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       netdev->poll_controller = gelic_net_poll_controller;
-#endif
+       netdev->netdev_ops = &gelic_wl_netdevice_ops;
+       netdev->wireless_data = &wl->wireless_data;
+       netdev->wireless_handlers = &gelic_wl_wext_handler_def;
 }
 
 /*
index 189ec29ac7a40678787ed8eb3706257268a28e6f..8b2823c8dccfafaf97b3b8c9f698cb25386d34c4 100644 (file)
@@ -2292,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(napi);
+               __napi_complete(napi);
                ql_update_small_bufq_prod_index(qdev);
                ql_update_lrg_bufq_prod_index(qdev);
                writel(qdev->rsp_consumer_index,
@@ -2351,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(&qdev->napi))) {
-                       __netif_rx_schedule(&qdev->napi);
+               if (likely(napi_schedule_prep(&qdev->napi))) {
+                       __napi_schedule(&qdev->napi);
                }
        } else {
                return IRQ_NONE;
index 3d1d7b6e55aa9153d2fddd8b032f6cc5b8346f4b..04bf2122264a84cf6b23bc30f73d0a18ec14f267 100644 (file)
@@ -1446,6 +1446,7 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev,
        qdev->stats.rx_packets++;
        qdev->stats.rx_bytes += skb->len;
        skb->protocol = eth_type_trans(skb, ndev);
+       skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]);
        if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) {
                QPRINTK(qdev, RX_STATUS, DEBUG,
                        "Passing a VLAN packet upstream.\n");
@@ -1652,7 +1653,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
                rx_ring->cq_id);
 
        if (work_done < budget) {
-               __netif_rx_complete(napi);
+               __napi_complete(napi);
                ql_enable_completion_interrupt(qdev, rx_ring->irq);
        }
        return work_done;
@@ -1737,7 +1738,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;
-       netif_rx_schedule(&rx_ring->napi);
+       napi_schedule(&rx_ring->napi);
        return IRQ_HANDLED;
 }
 
@@ -1823,7 +1824,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
                                                              &rx_ring->rx_work,
                                                              0);
                                else
-                                       netif_rx_schedule(&rx_ring->napi);
+                                       napi_schedule(&rx_ring->napi);
                                work_done++;
                        }
                }
index b2dcdb5ed8bde1b3ca424ad17fb310c4b5a2ba5e..3c27a7bfea49f70737004aead04b48f6d44f7d91 100644 (file)
@@ -676,7 +676,7 @@ static int r6040_poll(struct napi_struct *napi, int budget)
        work_done = r6040_rx(dev, budget);
 
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                /* Enable RX interrupt */
                iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
        }
@@ -713,7 +713,7 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
 
                /* Mask off RX interrupt */
                misr &= ~RX_INTS;
-               netif_rx_schedule(&lp->napi);
+               napi_schedule(&lp->napi);
        }
 
        /* TX interrupt request */
index 2c73ca606b35e0942e31a033791f550ed4db481c..1c4a980253fe1730b0bbd18ebc818badc74f9825 100644 (file)
@@ -3581,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(&tp->napi)))
-                       __netif_rx_schedule(&tp->napi);
+               if (likely(napi_schedule_prep(&tp->napi)))
+                       __napi_schedule(&tp->napi);
                else if (netif_msg_intr(tp)) {
                        printk(KERN_INFO "%s: interrupt %04x in poll\n",
                               dev->name, status);
@@ -3603,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(napi);
+               napi_complete(napi);
                tp->intr_mask = 0xffff;
                /*
                 * 20040426: the barrier is not strictly required but the
index f5c57c059bca15c7d9e35f0b26c39fb0551bc718..5cd2291bc0bc7d6f381bafe9f1b917d3e04d0392 100644 (file)
@@ -2852,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(napi);
+               napi_complete(napi);
                /*Re Enable MSI-Rx Vector*/
                addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
                addr += 7 - ring->ring_no;
@@ -2889,7 +2889,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
                        break;
        }
        if (pkts_processed < budget_org) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                /* Re enable the Rx interrupts for the ring */
                writeq(0, &bar0->rx_traffic_mask);
                readl(&bar0->rx_traffic_mask);
@@ -3862,7 +3862,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
        ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries);
        /* We fail init if error or we get less vectors than min required */
        if (ret) {
-               DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+               DBG_PRINT(ERR_DBG, "s2io: Enabling MSI-X failed\n");
                kfree(nic->entries);
                nic->mac_control.stats_info->sw_stat.mem_freed
                        += (nic->num_entries * sizeof(struct msix_entry));
@@ -4342,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(&ring->napi);
+               napi_schedule(&ring->napi);
        } else {
                rx_intr_handler(ring, 0);
                s2io_chk_rx_buffers(sp, ring);
@@ -4789,7 +4789,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
 
                if (config->napi) {
                        if (reason & GEN_INTR_RXTRAFFIC) {
-                               netif_rx_schedule(&sp->napi);
+                               napi_schedule(&sp->napi);
                                writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
                                writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
                                readl(&bar0->rx_traffic_int);
@@ -7542,6 +7542,7 @@ 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:
+       skb_record_rx_queue(skb, ring_no);
        queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
 aggregate:
        sp->mac_control.rings[ring_no].rx_bufs_left -= 1;
@@ -8009,8 +8010,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                if (ret) {
 
                        DBG_PRINT(ERR_DBG,
-                         "%s: MSI-X requested but failed to enable\n",
-                         dev->name);
+                         "s2io: MSI-X requested but failed to enable\n");
                        sp->config.intr_type = INTA;
                }
        }
index 31e38fae017f8def7273d568089914599a1b54d6..88dd2e09832f2875eba2ff0eebbe9f3e2abbb83b 100644 (file)
@@ -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(&sc->napi)) {
+               if (napi_schedule_prep(&sc->napi)) {
                        __raw_writeq(0, sc->sbm_imr);
-                       __netif_rx_schedule(&sc->napi);
+                       __napi_schedule(&sc->napi);
                        /* Depend on the exit from poll to reenable intr */
                }
                else {
@@ -2478,7 +2478,7 @@ static int sbmac_mii_probe(struct net_device *dev)
                return -ENXIO;
        }
 
-       phy_dev = phy_connect(dev, phy_dev->dev.bus_id, &sbmac_mii_poll, 0,
+       phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0,
                              PHY_INTERFACE_MODE_GMII);
        if (IS_ERR(phy_dev)) {
                printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
@@ -2500,7 +2500,7 @@ static int sbmac_mii_probe(struct net_device *dev)
 
        pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
                dev->name, phy_dev->drv->name,
-               phy_dev->dev.bus_id, phy_dev->irq);
+               dev_name(&phy_dev->dev), phy_dev->irq);
 
        sc->phy_dev = phy_dev;
 
@@ -2667,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(napi);
+               napi_complete(napi);
 
 #ifdef CONFIG_SBMAC_COALESCE
                __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
@@ -2697,7 +2697,7 @@ static int __init sbmac_probe(struct platform_device *pldev)
        sbm_base = ioremap_nocache(res->start, res->end - res->start + 1);
        if (!sbm_base) {
                printk(KERN_ERR "%s: unable to map device registers\n",
-                      pldev->dev.bus_id);
+                      dev_name(&pldev->dev));
                err = -ENOMEM;
                goto out_out;
        }
@@ -2708,7 +2708,7 @@ static int __init sbmac_probe(struct platform_device *pldev)
         * If we find a zero, skip this MAC.
         */
        sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR);
-       pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", pldev->dev.bus_id,
+       pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev),
                 sbmac_orig_hwaddr ? "" : "not ", (long long)res->start);
        if (sbmac_orig_hwaddr == 0) {
                err = 0;
@@ -2721,7 +2721,7 @@ static int __init sbmac_probe(struct platform_device *pldev)
        dev = alloc_etherdev(sizeof(struct sbmac_softc));
        if (!dev) {
                printk(KERN_ERR "%s: unable to allocate etherdev\n",
-                      pldev->dev.bus_id);
+                      dev_name(&pldev->dev));
                err = -ENOMEM;
                goto out_unmap;
        }
index 8b75bef4a841a7ae2d13552ea856b2630d14bee9..c13cbf099b88e6ef61fd51ba2cacc6973f4d8e30 100644 (file)
@@ -13,6 +13,9 @@
  *  Both are almost identical and seem to be based on pci-skeleton.c
  *
  *  Rewritten for 2.6 by Cesar Eduardo Barros
+ *
+ *  A datasheet for this chip can be found at
+ *  http://www.silan.com.cn/english/products/pdf/SC92031AY.pdf
  */
 
 /* Note about set_mac_address: I don't know how to change the hardware
 
 #include <asm/irq.h>
 
-#define PCI_VENDOR_ID_SILAN            0x1904
-#define PCI_DEVICE_ID_SILAN_SC92031    0x2031
-#define PCI_DEVICE_ID_SILAN_8139D      0x8139
-
 #define SC92031_NAME "sc92031"
-#define SC92031_DESCRIPTION "Silan SC92031 PCI Fast Ethernet Adapter driver"
-#define SC92031_VERSION "2.0c"
 
 /* BAR 0 is MMIO, BAR 1 is PIO */
 #ifndef SC92031_USE_BAR
@@ -1264,7 +1261,6 @@ static void sc92031_ethtool_get_drvinfo(struct net_device *dev,
        struct pci_dev *pdev = priv->pdev;
 
        strcpy(drvinfo->driver, SC92031_NAME);
-       strcpy(drvinfo->version, SC92031_VERSION);
        strcpy(drvinfo->bus_info, pci_name(pdev));
 }
 
@@ -1423,6 +1419,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
        struct net_device *dev;
        struct sc92031_priv *priv;
        u32 mac0, mac1;
+       unsigned long base_addr;
 
        err = pci_enable_device(pdev);
        if (unlikely(err < 0))
@@ -1497,6 +1494,14 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
        if (err < 0)
                goto out_register_netdev;
 
+#if SC92031_USE_BAR == 0
+       base_addr = dev->mem_start;
+#elif SC92031_USE_BAR == 1
+       base_addr = dev->base_addr;
+#endif
+       printk(KERN_INFO "%s: SC92031 at 0x%lx, %pM, IRQ %d\n", dev->name,
+                       base_addr, dev->dev_addr, dev->irq);
+
        return 0;
 
 out_register_netdev:
@@ -1586,8 +1591,8 @@ out:
 }
 
 static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = {
-       { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_SC92031) },
-       { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_8139D) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table);
@@ -1603,7 +1608,6 @@ static struct pci_driver sc92031_pci_driver = {
 
 static int __init sc92031_init(void)
 {
-       printk(KERN_INFO SC92031_DESCRIPTION " " SC92031_VERSION "\n");
        return pci_register_driver(&sc92031_pci_driver);
 }
 
@@ -1617,5 +1621,4 @@ module_exit(sc92031_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Cesar Eduardo Barros <cesarb@cesarb.net>");
-MODULE_DESCRIPTION(SC92031_DESCRIPTION);
-MODULE_VERSION(SC92031_VERSION);
+MODULE_DESCRIPTION("Silan SC92031 PCI Fast Ethernet Adapter driver");
index c535408ad6bef520262118f0283c0d004ee6cc56..12a82966b5779f2db7f115ac7f967afc4baff8e2 100644 (file)
@@ -2,7 +2,6 @@ config SFC
        tristate "Solarflare Solarstorm SFC4000 support"
        depends on PCI && INET
        select MII
-       select INET_LRO
        select CRC32
        select I2C
        select I2C_ALGOBIT
index d95c218280142108d8c490dea894ea6eb817b5f5..d54d84c267b906a4331f847008302b95566d2a33 100644 (file)
@@ -543,7 +543,7 @@ typedef union efx_oword {
 
 /* Static initialiser */
 #define EFX_OWORD32(a, b, c, d)                                                \
-       { .u32 = { __constant_cpu_to_le32(a), __constant_cpu_to_le32(b), \
-                  __constant_cpu_to_le32(c), __constant_cpu_to_le32(d) } }
+       { .u32 = { cpu_to_le32(a), cpu_to_le32(b), \
+                  cpu_to_le32(c), cpu_to_le32(d) } }
 
 #endif /* EFX_BITFIELD_H */
index ab0e09bf154d1f1fe2fdab401465e31cccdb2918..75836599e43dc87a51878f81d8b1058132df7f39 100644 (file)
@@ -182,7 +182,6 @@ static int efx_process_channel(struct efx_channel *channel, int rx_quota)
                channel->rx_pkt = NULL;
        }
 
-       efx_flush_lro(channel);
        efx_rx_strategy(channel);
 
        efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
@@ -225,11 +224,11 @@ static int efx_poll(struct napi_struct *napi, int budget)
 
        if (rx_packets < budget) {
                /* There is no race here; although napi_disable() will
-                * only wait for netif_rx_complete(), this isn't a problem
+                * only wait for napi_complete(), this isn't a problem
                 * since efx_channel_processed() will have no effect if
                 * interrupts have already been disabled.
                 */
-               netif_rx_complete(napi);
+               napi_complete(napi);
                efx_channel_processed(channel);
        }
 
@@ -1269,18 +1268,11 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 static int efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
-       int rc;
 
        efx_for_each_channel(channel, efx) {
                channel->napi_dev = efx->net_dev;
-               rc = efx_lro_init(&channel->lro_mgr, efx);
-               if (rc)
-                       goto err;
        }
        return 0;
- err:
-       efx_fini_napi(efx);
-       return rc;
 }
 
 static void efx_fini_napi(struct efx_nic *efx)
@@ -1288,7 +1280,6 @@ static void efx_fini_napi(struct efx_nic *efx)
        struct efx_channel *channel;
 
        efx_for_each_channel(channel, efx) {
-               efx_lro_fini(&channel->lro_mgr);
                channel->napi_dev = NULL;
        }
 }
@@ -2120,7 +2111,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
        net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG |
                              NETIF_F_HIGHDMA | NETIF_F_TSO);
        if (lro)
-               net_dev->features |= NETIF_F_LRO;
+               net_dev->features |= NETIF_F_GRO;
        /* Mask for features that also apply to VLAN devices */
        net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
                                   NETIF_F_HIGHDMA | NETIF_F_TSO);
index 55d0f131b0e90d83dda988ee81ee73a9d97b63f0..8bde1d2a21db3f7108d3126e3edf9aeb76a07f3c 100644 (file)
@@ -80,7 +80,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_str);
+       napi_schedule(&channel->napi_str);
 }
 
 #endif /* EFX_EFX_H */
index e019ad1fb9a0c7db773c0e7f1446078d3eaee2b0..19930ff9df7b71dceebbb4712a9d96cbaaf5f464 100644 (file)
 #include <linux/device.h>
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
-#include <linux/inet_lro.h>
 #include <linux/i2c.h>
 
 #include "enum.h"
 #include "bitfield.h"
 
-#define EFX_MAX_LRO_DESCRIPTORS 8
-#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
-
 /**************************************************************************
  *
  * Build definitions
@@ -340,13 +336,10 @@ enum efx_rx_alloc_method {
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
  * @eventq_magic: Event queue magic value for driver-generated test events
- * @lro_mgr: LRO state
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
  *     and diagnostic counters
  * @rx_alloc_push_pages: RX allocation method currently in use for pushing
  *     descriptors
- * @rx_alloc_pop_pages: RX allocation method currently in use for popping
- *     descriptors
  * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
  * @n_rx_ip_frag_err: Count of RX IP fragment errors
  * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
@@ -371,10 +364,8 @@ struct efx_channel {
        unsigned int last_eventq_read_ptr;
        unsigned int eventq_magic;
 
-       struct net_lro_mgr lro_mgr;
        int rx_alloc_level;
        int rx_alloc_push_pages;
-       int rx_alloc_pop_pages;
 
        unsigned n_rx_tobe_disc;
        unsigned n_rx_ip_frag_err;
index b8ba4bbad8897f384f6eb6f6168cce13df95132a..66d7fe3db3e6e74cc6c2c137226121828bb5577d 100644 (file)
@@ -99,109 +99,6 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
 }
 
 
-/**************************************************************************
- *
- * Linux generic LRO handling
- *
- **************************************************************************
- */
-
-static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr,
-                              void **tcpudp_hdr, u64 *hdr_flags, void *priv)
-{
-       struct efx_channel *channel = priv;
-       struct iphdr *iph;
-       struct tcphdr *th;
-
-       iph = (struct iphdr *)skb->data;
-       if (skb->protocol != htons(ETH_P_IP) || iph->protocol != IPPROTO_TCP)
-               goto fail;
-
-       th = (struct tcphdr *)(skb->data + iph->ihl * 4);
-
-       *tcpudp_hdr = th;
-       *ip_hdr = iph;
-       *hdr_flags = LRO_IPV4 | LRO_TCP;
-
-       channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
-       return 0;
-fail:
-       channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
-       return -1;
-}
-
-static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr,
-                           void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags,
-                           void *priv)
-{
-       struct efx_channel *channel = priv;
-       struct ethhdr *eh;
-       struct iphdr *iph;
-
-       /* We support EtherII and VLAN encapsulated IPv4 */
-       eh = page_address(frag->page) + frag->page_offset;
-       *mac_hdr = eh;
-
-       if (eh->h_proto == htons(ETH_P_IP)) {
-               iph = (struct iphdr *)(eh + 1);
-       } else {
-               struct vlan_ethhdr *veh = (struct vlan_ethhdr *)eh;
-               if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
-                       goto fail;
-
-               iph = (struct iphdr *)(veh + 1);
-       }
-       *ip_hdr = iph;
-
-       /* We can only do LRO over TCP */
-       if (iph->protocol != IPPROTO_TCP)
-               goto fail;
-
-       *hdr_flags = LRO_IPV4 | LRO_TCP;
-       *tcpudp_hdr = (struct tcphdr *)((u8 *) iph + iph->ihl * 4);
-
-       channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
-       return 0;
- fail:
-       channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
-       return -1;
-}
-
-int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx)
-{
-       size_t s = sizeof(struct net_lro_desc) * EFX_MAX_LRO_DESCRIPTORS;
-       struct net_lro_desc *lro_arr;
-
-       /* Allocate the LRO descriptors structure */
-       lro_arr = kzalloc(s, GFP_KERNEL);
-       if (lro_arr == NULL)
-               return -ENOMEM;
-
-       lro_mgr->lro_arr = lro_arr;
-       lro_mgr->max_desc = EFX_MAX_LRO_DESCRIPTORS;
-       lro_mgr->max_aggr = EFX_MAX_LRO_AGGR;
-       lro_mgr->frag_align_pad = EFX_PAGE_SKB_ALIGN;
-
-       lro_mgr->get_skb_header = efx_lro_get_skb_hdr;
-       lro_mgr->get_frag_header = efx_get_frag_hdr;
-       lro_mgr->dev = efx->net_dev;
-
-       lro_mgr->features = LRO_F_NAPI;
-
-       /* We can pass packets up with the checksum intact */
-       lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
-
-       lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
-
-       return 0;
-}
-
-void efx_lro_fini(struct net_lro_mgr *lro_mgr)
-{
-       kfree(lro_mgr->lro_arr);
-       lro_mgr->lro_arr = NULL;
-}
-
 /**
  * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation
  *
@@ -549,77 +446,31 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 static void efx_rx_packet_lro(struct efx_channel *channel,
                              struct efx_rx_buffer *rx_buf)
 {
-       struct net_lro_mgr *lro_mgr = &channel->lro_mgr;
-       void *priv = channel;
+       struct napi_struct *napi = &channel->napi_str;
 
        /* Pass the skb/page into the LRO engine */
        if (rx_buf->page) {
-               struct skb_frag_struct frags;
+               struct napi_gro_fraginfo info;
 
-               frags.page = rx_buf->page;
-               frags.page_offset = efx_rx_buf_offset(rx_buf);
-               frags.size = rx_buf->len;
+               info.frags[0].page = rx_buf->page;
+               info.frags[0].page_offset = efx_rx_buf_offset(rx_buf);
+               info.frags[0].size = rx_buf->len;
+               info.nr_frags = 1;
+               info.ip_summed = CHECKSUM_UNNECESSARY;
+               info.len = rx_buf->len;
 
-               lro_receive_frags(lro_mgr, &frags, rx_buf->len,
-                                 rx_buf->len, priv, 0);
+               napi_gro_frags(napi, &info);
 
                EFX_BUG_ON_PARANOID(rx_buf->skb);
                rx_buf->page = NULL;
        } else {
                EFX_BUG_ON_PARANOID(!rx_buf->skb);
 
-               lro_receive_skb(lro_mgr, rx_buf->skb, priv);
+               napi_gro_receive(napi, rx_buf->skb);
                rx_buf->skb = NULL;
        }
 }
 
-/* Allocate and construct an SKB around a struct page.*/
-static struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
-                                    struct efx_nic *efx,
-                                    int hdr_len)
-{
-       struct sk_buff *skb;
-
-       /* Allocate an SKB to store the headers */
-       skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN);
-       if (unlikely(skb == NULL)) {
-               EFX_ERR_RL(efx, "RX out of memory for skb\n");
-               return NULL;
-       }
-
-       EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags);
-       EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
-
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
-       skb_reserve(skb, EFX_PAGE_SKB_ALIGN);
-
-       skb->len = rx_buf->len;
-       skb->truesize = rx_buf->len + sizeof(struct sk_buff);
-       memcpy(skb->data, rx_buf->data, hdr_len);
-       skb->tail += hdr_len;
-
-       /* Append the remaining page onto the frag list */
-       if (unlikely(rx_buf->len > hdr_len)) {
-               struct skb_frag_struct *frag = skb_shinfo(skb)->frags;
-               frag->page = rx_buf->page;
-               frag->page_offset = efx_rx_buf_offset(rx_buf) + hdr_len;
-               frag->size = skb->len - hdr_len;
-               skb_shinfo(skb)->nr_frags = 1;
-               skb->data_len = frag->size;
-       } else {
-               __free_pages(rx_buf->page, efx->rx_buffer_order);
-               skb->data_len = 0;
-       }
-
-       /* Ownership has transferred from the rx_buf to skb */
-       rx_buf->page = NULL;
-
-       /* Move past the ethernet header */
-       skb->protocol = eth_type_trans(skb, efx->net_dev);
-
-       return skb;
-}
-
 void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
                   unsigned int len, bool checksummed, bool discard)
 {
@@ -687,7 +538,6 @@ void __efx_rx_packet(struct efx_channel *channel,
 {
        struct efx_nic *efx = channel->efx;
        struct sk_buff *skb;
-       bool lro = !!(efx->net_dev->features & NETIF_F_LRO);
 
        /* If we're in loopback test, then pass the packet directly to the
         * loopback layer, and free the rx_buf here
@@ -709,41 +559,23 @@ void __efx_rx_packet(struct efx_channel *channel,
                                                       efx->net_dev);
        }
 
-       /* Both our generic-LRO and SFC-SSR support skb and page based
-        * allocation, but neither support switching from one to the
-        * other on the fly. If we spot that the allocation mode has
-        * changed, then flush the LRO state.
-        */
-       if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) {
-               efx_flush_lro(channel);
-               channel->rx_alloc_pop_pages = (rx_buf->page != NULL);
-       }
-       if (likely(checksummed && lro)) {
+       if (likely(checksummed || rx_buf->page)) {
                efx_rx_packet_lro(channel, rx_buf);
                goto done;
        }
 
-       /* Form an skb if required */
-       if (rx_buf->page) {
-               int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
-               skb = efx_rx_mk_skb(rx_buf, efx, hdr_len);
-               if (unlikely(skb == NULL)) {
-                       efx_free_rx_buffer(efx, rx_buf);
-                       goto done;
-               }
-       } else {
-               /* We now own the SKB */
-               skb = rx_buf->skb;
-               rx_buf->skb = NULL;
-       }
+       /* We now own the SKB */
+       skb = rx_buf->skb;
+       rx_buf->skb = NULL;
 
        EFX_BUG_ON_PARANOID(rx_buf->page);
        EFX_BUG_ON_PARANOID(rx_buf->skb);
        EFX_BUG_ON_PARANOID(!skb);
 
        /* Set the SKB flags */
-       if (unlikely(!checksummed || !efx->rx_checksum_enabled))
-               skb->ip_summed = CHECKSUM_NONE;
+       skb->ip_summed = CHECKSUM_NONE;
+
+       skb_record_rx_queue(skb, channel->channel);
 
        /* Pass the packet up */
        netif_receive_skb(skb);
@@ -760,7 +592,7 @@ void efx_rx_strategy(struct efx_channel *channel)
        enum efx_rx_alloc_method method = rx_alloc_method;
 
        /* Only makes sense to use page based allocation if LRO is enabled */
-       if (!(channel->efx->net_dev->features & NETIF_F_LRO)) {
+       if (!(channel->efx->net_dev->features & NETIF_F_GRO)) {
                method = RX_ALLOC_METHOD_SKB;
        } else if (method == RX_ALLOC_METHOD_AUTO) {
                /* Constrain the rx_alloc_level */
@@ -865,11 +697,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
        rx_queue->buffer = NULL;
 }
 
-void efx_flush_lro(struct efx_channel *channel)
-{
-       lro_flush_all(&channel->lro_mgr);
-}
-
 
 module_param(rx_alloc_method, int, 0644);
 MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers");
index 0e88a9ddc1c64ae967337fa218a5d24388b479f3..42ee7555a80b30d52fea3332c3a47e18ebab5c7c 100644 (file)
@@ -17,9 +17,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
 void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
 void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
 
-int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx);
-void efx_lro_fini(struct net_lro_mgr *lro_mgr);
-void efx_flush_lro(struct efx_channel *channel);
 void efx_rx_strategy(struct efx_channel *channel);
 void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
 void efx_rx_work(struct work_struct *data);
index cb25ae5b257ae96a0d4da7b90aeea521a4d74299..c0e90683162339570a03154b14ae0a46e1ce4855 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/rtnetlink.h>
 #include "net_driver.h"
 #include "efx.h"
 #include "phy.h"
index f0efd246962cf01e2a9639b6fdb4421e8a3e1438..ac9eeab79f202a051dd1000a44ba7d7404d93b20 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/rtnetlink.h>
 #include <linux/seq_file.h>
 #include "efx.h"
 #include "mdio_10g.h"
index c9dbb06f8c9430cfb06779a8486544792972996a..952d37ffee51f8de796a20b650b946678ca5e333 100644 (file)
@@ -3214,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(napi);
+               __napi_complete(napi);
                hw->intr_mask |= napimask[skge->port];
                skge_write32(hw, B0_IMSK, hw->intr_mask);
                skge_read32(hw, B0_IMSK);
@@ -3377,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(&skge->napi);
+               napi_schedule(&skge->napi);
        }
 
        if (status & IS_PA_TO_TX1)
@@ -3397,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(&skge->napi);
+                       napi_schedule(&skge->napi);
                }
 
                if (status & IS_PA_TO_RX2) {
index 994703cc0db32c87229f7754f1a246c1cc44d9ea..d01c56eb962759e511cf269a27d4952e85e15cfc 100644 (file)
@@ -1068,13 +1068,16 @@ static void sky2_rx_submit(struct sky2_port *sky2,
 }
 
 
-static void sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
+static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
                            unsigned size)
 {
        struct sk_buff *skb = re->skb;
        int i;
 
        re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE);
+       if (unlikely(pci_dma_mapping_error(pdev, re->data_addr)))
+               return -EIO;
+
        pci_unmap_len_set(re, data_size, size);
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
@@ -1083,6 +1086,7 @@ static void sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
                                                skb_shinfo(skb)->frags[i].page_offset,
                                                skb_shinfo(skb)->frags[i].size,
                                                PCI_DMA_FROMDEVICE);
+       return 0;
 }
 
 static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re)
@@ -1354,7 +1358,12 @@ static int sky2_rx_start(struct sky2_port *sky2)
                if (!re->skb)
                        goto nomem;
 
-               sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size);
+               if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) {
+                       dev_kfree_skb(re->skb);
+                       re->skb = NULL;
+                       goto nomem;
+               }
+
                sky2_rx_submit(sky2, re);
        }
 
@@ -1547,7 +1556,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        struct sky2_hw *hw = sky2->hw;
        struct sky2_tx_le *le = NULL;
        struct tx_ring_info *re;
-       unsigned i, len;
+       unsigned i, len, first_slot;
        dma_addr_t mapping;
        u16 mss;
        u8 ctrl;
@@ -1555,13 +1564,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(tx_avail(sky2) < tx_le_req(skb)))
                return NETDEV_TX_BUSY;
 
-       if (unlikely(netif_msg_tx_queued(sky2)))
-               printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n",
-                      dev->name, sky2->tx_prod, skb->len);
-
        len = skb_headlen(skb);
        mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
+       if (pci_dma_mapping_error(hw->pdev, mapping))
+               goto mapping_error;
+
+       first_slot = sky2->tx_prod;
+       if (unlikely(netif_msg_tx_queued(sky2)))
+               printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n",
+                      dev->name, first_slot, skb->len);
+
        /* Send high bits if needed */
        if (sizeof(dma_addr_t) > sizeof(u32)) {
                le = get_tx_le(sky2);
@@ -1648,6 +1661,9 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
                mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
                                       frag->size, PCI_DMA_TODEVICE);
 
+               if (pci_dma_mapping_error(hw->pdev, mapping))
+                       goto mapping_unwind;
+
                if (sizeof(dma_addr_t) > sizeof(u32)) {
                        le = get_tx_le(sky2);
                        le->addr = cpu_to_le32(upper_32_bits(mapping));
@@ -1676,6 +1692,34 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 
        dev->trans_start = jiffies;
        return NETDEV_TX_OK;
+
+mapping_unwind:
+       for (i = first_slot; i != sky2->tx_prod; i = RING_NEXT(i, TX_RING_SIZE)) {
+               le = sky2->tx_le + i;
+               re = sky2->tx_ring + i;
+
+               switch(le->opcode & ~HW_OWNER) {
+               case OP_LARGESEND:
+               case OP_PACKET:
+                       pci_unmap_single(hw->pdev,
+                                        pci_unmap_addr(re, mapaddr),
+                                        pci_unmap_len(re, maplen),
+                                        PCI_DMA_TODEVICE);
+                       break;
+               case OP_BUFFER:
+                       pci_unmap_page(hw->pdev, pci_unmap_addr(re, mapaddr),
+                                      pci_unmap_len(re, maplen),
+                                      PCI_DMA_TODEVICE);
+                       break;
+               }
+       }
+
+       sky2->tx_prod = first_slot;
+mapping_error:
+       if (net_ratelimit())
+               dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
 }
 
 /*
@@ -2191,7 +2235,11 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
 
        prefetch(skb->data);
        re->skb = nskb;
-       sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space);
+       if (sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space)) {
+               dev_kfree_skb(nskb);
+               re->skb = skb;
+               return NULL;
+       }
 
        if (skb_shinfo(skb)->nr_frags)
                skb_put_frags(skb, hdr_space, length);
@@ -2687,13 +2735,6 @@ static int sky2_poll(struct napi_struct *napi, int work_limit)
                        goto done;
        }
 
-       /* Bug/Errata workaround?
-        * Need to kick the TX irq moderation timer.
-        */
-       if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
-               sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
-               sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
-       }
        napi_complete(napi);
        sky2_read32(hw, B0_Y2_SP_LISR);
 done:
@@ -3864,6 +3905,86 @@ static const struct ethtool_ops sky2_ethtool_ops = {
 
 static struct dentry *sky2_debug;
 
+
+/*
+ * Read and parse the first part of Vital Product Data
+ */
+#define VPD_SIZE       128
+#define VPD_MAGIC      0x82
+
+static const struct vpd_tag {
+       char tag[2];
+       char *label;
+} vpd_tags[] = {
+       { "PN", "Part Number" },
+       { "EC", "Engineering Level" },
+       { "MN", "Manufacturer" },
+       { "SN", "Serial Number" },
+       { "YA", "Asset Tag" },
+       { "VL", "First Error Log Message" },
+       { "VF", "Second Error Log Message" },
+       { "VB", "Boot Agent ROM Configuration" },
+       { "VE", "EFI UNDI Configuration" },
+};
+
+static void sky2_show_vpd(struct seq_file *seq, struct sky2_hw *hw)
+{
+       size_t vpd_size;
+       loff_t offs;
+       u8 len;
+       unsigned char *buf;
+       u16 reg2;
+
+       reg2 = sky2_pci_read16(hw, PCI_DEV_REG2);
+       vpd_size = 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+
+       seq_printf(seq, "%s Product Data\n", pci_name(hw->pdev));
+       buf = kmalloc(vpd_size, GFP_KERNEL);
+       if (!buf) {
+               seq_puts(seq, "no memory!\n");
+               return;
+       }
+
+       if (pci_read_vpd(hw->pdev, 0, vpd_size, buf) < 0) {
+               seq_puts(seq, "VPD read failed\n");
+               goto out;
+       }
+
+       if (buf[0] != VPD_MAGIC) {
+               seq_printf(seq, "VPD tag mismatch: %#x\n", buf[0]);
+               goto out;
+       }
+       len = buf[1];
+       if (len == 0 || len > vpd_size - 4) {
+               seq_printf(seq, "Invalid id length: %d\n", len);
+               goto out;
+       }
+
+       seq_printf(seq, "%.*s\n", len, buf + 3);
+       offs = len + 3;
+
+       while (offs < vpd_size - 4) {
+               int i;
+
+               if (!memcmp("RW", buf + offs, 2))       /* end marker */
+                       break;
+               len = buf[offs + 2];
+               if (offs + len + 3 >= vpd_size)
+                       break;
+
+               for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) {
+                       if (!memcmp(vpd_tags[i].tag, buf + offs, 2)) {
+                               seq_printf(seq, " %s: %.*s\n",
+                                          vpd_tags[i].label, len, buf + offs + 3);
+                               break;
+                       }
+               }
+               offs += len + 3;
+       }
+out:
+       kfree(buf);
+}
+
 static int sky2_debug_show(struct seq_file *seq, void *v)
 {
        struct net_device *dev = seq->private;
@@ -3873,14 +3994,18 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
        unsigned idx, last;
        int sop;
 
-       if (!netif_running(dev))
-               return -ENETDOWN;
+       sky2_show_vpd(seq, hw);
 
-       seq_printf(seq, "IRQ src=%x mask=%x control=%x\n",
+       seq_printf(seq, "\nIRQ src=%x mask=%x control=%x\n",
                   sky2_read32(hw, B0_ISRC),
                   sky2_read32(hw, B0_IMSK),
                   sky2_read32(hw, B0_Y2_SP_ICR));
 
+       if (!netif_running(dev)) {
+               seq_printf(seq, "network not running\n");
+               return 0;
+       }
+
        napi_disable(&hw->napi);
        last = sky2_read16(hw, STAT_PUT_IDX);
 
@@ -4204,69 +4329,6 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
        return err;
 }
 
-/*
- * Read and parse the first part of Vital Product Data
- */
-#define VPD_SIZE       128
-#define VPD_MAGIC      0x82
-
-static void __devinit sky2_vpd_info(struct sky2_hw *hw)
-{
-       int cap = pci_find_capability(hw->pdev, PCI_CAP_ID_VPD);
-       const u8 *p;
-       u8 *vpd_buf = NULL;
-       u16 len;
-       static struct vpd_tag {
-               char tag[2];
-               char *label;
-       } vpd_tags[] = {
-               { "PN", "Part Number" },
-               { "EC", "Engineering Level" },
-               { "MN", "Manufacturer" },
-       };
-
-       if (!cap)
-               goto out;
-
-       vpd_buf = kmalloc(VPD_SIZE, GFP_KERNEL);
-       if (!vpd_buf)
-               goto out;
-
-       if (sky2_vpd_read(hw, cap, vpd_buf, 0, VPD_SIZE))
-               goto out;
-
-       if (vpd_buf[0] != VPD_MAGIC)
-               goto out;
-       len = vpd_buf[1];
-       if (len == 0 || len > VPD_SIZE - 4)
-               goto out;
-       p = vpd_buf + 3;
-       dev_info(&hw->pdev->dev, "%.*s\n", len, p);
-       p += len;
-
-       while (p < vpd_buf + VPD_SIZE - 4) {
-               int i;
-
-               if (!memcmp("RW", p, 2))        /* end marker */
-                       break;
-
-               len = p[2];
-               if (len > (p - vpd_buf) - 4)
-                       break;
-
-               for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) {
-                       if (!memcmp(vpd_tags[i].tag, p, 2)) {
-                               printk(KERN_DEBUG " %s: %.*s\n",
-                                      vpd_tags[i].label, len, p + 3);
-                               break;
-                       }
-               }
-               p += len + 3;
-       }
-out:
-       kfree(vpd_buf);
-}
-
 /* This driver supports yukon2 chipset only */
 static const char *sky2_name(u8 chipid, char *buf, int sz)
 {
@@ -4294,6 +4356,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        struct net_device *dev;
        struct sky2_hw *hw;
        int err, using_dac = 0, wol_default;
+       u32 reg;
        char buf1[16];
 
        err = pci_enable_device(pdev);
@@ -4327,6 +4390,34 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                }
        }
 
+       /* Get configuration information
+        * Note: only regular PCI config access once to test for HW issues
+        *       other PCI access through shared memory for speed and to
+        *       avoid MMCONFIG problems.
+        */
+       err = pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+       if (err) {
+               dev_err(&pdev->dev, "PCI read config failed\n");
+               goto err_out_free_regions;
+       }
+
+       /* size of available VPD, only impact sysfs */
+       err = pci_vpd_truncate(pdev, 1ul << (((reg & PCI_VPD_ROM_SZ) >> 14) + 8));
+       if (err)
+               dev_warn(&pdev->dev, "Can't set VPD size\n");
+
+#ifdef __BIG_ENDIAN
+       /* The sk98lin vendor driver uses hardware byte swapping but
+        * this driver uses software swapping.
+        */
+       reg &= ~PCI_REV_DESC;
+       err = pci_write_config_dword(pdev,PCI_DEV_REG2, reg);
+       if (err) {
+               dev_err(&pdev->dev, "PCI write config failed\n");
+               goto err_out_free_regions;
+       }
+#endif
+
        wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
 
        err = -ENOMEM;
@@ -4344,18 +4435,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out_free_hw;
        }
 
-#ifdef __BIG_ENDIAN
-       /* The sk98lin vendor driver uses hardware byte swapping but
-        * this driver uses software swapping.
-        */
-       {
-               u32 reg;
-               reg = sky2_pci_read32(hw, PCI_DEV_REG2);
-               reg &= ~PCI_REV_DESC;
-               sky2_pci_write32(hw, PCI_DEV_REG2, reg);
-       }
-#endif
-
        /* ring for status responses */
        hw->st_le = pci_alloc_consistent(pdev, STATUS_LE_BYTES, &hw->st_dma);
        if (!hw->st_le)
@@ -4370,8 +4449,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
 
        sky2_reset(hw);
 
-       sky2_vpd_info(hw);
-
        dev = sky2_init_netdev(hw, 0, using_dac, wol_default);
        if (!dev) {
                err = -ENOMEM;
index 223cde0d43be8a6674f956cea35e3a490530cfdb..293610334a778b2ca81c4af52a2b8e391d13b204 100644 (file)
@@ -1545,7 +1545,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        strncpy(info->driver, CARDNAME, sizeof(info->driver));
        strncpy(info->version, version, sizeof(info->version));
-       strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+       strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
 static int smc911x_ethtool_nwayreset(struct net_device *dev)
index b215a8d85e62d5e2fc3eb54064918ae8dd90fd97..fdcbaf8dfa739618a5a8f25bc27f6c24222e8004 100644 (file)
@@ -1614,7 +1614,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        strncpy(info->driver, CARDNAME, sizeof(info->driver));
        strncpy(info->version, version, sizeof(info->version));
-       strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+       strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
 static int smc_ethtool_nwayreset(struct net_device *dev)
@@ -1643,6 +1643,117 @@ static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level)
        lp->msg_enable = level;
 }
 
+static int smc_write_eeprom_word(struct net_device *dev, u16 addr, u16 word)
+{
+       u16 ctl;
+       struct smc_local *lp = netdev_priv(dev);
+       void __iomem *ioaddr = lp->base;
+
+       spin_lock_irq(&lp->lock);
+       /* load word into GP register */
+       SMC_SELECT_BANK(lp, 1);
+       SMC_SET_GP(lp, word);
+       /* set the address to put the data in EEPROM */
+       SMC_SELECT_BANK(lp, 2);
+       SMC_SET_PTR(lp, addr);
+       /* tell it to write */
+       SMC_SELECT_BANK(lp, 1);
+       ctl = SMC_GET_CTL(lp);
+       SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_STORE));
+       /* wait for it to finish */
+       do {
+               udelay(1);
+       } while (SMC_GET_CTL(lp) & CTL_STORE);
+       /* clean up */
+       SMC_SET_CTL(lp, ctl);
+       SMC_SELECT_BANK(lp, 2);
+       spin_unlock_irq(&lp->lock);
+       return 0;
+}
+
+static int smc_read_eeprom_word(struct net_device *dev, u16 addr, u16 *word)
+{
+       u16 ctl;
+       struct smc_local *lp = netdev_priv(dev);
+       void __iomem *ioaddr = lp->base;
+
+       spin_lock_irq(&lp->lock);
+       /* set the EEPROM address to get the data from */
+       SMC_SELECT_BANK(lp, 2);
+       SMC_SET_PTR(lp, addr | PTR_READ);
+       /* tell it to load */
+       SMC_SELECT_BANK(lp, 1);
+       SMC_SET_GP(lp, 0xffff); /* init to known */
+       ctl = SMC_GET_CTL(lp);
+       SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_RELOAD));
+       /* wait for it to finish */
+       do {
+               udelay(1);
+       } while (SMC_GET_CTL(lp) & CTL_RELOAD);
+       /* read word from GP register */
+       *word = SMC_GET_GP(lp);
+       /* clean up */
+       SMC_SET_CTL(lp, ctl);
+       SMC_SELECT_BANK(lp, 2);
+       spin_unlock_irq(&lp->lock);
+       return 0;
+}
+
+static int smc_ethtool_geteeprom_len(struct net_device *dev)
+{
+       return 0x23 * 2;
+}
+
+static int smc_ethtool_geteeprom(struct net_device *dev,
+               struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i;
+       int imax;
+
+       DBG(1, "Reading %d bytes at %d(0x%x)\n",
+               eeprom->len, eeprom->offset, eeprom->offset);
+       imax = smc_ethtool_geteeprom_len(dev);
+       for (i = 0; i < eeprom->len; i += 2) {
+               int ret;
+               u16 wbuf;
+               int offset = i + eeprom->offset;
+               if (offset > imax)
+                       break;
+               ret = smc_read_eeprom_word(dev, offset >> 1, &wbuf);
+               if (ret != 0)
+                       return ret;
+               DBG(2, "Read 0x%x from 0x%x\n", wbuf, offset >> 1);
+               data[i] = (wbuf >> 8) & 0xff;
+               data[i+1] = wbuf & 0xff;
+       }
+       return 0;
+}
+
+static int smc_ethtool_seteeprom(struct net_device *dev,
+               struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i;
+       int imax;
+
+       DBG(1, "Writing %d bytes to %d(0x%x)\n",
+                       eeprom->len, eeprom->offset, eeprom->offset);
+       imax = smc_ethtool_geteeprom_len(dev);
+       for (i = 0; i < eeprom->len; i += 2) {
+               int ret;
+               u16 wbuf;
+               int offset = i + eeprom->offset;
+               if (offset > imax)
+                       break;
+               wbuf = (data[i] << 8) | data[i + 1];
+               DBG(2, "Writing 0x%x to 0x%x\n", wbuf, offset >> 1);
+               ret = smc_write_eeprom_word(dev, offset >> 1, wbuf);
+               if (ret != 0)
+                       return ret;
+       }
+       return 0;
+}
+
+
 static const struct ethtool_ops smc_ethtool_ops = {
        .get_settings   = smc_ethtool_getsettings,
        .set_settings   = smc_ethtool_setsettings,
@@ -1652,8 +1763,22 @@ static const struct ethtool_ops smc_ethtool_ops = {
        .set_msglevel   = smc_ethtool_setmsglevel,
        .nway_reset     = smc_ethtool_nwayreset,
        .get_link       = ethtool_op_get_link,
-//     .get_eeprom     = smc_ethtool_geteeprom,
-//     .set_eeprom     = smc_ethtool_seteeprom,
+       .get_eeprom_len = smc_ethtool_geteeprom_len,
+       .get_eeprom     = smc_ethtool_geteeprom,
+       .set_eeprom     = smc_ethtool_seteeprom,
+};
+
+static const struct net_device_ops smc_netdev_ops = {
+       .ndo_open               = smc_open,
+       .ndo_stop               = smc_close,
+       .ndo_start_xmit         = smc_hard_start_xmit,
+       .ndo_tx_timeout         = smc_timeout,
+       .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = smc_poll_controller,
+#endif
 };
 
 /*
@@ -1865,16 +1990,9 @@ static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
 
-       dev->open = smc_open;
-       dev->stop = smc_close;
-       dev->hard_start_xmit = smc_hard_start_xmit;
-       dev->tx_timeout = smc_timeout;
        dev->watchdog_timeo = msecs_to_jiffies(watchdog);
-       dev->set_multicast_list = smc_set_multicast_list;
+       dev->netdev_ops = &smc_netdev_ops;
        dev->ethtool_ops = &smc_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = smc_poll_controller;
-#endif
 
        tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
        INIT_WORK(&lp->phy_configure, smc_phy_configure);
index c4ccd121bc9c648ba90a2bbf8e3c110e2bacb187..ed9ae43523a12e88ec4e2ffada52d2f3844eea55 100644 (file)
@@ -1141,6 +1141,16 @@ static const char * chip_ids[ 16 ] =  {
 
 #define SMC_GET_MII(lp)                SMC_inw(ioaddr, MII_REG(lp))
 
+#define SMC_GET_GP(lp)         SMC_inw(ioaddr, GP_REG(lp))
+
+#define SMC_SET_GP(lp, x)                                              \
+       do {                                                            \
+               if (SMC_MUST_ALIGN_WRITE(lp))                           \
+                       SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1));   \
+               else                                                    \
+                       SMC_outw(x, ioaddr, GP_REG(lp));                \
+       } while (0)
+
 #define SMC_SET_MII(lp, x)             SMC_outw(x, ioaddr, MII_REG(lp))
 
 #define SMC_GET_MIR(lp)                SMC_inw(ioaddr, MIR_REG(lp))
index 783c1a7b869e62c20ccf1981cbe3000f5eaddf56..6e175e5555a11a89812af87989657c1264e006f8 100644 (file)
@@ -368,48 +368,53 @@ out:
        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)
+/* Switch to external phy. Assumes tx and rx are stopped. */
+static void smsc911x_phy_enable_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_) {
+       /* 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. Assuming tx and rx are stopped
-                * because smsc911x_phy_initialise is called before
-                * smsc911x_rx_initialise and tx_initialise. */
+       /* Switch to external phy */
+       hwcfg |= HW_CFG_EXT_PHY_EN_;
+       smsc911x_reg_write(pdata, HW_CFG, hwcfg);
 
-               /* 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 */
+       /* 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 */
 
-               /* 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);
+}
 
-               hwcfg |= HW_CFG_SMI_SEL_;
-               smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+/* Autodetects and enables external phy if present on supported chips.
+ * autodetection can be overridden by specifying SMSC911X_FORCE_INTERNAL_PHY
+ * or SMSC911X_FORCE_EXTERNAL_PHY in the platform_data flags. */
+static void smsc911x_phy_initialise_external(struct smsc911x_data *pdata)
+{
+       unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG);
 
-               SMSC_TRACE(HW, "Successfully switched to external PHY");
+       if (pdata->config.flags & SMSC911X_FORCE_INTERNAL_PHY) {
+               SMSC_TRACE(HW, "Forcing internal PHY");
+               pdata->using_extphy = 0;
+       } else if (pdata->config.flags & SMSC911X_FORCE_EXTERNAL_PHY) {
+               SMSC_TRACE(HW, "Forcing external PHY");
+               smsc911x_phy_enable_external(pdata);
+               pdata->using_extphy = 1;
+       } else if (hwcfg & HW_CFG_EXT_PHY_DET_) {
+               SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET set, using external PHY");
+               smsc911x_phy_enable_external(pdata);
                pdata->using_extphy = 1;
        } else {
-               SMSC_WARNING(HW, "No external PHY detected, "
-                       "Using internal PHY instead.");
-               /* Use internal phy */
-               return -ENODEV;
+               SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET clear, using internal PHY");
+               pdata->using_extphy = 0;
        }
-       return 0;
 }
 
 /* Fetches a tx status out of the status fifo */
@@ -769,7 +774,7 @@ static int smsc911x_mii_probe(struct net_device *dev)
                return -ENODEV;
        }
 
-       phydev = phy_connect(dev, phydev->dev.bus_id,
+       phydev = phy_connect(dev, dev_name(&phydev->dev),
                &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface);
 
        if (IS_ERR(phydev)) {
@@ -778,7 +783,8 @@ static int smsc911x_mii_probe(struct net_device *dev)
        }
 
        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);
+               dev->name, phydev->drv->name,
+               dev_name(&phydev->dev), phydev->irq);
 
        /* mask with MAC supported features */
        phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
@@ -824,22 +830,18 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev,
 
        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");
-               }
+               smsc911x_phy_initialise_external(pdata);
                break;
        default:
                SMSC_TRACE(HW, "External PHY is not supported, "
                        "using internal PHY");
+               pdata->using_extphy = 0;
                break;
        }
 
@@ -984,7 +986,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
                        /* 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);
+                       napi_complete(napi);
                        temp = smsc911x_reg_read(pdata, INT_EN);
                        temp |= INT_EN_RSFL_EN_;
                        smsc911x_reg_write(pdata, INT_EN, temp);
@@ -1246,7 +1248,7 @@ static int smsc911x_open(struct net_device *dev)
        napi_enable(&pdata->napi);
 
        temp = smsc911x_reg_read(pdata, INT_EN);
-       temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_);
+       temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_ | INT_EN_RXSTOP_INT_EN_);
        smsc911x_reg_write(pdata, INT_EN, temp);
 
        spin_lock_irq(&pdata->mac_lock);
@@ -1418,11 +1420,6 @@ static void smsc911x_set_multicast_list(struct net_device *dev)
 
                        /* 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);
@@ -1461,11 +1458,9 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id)
                /* 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);
+               if (pdata->multicast_update_pending)
+                       smsc911x_rx_multicast_update_workaround(pdata);
                serviced = IRQ_HANDLED;
        }
 
@@ -1485,16 +1480,16 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id)
        }
 
        if (likely(intsts & inten & INT_STS_RSFL_)) {
-               if (likely(netif_rx_schedule_prep(&pdata->napi))) {
+               if (likely(napi_schedule_prep(&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(&pdata->napi);
+                       __napi_schedule(&pdata->napi);
                } else {
                        SMSC_WARNING(RX_ERR,
-                               "netif_rx_schedule_prep failed");
+                               "napi_schedule_prep failed");
                }
                serviced = IRQ_HANDLED;
        }
@@ -1545,7 +1540,7 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
 {
        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,
+       strlcpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
@@ -1747,6 +1742,21 @@ static const struct net_device_ops smsc911x_netdev_ops = {
 #endif
 };
 
+/* copies the current mac address from hardware to dev->dev_addr */
+static void __devinit smsc911x_read_mac_address(struct net_device *dev)
+{
+       struct smsc911x_data *pdata = netdev_priv(dev);
+       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);
+}
+
 /* Initializing private device structures, only called from probe */
 static int __devinit smsc911x_init(struct net_device *dev)
 {
@@ -1834,6 +1844,12 @@ static int __devinit smsc911x_init(struct net_device *dev)
                SMSC_WARNING(PROBE,
                        "This driver is not intended for this chip revision");
 
+       /* workaround for platforms without an eeprom, where the mac address
+        * is stored elsewhere and set by the bootloader.  This saves the
+        * mac address before resetting the device */
+       if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS)
+               smsc911x_read_mac_address(dev);
+
        /* Reset the LAN911x */
        if (smsc911x_soft_reset(pdata))
                return -ENODEV;
@@ -1892,9 +1908,9 @@ 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;
+       struct resource *res, *irq_res;
        unsigned int intcfg = 0;
-       int res_size;
+       int res_size, irq_flags;
        int retval;
        DECLARE_MAC_BUF(mac);
 
@@ -1919,6 +1935,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        }
        res_size = res->end - res->start;
 
+       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq_res) {
+               pr_warning("%s: Could not allocate irq resource.\n",
+                       SMSC_CHIPNAME);
+               retval = -ENODEV;
+               goto out_0;
+       }
+
        if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) {
                retval = -EBUSY;
                goto out_0;
@@ -1935,7 +1959,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
 
        pdata = netdev_priv(dev);
 
-       dev->irq = platform_get_irq(pdev, 0);
+       dev->irq = irq_res->start;
+       irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
        pdata->ioaddr = ioremap_nocache(res->start, res_size);
 
        /* copy config parameters across to pdata */
@@ -1968,8 +1993,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        smsc911x_reg_write(pdata, INT_EN, 0);
        smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
 
-       retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED,
-                            dev->name, dev);
+       retval = request_irq(dev->irq, smsc911x_irqhandler,
+                            irq_flags | IRQF_SHARED, dev->name, dev);
        if (retval) {
                SMSC_WARNING(PROBE,
                        "Unable to claim requested irq: %d", dev->irq);
@@ -2005,14 +2030,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        } 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);
+               smsc911x_read_mac_address(dev);
 
                if (is_valid_ether_addr(dev->dev_addr)) {
                        /* eeprom values are valid  so use them */
index a1e4b3895b339d0a007ec07483e6039bf1d212d0..da8b977a5357338e039384a25ee885db535c1877 100644 (file)
@@ -666,7 +666,7 @@ static irqreturn_t smsc9420_isr(int irq, void *dev_id)
                        smsc9420_pci_flush_write(pd);
 
                        ints_to_clear |= (DMAC_STS_RX_ | DMAC_STS_NIS_);
-                       netif_rx_schedule(&pd->napi);
+                       napi_schedule(&pd->napi);
                }
 
                if (ints_to_clear)
@@ -889,7 +889,7 @@ static int smsc9420_rx_poll(struct napi_struct *napi, int budget)
        smsc9420_pci_flush_write(pd);
 
        if (work_done < budget) {
-               netif_rx_complete(&pd->napi);
+               napi_complete(&pd->napi);
 
                /* re-enable RX DMA interrupts */
                dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
@@ -1156,7 +1156,7 @@ static int smsc9420_mii_probe(struct net_device *dev)
        smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr,
                phydev->phy_id);
 
-       phydev = phy_connect(dev, phydev->dev.bus_id,
+       phydev = phy_connect(dev, dev_name(&phydev->dev),
                &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII);
 
        if (IS_ERR(phydev)) {
@@ -1165,7 +1165,7 @@ static int smsc9420_mii_probe(struct net_device *dev)
        }
 
        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);
+               dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        /* mask with MAC supported features */
        phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
index 88d2c67788dfd2ab8fb692b575b98e2f2066ec6d..7f6b4a4052eed1ef5e46a3cfcdea456fe636cc46 100644 (file)
@@ -1301,7 +1301,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(napi);
+               napi_complete(napi);
                spider_net_rx_irq_on(card);
                card->ignore_rx_ramfull = 0;
        }
@@ -1528,7 +1528,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->napi);
+                       napi_schedule(&card->napi);
                }
                show_error = 0;
                break;
@@ -1548,7 +1548,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->napi);
+               napi_schedule(&card->napi);
                show_error = 0;
                break;
 
@@ -1562,7 +1562,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->napi);
+               napi_schedule(&card->napi);
                show_error = 0;
                break;
 
@@ -1656,11 +1656,11 @@ spider_net_interrupt(int irq, void *ptr)
 
        if (status_reg & SPIDER_NET_RXINT ) {
                spider_net_rx_irq_off(card);
-               netif_rx_schedule(&card->napi);
+               napi_schedule(&card->napi);
                card->num_rx_ints ++;
        }
        if (status_reg & SPIDER_NET_TXINT)
-               netif_rx_schedule(&card->napi);
+               napi_schedule(&card->napi);
 
        if (status_reg & SPIDER_NET_LINKINT)
                spider_net_link_reset(netdev);
index da3a76b18effee66075bc0a09a93ea076215a0bd..98fe79515bab97bf2f8ff8d60d5ba35c94a4fa35 100644 (file)
@@ -1342,8 +1342,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
                if (intr_status & (IntrRxDone | IntrRxEmpty)) {
                        u32 enable;
 
-                       if (likely(netif_rx_schedule_prep(&np->napi))) {
-                               __netif_rx_schedule(&np->napi);
+                       if (likely(napi_schedule_prep(&np->napi))) {
+                               __napi_schedule(&np->napi);
                                enable = readl(ioaddr + IntrEnable);
                                enable &= ~(IntrRxDone | IntrRxEmpty);
                                writel(enable, ioaddr + IntrEnable);
@@ -1587,7 +1587,7 @@ static int netdev_poll(struct napi_struct *napi, int budget)
                intr_status = readl(ioaddr + IntrStatus);
        } while (intr_status & (IntrRxDone | IntrRxEmpty));
 
-       netif_rx_complete(napi);
+       napi_complete(napi);
        intr_status = readl(ioaddr + IntrEnable);
        intr_status |= IntrRxDone | IntrRxEmpty;
        writel(intr_status, ioaddr + IntrEnable);
index b17efa9cc530f660e3166e77c6db9d5a401c9b57..fc1e7f1d024b2e932304d79c5504784cd166c889 100644 (file)
@@ -921,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(napi);
+       __napi_complete(napi);
        gem_enable_ints(gp);
 
        spin_unlock_irqrestore(&gp->lock, flags);
@@ -944,7 +944,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
 
        spin_lock_irqsave(&gp->lock, flags);
 
-       if (netif_rx_schedule_prep(&gp->napi)) {
+       if (napi_schedule_prep(&gp->napi)) {
                u32 gem_status = readl(gp->regs + GREG_STAT);
 
                if (gem_status == 0) {
@@ -954,7 +954,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
                }
                gp->status = gem_status;
                gem_disable_ints(gp);
-               __netif_rx_schedule(&gp->napi);
+               __napi_schedule(&gp->napi);
        }
 
        spin_unlock_irqrestore(&gp->lock, flags);
index bcd0e60cbda98984c9383f55cc4df671510d33a1..b52a1c088f37717ff19e82df83ee0bd4743bd352 100644 (file)
@@ -725,7 +725,7 @@ static int tc_mii_probe(struct net_device *dev)
        }
 
        /* attach the mac to the phy */
-       phydev = phy_connect(dev, phydev->dev.bus_id,
+       phydev = phy_connect(dev, dev_name(&phydev->dev),
                             &tc_handle_link_change, 0,
                             lp->chiptype == TC35815_TX4939 ?
                             PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII);
@@ -735,7 +735,7 @@ static int tc_mii_probe(struct net_device *dev)
        }
        printk(KERN_INFO "%s: attached PHY driver [%s] "
                "(mii_bus:phy_addr=%s, id=%x)\n",
-               dev->name, phydev->drv->name, phydev->dev.bus_id,
+               dev->name, phydev->drv->name, dev_name(&phydev->dev),
                phydev->phy_id);
 
        /* mask with MAC supported features */
@@ -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(&lp->napi))
-                       __netif_rx_schedule(&lp->napi);
+               if (napi_schedule_prep(&lp->napi))
+                       __napi_schedule(&lp->napi);
                else {
                        printk(KERN_ERR "%s: interrupt taken in poll\n",
                               dev->name);
@@ -1919,7 +1919,7 @@ static int tc35815_poll(struct napi_struct *napi, int budget)
        spin_unlock(&lp->lock);
 
        if (received < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                /* enable interrupts */
                tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
        }
index a7a4dc4d6313c1403794435a14b99a83f8029505..be9f38f8f0bfae3173d452e48df8b4db2f747bb6 100644 (file)
@@ -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(&priv->napi))) {
-                       __netif_rx_schedule(&priv->napi);
+               if (likely(napi_schedule_prep(&priv->napi))) {
+                       __napi_schedule(&priv->napi);
                        RET(IRQ_HANDLED);
                } else {
                        /* NOTE: we get here if intr has slipped into window
@@ -302,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(napi);
+               napi_complete(napi);
                bdx_enable_interrupts(priv);
        }
        return work_done;
index 8b3f8468538794ff08c66b616a7bcdd848a127e2..5b3d60568d554196a1eb6549df1173b7aa7d9e1b 100644 (file)
@@ -860,7 +860,7 @@ static int tg3_bmcr_reset(struct tg3 *tp)
 
 static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 {
-       struct tg3 *tp = (struct tg3 *)bp->priv;
+       struct tg3 *tp = bp->priv;
        u32 val;
 
        if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
@@ -874,7 +874,7 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 
 static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val)
 {
-       struct tg3 *tp = (struct tg3 *)bp->priv;
+       struct tg3 *tp = bp->priv;
 
        if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
                return -EAGAIN;
@@ -4460,7 +4460,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(napi);
+                       napi_complete(napi);
                        tg3_restart_ints(tp);
                        break;
                }
@@ -4470,7 +4470,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(napi);
+       napi_complete(napi);
        schedule_work(&tp->reset_task);
        return work_done;
 }
@@ -4519,7 +4519,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(&tp->napi);
+               napi_schedule(&tp->napi);
 
        return IRQ_HANDLED;
 }
@@ -4544,7 +4544,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(&tp->napi);
+               napi_schedule(&tp->napi);
 
        return IRQ_RETVAL(1);
 }
@@ -4586,7 +4586,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(&tp->napi);
+               napi_schedule(&tp->napi);
        } else {
                /* No work, shared interrupt perhaps?  re-enable
                 * interrupts, and flush that PCI write
@@ -4632,7 +4632,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(&tp->napi)) {
+       if (napi_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
@@ -4640,7 +4640,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(&tp->napi);
+               __napi_schedule(&tp->napi);
        }
 out:
        return IRQ_RETVAL(handled);
index 43853e3b210e42977100f1c1b3828a3dfa9fe623..4a65fc2dd9282ffef9dc72a92a559c90b85dd7e3 100644 (file)
@@ -274,6 +274,15 @@ static void  xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value)
        
        return ; 
 }
+
+static const struct net_device_ops xl_netdev_ops = {
+       .ndo_open               = xl_open,
+       .ndo_stop               = xl_close,
+       .ndo_start_xmit         = xl_xmit,
+       .ndo_change_mtu         = xl_change_mtu,
+       .ndo_set_multicast_list = xl_set_rx_mode,
+       .ndo_set_mac_address    = xl_set_mac_address,
+};
  
 static int __devinit xl_probe(struct pci_dev *pdev,
                              const struct pci_device_id *ent) 
@@ -337,13 +346,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
                return i ; 
        }                               
 
-       dev->open=&xl_open;
-       dev->hard_start_xmit=&xl_xmit;
-       dev->change_mtu=&xl_change_mtu;
-       dev->stop=&xl_close;
-       dev->do_ioctl=NULL;
-       dev->set_multicast_list=&xl_set_rx_mode;
-       dev->set_mac_address=&xl_set_mac_address ; 
+       dev->netdev_ops = &xl_netdev_ops;
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        pci_set_drvdata(pdev,dev) ; 
index b566d6d79ecdbe7ce0a5f58f7546f50e77600ec5..b9db1b5a58a3db04af268a0c5148ac147aa40c89 100644 (file)
@@ -92,6 +92,8 @@ static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned
        outw(val, dev->base_addr + reg);
 }
 
+static struct net_device_ops abyss_netdev_ops;
+
 static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
 {      
        static int versionprinted;
@@ -157,8 +159,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
 
        memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
                
-       dev->open = abyss_open;
-       dev->stop = abyss_close;
+       dev->netdev_ops = &abyss_netdev_ops;
 
        pci_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -450,6 +451,11 @@ static struct pci_driver abyss_driver = {
 
 static int __init abyss_init (void)
 {
+       abyss_netdev_ops = tms380tr_netdev_ops;
+
+       abyss_netdev_ops.ndo_open = abyss_open;
+       abyss_netdev_ops.ndo_stop = abyss_close;
+
        return pci_register_driver(&abyss_driver);
 }
 
index fa7bce6e0c6dc56019d18197b2076ddfd3e6a3d8..9d896116cf761b6aea8a6b294a2da95fa07238f5 100644 (file)
@@ -200,7 +200,6 @@ static void         tr_rx(struct net_device *dev);
 static void    ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);
 static void    tok_rerun(unsigned long dev_addr);
 static void    ibmtr_readlog(struct net_device *dev);
-static struct  net_device_stats *tok_get_stats(struct net_device *dev);
 static int     ibmtr_change_mtu(struct net_device *dev, int mtu);
 static void    find_turbo_adapters(int *iolist);
 
@@ -816,18 +815,21 @@ static unsigned char __devinit get_sram_size(struct tok_info *adapt_info)
 
 /*****************************************************************************/
 
+static const struct net_device_ops trdev_netdev_ops = {
+       .ndo_open               = tok_open,
+       .ndo_stop               = tok_close,
+       .ndo_start_xmit         = tok_send_packet,
+       .ndo_set_multicast_list = tok_set_multicast_list,
+       .ndo_change_mtu         = ibmtr_change_mtu,
+};
+
 static int __devinit trdev_init(struct net_device *dev)
 {
        struct tok_info *ti = netdev_priv(dev);
 
        SET_PAGE(ti->srb_page);
         ti->open_failure = NO    ;
-       dev->open = tok_open;
-       dev->stop = tok_close;
-       dev->hard_start_xmit = tok_send_packet;
-       dev->get_stats = tok_get_stats;
-       dev->set_multicast_list = tok_set_multicast_list;
-       dev->change_mtu = ibmtr_change_mtu;
+       dev->netdev_ops = &trdev_netdev_ops;
 
        return 0;
 }
@@ -1460,7 +1462,7 @@ static irqreturn_t tok_interrupt(int irq, void *dev_id)
                                        "%02X\n",
                                        (int)retcode, (int)readb(ti->ssb + 6));
                        else
-                               ti->tr_stats.tx_packets++;
+                               dev->stats.tx_packets++;
                        break;
                case XMIT_XID_CMD:
                        DPRINTK("xmit xid ret_code: %02X\n",
@@ -1646,7 +1648,7 @@ static void tr_tx(struct net_device *dev)
                break;
        }
        writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
-       ti->tr_stats.tx_bytes += ti->current_skb->len;
+       dev->stats.tx_bytes += ti->current_skb->len;
        dev_kfree_skb_irq(ti->current_skb);
        ti->current_skb = NULL;
        netif_wake_queue(dev);
@@ -1722,7 +1724,7 @@ static void tr_rx(struct net_device *dev)
        if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) {
                SET_PAGE(ti->asb_page);
                writeb(DATA_LOST, ti->asb + RETCODE_OFST);
-               ti->tr_stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
                return;
        }
@@ -1757,7 +1759,7 @@ static void tr_rx(struct net_device *dev)
 
        if (!(skb = dev_alloc_skb(skb_size))) {
                DPRINTK("out of memory. frame dropped.\n");
-               ti->tr_stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                SET_PAGE(ti->asb_page);
                writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));
                writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
@@ -1813,8 +1815,8 @@ static void tr_rx(struct net_device *dev)
 
        writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
 
-       ti->tr_stats.rx_bytes += skb->len;
-       ti->tr_stats.rx_packets++;
+       dev->stats.rx_bytes += skb->len;
+       dev->stats.rx_packets++;
 
        skb->protocol = tr_type_trans(skb, dev);
        if (IPv4_p) {
@@ -1876,21 +1878,6 @@ static void ibmtr_readlog(struct net_device *dev)
 
 /*****************************************************************************/
 
-/* tok_get_stats():  Basically a scaffold routine which will return
-   the address of the tr_statistics structure associated with
-   this device -- the tr.... structure is an ethnet look-alike
-   so at least for this iteration may suffice.   */
-
-static struct net_device_stats *tok_get_stats(struct net_device *dev)
-{
-
-       struct tok_info *toki;
-       toki = netdev_priv(dev);
-       return (struct net_device_stats *) &toki->tr_stats;
-}
-
-/*****************************************************************************/
-
 static int ibmtr_change_mtu(struct net_device *dev, int mtu)
 {
        struct tok_info *ti = netdev_priv(dev);
index 239c75217b120624d7ae500ce919552a869507b5..0b2b7925da222b6668a873d34502ec33e18613a7 100644 (file)
@@ -207,7 +207,6 @@ static int streamer_xmit(struct sk_buff *skb, struct net_device *dev);
 static int streamer_close(struct net_device *dev);
 static void streamer_set_rx_mode(struct net_device *dev);
 static irqreturn_t streamer_interrupt(int irq, void *dev_id);
-static struct net_device_stats *streamer_get_stats(struct net_device *dev);
 static int streamer_set_mac_address(struct net_device *dev, void *addr);
 static void streamer_arb_cmd(struct net_device *dev);
 static int streamer_change_mtu(struct net_device *dev, int mtu);
@@ -222,6 +221,18 @@ struct streamer_private *dev_streamer=NULL;
 #endif
 #endif
 
+static const struct net_device_ops streamer_netdev_ops = {
+       .ndo_open               = streamer_open,
+       .ndo_stop               = streamer_close,
+       .ndo_start_xmit         = streamer_xmit,
+       .ndo_change_mtu         = streamer_change_mtu,
+#if STREAMER_IOCTL
+       .ndo_do_ioctl           = streamer_ioctl,
+#endif
+       .ndo_set_multicast_list = streamer_set_rx_mode,
+       .ndo_set_mac_address    = streamer_set_mac_address,
+};
+
 static int __devinit streamer_init_one(struct pci_dev *pdev,
                                       const struct pci_device_id *ent)
 {
@@ -321,18 +332,7 @@ static int __devinit streamer_init_one(struct pci_dev *pdev,
        init_waitqueue_head(&streamer_priv->srb_wait);
        init_waitqueue_head(&streamer_priv->trb_wait);
 
-       dev->open = &streamer_open;
-       dev->hard_start_xmit = &streamer_xmit;
-       dev->change_mtu = &streamer_change_mtu;
-       dev->stop = &streamer_close;
-#if STREAMER_IOCTL
-       dev->do_ioctl = &streamer_ioctl;
-#else
-       dev->do_ioctl = NULL;
-#endif
-       dev->set_multicast_list = &streamer_set_rx_mode;
-       dev->get_stats = &streamer_get_stats;
-       dev->set_mac_address = &streamer_set_mac_address;
+       dev->netdev_ops = &streamer_netdev_ops;
        dev->irq = pdev->irq;
        dev->base_addr=pio_start;
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -937,7 +937,7 @@ static void streamer_rx(struct net_device *dev)
                        if (skb == NULL) 
                        {
                                printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n", dev->name);
-                               streamer_priv->streamer_stats.rx_dropped++;
+                               dev->stats.rx_dropped++;
                        } else {        /* we allocated an skb OK */
                                if (buffer_cnt == 1) {
                                        /* release the DMA mapping */
@@ -1009,8 +1009,8 @@ static void streamer_rx(struct net_device *dev)
                                        /* send up to the protocol */
                                        netif_rx(skb);
                                }
-                               streamer_priv->streamer_stats.rx_packets++;
-                               streamer_priv->streamer_stats.rx_bytes += length;
+                               dev->stats.rx_packets++;
+                               dev->stats.rx_bytes += length;
                        }       /* if skb == null */
                }               /* end received without errors */
 
@@ -1053,8 +1053,8 @@ static irqreturn_t streamer_interrupt(int irq, void *dev_id)
                                while(streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) {
                                streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1);
                                streamer_priv->free_tx_ring_entries++;
-                               streamer_priv->streamer_stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len;
-                               streamer_priv->streamer_stats.tx_packets++;
+                               dev->stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len;
+                               dev->stats.tx_packets++;
                                dev_kfree_skb_irq(streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]);
                                streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buffer = 0xdeadbeef;
                                streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].status = 0;
@@ -1484,13 +1484,6 @@ static void streamer_srb_bh(struct net_device *dev)
        }                       /* switch srb[0] */
 }
 
-static struct net_device_stats *streamer_get_stats(struct net_device *dev)
-{
-       struct streamer_private *streamer_priv;
-       streamer_priv = netdev_priv(dev);
-       return (struct net_device_stats *) &streamer_priv->streamer_stats;
-}
-
 static int streamer_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr *saddr = addr;
index 13ccee6449c1314a08db9e1863f2f0619fadf9c8..3c58d6a3fbc98a5420975b1f4182915840235c0a 100644 (file)
@@ -299,7 +299,6 @@ struct streamer_private {
        int tx_ring_free, tx_ring_last_status, rx_ring_last_received,
            free_tx_ring_entries;
 
-       struct net_device_stats streamer_stats;
        __u16 streamer_lan_status;
        __u8 streamer_ring_speed;
        __u16 pkt_buf_sz;
index ecb5c7c969105ff6d79622f17f50a47c6ea3bd3e..77dc9da4c0b9dc7f3b9a55fc8c95bca47554cda6 100644 (file)
@@ -187,7 +187,6 @@ static int olympic_close(struct net_device *dev);
 static void olympic_set_rx_mode(struct net_device *dev);
 static void olympic_freemem(struct net_device *dev) ;  
 static irqreturn_t olympic_interrupt(int irq, void *dev_id);
-static struct net_device_stats * olympic_get_stats(struct net_device *dev);
 static int olympic_set_mac_address(struct net_device *dev, void *addr) ; 
 static void olympic_arb_cmd(struct net_device *dev);
 static int olympic_change_mtu(struct net_device *dev, int mtu);
@@ -195,6 +194,15 @@ static void olympic_srb_bh(struct net_device *dev) ;
 static void olympic_asb_bh(struct net_device *dev) ; 
 static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) ; 
 
+static const struct net_device_ops olympic_netdev_ops = {
+       .ndo_open               = olympic_open,
+       .ndo_stop               = olympic_close,
+       .ndo_start_xmit         = olympic_xmit,
+       .ndo_change_mtu         = olympic_change_mtu,
+       .ndo_set_multicast_list = olympic_set_rx_mode,
+       .ndo_set_mac_address    = olympic_set_mac_address,
+};
+
 static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev ; 
@@ -253,14 +261,7 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device
                goto op_free_iomap;
        }                               
 
-       dev->open=&olympic_open;
-       dev->hard_start_xmit=&olympic_xmit;
-       dev->change_mtu=&olympic_change_mtu;
-       dev->stop=&olympic_close;
-       dev->do_ioctl=NULL;
-       dev->set_multicast_list=&olympic_set_rx_mode;
-       dev->get_stats=&olympic_get_stats ;
-       dev->set_mac_address=&olympic_set_mac_address ;  
+       dev->netdev_ops = &olympic_netdev_ops;
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        pci_set_drvdata(pdev,dev) ; 
@@ -785,7 +786,7 @@ static void olympic_rx(struct net_device *dev)
                                } 
                                olympic_priv->rx_ring_last_received += i ; 
                                olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; 
-                               olympic_priv->olympic_stats.rx_errors++;         
+                               dev->stats.rx_errors++;
                        } else {        
                        
                                if (buffer_cnt == 1) {
@@ -796,7 +797,7 @@ static void olympic_rx(struct net_device *dev)
 
                                if (skb == NULL) {
                                        printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ;
-                                       olympic_priv->olympic_stats.rx_dropped++ ; 
+                                       dev->stats.rx_dropped++;
                                        /* Update counters even though we don't transfer the frame */
                                        olympic_priv->rx_ring_last_received += i ; 
                                        olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;  
@@ -862,8 +863,8 @@ static void olympic_rx(struct net_device *dev)
                                                skb->protocol = tr_type_trans(skb,dev);
                                                netif_rx(skb) ; 
                                        } 
-                                       olympic_priv->olympic_stats.rx_packets++ ; 
-                                       olympic_priv->olympic_stats.rx_bytes += length ; 
+                                       dev->stats.rx_packets++ ;
+                                       dev->stats.rx_bytes += length ;
                                } /* if skb == null */
                        } /* If status & 0x3b */
 
@@ -971,8 +972,8 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id)
                                olympic_priv->tx_ring_last_status++;
                                olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1);
                                olympic_priv->free_tx_ring_entries++;
-                               olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;
-                               olympic_priv->olympic_stats.tx_packets++ ; 
+                               dev->stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;
+                               dev->stats.tx_packets++ ;
                                pci_unmap_single(olympic_priv->pdev, 
                                        le32_to_cpu(olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer), 
                                        olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len,PCI_DMA_TODEVICE);
@@ -1344,13 +1345,6 @@ static void olympic_srb_bh(struct net_device *dev)
 
 } 
 
-static struct net_device_stats * olympic_get_stats(struct net_device *dev)
-{
-       struct olympic_private *olympic_priv ;
-       olympic_priv=netdev_priv(dev);
-       return (struct net_device_stats *) &olympic_priv->olympic_stats; 
-}
-
 static int olympic_set_mac_address (struct net_device *dev, void *addr) 
 {
        struct sockaddr *saddr = addr ; 
index 10fbba08978f4592666d92c6f4f55369589de825..30631bae4c9481e6676911e20659c285c74c2ec1 100644 (file)
@@ -275,7 +275,6 @@ struct olympic_private {
        struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE];  
        int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries;
 
-       struct net_device_stats olympic_stats ;
        u16 olympic_lan_status ;
        u8 olympic_ring_speed ;
        u16 pkt_buf_sz ; 
index 5be34c2fd48385751844d82dc0c12b1e6d5390d4..b11bb72dc7abae085326c605351cd92f52c6f70d 100644 (file)
@@ -2330,6 +2330,17 @@ void tmsdev_term(struct net_device *dev)
                DMA_BIDIRECTIONAL);
 }
 
+const struct net_device_ops tms380tr_netdev_ops = {
+       .ndo_open               = tms380tr_open,
+       .ndo_stop               = tms380tr_close,
+       .ndo_start_xmit         = tms380tr_send_packet,
+       .ndo_tx_timeout         = tms380tr_timeout,
+       .ndo_get_stats          = tms380tr_get_stats,
+       .ndo_set_multicast_list = tms380tr_set_multicast_list,
+       .ndo_set_mac_address    = tms380tr_set_mac_address,
+};
+EXPORT_SYMBOL(tms380tr_netdev_ops);
+
 int tmsdev_init(struct net_device *dev, struct device *pdev)
 {
        struct net_local *tms_local;
@@ -2353,16 +2364,8 @@ int tmsdev_init(struct net_device *dev, struct device *pdev)
                return -ENOMEM;
        }
        
-       /* These can be overridden by the card driver if needed */
-       dev->open               = tms380tr_open;
-       dev->stop               = tms380tr_close;
-       dev->do_ioctl           = NULL; 
-       dev->hard_start_xmit    = tms380tr_send_packet;
-       dev->tx_timeout         = tms380tr_timeout;
+       dev->netdev_ops         = &tms380tr_netdev_ops;
        dev->watchdog_timeo     = HZ;
-       dev->get_stats          = tms380tr_get_stats;
-       dev->set_multicast_list = &tms380tr_set_multicast_list;
-       dev->set_mac_address    = tms380tr_set_mac_address;
 
        return 0;
 }
index 7af76d7088490f61b57af4adcf832c7b16a018f7..60b30ee38dcbea0dd7d1c116eff56834ec32ec8d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 
 /* module prototypes */
+extern const struct net_device_ops tms380tr_netdev_ops;
 int tms380tr_open(struct net_device *dev);
 int tms380tr_close(struct net_device *dev);
 irqreturn_t tms380tr_interrupt(int irq, void *dev_id);
index 5f601773c26064e7962e6bc5026018f5f1c666af..b397e8785d6d3e5c3f7eb9ba8e3683214dddf9e1 100644 (file)
@@ -157,8 +157,8 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
 
        tp->tmspriv = cardinfo;
 
-       dev->open = tms380tr_open;
-       dev->stop = tms380tr_close;
+       dev->netdev_ops = &tms380tr_netdev_ops;
+
        pci_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
index a9fd2b2ccaf6be90517b491bbb78f8e013fb3939..bb43e7fb2a508b35e073f89a9eca2ce4d752bec0 100644 (file)
@@ -888,7 +888,7 @@ static int tsi108_poll(struct napi_struct *napi, int budget)
 
        if (num_received < budget) {
                data->rxpending = 0;
-               netif_rx_complete(napi);
+               napi_complete(napi);
 
                TSI_WRITE(TSI108_EC_INTMASK,
                                     TSI_READ(TSI108_EC_INTMASK)
@@ -915,11 +915,11 @@ static void tsi108_rx_int(struct net_device *dev)
         *
         * This can happen if this code races with tsi108_poll(), which masks
         * the interrupts after tsi108_irq_one() read the mask, but before
-        * netif_rx_schedule is called.  It could also happen due to calls
+        * napi_schedule is called.  It could also happen due to calls
         * from tsi108_check_rxring().
         */
 
-       if (netif_rx_schedule_prep(&data->napi)) {
+       if (napi_schedule_prep(&data->napi)) {
                /* Mask, rather than ack, the receive interrupts.  The ack
                 * will happen in tsi108_poll().
                 */
@@ -930,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(&data->napi);
+               __napi_schedule(&data->napi);
        } else {
                if (!netif_running(dev)) {
                        /* This can happen if an interrupt occurs while the
index 6c3428a37c0b9d5c672e777b052a199710d01c97..9f946d4210885f3650ece6ece8629fc8a1c0724e 100644 (file)
@@ -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(&tp->napi);
+       napi_schedule(&tp->napi);
 }
 
 int tulip_poll(struct napi_struct *napi, int budget)
@@ -300,7 +300,7 @@ int tulip_poll(struct napi_struct *napi, int budget)
 
          /* Remove us from polling list and enable RX intr. */
 
-         netif_rx_complete(napi);
+         napi_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:
@@ -333,10 +333,10 @@ int tulip_poll(struct napi_struct *napi, int budget)
 
          /* Think: timer_pending() was an explicit signature of bug.
           * Timer can be pending now but fired and completed
-          * before we did netif_rx_complete(). See? We would lose it. */
+          * before we did napi_complete(). See? We would lose it. */
 
          /* remove ourselves from the polling list */
-         netif_rx_complete(napi);
+         napi_complete(napi);
 
          return work_done;
 }
@@ -519,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(&tp->napi);
+                       napi_schedule(&tp->napi);
 
                        if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
                                break;
index d7b81e4fdd5631c0c537cd971cad3bebb72bb38d..15d67635bb10540ee1185818aaa2b83c86bbee5b 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/virtio_net.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
+#include <net/rtnetlink.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -87,14 +88,19 @@ struct tap_filter {
        unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
+struct tun_file {
+       atomic_t count;
+       struct tun_struct *tun;
+       struct net *net;
+       wait_queue_head_t       read_wait;
+};
+
 struct tun_struct {
-       struct list_head        list;
+       struct tun_file         *tfile;
        unsigned int            flags;
-       int                     attached;
        uid_t                   owner;
        gid_t                   group;
 
-       wait_queue_head_t       read_wait;
        struct sk_buff_head     readq;
 
        struct net_device       *dev;
@@ -107,6 +113,88 @@ struct tun_struct {
 #endif
 };
 
+static int tun_attach(struct tun_struct *tun, struct file *file)
+{
+       struct tun_file *tfile = file->private_data;
+       const struct cred *cred = current_cred();
+       int err;
+
+       ASSERT_RTNL();
+
+       /* Check permissions */
+       if (((tun->owner != -1 && cred->euid != tun->owner) ||
+            (tun->group != -1 && !in_egroup_p(tun->group))) &&
+               !capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       netif_tx_lock_bh(tun->dev);
+
+       err = -EINVAL;
+       if (tfile->tun)
+               goto out;
+
+       err = -EBUSY;
+       if (tun->tfile)
+               goto out;
+
+       err = 0;
+       tfile->tun = tun;
+       tun->tfile = tfile;
+       dev_hold(tun->dev);
+       atomic_inc(&tfile->count);
+
+out:
+       netif_tx_unlock_bh(tun->dev);
+       return err;
+}
+
+static void __tun_detach(struct tun_struct *tun)
+{
+       struct tun_file *tfile = tun->tfile;
+
+       /* Detach from net device */
+       netif_tx_lock_bh(tun->dev);
+       tfile->tun = NULL;
+       tun->tfile = NULL;
+       netif_tx_unlock_bh(tun->dev);
+
+       /* Drop read queue */
+       skb_queue_purge(&tun->readq);
+
+       /* Drop the extra count on the net device */
+       dev_put(tun->dev);
+}
+
+static void tun_detach(struct tun_struct *tun)
+{
+       rtnl_lock();
+       __tun_detach(tun);
+       rtnl_unlock();
+}
+
+static struct tun_struct *__tun_get(struct tun_file *tfile)
+{
+       struct tun_struct *tun = NULL;
+
+       if (atomic_inc_not_zero(&tfile->count))
+               tun = tfile->tun;
+
+       return tun;
+}
+
+static struct tun_struct *tun_get(struct file *file)
+{
+       return __tun_get(file->private_data);
+}
+
+static void tun_put(struct tun_struct *tun)
+{
+       struct tun_file *tfile = tun->tfile;
+
+       if (atomic_dec_and_test(&tfile->count))
+               tun_detach(tfile->tun);
+}
+
 /* TAP filterting */
 static void addr_hash_set(u32 *mask, const u8 *addr)
 {
@@ -213,13 +301,23 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
 
 /* Network device part of the driver */
 
-static int tun_net_id;
-struct tun_net {
-       struct list_head dev_list;
-};
-
 static const struct ethtool_ops tun_ethtool_ops;
 
+/* Net device detach from fd. */
+static void tun_net_uninit(struct net_device *dev)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+       struct tun_file *tfile = tun->tfile;
+
+       /* Inform the methods they need to stop using the dev.
+        */
+       if (tfile) {
+               wake_up_all(&tfile->read_wait);
+               if (atomic_dec_and_test(&tfile->count))
+                       __tun_detach(tun);
+       }
+}
+
 /* Net device open. */
 static int tun_net_open(struct net_device *dev)
 {
@@ -242,7 +340,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
        DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len);
 
        /* Drop packet if interface is not attached */
-       if (!tun->attached)
+       if (!tun->tfile)
                goto drop;
 
        /* Drop if the filter does not like it.
@@ -274,7 +372,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Notify and wake up reader process */
        if (tun->flags & TUN_FASYNC)
                kill_fasync(&tun->fasync, SIGIO, POLL_IN);
-       wake_up_interruptible(&tun->read_wait);
+       wake_up_interruptible(&tun->tfile->read_wait);
        return 0;
 
 drop:
@@ -306,6 +404,7 @@ tun_net_change_mtu(struct net_device *dev, int new_mtu)
 }
 
 static const struct net_device_ops tun_netdev_ops = {
+       .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
@@ -313,6 +412,7 @@ static const struct net_device_ops tun_netdev_ops = {
 };
 
 static const struct net_device_ops tap_netdev_ops = {
+       .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
@@ -359,19 +459,24 @@ static void tun_net_init(struct net_device *dev)
 /* Poll */
 static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_file *tfile = file->private_data;
+       struct tun_struct *tun = __tun_get(tfile);
        unsigned int mask = POLLOUT | POLLWRNORM;
 
        if (!tun)
-               return -EBADFD;
+               return POLLERR;
 
        DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
 
-       poll_wait(file, &tun->read_wait, wait);
+       poll_wait(file, &tfile->read_wait, wait);
 
        if (!skb_queue_empty(&tun->readq))
                mask |= POLLIN | POLLRDNORM;
 
+       if (tun->dev->reg_state != NETREG_REGISTERED)
+               mask = POLLERR;
+
+       tun_put(tun);
        return mask;
 }
 
@@ -438,7 +543,7 @@ static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear,
 /* Get packet from user space buffer */
 static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count)
 {
-       struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
+       struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
        struct sk_buff *skb;
        size_t len = count, align = 0;
        struct virtio_net_hdr gso = { 0 };
@@ -556,14 +661,18 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
 static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
                              unsigned long count, loff_t pos)
 {
-       struct tun_struct *tun = iocb->ki_filp->private_data;
+       struct tun_struct *tun = tun_get(iocb->ki_filp);
+       ssize_t result;
 
        if (!tun)
                return -EBADFD;
 
        DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
 
-       return tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count));
+       result = tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count));
+
+       tun_put(tun);
+       return result;
 }
 
 /* Put packet to the user space buffer */
@@ -636,7 +745,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
                            unsigned long count, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
-       struct tun_struct *tun = file->private_data;
+       struct tun_file *tfile = file->private_data;
+       struct tun_struct *tun = __tun_get(tfile);
        DECLARE_WAITQUEUE(wait, current);
        struct sk_buff *skb;
        ssize_t len, ret = 0;
@@ -647,10 +757,12 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
        DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
 
        len = iov_length(iv, count);
-       if (len < 0)
-               return -EINVAL;
+       if (len < 0) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-       add_wait_queue(&tun->read_wait, &wait);
+       add_wait_queue(&tfile->read_wait, &wait);
        while (len) {
                current->state = TASK_INTERRUPTIBLE;
 
@@ -664,6 +776,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
                                ret = -ERESTARTSYS;
                                break;
                        }
+                       if (tun->dev->reg_state != NETREG_REGISTERED) {
+                               ret = -EIO;
+                               break;
+                       }
 
                        /* Nothing to read, let's sleep */
                        schedule();
@@ -677,8 +793,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
        }
 
        current->state = TASK_RUNNING;
-       remove_wait_queue(&tun->read_wait, &wait);
+       remove_wait_queue(&tfile->read_wait, &wait);
 
+out:
+       tun_put(tun);
        return ret;
 }
 
@@ -687,54 +805,49 @@ static void tun_setup(struct net_device *dev)
        struct tun_struct *tun = netdev_priv(dev);
 
        skb_queue_head_init(&tun->readq);
-       init_waitqueue_head(&tun->read_wait);
 
        tun->owner = -1;
        tun->group = -1;
 
        dev->ethtool_ops = &tun_ethtool_ops;
        dev->destructor = free_netdev;
-       dev->features |= NETIF_F_NETNS_LOCAL;
 }
 
-static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
+/* Trivial set of netlink ops to allow deleting tun or tap
+ * device with netlink.
+ */
+static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
 {
-       struct tun_struct *tun;
+       return -EINVAL;
+}
 
-       ASSERT_RTNL();
-       list_for_each_entry(tun, &tn->dev_list, list) {
-               if (!strncmp(tun->dev->name, name, IFNAMSIZ))
-                   return tun;
-       }
+static struct rtnl_link_ops tun_link_ops __read_mostly = {
+       .kind           = DRV_NAME,
+       .priv_size      = sizeof(struct tun_struct),
+       .setup          = tun_setup,
+       .validate       = tun_validate,
+};
 
-       return NULL;
-}
 
 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);
-       tun = tun_get_by_name(tn, ifr->ifr_name);
-       if (tun) {
-               if (tun->attached)
-                       return -EBUSY;
-
-               /* Check permissions */
-               if (((tun->owner != -1 &&
-                     cred->euid != tun->owner) ||
-                    (tun->group != -1 &&
-                     cred->egid != tun->group)) &&
-                   !capable(CAP_NET_ADMIN)) {
-                       return -EPERM;
-               }
+       dev = __dev_get_by_name(net, ifr->ifr_name);
+       if (dev) {
+               if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
+                       tun = netdev_priv(dev);
+               else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops)
+                       tun = netdev_priv(dev);
+               else
+                       return -EINVAL;
+
+               err = tun_attach(tun, file);
+               if (err < 0)
+                       return err;
        }
-       else if (__dev_get_by_name(net, ifr->ifr_name))
-               return -EINVAL;
        else {
                char *name;
                unsigned long flags = 0;
@@ -765,6 +878,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                        return -ENOMEM;
 
                dev_net_set(dev, net);
+               dev->rtnl_link_ops = &tun_link_ops;
 
                tun = netdev_priv(dev);
                tun->dev = dev;
@@ -783,7 +897,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                if (err < 0)
                        goto err_free_dev;
 
-               list_add(&tun->list, &tn->dev_list);
+               err = tun_attach(tun, file);
+               if (err < 0)
+                       goto err_free_dev;
        }
 
        DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
@@ -803,10 +919,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        else
                tun->flags &= ~TUN_VNET_HDR;
 
-       file->private_data = tun;
-       tun->attached = 1;
-       get_net(dev_net(tun->dev));
-
        /* Make sure persistent devices do not get stuck in
         * xoff state.
         */
@@ -824,7 +936,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
 static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_struct *tun = tun_get(file);
 
        if (!tun)
                return -EBADFD;
@@ -849,6 +961,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
        if (tun->flags & TUN_VNET_HDR)
                ifr->ifr_flags |= IFF_VNET_HDR;
 
+       tun_put(tun);
        return 0;
 }
 
@@ -895,7 +1008,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
 static int tun_chr_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_file *tfile = file->private_data;
+       struct tun_struct *tun;
        void __user* argp = (void __user*)arg;
        struct ifreq ifr;
        int ret;
@@ -904,13 +1018,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                if (copy_from_user(&ifr, argp, sizeof ifr))
                        return -EFAULT;
 
+       if (cmd == TUNGETFEATURES) {
+               /* Currently this just means: "what IFF flags are valid?".
+                * This is needed because we never checked for invalid flags on
+                * TUNSETIFF. */
+               return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
+                               IFF_VNET_HDR,
+                               (unsigned int __user*)argp);
+       }
+
+       tun = __tun_get(tfile);
        if (cmd == TUNSETIFF && !tun) {
                int err;
 
                ifr.ifr_name[IFNAMSIZ-1] = '\0';
 
                rtnl_lock();
-               err = tun_set_iff(current->nsproxy->net_ns, file, &ifr);
+               err = tun_set_iff(tfile->net, file, &ifr);
                rtnl_unlock();
 
                if (err)
@@ -921,28 +1045,21 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                return 0;
        }
 
-       if (cmd == TUNGETFEATURES) {
-               /* Currently this just means: "what IFF flags are valid?".
-                * This is needed because we never checked for invalid flags on
-                * TUNSETIFF. */
-               return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-                               IFF_VNET_HDR,
-                               (unsigned int __user*)argp);
-       }
 
        if (!tun)
                return -EBADFD;
 
        DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
 
+       ret = 0;
        switch (cmd) {
        case TUNGETIFF:
                ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
                if (ret)
-                       return ret;
+                       break;
 
                if (copy_to_user(argp, &ifr, sizeof(ifr)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
 
        case TUNSETNOCSUM:
@@ -994,7 +1111,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                        ret = 0;
                }
                rtnl_unlock();
-               return ret;
+               break;
 
 #ifdef TUN_DEBUG
        case TUNSETDEBUG:
@@ -1005,24 +1122,25 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                rtnl_lock();
                ret = set_offload(tun->dev, arg);
                rtnl_unlock();
-               return ret;
+               break;
 
        case TUNSETTXFILTER:
                /* Can be set only for TAPs */
+               ret = -EINVAL;
                if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
-                       return -EINVAL;
+                       break;
                rtnl_lock();
                ret = update_filter(&tun->txflt, (void __user *)arg);
                rtnl_unlock();
-               return ret;
+               break;
 
        case SIOCGIFHWADDR:
                /* Get hw addres */
                memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
                ifr.ifr_hwaddr.sa_family = tun->dev->type;
                if (copy_to_user(argp, &ifr, sizeof ifr))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
 
        case SIOCSIFHWADDR:
                /* Set hw address */
@@ -1032,18 +1150,19 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                rtnl_lock();
                ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
                rtnl_unlock();
-               return ret;
-
+               break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
        };
 
-       return 0;
+       tun_put(tun);
+       return ret;
 }
 
 static int tun_chr_fasync(int fd, struct file *file, int on)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_struct *tun = tun_get(file);
        int ret;
 
        if (!tun)
@@ -1065,42 +1184,48 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
        ret = 0;
 out:
        unlock_kernel();
+       tun_put(tun);
        return ret;
 }
 
 static int tun_chr_open(struct inode *inode, struct file * file)
 {
+       struct tun_file *tfile;
        cycle_kernel_lock();
        DBG1(KERN_INFO "tunX: tun_chr_open\n");
-       file->private_data = NULL;
+
+       tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+       if (!tfile)
+               return -ENOMEM;
+       atomic_set(&tfile->count, 0);
+       tfile->tun = NULL;
+       tfile->net = get_net(current->nsproxy->net_ns);
+       init_waitqueue_head(&tfile->read_wait);
+       file->private_data = tfile;
        return 0;
 }
 
 static int tun_chr_close(struct inode *inode, struct file *file)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_file *tfile = file->private_data;
+       struct tun_struct *tun = __tun_get(tfile);
 
-       if (!tun)
-               return 0;
-
-       DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
 
-       rtnl_lock();
+       if (tun) {
+               DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
 
-       /* Detach from net device */
-       file->private_data = NULL;
-       tun->attached = 0;
-       put_net(dev_net(tun->dev));
+               rtnl_lock();
+               __tun_detach(tun);
 
-       /* Drop read queue */
-       skb_queue_purge(&tun->readq);
+               /* If desireable, unregister the netdevice. */
+               if (!(tun->flags & TUN_PERSIST))
+                       unregister_netdevice(tun->dev);
 
-       if (!(tun->flags & TUN_PERSIST)) {
-               list_del(&tun->list);
-               unregister_netdevice(tun->dev);
+               rtnl_unlock();
        }
 
-       rtnl_unlock();
+       put_net(tfile->net);
+       kfree(tfile);
 
        return 0;
 }
@@ -1181,7 +1306,7 @@ static void tun_set_msglevel(struct net_device *dev, u32 value)
 static u32 tun_get_link(struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
-       return tun->attached;
+       return !!tun->tfile;
 }
 
 static u32 tun_get_rx_csum(struct net_device *dev)
@@ -1210,45 +1335,6 @@ static const struct ethtool_ops tun_ethtool_ops = {
        .set_rx_csum    = tun_set_rx_csum
 };
 
-static int tun_init_net(struct net *net)
-{
-       struct tun_net *tn;
-
-       tn = kmalloc(sizeof(*tn), GFP_KERNEL);
-       if (tn == NULL)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&tn->dev_list);
-
-       if (net_assign_generic(net, tun_net_id, tn)) {
-               kfree(tn);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static void tun_exit_net(struct net *net)
-{
-       struct tun_net *tn;
-       struct tun_struct *tun, *nxt;
-
-       tn = net_generic(net, tun_net_id);
-
-       rtnl_lock();
-       list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) {
-               DBG(KERN_INFO "%s cleaned up\n", tun->dev->name);
-               unregister_netdevice(tun->dev);
-       }
-       rtnl_unlock();
-
-       kfree(tn);
-}
-
-static struct pernet_operations tun_net_ops = {
-       .init = tun_init_net,
-       .exit = tun_exit_net,
-};
 
 static int __init tun_init(void)
 {
@@ -1257,10 +1343,10 @@ static int __init tun_init(void)
        printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
        printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
 
-       ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops);
+       ret = rtnl_link_register(&tun_link_ops);
        if (ret) {
-               printk(KERN_ERR "tun: Can't register pernet ops\n");
-               goto err_pernet;
+               printk(KERN_ERR "tun: Can't register link_ops\n");
+               goto err_linkops;
        }
 
        ret = misc_register(&tun_miscdev);
@@ -1268,18 +1354,17 @@ static int __init tun_init(void)
                printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
                goto err_misc;
        }
-       return 0;
-
+       return  0;
 err_misc:
-       unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
-err_pernet:
+       rtnl_link_unregister(&tun_link_ops);
+err_linkops:
        return ret;
 }
 
 static void tun_cleanup(void)
 {
        misc_deregister(&tun_miscdev);
-       unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
+       rtnl_link_unregister(&tun_link_ops);
 }
 
 module_init(tun_init);
index 3af9a9516ccb530e03fe7d5b1947018569fec773..a8e5651f31654bfb328545efe07cf1dbfd43276b 100644 (file)
@@ -1783,7 +1783,7 @@ typhoon_poll(struct napi_struct *napi, int budget)
        }
 
        if (work_done < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                iowrite32(TYPHOON_INTR_NONE,
                                tp->ioaddr + TYPHOON_REG_INTR_MASK);
                typhoon_post_pci_writes(tp->ioaddr);
@@ -1806,10 +1806,10 @@ typhoon_interrupt(int irq, void *dev_instance)
 
        iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
 
-       if (netif_rx_schedule_prep(&tp->napi)) {
+       if (napi_schedule_prep(&tp->napi)) {
                iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
                typhoon_post_pci_writes(ioaddr);
-               __netif_rx_schedule(&tp->napi);
+               __napi_schedule(&tp->napi);
        } else {
                printk(KERN_ERR "%s: Error, poll already scheduled\n",
                        dev->name);
@@ -1944,7 +1944,7 @@ typhoon_start_runtime(struct typhoon *tp)
                goto error_out;
 
        INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_VLAN_TYPE_WRITE);
-       xp_cmd.parm1 = __constant_cpu_to_le16(ETH_P_8021Q);
+       xp_cmd.parm1 = cpu_to_le16(ETH_P_8021Q);
        err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
        if(err < 0)
                goto error_out;
index dd7022ca735421763a0cac5bfa2f7fad595f0655..673fd512591402c9729fe5e52dc88187357d31c6 100644 (file)
@@ -174,18 +174,18 @@ struct tx_desc {
                u64 tx_addr;    /* opaque for hardware, for TX_DESC */
        };
        __le32 processFlags;
-#define TYPHOON_TX_PF_NO_CRC           __constant_cpu_to_le32(0x00000001)
-#define TYPHOON_TX_PF_IP_CHKSUM                __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_TX_PF_TCP_CHKSUM       __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_TX_PF_TCP_SEGMENT      __constant_cpu_to_le32(0x00000008)
-#define TYPHOON_TX_PF_INSERT_VLAN      __constant_cpu_to_le32(0x00000010)
-#define TYPHOON_TX_PF_IPSEC            __constant_cpu_to_le32(0x00000020)
-#define TYPHOON_TX_PF_VLAN_PRIORITY    __constant_cpu_to_le32(0x00000040)
-#define TYPHOON_TX_PF_UDP_CHKSUM       __constant_cpu_to_le32(0x00000080)
-#define TYPHOON_TX_PF_PAD_FRAME                __constant_cpu_to_le32(0x00000100)
-#define TYPHOON_TX_PF_RESERVED         __constant_cpu_to_le32(0x00000e00)
-#define TYPHOON_TX_PF_VLAN_MASK                __constant_cpu_to_le32(0x0ffff000)
-#define TYPHOON_TX_PF_INTERNAL         __constant_cpu_to_le32(0xf0000000)
+#define TYPHOON_TX_PF_NO_CRC           cpu_to_le32(0x00000001)
+#define TYPHOON_TX_PF_IP_CHKSUM                cpu_to_le32(0x00000002)
+#define TYPHOON_TX_PF_TCP_CHKSUM       cpu_to_le32(0x00000004)
+#define TYPHOON_TX_PF_TCP_SEGMENT      cpu_to_le32(0x00000008)
+#define TYPHOON_TX_PF_INSERT_VLAN      cpu_to_le32(0x00000010)
+#define TYPHOON_TX_PF_IPSEC            cpu_to_le32(0x00000020)
+#define TYPHOON_TX_PF_VLAN_PRIORITY    cpu_to_le32(0x00000040)
+#define TYPHOON_TX_PF_UDP_CHKSUM       cpu_to_le32(0x00000080)
+#define TYPHOON_TX_PF_PAD_FRAME                cpu_to_le32(0x00000100)
+#define TYPHOON_TX_PF_RESERVED         cpu_to_le32(0x00000e00)
+#define TYPHOON_TX_PF_VLAN_MASK                cpu_to_le32(0x0ffff000)
+#define TYPHOON_TX_PF_INTERNAL         cpu_to_le32(0xf0000000)
 #define TYPHOON_TX_PF_VLAN_TAG_SHIFT   12
 } __attribute__ ((packed));
 
@@ -203,8 +203,8 @@ struct tcpopt_desc {
        u8  flags;
        u8  numDesc;
        __le16 mss_flags;
-#define TYPHOON_TSO_FIRST              __constant_cpu_to_le16(0x1000)
-#define TYPHOON_TSO_LAST               __constant_cpu_to_le16(0x2000)
+#define TYPHOON_TSO_FIRST              cpu_to_le16(0x1000)
+#define TYPHOON_TSO_LAST               cpu_to_le16(0x2000)
        __le32 respAddrLo;
        __le32 bytesTx;
        __le32 status;
@@ -222,8 +222,8 @@ struct ipsec_desc {
        u8  flags;
        u8  numDesc;
        __le16 ipsecFlags;
-#define TYPHOON_IPSEC_GEN_IV   __constant_cpu_to_le16(0x0000)
-#define TYPHOON_IPSEC_USE_IV   __constant_cpu_to_le16(0x0001)
+#define TYPHOON_IPSEC_GEN_IV   cpu_to_le16(0x0000)
+#define TYPHOON_IPSEC_USE_IV   cpu_to_le16(0x0001)
        __le32 sa1;
        __le32 sa2;
        __le32 reserved;
@@ -248,41 +248,41 @@ struct rx_desc {
        u32 addr;       /* opaque, comes from virtAddr */
        u32 addrHi;     /* opaque, comes from virtAddrHi */
        __le32 rxStatus;
-#define TYPHOON_RX_ERR_INTERNAL                __constant_cpu_to_le32(0x00000000)
-#define TYPHOON_RX_ERR_FIFO_UNDERRUN   __constant_cpu_to_le32(0x00000001)
-#define TYPHOON_RX_ERR_BAD_SSD         __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_RX_ERR_RUNT            __constant_cpu_to_le32(0x00000003)
-#define TYPHOON_RX_ERR_CRC             __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_RX_ERR_OVERSIZE                __constant_cpu_to_le32(0x00000005)
-#define TYPHOON_RX_ERR_ALIGN           __constant_cpu_to_le32(0x00000006)
-#define TYPHOON_RX_ERR_DRIBBLE         __constant_cpu_to_le32(0x00000007)
-#define TYPHOON_RX_PROTO_MASK          __constant_cpu_to_le32(0x00000003)
-#define TYPHOON_RX_PROTO_UNKNOWN       __constant_cpu_to_le32(0x00000000)
-#define TYPHOON_RX_PROTO_IP            __constant_cpu_to_le32(0x00000001)
-#define TYPHOON_RX_PROTO_IPX           __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_RX_VLAN                        __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_RX_IP_FRAG             __constant_cpu_to_le32(0x00000008)
-#define TYPHOON_RX_IPSEC               __constant_cpu_to_le32(0x00000010)
-#define TYPHOON_RX_IP_CHK_FAIL         __constant_cpu_to_le32(0x00000020)
-#define TYPHOON_RX_TCP_CHK_FAIL                __constant_cpu_to_le32(0x00000040)
-#define TYPHOON_RX_UDP_CHK_FAIL                __constant_cpu_to_le32(0x00000080)
-#define TYPHOON_RX_IP_CHK_GOOD         __constant_cpu_to_le32(0x00000100)
-#define TYPHOON_RX_TCP_CHK_GOOD                __constant_cpu_to_le32(0x00000200)
-#define TYPHOON_RX_UDP_CHK_GOOD                __constant_cpu_to_le32(0x00000400)
+#define TYPHOON_RX_ERR_INTERNAL                cpu_to_le32(0x00000000)
+#define TYPHOON_RX_ERR_FIFO_UNDERRUN   cpu_to_le32(0x00000001)
+#define TYPHOON_RX_ERR_BAD_SSD         cpu_to_le32(0x00000002)
+#define TYPHOON_RX_ERR_RUNT            cpu_to_le32(0x00000003)
+#define TYPHOON_RX_ERR_CRC             cpu_to_le32(0x00000004)
+#define TYPHOON_RX_ERR_OVERSIZE                cpu_to_le32(0x00000005)
+#define TYPHOON_RX_ERR_ALIGN           cpu_to_le32(0x00000006)
+#define TYPHOON_RX_ERR_DRIBBLE         cpu_to_le32(0x00000007)
+#define TYPHOON_RX_PROTO_MASK          cpu_to_le32(0x00000003)
+#define TYPHOON_RX_PROTO_UNKNOWN       cpu_to_le32(0x00000000)
+#define TYPHOON_RX_PROTO_IP            cpu_to_le32(0x00000001)
+#define TYPHOON_RX_PROTO_IPX           cpu_to_le32(0x00000002)
+#define TYPHOON_RX_VLAN                        cpu_to_le32(0x00000004)
+#define TYPHOON_RX_IP_FRAG             cpu_to_le32(0x00000008)
+#define TYPHOON_RX_IPSEC               cpu_to_le32(0x00000010)
+#define TYPHOON_RX_IP_CHK_FAIL         cpu_to_le32(0x00000020)
+#define TYPHOON_RX_TCP_CHK_FAIL                cpu_to_le32(0x00000040)
+#define TYPHOON_RX_UDP_CHK_FAIL                cpu_to_le32(0x00000080)
+#define TYPHOON_RX_IP_CHK_GOOD         cpu_to_le32(0x00000100)
+#define TYPHOON_RX_TCP_CHK_GOOD                cpu_to_le32(0x00000200)
+#define TYPHOON_RX_UDP_CHK_GOOD                cpu_to_le32(0x00000400)
        __le16 filterResults;
-#define TYPHOON_RX_FILTER_MASK         __constant_cpu_to_le16(0x7fff)
-#define TYPHOON_RX_FILTERED            __constant_cpu_to_le16(0x8000)
+#define TYPHOON_RX_FILTER_MASK         cpu_to_le16(0x7fff)
+#define TYPHOON_RX_FILTERED            cpu_to_le16(0x8000)
        __le16 ipsecResults;
-#define TYPHOON_RX_OUTER_AH_GOOD       __constant_cpu_to_le16(0x0001)
-#define TYPHOON_RX_OUTER_ESP_GOOD      __constant_cpu_to_le16(0x0002)
-#define TYPHOON_RX_INNER_AH_GOOD       __constant_cpu_to_le16(0x0004)
-#define TYPHOON_RX_INNER_ESP_GOOD      __constant_cpu_to_le16(0x0008)
-#define TYPHOON_RX_OUTER_AH_FAIL       __constant_cpu_to_le16(0x0010)
-#define TYPHOON_RX_OUTER_ESP_FAIL      __constant_cpu_to_le16(0x0020)
-#define TYPHOON_RX_INNER_AH_FAIL       __constant_cpu_to_le16(0x0040)
-#define TYPHOON_RX_INNER_ESP_FAIL      __constant_cpu_to_le16(0x0080)
-#define TYPHOON_RX_UNKNOWN_SA          __constant_cpu_to_le16(0x0100)
-#define TYPHOON_RX_ESP_FORMAT_ERR      __constant_cpu_to_le16(0x0200)
+#define TYPHOON_RX_OUTER_AH_GOOD       cpu_to_le16(0x0001)
+#define TYPHOON_RX_OUTER_ESP_GOOD      cpu_to_le16(0x0002)
+#define TYPHOON_RX_INNER_AH_GOOD       cpu_to_le16(0x0004)
+#define TYPHOON_RX_INNER_ESP_GOOD      cpu_to_le16(0x0008)
+#define TYPHOON_RX_OUTER_AH_FAIL       cpu_to_le16(0x0010)
+#define TYPHOON_RX_OUTER_ESP_FAIL      cpu_to_le16(0x0020)
+#define TYPHOON_RX_INNER_AH_FAIL       cpu_to_le16(0x0040)
+#define TYPHOON_RX_INNER_ESP_FAIL      cpu_to_le16(0x0080)
+#define TYPHOON_RX_UNKNOWN_SA          cpu_to_le16(0x0100)
+#define TYPHOON_RX_ESP_FORMAT_ERR      cpu_to_le16(0x0200)
        __be32 vlanTag;
 } __attribute__ ((packed));
 
@@ -318,31 +318,31 @@ struct cmd_desc {
        u8  flags;
        u8  numDesc;
        __le16 cmd;
-#define TYPHOON_CMD_TX_ENABLE          __constant_cpu_to_le16(0x0001)
-#define TYPHOON_CMD_TX_DISABLE         __constant_cpu_to_le16(0x0002)
-#define TYPHOON_CMD_RX_ENABLE          __constant_cpu_to_le16(0x0003)
-#define TYPHOON_CMD_RX_DISABLE         __constant_cpu_to_le16(0x0004)
-#define TYPHOON_CMD_SET_RX_FILTER      __constant_cpu_to_le16(0x0005)
-#define TYPHOON_CMD_READ_STATS         __constant_cpu_to_le16(0x0007)
-#define TYPHOON_CMD_XCVR_SELECT                __constant_cpu_to_le16(0x0013)
-#define TYPHOON_CMD_SET_MAX_PKT_SIZE   __constant_cpu_to_le16(0x001a)
-#define TYPHOON_CMD_READ_MEDIA_STATUS  __constant_cpu_to_le16(0x001b)
-#define TYPHOON_CMD_GOTO_SLEEP         __constant_cpu_to_le16(0x0023)
-#define TYPHOON_CMD_SET_MULTICAST_HASH __constant_cpu_to_le16(0x0025)
-#define TYPHOON_CMD_SET_MAC_ADDRESS    __constant_cpu_to_le16(0x0026)
-#define TYPHOON_CMD_READ_MAC_ADDRESS   __constant_cpu_to_le16(0x0027)
-#define TYPHOON_CMD_VLAN_TYPE_WRITE    __constant_cpu_to_le16(0x002b)
-#define TYPHOON_CMD_CREATE_SA          __constant_cpu_to_le16(0x0034)
-#define TYPHOON_CMD_DELETE_SA          __constant_cpu_to_le16(0x0035)
-#define TYPHOON_CMD_READ_VERSIONS      __constant_cpu_to_le16(0x0043)
-#define TYPHOON_CMD_IRQ_COALESCE_CTRL  __constant_cpu_to_le16(0x0045)
-#define TYPHOON_CMD_ENABLE_WAKE_EVENTS __constant_cpu_to_le16(0x0049)
-#define TYPHOON_CMD_SET_OFFLOAD_TASKS  __constant_cpu_to_le16(0x004f)
-#define TYPHOON_CMD_HELLO_RESP         __constant_cpu_to_le16(0x0057)
-#define TYPHOON_CMD_HALT               __constant_cpu_to_le16(0x005d)
-#define TYPHOON_CMD_READ_IPSEC_INFO    __constant_cpu_to_le16(0x005e)
-#define TYPHOON_CMD_GET_IPSEC_ENABLE   __constant_cpu_to_le16(0x0067)
-#define TYPHOON_CMD_GET_CMD_LVL                __constant_cpu_to_le16(0x0069)
+#define TYPHOON_CMD_TX_ENABLE          cpu_to_le16(0x0001)
+#define TYPHOON_CMD_TX_DISABLE         cpu_to_le16(0x0002)
+#define TYPHOON_CMD_RX_ENABLE          cpu_to_le16(0x0003)
+#define TYPHOON_CMD_RX_DISABLE         cpu_to_le16(0x0004)
+#define TYPHOON_CMD_SET_RX_FILTER      cpu_to_le16(0x0005)
+#define TYPHOON_CMD_READ_STATS         cpu_to_le16(0x0007)
+#define TYPHOON_CMD_XCVR_SELECT                cpu_to_le16(0x0013)
+#define TYPHOON_CMD_SET_MAX_PKT_SIZE   cpu_to_le16(0x001a)
+#define TYPHOON_CMD_READ_MEDIA_STATUS  cpu_to_le16(0x001b)
+#define TYPHOON_CMD_GOTO_SLEEP         cpu_to_le16(0x0023)
+#define TYPHOON_CMD_SET_MULTICAST_HASH cpu_to_le16(0x0025)
+#define TYPHOON_CMD_SET_MAC_ADDRESS    cpu_to_le16(0x0026)
+#define TYPHOON_CMD_READ_MAC_ADDRESS   cpu_to_le16(0x0027)
+#define TYPHOON_CMD_VLAN_TYPE_WRITE    cpu_to_le16(0x002b)
+#define TYPHOON_CMD_CREATE_SA          cpu_to_le16(0x0034)
+#define TYPHOON_CMD_DELETE_SA          cpu_to_le16(0x0035)
+#define TYPHOON_CMD_READ_VERSIONS      cpu_to_le16(0x0043)
+#define TYPHOON_CMD_IRQ_COALESCE_CTRL  cpu_to_le16(0x0045)
+#define TYPHOON_CMD_ENABLE_WAKE_EVENTS cpu_to_le16(0x0049)
+#define TYPHOON_CMD_SET_OFFLOAD_TASKS  cpu_to_le16(0x004f)
+#define TYPHOON_CMD_HELLO_RESP         cpu_to_le16(0x0057)
+#define TYPHOON_CMD_HALT               cpu_to_le16(0x005d)
+#define TYPHOON_CMD_READ_IPSEC_INFO    cpu_to_le16(0x005e)
+#define TYPHOON_CMD_GET_IPSEC_ENABLE   cpu_to_le16(0x0067)
+#define TYPHOON_CMD_GET_CMD_LVL                cpu_to_le16(0x0069)
        u16 seqNo;
        __le16 parm1;
        __le32 parm2;
@@ -380,11 +380,11 @@ struct resp_desc {
 
 /* TYPHOON_CMD_SET_RX_FILTER filter bits (cmd.parm1)
  */
-#define TYPHOON_RX_FILTER_DIRECTED     __constant_cpu_to_le16(0x0001)
-#define TYPHOON_RX_FILTER_ALL_MCAST    __constant_cpu_to_le16(0x0002)
-#define TYPHOON_RX_FILTER_BROADCAST    __constant_cpu_to_le16(0x0004)
-#define TYPHOON_RX_FILTER_PROMISCOUS   __constant_cpu_to_le16(0x0008)
-#define TYPHOON_RX_FILTER_MCAST_HASH   __constant_cpu_to_le16(0x0010)
+#define TYPHOON_RX_FILTER_DIRECTED     cpu_to_le16(0x0001)
+#define TYPHOON_RX_FILTER_ALL_MCAST    cpu_to_le16(0x0002)
+#define TYPHOON_RX_FILTER_BROADCAST    cpu_to_le16(0x0004)
+#define TYPHOON_RX_FILTER_PROMISCOUS   cpu_to_le16(0x0008)
+#define TYPHOON_RX_FILTER_MCAST_HASH   cpu_to_le16(0x0010)
 
 /* TYPHOON_CMD_READ_STATS response format
  */
@@ -416,40 +416,40 @@ struct stats_resp {
        __le32 rxOverflow;
        __le32 rxFiltered;
        __le32 linkStatus;
-#define TYPHOON_LINK_STAT_MASK         __constant_cpu_to_le32(0x00000001)
-#define TYPHOON_LINK_GOOD              __constant_cpu_to_le32(0x00000001)
-#define TYPHOON_LINK_BAD               __constant_cpu_to_le32(0x00000000)
-#define TYPHOON_LINK_SPEED_MASK                __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_LINK_100MBPS           __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_LINK_10MBPS            __constant_cpu_to_le32(0x00000000)
-#define TYPHOON_LINK_DUPLEX_MASK       __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_LINK_FULL_DUPLEX       __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_LINK_HALF_DUPLEX       __constant_cpu_to_le32(0x00000000)
+#define TYPHOON_LINK_STAT_MASK         cpu_to_le32(0x00000001)
+#define TYPHOON_LINK_GOOD              cpu_to_le32(0x00000001)
+#define TYPHOON_LINK_BAD               cpu_to_le32(0x00000000)
+#define TYPHOON_LINK_SPEED_MASK                cpu_to_le32(0x00000002)
+#define TYPHOON_LINK_100MBPS           cpu_to_le32(0x00000002)
+#define TYPHOON_LINK_10MBPS            cpu_to_le32(0x00000000)
+#define TYPHOON_LINK_DUPLEX_MASK       cpu_to_le32(0x00000004)
+#define TYPHOON_LINK_FULL_DUPLEX       cpu_to_le32(0x00000004)
+#define TYPHOON_LINK_HALF_DUPLEX       cpu_to_le32(0x00000000)
        __le32 unused2;
        __le32 unused3;
 } __attribute__ ((packed));
 
 /* TYPHOON_CMD_XCVR_SELECT xcvr values (resp.parm1)
  */
-#define TYPHOON_XCVR_10HALF    __constant_cpu_to_le16(0x0000)
-#define TYPHOON_XCVR_10FULL    __constant_cpu_to_le16(0x0001)
-#define TYPHOON_XCVR_100HALF   __constant_cpu_to_le16(0x0002)
-#define TYPHOON_XCVR_100FULL   __constant_cpu_to_le16(0x0003)
-#define TYPHOON_XCVR_AUTONEG   __constant_cpu_to_le16(0x0004)
+#define TYPHOON_XCVR_10HALF    cpu_to_le16(0x0000)
+#define TYPHOON_XCVR_10FULL    cpu_to_le16(0x0001)
+#define TYPHOON_XCVR_100HALF   cpu_to_le16(0x0002)
+#define TYPHOON_XCVR_100FULL   cpu_to_le16(0x0003)
+#define TYPHOON_XCVR_AUTONEG   cpu_to_le16(0x0004)
 
 /* TYPHOON_CMD_READ_MEDIA_STATUS (resp.parm1)
  */
-#define TYPHOON_MEDIA_STAT_CRC_STRIP_DISABLE   __constant_cpu_to_le16(0x0004)
-#define TYPHOON_MEDIA_STAT_COLLISION_DETECT    __constant_cpu_to_le16(0x0010)
-#define TYPHOON_MEDIA_STAT_CARRIER_SENSE       __constant_cpu_to_le16(0x0020)
-#define TYPHOON_MEDIA_STAT_POLARITY_REV                __constant_cpu_to_le16(0x0400)
-#define TYPHOON_MEDIA_STAT_NO_LINK             __constant_cpu_to_le16(0x0800)
+#define TYPHOON_MEDIA_STAT_CRC_STRIP_DISABLE   cpu_to_le16(0x0004)
+#define TYPHOON_MEDIA_STAT_COLLISION_DETECT    cpu_to_le16(0x0010)
+#define TYPHOON_MEDIA_STAT_CARRIER_SENSE       cpu_to_le16(0x0020)
+#define TYPHOON_MEDIA_STAT_POLARITY_REV                cpu_to_le16(0x0400)
+#define TYPHOON_MEDIA_STAT_NO_LINK             cpu_to_le16(0x0800)
 
 /* TYPHOON_CMD_SET_MULTICAST_HASH enable values (cmd.parm1)
  */
-#define TYPHOON_MCAST_HASH_DISABLE     __constant_cpu_to_le16(0x0000)
-#define TYPHOON_MCAST_HASH_ENABLE      __constant_cpu_to_le16(0x0001)
-#define TYPHOON_MCAST_HASH_SET         __constant_cpu_to_le16(0x0002)
+#define TYPHOON_MCAST_HASH_DISABLE     cpu_to_le16(0x0000)
+#define TYPHOON_MCAST_HASH_ENABLE      cpu_to_le16(0x0001)
+#define TYPHOON_MCAST_HASH_SET         cpu_to_le16(0x0002)
 
 /* TYPHOON_CMD_CREATE_SA descriptor and settings
  */
@@ -459,9 +459,9 @@ struct sa_descriptor {
        u16 cmd;
        u16 seqNo;
        u16 mode;
-#define TYPHOON_SA_MODE_NULL           __constant_cpu_to_le16(0x0000)
-#define TYPHOON_SA_MODE_AH             __constant_cpu_to_le16(0x0001)
-#define TYPHOON_SA_MODE_ESP            __constant_cpu_to_le16(0x0002)
+#define TYPHOON_SA_MODE_NULL           cpu_to_le16(0x0000)
+#define TYPHOON_SA_MODE_AH             cpu_to_le16(0x0001)
+#define TYPHOON_SA_MODE_ESP            cpu_to_le16(0x0002)
        u8  hashFlags;
 #define TYPHOON_SA_HASH_ENABLE         0x01
 #define TYPHOON_SA_HASH_SHA1           0x02
@@ -493,22 +493,22 @@ struct sa_descriptor {
 /* TYPHOON_CMD_SET_OFFLOAD_TASKS bits (cmd.parm2 (Tx) & cmd.parm3 (Rx))
  * This is all for IPv4.
  */
-#define TYPHOON_OFFLOAD_TCP_CHKSUM     __constant_cpu_to_le32(0x00000002)
-#define TYPHOON_OFFLOAD_UDP_CHKSUM     __constant_cpu_to_le32(0x00000004)
-#define TYPHOON_OFFLOAD_IP_CHKSUM      __constant_cpu_to_le32(0x00000008)
-#define TYPHOON_OFFLOAD_IPSEC          __constant_cpu_to_le32(0x00000010)
-#define TYPHOON_OFFLOAD_BCAST_THROTTLE __constant_cpu_to_le32(0x00000020)
-#define TYPHOON_OFFLOAD_DHCP_PREVENT   __constant_cpu_to_le32(0x00000040)
-#define TYPHOON_OFFLOAD_VLAN           __constant_cpu_to_le32(0x00000080)
-#define TYPHOON_OFFLOAD_FILTERING      __constant_cpu_to_le32(0x00000100)
-#define TYPHOON_OFFLOAD_TCP_SEGMENT    __constant_cpu_to_le32(0x00000200)
+#define TYPHOON_OFFLOAD_TCP_CHKSUM     cpu_to_le32(0x00000002)
+#define TYPHOON_OFFLOAD_UDP_CHKSUM     cpu_to_le32(0x00000004)
+#define TYPHOON_OFFLOAD_IP_CHKSUM      cpu_to_le32(0x00000008)
+#define TYPHOON_OFFLOAD_IPSEC          cpu_to_le32(0x00000010)
+#define TYPHOON_OFFLOAD_BCAST_THROTTLE cpu_to_le32(0x00000020)
+#define TYPHOON_OFFLOAD_DHCP_PREVENT   cpu_to_le32(0x00000040)
+#define TYPHOON_OFFLOAD_VLAN           cpu_to_le32(0x00000080)
+#define TYPHOON_OFFLOAD_FILTERING      cpu_to_le32(0x00000100)
+#define TYPHOON_OFFLOAD_TCP_SEGMENT    cpu_to_le32(0x00000200)
 
 /* TYPHOON_CMD_ENABLE_WAKE_EVENTS bits (cmd.parm1)
  */
-#define TYPHOON_WAKE_MAGIC_PKT         __constant_cpu_to_le16(0x01)
-#define TYPHOON_WAKE_LINK_EVENT                __constant_cpu_to_le16(0x02)
-#define TYPHOON_WAKE_ICMP_ECHO         __constant_cpu_to_le16(0x04)
-#define TYPHOON_WAKE_ARP               __constant_cpu_to_le16(0x08)
+#define TYPHOON_WAKE_MAGIC_PKT         cpu_to_le16(0x01)
+#define TYPHOON_WAKE_LINK_EVENT                cpu_to_le16(0x02)
+#define TYPHOON_WAKE_ICMP_ECHO         cpu_to_le16(0x04)
+#define TYPHOON_WAKE_ARP               cpu_to_le16(0x08)
 
 /* These are used to load the firmware image on the NIC
  */
index e87986867ba5b3042be2434f5620ca662242c1b8..1c095c63f98f482b10cf7ee71c3b84f472da12cf 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/ucc_fast.h>
 
 #include "ucc_geth.h"
-#include "ucc_geth_mii.h"
+#include "fsl_pq_mdio.h"
 
 #undef DEBUG
 
@@ -1557,7 +1557,7 @@ static int init_phy(struct net_device *dev)
        of_node_put(phy);
        of_node_put(mdio);
 
-       uec_mdio_bus_name(bus_name, mdio);
+       fsl_pq_mdio_bus_name(bus_name, mdio);
        snprintf(phy_id, sizeof(phy_id), "%s:%02x",
                                 bus_name, *id);
 
@@ -3266,7 +3266,7 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
                howmany += ucc_geth_rx(ugeth, i, budget - howmany);
 
        if (howmany < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS);
        }
 
@@ -3297,10 +3297,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(&ugeth->napi)) {
+               if (napi_schedule_prep(&ugeth->napi)) {
                        uccm &= ~UCCE_RX_EVENTS;
                        out_be32(uccf->p_uccm, uccm);
-                       __netif_rx_schedule(&ugeth->napi);
+                       __napi_schedule(&ugeth->napi);
                }
        }
 
@@ -3657,7 +3657,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
                if (err)
                        return -1;
 
-               snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start);
+               snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x",
+                               res.start&0xfffff);
        }
 
        /* get the phy interface type, or default to MII */
@@ -3803,11 +3804,6 @@ static int __init ucc_geth_init(void)
 {
        int i, ret;
 
-       ret = uec_mdio_init();
-
-       if (ret)
-               return ret;
-
        if (netif_msg_drv(&debug))
                printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
        for (i = 0; i < 8; i++)
@@ -3816,16 +3812,12 @@ static int __init ucc_geth_init(void)
 
        ret = of_register_platform_driver(&ucc_geth_driver);
 
-       if (ret)
-               uec_mdio_exit();
-
        return ret;
 }
 
 static void __exit ucc_geth_exit(void)
 {
        of_unregister_platform_driver(&ucc_geth_driver);
-       uec_mdio_exit();
 }
 
 module_init(ucc_geth_init);
index 16cbe42ba43c9b0f8097222306324498da489abe..66d18971fa0c74cf2dbd7b127fd7ebcdc5beac2f 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/ucc.h>
 #include <asm/ucc_fast.h>
 
-#include "ucc_geth_mii.h"
-
 #define DRV_DESC "QE UCC Gigabit Ethernet Controller"
 #define DRV_NAME "ucc_geth"
 #define DRV_VERSION "1.1"
@@ -184,6 +182,18 @@ struct ucc_geth {
 #define UCCE_RX_EVENTS  (UCCE_RXF | UCC_GETH_UCCE_BSY)
 #define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE)
 
+/* TBI defines */
+#define        ENET_TBI_MII_CR         0x00    /* Control */
+#define        ENET_TBI_MII_SR         0x01    /* Status */
+#define        ENET_TBI_MII_ANA        0x04    /* AN advertisement */
+#define        ENET_TBI_MII_ANLPBPA    0x05    /* AN link partner base page ability */
+#define        ENET_TBI_MII_ANEX       0x06    /* AN expansion */
+#define        ENET_TBI_MII_ANNPT      0x07    /* AN next page transmit */
+#define        ENET_TBI_MII_ANLPANP    0x08    /* AN link partner ability next page */
+#define        ENET_TBI_MII_EXST       0x0F    /* Extended status */
+#define        ENET_TBI_MII_JD         0x10    /* Jitter diagnostics */
+#define        ENET_TBI_MII_TBICON     0x11    /* TBI control */
+
 /* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
 #define MACCFG1_FLOW_RX                         0x00000020     /* Flow Control
                                                                   Rx */
index 68a7f5414133d230bcb36b54a9e9ac4d626b8a08..a755bea559b98deb9d091c95eba19db84642a732 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/types.h>
 
 #include "ucc_geth.h"
-#include "ucc_geth_mii.h"
 
 static char hw_stat_gstrings[][ETH_GSTRING_LEN] = {
        "tx-64-frames",
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
deleted file mode 100644 (file)
index 5463591..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * drivers/net/ucc_geth_mii.c
- *
- * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
- * Provides Bus interface for MII Management regs in the UCC register space
- *
- * Copyright (C) 2007 Freescale Semiconductor, Inc.
- *
- * Authors: Li Yang <leoli@freescale.com>
- *         Kim Phillips <kim.phillips@freescale.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.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/platform_device.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/phy.h>
-#include <linux/fsl_devices.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/ucc.h>
-
-#include "ucc_geth_mii.h"
-#include "ucc_geth.h"
-
-#define DEBUG
-#ifdef DEBUG
-#define vdbg(format, arg...) printk(KERN_DEBUG , format "\n" , ## arg)
-#else
-#define vdbg(format, arg...) do {} while(0)
-#endif
-
-#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus"
-#define MII_DRV_NAME "fsl-uec_mdio"
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns.  All PHY */
-/* configuration has to be done through the master UEC MIIM regs */
-int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
-{
-       struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
-
-       /* Setting up the MII Mangement Address Register */
-       out_be32(&regs->miimadd,
-                (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
-
-       /* Setting up the MII Mangement Control Register with the value */
-       out_be32(&regs->miimcon, value);
-
-       /* Wait till MII management write is complete */
-       while ((in_be32(&regs->miimind)) & MIIMIND_BUSY)
-               cpu_relax();
-
-       return 0;
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value.  Clears miimcom first.  All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
-       struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
-       u16 value;
-
-       /* Setting up the MII Mangement Address Register */
-       out_be32(&regs->miimadd,
-                (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
-
-       /* Clear miimcom, perform an MII management read cycle */
-       out_be32(&regs->miimcom, 0);
-       out_be32(&regs->miimcom, MIIMCOM_READ_CYCLE);
-
-       /* Wait till MII management write is complete */
-       while ((in_be32(&regs->miimind)) & (MIIMIND_BUSY | MIIMIND_NOT_VALID))
-               cpu_relax();
-
-       /* Read MII management status  */
-       value = in_be32(&regs->miimstat);
-
-       return value;
-}
-
-/* Reset the MIIM registers, and wait for the bus to free */
-static int uec_mdio_reset(struct mii_bus *bus)
-{
-       struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
-       unsigned int timeout = PHY_INIT_TIMEOUT;
-
-       mutex_lock(&bus->mdio_lock);
-
-       /* Reset the management interface */
-       out_be32(&regs->miimcfg, MIIMCFG_RESET_MANAGEMENT);
-
-       /* Setup the MII Mgmt clock speed */
-       out_be32(&regs->miimcfg, MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112);
-
-       /* Wait until the bus is free */
-       while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
-               cpu_relax();
-
-       mutex_unlock(&bus->mdio_lock);
-
-       if (timeout <= 0) {
-               printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *match)
-{
-       struct device *device = &ofdev->dev;
-       struct device_node *np = ofdev->node, *tempnp = NULL;
-       struct device_node *child = NULL;
-       struct ucc_mii_mng __iomem *regs;
-       struct mii_bus *new_bus;
-       struct resource res;
-       int k, err = 0;
-
-       new_bus = mdiobus_alloc();
-       if (NULL == new_bus)
-               return -ENOMEM;
-
-       new_bus->name = "UCC Ethernet Controller MII Bus";
-       new_bus->read = &uec_mdio_read;
-       new_bus->write = &uec_mdio_write;
-       new_bus->reset = &uec_mdio_reset;
-
-       memset(&res, 0, sizeof(res));
-
-       err = of_address_to_resource(np, 0, &res);
-       if (err)
-               goto reg_map_fail;
-
-       uec_mdio_bus_name(new_bus->id, np);
-
-       new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
-
-       if (NULL == new_bus->irq) {
-               err = -ENOMEM;
-               goto reg_map_fail;
-       }
-
-       for (k = 0; k < 32; k++)
-               new_bus->irq[k] = PHY_POLL;
-
-       while ((child = of_get_next_child(np, child)) != NULL) {
-               int irq = irq_of_parse_and_map(child, 0);
-               if (irq != NO_IRQ) {
-                       const u32 *id = of_get_property(child, "reg", NULL);
-                       new_bus->irq[*id] = irq;
-               }
-       }
-
-       /* Set the base address */
-       regs = ioremap(res.start, sizeof(struct ucc_mii_mng));
-
-       if (NULL == regs) {
-               err = -ENOMEM;
-               goto ioremap_fail;
-       }
-
-       new_bus->priv = (void __force *)regs;
-
-       new_bus->parent = device;
-       dev_set_drvdata(device, new_bus);
-
-       /* Read MII management master from device tree */
-       while ((tempnp = of_find_compatible_node(tempnp, "network", "ucc_geth"))
-              != NULL) {
-               struct resource tempres;
-
-               err = of_address_to_resource(tempnp, 0, &tempres);
-               if (err)
-                       goto bus_register_fail;
-
-               /* if our mdio regs fall within this UCC regs range */
-               if ((res.start >= tempres.start) &&
-                   (res.end <= tempres.end)) {
-                       /* set this UCC to be the MII master */
-                       const u32 *id;
-
-                       id = of_get_property(tempnp, "cell-index", NULL);
-                       if (!id) {
-                               id = of_get_property(tempnp, "device-id", NULL);
-                               if (!id)
-                                       goto bus_register_fail;
-                       }
-
-                       ucc_set_qe_mux_mii_mng(*id - 1);
-
-                       /* assign the TBI an address which won't
-                        * conflict with the PHYs */
-                       out_be32(&regs->utbipar, UTBIPAR_INIT_TBIPA);
-                       break;
-               }
-       }
-
-       err = mdiobus_register(new_bus);
-       if (0 != err) {
-               printk(KERN_ERR "%s: Cannot register as MDIO bus\n",
-                      new_bus->name);
-               goto bus_register_fail;
-       }
-
-       return 0;
-
-bus_register_fail:
-       iounmap(regs);
-ioremap_fail:
-       kfree(new_bus->irq);
-reg_map_fail:
-       mdiobus_free(new_bus);
-
-       return err;
-}
-
-static int uec_mdio_remove(struct of_device *ofdev)
-{
-       struct device *device = &ofdev->dev;
-       struct mii_bus *bus = dev_get_drvdata(device);
-
-       mdiobus_unregister(bus);
-
-       dev_set_drvdata(device, NULL);
-
-       iounmap((void __iomem *)bus->priv);
-       bus->priv = NULL;
-       mdiobus_free(bus);
-
-       return 0;
-}
-
-static struct of_device_id uec_mdio_match[] = {
-       {
-               .type = "mdio",
-               .compatible = "ucc_geth_phy",
-       },
-       {
-               .compatible = "fsl,ucc-mdio",
-       },
-       {},
-};
-
-static struct of_platform_driver uec_mdio_driver = {
-       .name   = MII_DRV_NAME,
-       .probe  = uec_mdio_probe,
-       .remove = uec_mdio_remove,
-       .match_table    = uec_mdio_match,
-};
-
-int __init uec_mdio_init(void)
-{
-       return of_register_platform_driver(&uec_mdio_driver);
-}
-
-/* called from __init ucc_geth_init, therefore can not be __exit */
-void uec_mdio_exit(void)
-{
-       of_unregister_platform_driver(&uec_mdio_driver);
-}
-
-void uec_mdio_bus_name(char *name, struct device_node *np)
-{
-        const u32 *reg;
-
-        reg = of_get_property(np, "reg", NULL);
-
-        snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
-}
-
diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h
deleted file mode 100644 (file)
index 840cf80..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * drivers/net/ucc_geth_mii.h
- *
- * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
- * Provides Bus interface for MII Management regs in the UCC register space
- *
- * Copyright (C) 2007 Freescale Semiconductor, Inc.
- *
- * Authors: Li Yang <leoli@freescale.com>
- *         Kim Phillips <kim.phillips@freescale.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#ifndef __UEC_MII_H
-#define __UEC_MII_H
-
-/* UCC GETH MIIMCFG (MII Management Configuration Register) */
-#define MIIMCFG_RESET_MANAGEMENT                0x80000000     /* Reset
-                                                                  management */
-#define MIIMCFG_NO_PREAMBLE                     0x00000010     /* Preamble
-                                                                  suppress */
-#define MIIMCFG_CLOCK_DIVIDE_SHIFT              (31 - 31)      /* clock divide
-                                                                  << shift */
-#define MIIMCFG_CLOCK_DIVIDE_MAX                0xf    /* max clock divide */
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2    0x00000000
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4    0x00000001
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6    0x00000002
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8    0x00000003
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10   0x00000004
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14   0x00000005
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16   0x00000008
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20   0x00000006
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28   0x00000007
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32   0x00000009
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48   0x0000000a
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64   0x0000000b
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80   0x0000000c
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112  0x0000000d
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160  0x0000000e
-#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224  0x0000000f
-
-/* UCC GETH MIIMCOM (MII Management Command Register) */
-#define MIIMCOM_SCAN_CYCLE                      0x00000002     /* Scan cycle */
-#define MIIMCOM_READ_CYCLE                      0x00000001     /* Read cycle */
-
-/* UCC GETH MIIMADD (MII Management Address Register) */
-#define MIIMADD_PHY_ADDRESS_SHIFT               (31 - 23)      /* PHY Address
-                                                                  << shift */
-#define MIIMADD_PHY_REGISTER_SHIFT              (31 - 31)      /* PHY Register
-                                                                  << shift */
-
-/* UCC GETH MIIMCON (MII Management Control Register) */
-#define MIIMCON_PHY_CONTROL_SHIFT               (31 - 31)      /* PHY Control
-                                                                  << shift */
-#define MIIMCON_PHY_STATUS_SHIFT                (31 - 31)      /* PHY Status
-                                                                  << shift */
-
-/* UCC GETH MIIMIND (MII Management Indicator Register) */
-#define MIIMIND_NOT_VALID                       0x00000004     /* Not valid */
-#define MIIMIND_SCAN                            0x00000002     /* Scan in
-                                                                  progress */
-#define MIIMIND_BUSY                            0x00000001
-
-/* Initial TBI Physical Address */
-#define UTBIPAR_INIT_TBIPA                     0x1f
-
-struct ucc_mii_mng {
-       u32 miimcfg;            /* MII management configuration reg */
-       u32 miimcom;            /* MII management command reg */
-       u32 miimadd;            /* MII management address reg */
-       u32 miimcon;            /* MII management control reg */
-       u32 miimstat;           /* MII management status reg */
-       u32 miimind;            /* MII management indication reg */
-       u8 notcare[28];         /* Space holder */
-       u32 utbipar;            /* TBI phy address reg */
-} __attribute__ ((packed));
-
-/* TBI / MII Set Register */
-enum enet_tbi_mii_reg {
-       ENET_TBI_MII_CR = 0x00, /* Control */
-       ENET_TBI_MII_SR = 0x01, /* Status */
-       ENET_TBI_MII_ANA = 0x04,        /* AN advertisement */
-       ENET_TBI_MII_ANLPBPA = 0x05,    /* AN link partner base page ability */
-       ENET_TBI_MII_ANEX = 0x06,       /* AN expansion */
-       ENET_TBI_MII_ANNPT = 0x07,      /* AN next page transmit */
-       ENET_TBI_MII_ANLPANP = 0x08,    /* AN link partner ability next page */
-       ENET_TBI_MII_EXST = 0x0F,       /* Extended status */
-       ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics */
-       ENET_TBI_MII_TBICON = 0x11      /* TBI control */
-};
-
-int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
-int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
-int __init uec_mdio_init(void);
-void uec_mdio_exit(void);
-void uec_mdio_bus_name(char *name, struct device_node *np);
-#endif                         /* __UEC_MII_H */
index fe98acaead976a1bdd6c5158377500e0a14a32b2..e6d62fe405cd109cbb488b72143039af1af23cc5 100644 (file)
@@ -936,8 +936,7 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,
                        if (!odev->rx_buf_missing) {
                                /* Packet is complete. Inject into stack. */
                                /* We have IP packet here */
-                               odev->skb_rx_buf->protocol =
-                                               __constant_htons(ETH_P_IP);
+                               odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP);
                                /* don't check it */
                                odev->skb_rx_buf->ip_summed =
                                        CHECKSUM_UNNECESSARY;
index 5574abe29c73b64c63d0e123e132f3afb762e7f3..5b0b9647382c26cf13234bd0d82f20d6551e86ba 100644 (file)
@@ -55,7 +55,6 @@ struct smsc95xx_priv {
 
 struct usb_context {
        struct usb_ctrlrequest req;
-       struct completion notify;
        struct usbnet *dev;
 };
 
@@ -307,7 +306,7 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
        return 0;
 }
 
-static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+static void smsc95xx_async_cmd_callback(struct urb *urb)
 {
        struct usb_context *usb_context = urb->context;
        struct usbnet *dev = usb_context->dev;
@@ -316,8 +315,6 @@ static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
        if (status < 0)
                devwarn(dev, "async callback failed with %d", status);
 
-       complete(&usb_context->notify);
-
        kfree(usb_context);
        usb_free_urb(urb);
 }
@@ -348,11 +345,10 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data)
        usb_context->req.wValue = 00;
        usb_context->req.wIndex = cpu_to_le16(index);
        usb_context->req.wLength = cpu_to_le16(size);
-       init_completion(&usb_context->notify);
 
        usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
                (void *)&usb_context->req, data, size,
-               (usb_complete_t)smsc95xx_async_cmd_callback,
+               smsc95xx_async_cmd_callback,
                (void *)usb_context);
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
index 3b8e63254277e1bdb5c1d7b86afcc47c77939646..4671436ecf0ed236d3263e9f0ac70096fbe4e6ec 100644 (file)
@@ -589,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(napi);
+               napi_complete(napi);
 
                iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
                          IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -1319,7 +1319,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
                                  IntrPCIErr | IntrStatsMax | IntrLinkChange,
                                  ioaddr + IntrEnable);
 
-                       netif_rx_schedule(&rp->napi);
+                       napi_schedule(&rp->napi);
                }
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
index 29a33090d3d4d7775c44eea63f13d5bbe1881c1a..ea43e1832afba07d389861b05ef3b2f6102f4595 100644 (file)
@@ -183,7 +183,7 @@ struct rdesc1 {
 };
 
 enum {
-       RX_INTEN = __constant_cpu_to_le16(0x8000)
+       RX_INTEN = cpu_to_le16(0x8000)
 };
 
 struct rx_desc {
@@ -210,7 +210,7 @@ struct tdesc1 {
 } __attribute__ ((__packed__));
 
 enum {
-       TD_QUEUE = __constant_cpu_to_le16(0x8000)
+       TD_QUEUE = cpu_to_le16(0x8000)
 };
 
 struct td_buf {
@@ -242,7 +242,7 @@ struct velocity_td_info {
 
 enum  velocity_owner {
        OWNED_BY_HOST = 0,
-       OWNED_BY_NIC = __constant_cpu_to_le16(0x8000)
+       OWNED_BY_NIC = cpu_to_le16(0x8000)
 };
 
 
index c68808336c8c4d84e90e03a8d0649592b72c1626..3d0033920224715360c67a75c608f9a7f42da17b 100644 (file)
@@ -37,12 +37,15 @@ module_param(gso, bool, 0444);
 #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
 #define GOOD_COPY_LEN  128
 
+#define VIRTNET_SEND_COMMAND_SG_MAX    2
+
 struct virtnet_info
 {
        struct virtio_device *vdev;
-       struct virtqueue *rvq, *svq;
+       struct virtqueue *rvq, *svq, *cvq;
        struct net_device *dev;
        struct napi_struct napi;
+       unsigned int status;
 
        /* The skb we couldn't send because buffers were full. */
        struct sk_buff *last_xmit_skb;
@@ -375,9 +378,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->napi)) {
+       if (napi_schedule_prep(&vi->napi)) {
                rvq->vq_ops->disable_cb(rvq);
-               __netif_rx_schedule(&vi->napi);
+               __napi_schedule(&vi->napi);
        }
 }
 
@@ -403,11 +406,11 @@ again:
 
        /* Out of packets? */
        if (received < budget) {
-               netif_rx_complete(napi);
+               napi_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(napi);
+                       __napi_schedule(napi);
                        goto again;
                }
        }
@@ -562,6 +565,22 @@ stop_queue:
        goto done;
 }
 
+static int virtnet_set_mac_address(struct net_device *dev, void *p)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct virtio_device *vdev = vi->vdev;
+       int ret;
+
+       ret = eth_mac_addr(dev, p);
+       if (ret)
+               return ret;
+
+       vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
+                         dev->dev_addr, dev->addr_len);
+
+       return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void virtnet_netpoll(struct net_device *dev)
 {
@@ -581,13 +600,60 @@ 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(&vi->napi)) {
+       if (napi_schedule_prep(&vi->napi)) {
                vi->rvq->vq_ops->disable_cb(vi->rvq);
-               __netif_rx_schedule(&vi->napi);
+               __napi_schedule(&vi->napi);
        }
        return 0;
 }
 
+/*
+ * Send command via the control virtqueue and check status.  Commands
+ * supported by the hypervisor, as indicated by feature bits, should
+ * never fail unless improperly formated.
+ */
+static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
+                                struct scatterlist *data, int out, int in)
+{
+       struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
+       struct virtio_net_ctrl_hdr ctrl;
+       virtio_net_ctrl_ack status = ~0;
+       unsigned int tmp;
+
+       if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
+               BUG();  /* Caller should know better */
+               return false;
+       }
+
+       BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX);
+
+       out++; /* Add header */
+       in++; /* Add return status */
+
+       ctrl.class = class;
+       ctrl.cmd = cmd;
+
+       sg_init_table(sg, out + in);
+
+       sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
+       memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2));
+       sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
+
+       if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0)
+               BUG();
+
+       vi->cvq->vq_ops->kick(vi->cvq);
+
+       /*
+        * Spin for a response, the kick causes an ioport write, trapping
+        * into the hypervisor, so the request should be handled immediately.
+        */
+       while (!vi->cvq->vq_ops->get_buf(vi->cvq, &tmp))
+               cpu_relax();
+
+       return status == VIRTIO_NET_OK;
+}
+
 static int virtnet_close(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
@@ -608,10 +674,104 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
        return ethtool_op_set_tx_hw_csum(dev, data);
 }
 
+static void virtnet_set_rx_mode(struct net_device *dev)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct scatterlist sg[2];
+       u8 promisc, allmulti;
+       struct virtio_net_ctrl_mac *mac_data;
+       struct dev_addr_list *addr;
+       void *buf;
+       int i;
+
+       /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */
+       if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
+               return;
+
+       promisc = ((dev->flags & IFF_PROMISC) != 0);
+       allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
+
+       sg_set_buf(sg, &promisc, sizeof(promisc));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
+                                 VIRTIO_NET_CTRL_RX_PROMISC,
+                                 sg, 1, 0))
+               dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
+                        promisc ? "en" : "dis");
+
+       sg_set_buf(sg, &allmulti, sizeof(allmulti));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
+                                 VIRTIO_NET_CTRL_RX_ALLMULTI,
+                                 sg, 1, 0))
+               dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
+                        allmulti ? "en" : "dis");
+
+       /* MAC filter - use one buffer for both lists */
+       mac_data = buf = kzalloc(((dev->uc_count + dev->mc_count) * ETH_ALEN) +
+                                (2 * sizeof(mac_data->entries)), GFP_ATOMIC);
+       if (!buf) {
+               dev_warn(&dev->dev, "No memory for MAC address buffer\n");
+               return;
+       }
+
+       /* Store the unicast list and count in the front of the buffer */
+       mac_data->entries = dev->uc_count;
+       addr = dev->uc_list;
+       for (i = 0; i < dev->uc_count; i++, addr = addr->next)
+               memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN);
+
+       sg_set_buf(&sg[0], mac_data,
+                  sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN));
+
+       /* multicast list and count fill the end */
+       mac_data = (void *)&mac_data->macs[dev->uc_count][0];
+
+       mac_data->entries = dev->mc_count;
+       addr = dev->mc_list;
+       for (i = 0; i < dev->mc_count; i++, addr = addr->next)
+               memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN);
+
+       sg_set_buf(&sg[1], mac_data,
+                  sizeof(mac_data->entries) + (dev->mc_count * ETH_ALEN));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
+                                 VIRTIO_NET_CTRL_MAC_TABLE_SET,
+                                 sg, 2, 0))
+               dev_warn(&dev->dev, "Failed to set MAC fitler table.\n");
+
+       kfree(buf);
+}
+
+static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct scatterlist sg;
+
+       sg_set_buf(&sg, &vid, sizeof(vid));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
+                                 VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
+               dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
+}
+
+static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct scatterlist sg;
+
+       sg_set_buf(&sg, &vid, sizeof(vid));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
+                                 VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
+               dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
+}
+
 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,
+       .get_link = ethtool_op_get_link,
 };
 
 #define MIN_MTU 68
@@ -630,13 +790,51 @@ static const struct net_device_ops virtnet_netdev = {
        .ndo_stop            = virtnet_close,
        .ndo_start_xmit      = start_xmit,
        .ndo_validate_addr   = eth_validate_addr,
-       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_set_mac_address = virtnet_set_mac_address,
+       .ndo_set_rx_mode     = virtnet_set_rx_mode,
        .ndo_change_mtu      = virtnet_change_mtu,
+       .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = virtnet_netpoll,
 #endif
 };
 
+static void virtnet_update_status(struct virtnet_info *vi)
+{
+       u16 v;
+
+       if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
+               return;
+
+       vi->vdev->config->get(vi->vdev,
+                             offsetof(struct virtio_net_config, status),
+                             &v, sizeof(v));
+
+       /* Ignore unknown (future) status bits */
+       v &= VIRTIO_NET_S_LINK_UP;
+
+       if (vi->status == v)
+               return;
+
+       vi->status = v;
+
+       if (vi->status & VIRTIO_NET_S_LINK_UP) {
+               netif_carrier_on(vi->dev);
+               netif_wake_queue(vi->dev);
+       } else {
+               netif_carrier_off(vi->dev);
+               netif_stop_queue(vi->dev);
+       }
+}
+
+static void virtnet_config_changed(struct virtio_device *vdev)
+{
+       struct virtnet_info *vi = vdev->priv;
+
+       virtnet_update_status(vi);
+}
+
 static int virtnet_probe(struct virtio_device *vdev)
 {
        int err;
@@ -678,8 +876,11 @@ static int virtnet_probe(struct virtio_device *vdev)
                vdev->config->get(vdev,
                                  offsetof(struct virtio_net_config, mac),
                                  dev->dev_addr, dev->addr_len);
-       } else
+       } else {
                random_ether_addr(dev->dev_addr);
+               vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
+                                 dev->dev_addr, dev->addr_len);
+       }
 
        /* Set up our device-specific information */
        vi = netdev_priv(dev);
@@ -715,6 +916,17 @@ static int virtnet_probe(struct virtio_device *vdev)
                goto free_recv;
        }
 
+       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
+               vi->cvq = vdev->config->find_vq(vdev, 2, NULL);
+               if (IS_ERR(vi->cvq)) {
+                       err = PTR_ERR(vi->svq);
+                       goto free_send;
+               }
+
+               if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
+                       dev->features |= NETIF_F_HW_VLAN_FILTER;
+       }
+
        /* Initialize our empty receive and send queues. */
        skb_queue_head_init(&vi->recv);
        skb_queue_head_init(&vi->send);
@@ -727,7 +939,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        err = register_netdev(dev);
        if (err) {
                pr_debug("virtio_net: registering device failed\n");
-               goto free_send;
+               goto free_ctrl;
        }
 
        /* Last of all, set up some receive buffers. */
@@ -739,11 +951,17 @@ static int virtnet_probe(struct virtio_device *vdev)
                goto unregister;
        }
 
+       vi->status = VIRTIO_NET_S_LINK_UP;
+       virtnet_update_status(vi);
+
        pr_debug("virtnet: registered device %s\n", dev->name);
        return 0;
 
 unregister:
        unregister_netdev(dev);
+free_ctrl:
+       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
+               vdev->config->del_vq(vi->cvq);
 free_send:
        vdev->config->del_vq(vi->svq);
 free_recv:
@@ -775,6 +993,8 @@ static void virtnet_remove(struct virtio_device *vdev)
 
        vdev->config->del_vq(vi->svq);
        vdev->config->del_vq(vi->rvq);
+       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
+               vdev->config->del_vq(vi->cvq);
        unregister_netdev(vi->dev);
 
        while (vi->pages)
@@ -794,7 +1014,8 @@ 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_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
+       VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
        VIRTIO_F_NOTIFY_ON_EMPTY,
 };
 
@@ -806,6 +1027,7 @@ static struct virtio_driver virtio_net = {
        .id_table =     id_table,
        .probe =        virtnet_probe,
        .remove =       __devexit_p(virtnet_remove),
+       .config_changed = virtnet_config_changed,
 };
 
 static int __init init(void)
index b46897996f7e3edf98645c3ec433f006d0f95059..9693b0fd323dbb82c252ba53720ab971445af126 100644 (file)
@@ -296,7 +296,13 @@ static void c101_destroy_card(card_t *card)
        kfree(card);
 }
 
-
+static const struct net_device_ops c101_ops = {
+       .ndo_open       = c101_open,
+       .ndo_stop       = c101_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = c101_ioctl,
+};
 
 static int __init c101_run(unsigned long irq, unsigned long winbase)
 {
@@ -367,9 +373,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
        dev->mem_start = winbase;
        dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
        dev->tx_queue_len = 50;
-       dev->do_ioctl = c101_ioctl;
-       dev->open = c101_open;
-       dev->stop = c101_close;
+       dev->netdev_ops = &c101_ops;
        hdlc->attach = sca_attach;
        hdlc->xmit = sca_xmit;
        card->settings.clock_type = CLOCK_EXT;
index d80b72e22dea6be26d69b4e2d0fd016541a546f8..0d7ba117ef608debcafeb4185809a882487d6134 100644 (file)
@@ -427,6 +427,15 @@ static void __exit cosa_exit(void)
 }
 module_exit(cosa_exit);
 
+static const struct net_device_ops cosa_ops = {
+       .ndo_open       = cosa_net_open,
+       .ndo_stop       = cosa_net_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = cosa_net_ioctl,
+       .ndo_tx_timeout = cosa_net_timeout,
+};
+
 static int cosa_probe(int base, int irq, int dma)
 {
        struct cosa_data *cosa = cosa_cards+nr_cards;
@@ -575,10 +584,7 @@ static int cosa_probe(int base, int irq, int dma)
                }
                dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
                dev_to_hdlc(chan->netdev)->xmit = cosa_net_tx;
-               chan->netdev->open = cosa_net_open;
-               chan->netdev->stop = cosa_net_close;
-               chan->netdev->do_ioctl = cosa_net_ioctl;
-               chan->netdev->tx_timeout = cosa_net_timeout;
+               chan->netdev->netdev_ops = &cosa_ops;
                chan->netdev->watchdog_timeo = TX_TIMEOUT;
                chan->netdev->base_addr = chan->cosa->datareg;
                chan->netdev->irq = chan->cosa->irq;
index 888025db2f022616d6c0bd4343835be5e5c6a989..8face5db8f32a132be74c053ccafe6fec25d4ae1 100644 (file)
@@ -883,6 +883,15 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
        return ret;
 }
 
+static const struct net_device_ops dscc4_ops = {
+       .ndo_open       = dscc4_open,
+       .ndo_stop       = dscc4_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = dscc4_ioctl,
+       .ndo_tx_timeout = dscc4_tx_timeout,
+};
+
 static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
 {
        struct dscc4_pci_priv *ppriv;
@@ -916,13 +925,8 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
                hdlc_device *hdlc = dev_to_hdlc(d);
 
                d->base_addr = (unsigned long)ioaddr;
-               d->init = NULL;
                d->irq = pdev->irq;
-               d->open = dscc4_open;
-               d->stop = dscc4_close;
-               d->set_multicast_list = NULL;
-               d->do_ioctl = dscc4_ioctl;
-               d->tx_timeout = dscc4_tx_timeout;
+               d->netdev_ops = &dscc4_ops;
                d->watchdog_timeo = TX_TIMEOUT;
                SET_NETDEV_DEV(d, &pdev->dev);
 
@@ -1048,7 +1052,7 @@ static int dscc4_open(struct net_device *dev)
        struct dscc4_pci_priv *ppriv;
        int ret = -EAGAIN;
 
-       if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit)
+       if ((dscc4_loopback_check(dpriv) < 0))
                goto err;
 
        if ((ret = hdlc_open(dev)))
index 48a2c9d28950fc875a72334623343300bda21181..00945f7c1e9b07f7c3c0db54bf0d6db698825ece 100644 (file)
@@ -2424,6 +2424,15 @@ fst_init_card(struct fst_card_info *card)
               type_strings[card->type], card->irq, card->nports);
 }
 
+static const struct net_device_ops fst_ops = {
+       .ndo_open       = fst_open,
+       .ndo_stop       = fst_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = fst_ioctl,
+       .ndo_tx_timeout = fst_tx_timeout,
+};
+
 /*
  *      Initialise card when detected.
  *      Returns 0 to indicate success, or errno otherwise.
@@ -2565,12 +2574,9 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                 dev->base_addr   = card->pci_conf;
                 dev->irq         = card->irq;
 
-                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
-                dev->open                  = fst_open;
-                dev->stop                  = fst_close;
-                dev->do_ioctl              = fst_ioctl;
-                dev->watchdog_timeo        = FST_TX_TIMEOUT;
-                dev->tx_timeout            = fst_tx_timeout;
+               dev->netdev_ops = &fst_ops;
+               dev->tx_queue_len = FST_TX_QUEUE_LEN;
+               dev->watchdog_timeo = FST_TX_TIMEOUT;
                 hdlc->attach = fst_attach;
                 hdlc->xmit   = fst_start_xmit;
        }
index 08b3536944fe034544c74dc2470d7745393b89aa..497b003d72392a1ba87968ba3ea8fc47b077f610 100644 (file)
@@ -341,7 +341,7 @@ static int sca_poll(struct napi_struct *napi, int budget)
                received = sca_rx_done(port, budget);
 
        if (received < budget) {
-               netif_rx_complete(napi);
+               napi_complete(napi);
                enable_intr(port);
        }
 
@@ -359,7 +359,7 @@ static irqreturn_t sca_intr(int irq, void *dev_id)
                if (port && (isr0 & (i ? 0x08002200 : 0x00080022))) {
                        handled = 1;
                        disable_intr(port);
-                       netif_rx_schedule(&port->napi);
+                       napi_schedule(&port->napi);
                }
        }
 
index 1f2a140c9f7c6f113348966ef79dd69679963d91..5ce4372055582bcb652a3aaa14562470bbf2c6c1 100644 (file)
@@ -44,7 +44,7 @@ static const char* version = "HDLC support module revision 1.22";
 
 static struct hdlc_proto *first_proto;
 
-static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
+int hdlc_change_mtu(struct net_device *dev, int new_mtu)
 {
        if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
                return -EINVAL;
@@ -52,15 +52,6 @@ static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-
-
-static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
-{
-       return &dev->stats;
-}
-
-
-
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
                    struct packet_type *p, struct net_device *orig_dev)
 {
@@ -75,7 +66,15 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
        return hdlc->proto->netif_rx(skb);
 }
 
+int hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+
+       if (hdlc->proto->xmit)
+               return hdlc->proto->xmit(skb, dev);
 
+       return hdlc->xmit(skb, dev); /* call hardware driver directly */
+}
 
 static inline void hdlc_proto_start(struct net_device *dev)
 {
@@ -102,11 +101,11 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
        hdlc_device *hdlc;
        unsigned long flags;
        int on;
+
        if (dev_net(dev) != &init_net)
                return NOTIFY_DONE;
 
-       if (dev->get_stats != hdlc_get_stats)
+       if (!(dev->priv_flags & IFF_WAN_HDLC))
                return NOTIFY_DONE; /* not an HDLC device */
 
        if (event != NETDEV_CHANGE)
@@ -233,15 +232,13 @@ static void hdlc_setup_dev(struct net_device *dev)
        /* Re-init all variables changed by HDLC protocol drivers,
         * including ether_setup() called from hdlc_raw_eth.c.
         */
-       dev->get_stats           = hdlc_get_stats;
        dev->flags               = IFF_POINTOPOINT | IFF_NOARP;
+       dev->priv_flags          = IFF_WAN_HDLC;
        dev->mtu                 = HDLC_MAX_MTU;
        dev->type                = ARPHRD_RAWHDLC;
        dev->hard_header_len     = 16;
        dev->addr_len            = 0;
        dev->header_ops          = &hdlc_null_ops;
-
-       dev->change_mtu          = hdlc_change_mtu;
 }
 
 static void hdlc_setup(struct net_device *dev)
@@ -339,6 +336,8 @@ MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 MODULE_DESCRIPTION("HDLC support module");
 MODULE_LICENSE("GPL v2");
 
+EXPORT_SYMBOL(hdlc_change_mtu);
+EXPORT_SYMBOL(hdlc_start_xmit);
 EXPORT_SYMBOL(hdlc_open);
 EXPORT_SYMBOL(hdlc_close);
 EXPORT_SYMBOL(hdlc_ioctl);
@@ -350,7 +349,7 @@ EXPORT_SYMBOL(attach_hdlc_protocol);
 EXPORT_SYMBOL(detach_hdlc_protocol);
 
 static struct packet_type hdlc_packet_type = {
-       .type = __constant_htons(ETH_P_HDLC),
+       .type = cpu_to_be16(ETH_P_HDLC),
        .func = hdlc_rcv,
 };
 
index 44e64b15dbd10b64f626d7a31d98c08b86f25eff..cf5fd17ad7075b7f1753ff1c4d84f028ea03338b 100644 (file)
@@ -117,7 +117,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        data->type = htonl(type);
        data->par1 = par1;
        data->par2 = par2;
-       data->rel = __constant_htons(0xFFFF);
+       data->rel = cpu_to_be16(0xFFFF);
        /* we will need do_div here if 1000 % HZ != 0 */
        data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ));
 
@@ -136,20 +136,20 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
        struct hdlc_header *data = (struct hdlc_header*)skb->data;
 
        if (skb->len < sizeof(struct hdlc_header))
-               return __constant_htons(ETH_P_HDLC);
+               return cpu_to_be16(ETH_P_HDLC);
 
        if (data->address != CISCO_MULTICAST &&
            data->address != CISCO_UNICAST)
-               return __constant_htons(ETH_P_HDLC);
+               return cpu_to_be16(ETH_P_HDLC);
 
        switch(data->protocol) {
-       case __constant_htons(ETH_P_IP):
-       case __constant_htons(ETH_P_IPX):
-       case __constant_htons(ETH_P_IPV6):
+       case cpu_to_be16(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IPX):
+       case cpu_to_be16(ETH_P_IPV6):
                skb_pull(skb, sizeof(struct hdlc_header));
                return data->protocol;
        default:
-               return __constant_htons(ETH_P_HDLC);
+               return cpu_to_be16(ETH_P_HDLC);
        }
 }
 
@@ -194,7 +194,7 @@ static int cisco_rx(struct sk_buff *skb)
                case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
                        in_dev = dev->ip_ptr;
                        addr = 0;
-                       mask = __constant_htonl(~0); /* is the mask correct? */
+                       mask = ~cpu_to_be32(0); /* is the mask correct? */
 
                        if (in_dev != NULL) {
                                struct in_ifaddr **ifap = &in_dev->ifa_list;
@@ -382,7 +382,6 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 
                memcpy(&state(hdlc)->settings, &new_settings, size);
                spin_lock_init(&state(hdlc)->lock);
-               dev->hard_start_xmit = hdlc->xmit;
                dev->header_ops = &cisco_header_ops;
                dev->type = ARPHRD_CISCO;
                netif_dormant_on(dev);
index f1ddd7c3459cdfeeccc1884de43e80e0fb189a9c..800530101093a10901ee16956bf75040a6ec971a 100644 (file)
@@ -278,31 +278,31 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
        struct sk_buff *skb = *skb_p;
 
        switch (skb->protocol) {
-       case __constant_htons(NLPID_CCITT_ANSI_LMI):
+       case cpu_to_be16(NLPID_CCITT_ANSI_LMI):
                head_len = 4;
                skb_push(skb, head_len);
                skb->data[3] = NLPID_CCITT_ANSI_LMI;
                break;
 
-       case __constant_htons(NLPID_CISCO_LMI):
+       case cpu_to_be16(NLPID_CISCO_LMI):
                head_len = 4;
                skb_push(skb, head_len);
                skb->data[3] = NLPID_CISCO_LMI;
                break;
 
-       case __constant_htons(ETH_P_IP):
+       case cpu_to_be16(ETH_P_IP):
                head_len = 4;
                skb_push(skb, head_len);
                skb->data[3] = NLPID_IP;
                break;
 
-       case __constant_htons(ETH_P_IPV6):
+       case cpu_to_be16(ETH_P_IPV6):
                head_len = 4;
                skb_push(skb, head_len);
                skb->data[3] = NLPID_IPV6;
                break;
 
-       case __constant_htons(ETH_P_802_3):
+       case cpu_to_be16(ETH_P_802_3):
                head_len = 10;
                if (skb_headroom(skb) < head_len) {
                        struct sk_buff *skb2 = skb_realloc_headroom(skb,
@@ -426,7 +426,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
                                skb_put(skb, pad);
                                memset(skb->data + len, 0, pad);
                        }
-                       skb->protocol = __constant_htons(ETH_P_802_3);
+                       skb->protocol = cpu_to_be16(ETH_P_802_3);
                }
                if (!fr_hard_header(&skb, pvc->dlci)) {
                        dev->stats.tx_bytes += skb->len;
@@ -444,18 +444,6 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-
-
-static int pvc_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-
-
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
        printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
@@ -508,10 +496,10 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
        memset(skb->data, 0, len);
        skb_reserve(skb, 4);
        if (lmi == LMI_CISCO) {
-               skb->protocol = __constant_htons(NLPID_CISCO_LMI);
+               skb->protocol = cpu_to_be16(NLPID_CISCO_LMI);
                fr_hard_header(&skb, LMI_CISCO_DLCI);
        } else {
-               skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);
+               skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI);
                fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
        }
        data = skb_tail_pointer(skb);
@@ -1068,6 +1056,14 @@ static void pvc_setup(struct net_device *dev)
        dev->addr_len = 2;
 }
 
+static const struct net_device_ops pvc_ops = {
+       .ndo_open       = pvc_open,
+       .ndo_stop       = pvc_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = pvc_xmit,
+       .ndo_do_ioctl   = pvc_ioctl,
+};
+
 static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 {
        hdlc_device *hdlc = dev_to_hdlc(frad);
@@ -1104,11 +1100,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
                *(__be16*)dev->dev_addr = htons(dlci);
                dlci_to_q922(dev->broadcast, dlci);
        }
-       dev->hard_start_xmit = pvc_xmit;
-       dev->open = pvc_open;
-       dev->stop = pvc_close;
-       dev->do_ioctl = pvc_ioctl;
-       dev->change_mtu = pvc_change_mtu;
+       dev->netdev_ops = &pvc_ops;
        dev->mtu = HDLC_MAX_MTU;
        dev->tx_queue_len = 0;
        dev->ml_priv = pvc;
@@ -1260,8 +1252,6 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
                        state(hdlc)->dce_pvc_count = 0;
                }
                memcpy(&state(hdlc)->settings, &new_settings, size);
-
-               dev->hard_start_xmit = hdlc->xmit;
                dev->type = ARPHRD_FRAD;
                return 0;
 
index 57fe714c1c7f63376e1694fc84d2f73788e50c2a..72a7cdab424531850f51462d6b16bf40c3faea50 100644 (file)
@@ -150,11 +150,11 @@ static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
                return htons(ETH_P_HDLC);
 
        switch (data->protocol) {
-       case __constant_htons(PID_IP):
+       case cpu_to_be16(PID_IP):
                skb_pull(skb, sizeof(struct hdlc_header));
                return htons(ETH_P_IP);
 
-       case __constant_htons(PID_IPV6):
+       case cpu_to_be16(PID_IPV6):
                skb_pull(skb, sizeof(struct hdlc_header));
                return htons(ETH_P_IPV6);
 
@@ -558,7 +558,6 @@ out:
        return NET_RX_DROP;
 }
 
-
 static void ppp_timer(unsigned long arg)
 {
        struct proto *proto = (struct proto *)arg;
@@ -679,7 +678,6 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
                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;
index 8612311748f415fe849aea5ced149888cb40e539..19f51fdd55227debdbcae8b10ab100feb93ee3d6 100644 (file)
@@ -27,11 +27,9 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-       return __constant_htons(ETH_P_IP);
+       return cpu_to_be16(ETH_P_IP);
 }
 
-
-
 static struct hdlc_proto proto = {
        .type_trans     = raw_type_trans,
        .ioctl          = raw_ioctl,
@@ -86,7 +84,6 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
                memcpy(hdlc->state, &new_settings, size);
-               dev->hard_start_xmit = hdlc->xmit;
                dev->type = ARPHRD_RAWHDLC;
                netif_dormant_off(dev);
                return 0;
index a13fc320752047cbdf0dfdb5f4c4ee685688aa73..49e68f5ca5f2c95630635ac0fdf7a74512ce90aa 100644 (file)
@@ -45,6 +45,7 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 
 static struct hdlc_proto proto = {
        .type_trans     = eth_type_trans,
+       .xmit           = eth_tx,
        .ioctl          = raw_eth_ioctl,
        .module         = THIS_MODULE,
 };
@@ -56,9 +57,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
        const size_t size = sizeof(raw_hdlc_proto);
        raw_hdlc_proto new_settings;
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       int result;
-       int (*old_ch_mtu)(struct net_device *, int);
-       int old_qlen;
+       int result, old_qlen;
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
@@ -99,11 +98,8 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
                memcpy(hdlc->state, &new_settings, size);
-               dev->hard_start_xmit = eth_tx;
-               old_ch_mtu = dev->change_mtu;
                old_qlen = dev->tx_queue_len;
                ether_setup(dev);
-               dev->change_mtu = old_ch_mtu;
                dev->tx_queue_len = old_qlen;
                random_ether_addr(dev->dev_addr);
                netif_dormant_off(dev);
index cbcbf6f0414c9254aea1d14f95e7220b50ccab13..b1dc29ed15835675b1231505fc25696a62f29f73 100644 (file)
@@ -184,6 +184,7 @@ static struct hdlc_proto proto = {
        .close          = x25_close,
        .ioctl          = x25_ioctl,
        .netif_rx       = x25_rx,
+       .xmit           = x25_xmit,
        .module         = THIS_MODULE,
 };
 
@@ -213,7 +214,6 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 
                if ((result = attach_hdlc_protocol(dev, &proto, 0)))
                        return result;
-               dev->hard_start_xmit = x25_xmit;
                dev->type = ARPHRD_X25;
                netif_dormant_off(dev);
                return 0;
index af54f0cf1b35fcc2d6f0130411df5432d5b55cc2..567d4f5062d6517bb397895093ebc560910ff023 100644 (file)
@@ -173,6 +173,14 @@ static int hostess_attach(struct net_device *dev, unsigned short encoding,
  *     Description block for a Comtrol Hostess SV11 card
  */
 
+static const struct net_device_ops hostess_ops = {
+       .ndo_open       = hostess_open,
+       .ndo_stop       = hostess_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hostess_ioctl,
+};
+
 static struct z8530_dev *sv11_init(int iobase, int irq)
 {
        struct z8530_dev *sv;
@@ -267,9 +275,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
 
        dev_to_hdlc(netdev)->attach = hostess_attach;
        dev_to_hdlc(netdev)->xmit = hostess_queue_xmit;
-       netdev->open = hostess_open;
-       netdev->stop = hostess_close;
-       netdev->do_ioctl = hostess_ioctl;
+       netdev->netdev_ops = &hostess_ops;
        netdev->base_addr = iobase;
        netdev->irq = irq;
 
index 0dbd85b0162da72a9a577cd91358b90b5d52d07b..3bf7d3f447db83002e3e7929e864eeb35303a272 100644 (file)
@@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev)
        printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name);
 #endif
        qmgr_disable_irq(queue_ids[port->id].rx);
-       netif_rx_schedule(&port->napi);
+       napi_schedule(&port->napi);
 }
 
 static int hss_hdlc_poll(struct napi_struct *napi, int budget)
@@ -649,15 +649,15 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
                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);
+                              " napi_complete\n", dev->name);
 #endif
-                       netif_rx_complete(napi);
+                       napi_complete(napi);
                        qmgr_enable_irq(rxq);
                        if (!qmgr_stat_empty(rxq) &&
-                           netif_rx_reschedule(napi)) {
+                           napi_reschedule(napi)) {
 #if DEBUG_RX
                                printk(KERN_DEBUG "%s: hss_hdlc_poll"
-                                      " netif_rx_reschedule succeeded\n",
+                                      " napi_reschedule succeeded\n",
                                       dev->name);
 #endif
                                qmgr_disable_irq(rxq);
@@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev)
        hss_start_hdlc(port);
 
        /* we may already have RX data, enables IRQ */
-       netif_rx_schedule(&port->napi);
+       napi_schedule(&port->napi);
        return 0;
 
 err_unlock:
@@ -1230,6 +1230,14 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  * initialization
  ****************************************************************************/
 
+static const struct net_device_ops hss_hdlc_ops = {
+       .ndo_open       = hss_hdlc_open,
+       .ndo_stop       = hss_hdlc_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = hss_hdlc_ioctl,
+};
+
 static int __devinit hss_init_one(struct platform_device *pdev)
 {
        struct port *port;
@@ -1254,9 +1262,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
        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->netdev_ops = &hss_hdlc_ops;
        dev->tx_queue_len = 100;
        port->clock_type = CLOCK_EXT;
        port->clock_rate = 2048000;
index 5b61b3eef45f5b19da53e8e249b02895eaa6657a..da9dcf59de243d8bbfad5458e1f1d9ecb0491f6c 100644 (file)
@@ -422,7 +422,7 @@ static int lapbeth_device_event(struct notifier_block *this,
 /* ------------------------------------------------------------------------ */
 
 static struct packet_type lapbeth_packet_type = {
-       .type = __constant_htons(ETH_P_DEC),
+       .type = cpu_to_be16(ETH_P_DEC),
        .func = lapbeth_rcv,
 };
 
index feac3b99f8fe7f42192062fca6b63189b73ec62b..45b1822c962dabf212b644092b761ac674264079 100644 (file)
@@ -806,6 +806,16 @@ static int lmc_attach(struct net_device *dev, unsigned short encoding,
        return -EINVAL;
 }
 
+static const struct net_device_ops lmc_ops = {
+       .ndo_open       = lmc_open,
+       .ndo_stop       = lmc_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = lmc_ioctl,
+       .ndo_tx_timeout = lmc_driver_timeout,
+       .ndo_get_stats  = lmc_get_stats,
+};
+
 static int __devinit lmc_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
@@ -849,11 +859,7 @@ static int __devinit lmc_init_one(struct pci_dev *pdev,
        dev->type = ARPHRD_HDLC;
        dev_to_hdlc(dev)->xmit = lmc_start_xmit;
        dev_to_hdlc(dev)->attach = lmc_attach;
-       dev->open = lmc_open;
-       dev->stop = lmc_close;
-       dev->get_stats = lmc_get_stats;
-       dev->do_ioctl = lmc_ioctl;
-       dev->tx_timeout = lmc_driver_timeout;
+       dev->netdev_ops = &lmc_ops;
        dev->watchdog_timeo = HZ; /* 1 second */
        dev->tx_queue_len = 100;
        sc->lmc_device = dev;
@@ -1059,9 +1065,6 @@ static int lmc_open(struct net_device *dev)
     if ((err = lmc_proto_open(sc)) != 0)
            return err;
 
-    dev->do_ioctl = lmc_ioctl;
-
-
     netif_start_queue(dev);
     sc->extra_stats.tx_tbusy0++;
 
index 94b4c208b013e1a0a936ed25afc46785f90ab5a0..044a48175c42e4d4076d950cc23b0a2ffc162765 100644 (file)
 void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/
 {
     lmc_trace(sc->lmc_device, "lmc_proto_attach in");
-    switch(sc->if_type){
-    case LMC_PPP:
-        {
-            struct net_device *dev = sc->lmc_device;
-            dev->do_ioctl = lmc_ioctl;
-        }
-        break;
-    case LMC_NET:
-        {
+    if (sc->if_type == LMC_NET) {
             struct net_device *dev = sc->lmc_device;
             /*
             * They set a few basics because they don't use HDLC
              */
             dev->flags |= IFF_POINTOPOINT;
-
             dev->hard_header_len = 0;
             dev->addr_len = 0;
         }
-    case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */
-        {
-        }
-    default:
-        break;
-    }
     lmc_trace(sc->lmc_device, "lmc_proto_attach out");
 }
 
index 697715ae80f46917a463b5be6936c1f200ce8473..83da596e2052a84df3920cb2d681579e0caa9205 100644 (file)
@@ -324,7 +324,13 @@ static void n2_destroy_card(card_t *card)
        kfree(card);
 }
 
-
+static const struct net_device_ops n2_ops = {
+       .ndo_open       = n2_open,
+       .ndo_stop       = n2_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = n2_ioctl,
+};
 
 static int __init n2_run(unsigned long io, unsigned long irq,
                         unsigned long winbase, long valid0, long valid1)
@@ -460,9 +466,7 @@ static int __init n2_run(unsigned long io, unsigned long irq,
                dev->mem_start = winbase;
                dev->mem_end = winbase + USE_WINDOWSIZE - 1;
                dev->tx_queue_len = 50;
-               dev->do_ioctl = n2_ioctl;
-               dev->open = n2_open;
-               dev->stop = n2_close;
+               dev->netdev_ops = &n2_ops;
                hdlc->attach = sca_attach;
                hdlc->xmit = sca_xmit;
                port->settings.clock_type = CLOCK_EXT;
index f247e5d9002a3b8837f64e390583c3efcb1470c5..60ece54bdd940452f301215743b4658c7bbe2e59 100644 (file)
@@ -287,7 +287,13 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
        kfree(card);
 }
 
-
+static const struct net_device_ops pc300_ops = {
+       .ndo_open       = pc300_open,
+       .ndo_stop       = pc300_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = pc300_ioctl,
+};
 
 static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
                                        const struct pci_device_id *ent)
@@ -448,9 +454,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
                dev->mem_start = ramphys;
                dev->mem_end = ramphys + ramsize - 1;
                dev->tx_queue_len = 50;
-               dev->do_ioctl = pc300_ioctl;
-               dev->open = pc300_open;
-               dev->stop = pc300_close;
+               dev->netdev_ops = &pc300_ops;
                hdlc->attach = sca_attach;
                hdlc->xmit = sca_xmit;
                port->settings.clock_type = CLOCK_EXT;
index 1104d3a692f77b52b72bc4b3b6d7cb3056b5646e..e035d8c57e119b5d0a875d503b25821c1b64b548 100644 (file)
@@ -265,7 +265,13 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
        kfree(card);
 }
 
-
+static const struct net_device_ops pci200_ops = {
+       .ndo_open       = pci200_open,
+       .ndo_stop       = pci200_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = pci200_ioctl,
+};
 
 static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
                                         const struct pci_device_id *ent)
@@ -395,9 +401,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
                dev->mem_start = ramphys;
                dev->mem_end = ramphys + ramsize - 1;
                dev->tx_queue_len = 50;
-               dev->do_ioctl = pci200_ioctl;
-               dev->open = pci200_open;
-               dev->stop = pci200_close;
+               dev->netdev_ops = &pci200_ops;
                hdlc->attach = sca_attach;
                hdlc->xmit = sca_xmit;
                port->settings.clock_type = CLOCK_EXT;
index 0941a26f6e3f9b94d794bc2f43ecce49a35290cb..23b26902745310b5d93fca475467e25a6487fb23 100644 (file)
@@ -169,6 +169,14 @@ static int sealevel_attach(struct net_device *dev, unsigned short encoding,
        return -EINVAL;
 }
 
+static const struct net_device_ops sealevel_ops = {
+       .ndo_open       = sealevel_open,
+       .ndo_stop       = sealevel_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = sealevel_ioctl,
+};
+
 static int slvl_setup(struct slvl_device *sv, int iobase, int irq)
 {
        struct net_device *dev = alloc_hdlcdev(sv);
@@ -177,9 +185,7 @@ static int slvl_setup(struct slvl_device *sv, int iobase, int irq)
 
        dev_to_hdlc(dev)->attach = sealevel_attach;
        dev_to_hdlc(dev)->xmit = sealevel_queue_xmit;
-       dev->open = sealevel_open;
-       dev->stop = sealevel_close;
-       dev->do_ioctl = sealevel_ioctl;
+       dev->netdev_ops = &sealevel_ops;
        dev->base_addr = iobase;
        dev->irq = irq;
 
index 4bffb67ebcae32b9fbd2676bcb6e151fa16f9edf..887acb0dc8075f183925c19225d5d4cf725695dd 100644 (file)
@@ -547,6 +547,15 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
 
 #include "wanxlfw.inc"
 
+static const struct net_device_ops wanxl_ops = {
+       .ndo_open       = wanxl_open,
+       .ndo_stop       = wanxl_close,
+       .ndo_change_mtu = hdlc_change_mtu,
+       .ndo_start_xmit = hdlc_start_xmit,
+       .ndo_do_ioctl   = wanxl_ioctl,
+       .ndo_get_stats  = wanxl_get_stats,
+};
+
 static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
                                        const struct pci_device_id *ent)
 {
@@ -777,12 +786,9 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
                hdlc = dev_to_hdlc(dev);
                spin_lock_init(&port->lock);
                dev->tx_queue_len = 50;
-               dev->do_ioctl = wanxl_ioctl;
-               dev->open = wanxl_open;
-               dev->stop = wanxl_close;
+               dev->netdev_ops = &wanxl_ops;
                hdlc->attach = wanxl_attach;
                hdlc->xmit = wanxl_xmit;
-               dev->get_stats = wanxl_get_stats;
                port->card = card;
                port->node = i;
                get_status(port)->clocking = CLOCK_EXT;
index 1d8271f34c3832b35feafeaabe854cad7278e22b..ecd0cfaefdcc583785484b6b4c1cedadead9bc60 100644 (file)
 
 
 static const __le32 i2400m_ACK_BARKER[4] = {
-       __constant_cpu_to_le32(I2400M_ACK_BARKER),
-       __constant_cpu_to_le32(I2400M_ACK_BARKER),
-       __constant_cpu_to_le32(I2400M_ACK_BARKER),
-       __constant_cpu_to_le32(I2400M_ACK_BARKER)
+       cpu_to_le32(I2400M_ACK_BARKER),
+       cpu_to_le32(I2400M_ACK_BARKER),
+       cpu_to_le32(I2400M_ACK_BARKER),
+       cpu_to_le32(I2400M_ACK_BARKER)
 };
 
 
@@ -771,8 +771,8 @@ static
 int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
 {
 #define POKE(a, d) {                                   \
-       .address = __constant_cpu_to_le32(a),           \
-       .data = __constant_cpu_to_le32(d)               \
+       .address = cpu_to_le32(a),              \
+       .data = cpu_to_le32(d)          \
 }
        static const struct {
                __le32 address;
index 067c871cc2266e62a08112161a38bb43a6724d8d..236f19ea4c853c72f7e27ce1bb5eece628b837aa 100644 (file)
@@ -664,17 +664,17 @@ extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *);
 extern void i2400m_tx_msg_sent(struct i2400m *);
 
 static const __le32 i2400m_NBOOT_BARKER[4] = {
-       __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_NBOOT_BARKER)
+       cpu_to_le32(I2400M_NBOOT_BARKER),
+       cpu_to_le32(I2400M_NBOOT_BARKER),
+       cpu_to_le32(I2400M_NBOOT_BARKER),
+       cpu_to_le32(I2400M_NBOOT_BARKER)
 };
 
 static const __le32 i2400m_SBOOT_BARKER[4] = {
-       __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
-       __constant_cpu_to_le32(I2400M_SBOOT_BARKER)
+       cpu_to_le32(I2400M_SBOOT_BARKER),
+       cpu_to_le32(I2400M_SBOOT_BARKER),
+       cpu_to_le32(I2400M_SBOOT_BARKER),
+       cpu_to_le32(I2400M_SBOOT_BARKER)
 };
 
 
index 63fe708e8a31509394422a0f8cc921dd7308e5c3..be8be4d0709c0963006b0243bce14b6d1e3e75ce 100644 (file)
@@ -419,7 +419,7 @@ void i2400m_rx_fake_eth_header(struct net_device *net_dev,
 
        memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest));
        memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest));
-       eth_hdr->h_proto = __constant_cpu_to_be16(ETH_P_IP);
+       eth_hdr->h_proto = cpu_to_be16(ETH_P_IP);
 }
 
 
@@ -493,6 +493,14 @@ error_skb_realloc:
                i2400m, buf, buf_len);
 }
 
+static const struct net_device_ops i2400m_netdev_ops = {
+       .ndo_open = i2400m_open,
+       .ndo_stop = i2400m_stop,
+       .ndo_start_xmit = i2400m_hard_start_xmit,
+       .ndo_tx_timeout = i2400m_tx_timeout,
+       .ndo_change_mtu = i2400m_change_mtu,
+};
+
 
 /**
  * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data
@@ -513,11 +521,7 @@ void i2400m_netdev_setup(struct net_device *net_dev)
                & (~IFF_BROADCAST       /* i2400m is P2P */
                   & ~IFF_MULTICAST);
        net_dev->watchdog_timeo = I2400M_TX_TIMEOUT;
-       net_dev->open = i2400m_open;
-       net_dev->stop = i2400m_stop;
-       net_dev->hard_start_xmit = i2400m_hard_start_xmit;
-       net_dev->change_mtu = i2400m_change_mtu;
-       net_dev->tx_timeout = i2400m_tx_timeout;
+       net_dev->netdev_ops = &i2400m_netdev_ops;
        d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev);
 }
 EXPORT_SYMBOL_GPL(i2400m_netdev_setup);
index 1bfa283bbd8aabef64c88364cdd749933b02cde8..123a5f8db6adddbe27966e18dd194dcd3210270d 100644 (file)
@@ -255,16 +255,16 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
                container_of(i2400m, struct i2400ms, i2400m);
        struct device *dev = i2400m_dev(i2400m);
        static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
        };
        static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
        };
 
        if (rt == I2400M_RT_WARM)
index c6d93465c7e24d8e3883061814411edc00f0ecc0..7c28610da6f32b7382c1b48dd6f2b434f9721901 100644 (file)
@@ -211,16 +211,16 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
                container_of(i2400m, struct i2400mu, i2400m);
        struct device *dev = i2400m_dev(i2400m);
        static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
+               cpu_to_le32(I2400M_WARM_RESET_BARKER),
        };
        static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
-               __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
+               cpu_to_le32(I2400M_COLD_RESET_BARKER),
        };
 
        d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt);
index e4f9f747de88c94404ddbe17294783a3e37fa1ff..fe819a785714f50f5f30299b0d677e595c51b33e 100644 (file)
@@ -151,6 +151,12 @@ config LIBERTAS_SDIO
        ---help---
          A driver for Marvell Libertas 8385 and 8686 SDIO devices.
 
+config LIBERTAS_SPI
+       tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
+       depends on LIBERTAS && SPI && GENERIC_GPIO
+       ---help---
+         A driver for Marvell Libertas 8686 SPI devices.
+
 config LIBERTAS_DEBUG
        bool "Enable full debugging output in the Libertas module."
        depends on LIBERTAS
@@ -188,127 +194,6 @@ config AIRO
 
          The driver can be compiled as a module and will be named "airo".
 
-config HERMES
-       tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
-       depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
-       select WIRELESS_EXT
-       select FW_LOADER
-       select CRYPTO
-       select CRYPTO_MICHAEL_MIC
-       ---help---
-         A driver for 802.11b wireless cards based on the "Hermes" or
-         Intersil HFA384x (Prism 2) MAC controller.  This includes the vast
-         majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
-         - except for the Cisco/Aironet cards.  Cards supported include the
-         Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
-         Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
-         IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
-         MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
-         IPW2011, and Symbol Spectrum24 High Rate amongst others.
-
-         This option includes the guts of the driver, but in order to
-         actually use a card you will also need to enable support for PCMCIA
-         Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
-
-         You will also very likely also need the Wireless Tools in order to
-         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
-       help
-         Say Y here to support the Airport 802.11b wireless Ethernet hardware
-         built into the Macintosh iBook and other recent PowerPC-based
-         Macintosh machines. This is essentially a Lucent Orinoco card with 
-         a non-standard interface.
-
-         This driver does not support the Airport Extreme (802.11b/g). Use
-         the BCM43xx driver for Airport Extreme cards.
-
-config PLX_HERMES
-       tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
-       depends on PCI && HERMES
-       help
-         Enable support for PCMCIA cards supported by the "Hermes" (aka
-         orinoco) driver when used in PLX9052 based PCI adaptors.  These
-         adaptors are not a full PCMCIA controller but act as a more limited
-         PCI <-> PCMCIA bridge.  Several vendors sell such adaptors so that
-         802.11b PCMCIA cards can be used in desktop machines.  The Netgear
-         MA301 is such an adaptor.
-
-config TMD_HERMES
-       tristate "Hermes in TMD7160 based PCI adaptor support"
-       depends on PCI && HERMES
-       help
-         Enable support for PCMCIA cards supported by the "Hermes" (aka
-         orinoco) driver when used in TMD7160 based PCI adaptors.  These
-         adaptors are not a full PCMCIA controller but act as a more limited
-         PCI <-> PCMCIA bridge.  Several vendors sell such adaptors so that
-         802.11b PCMCIA cards can be used in desktop machines.
-
-config NORTEL_HERMES
-       tristate "Nortel emobility PCI adaptor support"
-       depends on PCI && HERMES
-       help
-         Enable support for PCMCIA cards supported by the "Hermes" (aka
-         orinoco) driver when used in Nortel emobility PCI adaptors.  These
-         adaptors are not full PCMCIA controllers, but act as a more limited
-         PCI <-> PCMCIA bridge.
-
-config PCI_HERMES
-       tristate "Prism 2.5 PCI 802.11b adaptor support"
-       depends on PCI && HERMES
-       help
-         Enable support for PCI and mini-PCI 802.11b wireless NICs based on
-         the Prism 2.5 chipset.  These are true PCI cards, not the 802.11b
-         PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
-         common.  Some of the built-in wireless adaptors in laptops are of
-         this variety.
-
-config PCMCIA_HERMES
-       tristate "Hermes PCMCIA card support"
-       depends on PCMCIA && HERMES
-       ---help---
-         A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
-         as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
-         EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
-         others).  It should also be usable on various Prism II based cards
-         such as the Linksys, D-Link and Farallon Skyline.  It should also
-         work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
-
-         You will very likely need the Wireless Tools in order to
-         configure your card and that /etc/pcmcia/wireless.opts works:
-         <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
-
-config PCMCIA_SPECTRUM
-       tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
-       depends on PCMCIA && HERMES
-       ---help---
-
-         This is a driver for 802.11b cards using RAM-loadable Symbol
-         firmware, such as Symbol Wireless Networker LA4100, CompactFlash
-         cards by Socket Communications and Intel PRO/Wireless 2011B.
-
-         This driver requires firmware download on startup.  Utilities
-         for downloading Symbol firmware are available at
-         <http://sourceforge.net/projects/orinoco/>
-
 config ATMEL
       tristate "Atmel at76c50x chipset  802.11b support"
       depends on (PCI || PCMCIA) && WLAN_80211
@@ -590,5 +475,6 @@ source "drivers/net/wireless/b43/Kconfig"
 source "drivers/net/wireless/b43legacy/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
+source "drivers/net/wireless/orinoco/Kconfig"
 
 endmenu
index fc4322ca669fa3a33c56650a784debdc15e8dab3..acda45838e98eef62e5ec4d3e3a0a9bb82795e88 100644 (file)
@@ -496,39 +496,41 @@ typedef struct {
  * so all rid access should use the read/writeXXXRid routines.
  */
 
-/* This is redundant for x86 archs, but it seems necessary for ARM */
-#pragma pack(1)
-
 /* This structure came from an email sent to me from an engineer at
    aironet for inclusion into this driver */
-typedef struct {
+typedef struct WepKeyRid WepKeyRid;
+struct WepKeyRid {
        __le16 len;
        __le16 kindex;
        u8 mac[ETH_ALEN];
        __le16 klen;
        u8 key[16];
-} WepKeyRid;
+} __attribute__ ((packed));
 
 /* These structures are from the Aironet's PC4500 Developers Manual */
-typedef struct {
+typedef struct Ssid Ssid;
+struct Ssid {
        __le16 len;
        u8 ssid[32];
-} Ssid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct SsidRid SsidRid;
+struct SsidRid {
        __le16 len;
        Ssid ssids[3];
-} SsidRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct ModulationRid ModulationRid;
+struct ModulationRid {
         __le16 len;
         __le16 modulation;
 #define MOD_DEFAULT cpu_to_le16(0)
 #define MOD_CCK cpu_to_le16(1)
 #define MOD_MOK cpu_to_le16(2)
-} ModulationRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct ConfigRid ConfigRid;
+struct ConfigRid {
        __le16 len; /* sizeof(ConfigRid) */
        __le16 opmode; /* operating mode */
 #define MODE_STA_IBSS cpu_to_le16(0)
@@ -649,9 +651,10 @@ typedef struct {
 #define MAGIC_STAY_IN_CAM (1<<10)
        u8 magicControl;
        __le16 autoWake;
-} ConfigRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct StatusRid StatusRid;
+struct StatusRid {
        __le16 len;
        u8 mac[ETH_ALEN];
        __le16 mode;
@@ -707,21 +710,23 @@ typedef struct {
 #define STAT_LEAPFAILED 91
 #define STAT_LEAPTIMEDOUT 92
 #define STAT_LEAPCOMPLETE 93
-} StatusRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct StatsRid StatsRid;
+struct StatsRid {
        __le16 len;
        __le16 spacer;
        __le32 vals[100];
-} StatsRid;
-
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct APListRid APListRid;
+struct APListRid {
        __le16 len;
        u8 ap[4][ETH_ALEN];
-} APListRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct CapabilityRid CapabilityRid;
+struct CapabilityRid {
        __le16 len;
        char oui[3];
        char zero;
@@ -748,17 +753,18 @@ typedef struct {
        __le16 bootBlockVer;
        __le16 requiredHard;
        __le16 extSoftCap;
-} CapabilityRid;
-
+} __attribute__ ((packed));
 
 /* Only present on firmware >= 5.30.17 */
-typedef struct {
+typedef struct BSSListRidExtra BSSListRidExtra;
+struct BSSListRidExtra {
   __le16 unknown[4];
   u8 fixed[12]; /* WLAN management frame */
   u8 iep[624];
-} BSSListRidExtra;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct BSSListRid BSSListRid;
+struct BSSListRid {
   __le16 len;
   __le16 index; /* First is 0 and 0xffff means end of list */
 #define RADIO_FH 1 /* Frequency hopping radio type */
@@ -789,33 +795,37 @@ typedef struct {
 
   /* Only present on firmware >= 5.30.17 */
   BSSListRidExtra extra;
-} BSSListRid;
+} __attribute__ ((packed));
 
 typedef struct {
   BSSListRid bss;
   struct list_head list;
 } BSSListElement;
 
-typedef struct {
+typedef struct tdsRssiEntry tdsRssiEntry;
+struct tdsRssiEntry {
   u8 rssipct;
   u8 rssidBm;
-} tdsRssiEntry;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct tdsRssiRid tdsRssiRid;
+struct tdsRssiRid {
   u16 len;
   tdsRssiEntry x[256];
-} tdsRssiRid;
+} __attribute__ ((packed));
 
-typedef struct {
-       u16 len;
-       u16 state;
-       u16 multicastValid;
+typedef struct MICRid MICRid;
+struct MICRid {
+       __le16 len;
+       __le16 state;
+       __le16 multicastValid;
        u8  multicast[16];
-       u16 unicastValid;
+       __le16 unicastValid;
        u8  unicast[16];
-} MICRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct MICBuffer MICBuffer;
+struct MICBuffer {
        __be16 typelen;
 
        union {
@@ -830,15 +840,13 @@ typedef struct {
        } u;
        __be32 mic;
        __be32 seq;
-} MICBuffer;
+} __attribute__ ((packed));
 
 typedef struct {
        u8 da[ETH_ALEN];
        u8 sa[ETH_ALEN];
 } etherHead;
 
-#pragma pack()
-
 #define TXCTL_TXOK (1<<1) /* report if tx is ok */
 #define TXCTL_TXEX (1<<2) /* report if tx fails */
 #define TXCTL_802_3 (0<<3) /* 802.3 packet */
@@ -981,6 +989,14 @@ typedef struct {
        dma_addr_t host_addr;
 } TxFid;
 
+struct rx_hdr {
+       __le16 status, len;
+       u8 rssi[2];
+       u8 rate;
+       u8 freq;
+       __le16 tmp[4];
+} __attribute__ ((packed));
+
 typedef struct {
        unsigned int  ctl: 15;
        unsigned int  rdy: 1;
@@ -1070,10 +1086,6 @@ static WifiCtlHdr wifictlhdr8023 = {
        }
 };
 
-// Frequency list (map channels to frequencies)
-static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-                               2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-
 // A few details needed for WEP (Wireless Equivalent Privacy)
 #define MAX_KEY_SIZE 13                        // 128 (?) bits
 #define MIN_KEY_SIZE  5                        // 40 bits RC4 - WEP
@@ -1082,12 +1094,6 @@ typedef struct wep_key_t {
        u8      key[16];        /* 40-bit and 104-bit keys */
 } wep_key_t;
 
-/* Backward compatibility */
-#ifndef IW_ENCODE_NOKEY
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
-#define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
-#endif /* IW_ENCODE_NOKEY */
-
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def     airo_handler_def;
 
@@ -1229,6 +1235,9 @@ struct airo_info {
 #define        PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
        char                    proc_name[IFNAMSIZ];
 
+       int                     wep_capable;
+       int                     max_wep_idx;
+
        /* WPA-related stuff */
        unsigned int bssListFirst;
        unsigned int bssListNext;
@@ -1287,6 +1296,29 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
 static void emmh32_final(emmh32_context *context, u8 digest[4]);
 static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
 
+static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len,
+                           struct crypto_cipher *tfm)
+{
+       /* If the current MIC context is valid and its key is the same as
+        * the MIC register, there's nothing to do.
+        */
+       if (cur->valid && (memcmp(cur->key, key, key_len) == 0))
+               return;
+
+       /* Age current mic Context */
+       memcpy(old, cur, sizeof(*cur));
+
+       /* Initialize new context */
+       memcpy(cur->key, key, key_len);
+       cur->window  = 33; /* Window always points to the middle */
+       cur->rx      = 0;  /* Rx Sequence numbers */
+       cur->tx      = 0;  /* Tx sequence numbers */
+       cur->valid   = 1;  /* Key is now valid */
+
+       /* Give key to mic seed */
+       emmh32_setseed(&cur->seed, key, key_len, tfm);
+}
+
 /* micinit - Initialize mic seed */
 
 static void micinit(struct airo_info *ai)
@@ -1297,49 +1329,26 @@ static void micinit(struct airo_info *ai)
        PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
        up(&ai->sem);
 
-       ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;
-
-       if (ai->micstats.enabled) {
-               /* Key must be valid and different */
-               if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||
-                   (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,
-                            sizeof(ai->mod[0].mCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));
-                       ai->mod[0].mCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].mCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].mCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].mCtx.valid   = 1;  //Key is now valid
-  
-                       /* Give key to mic seed */
-                       emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);
-               }
-
-               /* Key must be valid and different */
-               if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || 
-                   (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,
-                           sizeof(ai->mod[0].uCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));
-       
-                       ai->mod[0].uCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].uCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].uCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].uCtx.valid   = 1;  //Key is now valid
-       
-                       //Give key to mic seed
-                       emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);
-               }
-       } else {
-      /* So next time we have a valid key and mic is enabled, we will update
-       * the sequence number if the key is the same as before.
-       */
+       ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0;
+       if (!ai->micstats.enabled) {
+               /* So next time we have a valid key and mic is enabled, we will
+                * update the sequence number if the key is the same as before.
+                */
                ai->mod[0].uCtx.valid = 0;
                ai->mod[0].mCtx.valid = 0;
+               return;
+       }
+
+       if (mic_rid.multicastValid) {
+               age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx,
+                               mic_rid.multicast, sizeof(mic_rid.multicast),
+                               ai->tfm);
+       }
+
+       if (mic_rid.unicastValid) {
+               age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx,
+                               mic_rid.unicast, sizeof(mic_rid.unicast),
+                               ai->tfm);
        }
 }
 
@@ -2730,28 +2739,6 @@ static void airo_networks_initialize(struct airo_info *ai)
                              &ai->network_free_list);
 }
 
-static int airo_test_wpa_capable(struct airo_info *ai)
-{
-       int status;
-       CapabilityRid cap_rid;
-
-       status = readCapabilityRid(ai, &cap_rid, 1);
-       if (status != SUCCESS) return 0;
-
-       /* Only firmware versions 5.30.17 or better can do WPA */
-       if (le16_to_cpu(cap_rid.softVer) > 0x530
-         || (le16_to_cpu(cap_rid.softVer) == 0x530
-             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
-               airo_print_info("", "WPA is supported.");
-               return 1;
-       }
-
-       /* No WPA support */
-       airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
-               " and greater support WPA.  Detected %s)", cap_rid.prodVer);
-       return 0;
-}
-
 static struct net_device *_init_airo_card( unsigned short irq, int port,
                                           int is_pcmcia, struct pci_dev *pci,
                                           struct device *dmdev )
@@ -2759,6 +2746,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        struct net_device *dev;
        struct airo_info *ai;
        int i, rc;
+       CapabilityRid cap_rid;
 
        /* Create the network device object. */
        dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2828,7 +2816,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        }
 
        if (probe) {
-               if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
+               if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
                        airo_print_err(dev->name, "MAC could not be enabled" );
                        rc = -EIO;
                        goto err_out_map;
@@ -2838,28 +2826,50 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                set_bit(FLAG_FLASHING, &ai->flags);
        }
 
+       strcpy(dev->name, "eth%d");
+       rc = register_netdev(dev);
+       if (rc) {
+               airo_print_err(dev->name, "Couldn't register_netdev");
+               goto err_out_map;
+       }
+       ai->wifidev = init_wifidev(ai, dev);
+       if (!ai->wifidev)
+               goto err_out_reg;
+
+       rc = readCapabilityRid(ai, &cap_rid, 1);
+       if (rc != SUCCESS) {
+               rc = -EIO;
+               goto err_out_wifi;
+       }
+       /* WEP capability discovery */
+       ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0;
+       ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0;
+
+       airo_print_info(dev->name, "Firmware version %x.%x.%02x",
+                       ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF),
+                       (le16_to_cpu(cap_rid.softVer) & 0xFF),
+                       le16_to_cpu(cap_rid.softSubVer));
+
        /* Test for WPA support */
-       if (airo_test_wpa_capable(ai)) {
+       /* Only firmware versions 5.30.17 or better can do WPA */
+       if (le16_to_cpu(cap_rid.softVer) > 0x530
+        || (le16_to_cpu(cap_rid.softVer) == 0x530
+             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
+               airo_print_info(ai->dev->name, "WPA supported.");
+
                set_bit(FLAG_WPA_CAPABLE, &ai->flags);
                ai->bssListFirst = RID_WPA_BSSLISTFIRST;
                ai->bssListNext = RID_WPA_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid);
        } else {
+               airo_print_info(ai->dev->name, "WPA unsupported with firmware "
+                       "versions older than 5.30.17.");
+
                ai->bssListFirst = RID_BSSLISTFIRST;
                ai->bssListNext = RID_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
        }
 
-       strcpy(dev->name, "eth%d");
-       rc = register_netdev(dev);
-       if (rc) {
-               airo_print_err(dev->name, "Couldn't register_netdev");
-               goto err_out_map;
-       }
-       ai->wifidev = init_wifidev(ai, dev);
-       if (!ai->wifidev)
-               goto err_out_reg;
-
        set_bit(FLAG_REGISTERED,&ai->flags);
        airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
 
@@ -3127,314 +3137,354 @@ static int header_len(__le16 ctl)
        return 24;
 }
 
-static irqreturn_t airo_interrupt(int irq, void *dev_id)
+static void airo_handle_cisco_mic(struct airo_info *ai)
 {
-       struct net_device *dev = dev_id;
+       if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) {
+               set_bit(JOB_MIC, &ai->jobs);
+               wake_up_interruptible(&ai->thr_wait);
+       }
+}
+
+/* Airo Status codes */
+#define STAT_NOBEACON  0x8000 /* Loss of sync - missed beacons */
+#define STAT_MAXRETRIES        0x8001 /* Loss of sync - max retries */
+#define STAT_MAXARL    0x8002 /* Loss of sync - average retry level exceeded*/
+#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */
+#define STAT_TSFSYNC   0x8004 /* Loss of sync - TSF synchronization */
+#define STAT_DEAUTH    0x8100 /* low byte is 802.11 reason code */
+#define STAT_DISASSOC  0x8200 /* low byte is 802.11 reason code */
+#define STAT_ASSOC_FAIL        0x8400 /* low byte is 802.11 reason code */
+#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */
+#define STAT_ASSOC     0x0400 /* Associated */
+#define STAT_REASSOC    0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
+
+static void airo_print_status(const char *devname, u16 status)
+{
+       u8 reason = status & 0xFF;
+
+       switch (status) {
+       case STAT_NOBEACON:
+               airo_print_dbg(devname, "link lost (missed beacons)");
+               break;
+       case STAT_MAXRETRIES:
+       case STAT_MAXARL:
+               airo_print_dbg(devname, "link lost (max retries)");
+               break;
+       case STAT_FORCELOSS:
+               airo_print_dbg(devname, "link lost (local choice)");
+               break;
+       case STAT_TSFSYNC:
+               airo_print_dbg(devname, "link lost (TSF sync lost)");
+               break;
+       case STAT_DEAUTH:
+               airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
+               break;
+       case STAT_DISASSOC:
+               airo_print_dbg(devname, "disassociated (reason: %d)", reason);
+               break;
+       case STAT_ASSOC_FAIL:
+               airo_print_dbg(devname, "association failed (reason: %d)",
+                              reason);
+               break;
+       case STAT_AUTH_FAIL:
+               airo_print_dbg(devname, "authentication failed (reason: %d)",
+                              reason);
+               break;
+       default:
+               break;
+       }
+}
+
+static void airo_handle_link(struct airo_info *ai)
+{
+       union iwreq_data wrqu;
+       int scan_forceloss = 0;
        u16 status;
-       u16 fid;
-       struct airo_info *apriv = dev->ml_priv;
-       u16 savedInterrupts = 0;
-       int handled = 0;
 
-       if (!netif_device_present(dev))
-               return IRQ_NONE;
+       /* Get new status and acknowledge the link change */
+       status = le16_to_cpu(IN4500(ai, LINKSTAT));
+       OUT4500(ai, EVACK, EV_LINK);
 
-       for (;;) {
-               status = IN4500( apriv, EVSTAT );
-               if ( !(status & STATUS_INTS) || status == 0xffff ) break;
+       if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0))
+               scan_forceloss = 1;
 
-               handled = 1;
+       airo_print_status(ai->dev->name, status);
 
-               if ( status & EV_AWAKE ) {
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-               }
+       if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) {
+               if (auto_wep)
+                       ai->expires = 0;
+               if (ai->list_bss_task)
+                       wake_up_process(ai->list_bss_task);
+               set_bit(FLAG_UPDATE_UNI, &ai->flags);
+               set_bit(FLAG_UPDATE_MULTI, &ai->flags);
 
-               if (!savedInterrupts) {
-                       savedInterrupts = IN4500( apriv, EVINTEN );
-                       OUT4500( apriv, EVINTEN, 0 );
+               if (down_trylock(&ai->sem) != 0) {
+                       set_bit(JOB_EVENT, &ai->jobs);
+                       wake_up_interruptible(&ai->thr_wait);
+               } else
+                       airo_send_event(ai->dev);
+       } else if (!scan_forceloss) {
+               if (auto_wep && !ai->expires) {
+                       ai->expires = RUN_AT(3*HZ);
+                       wake_up_interruptible(&ai->thr_wait);
                }
 
-               if ( status & EV_MIC ) {
-                       OUT4500( apriv, EVACK, EV_MIC );
-                       if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
-                               set_bit(JOB_MIC, &apriv->jobs);
-                               wake_up_interruptible(&apriv->thr_wait);
-                       }
-               }
-               if ( status & EV_LINK ) {
-                       union iwreq_data        wrqu;
-                       int scan_forceloss = 0;
-                       /* The link status has changed, if you want to put a
-                          monitor hook in, do it here.  (Remember that
-                          interrupts are still disabled!)
-                       */
-                       u16 newStatus = IN4500(apriv, LINKSTAT);
-                       OUT4500( apriv, EVACK, EV_LINK);
-                       /* Here is what newStatus means: */
-#define NOBEACON 0x8000 /* Loss of sync - missed beacons */
-#define MAXRETRIES 0x8001 /* Loss of sync - max retries */
-#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
-#define FORCELOSS 0x8003 /* Loss of sync - host request */
-#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
-#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
-#define DISASS 0x8200 /* Disassociation (low byte is reason code) */
-#define ASSFAIL 0x8400 /* Association failure (low byte is reason
-                         code) */
-#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
-                          code) */
-#define ASSOCIATED 0x0400 /* Associated */
-#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
-#define RC_RESERVED 0 /* Reserved return code */
-#define RC_NOREASON 1 /* Unspecified reason */
-#define RC_AUTHINV 2 /* Previous authentication invalid */
-#define RC_DEAUTH 3 /* Deauthenticated because sending station is
-                      leaving */
-#define RC_NOACT 4 /* Disassociated due to inactivity */
-#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
-                       all currently associated stations */
-#define RC_BADCLASS2 6 /* Class 2 frame received from
-                         non-Authenticated station */
-#define RC_BADCLASS3 7 /* Class 3 frame received from
-                         non-Associated station */
-#define RC_STATLEAVE 8 /* Disassociated because sending station is
-                         leaving BSS */
-#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
-                      Authenticated with the responding station */
-                       if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
-                               scan_forceloss = 1;
-                       if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
-                               if (auto_wep)
-                                       apriv->expires = 0;
-                               if (apriv->list_bss_task)
-                                       wake_up_process(apriv->list_bss_task);
-                               set_bit(FLAG_UPDATE_UNI, &apriv->flags);
-                               set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-
-                               if (down_trylock(&apriv->sem) != 0) {
-                                       set_bit(JOB_EVENT, &apriv->jobs);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               } else
-                                       airo_send_event(dev);
-                       } else if (!scan_forceloss) {
-                               if (auto_wep && !apriv->expires) {
-                                       apriv->expires = RUN_AT(3*HZ);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               }
+               /* Send event to user space */
+               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+               wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL);
+       }
+}
 
-                               /* Send event to user space */
-                               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
-                               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-                               wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
-                       }
-               }
+static void airo_handle_rx(struct airo_info *ai)
+{
+       struct sk_buff *skb = NULL;
+       __le16 fc, v, *buffer, tmpbuf[4];
+       u16 len, hdrlen = 0, gap, fid;
+       struct rx_hdr hdr;
+       int success = 0;
 
-               /* Check to see if there is something to receive */
-               if ( status & EV_RX  ) {
-                       struct sk_buff *skb = NULL;
-                       __le16 fc, v;
-                       u16 len, hdrlen = 0;
-#pragma pack(1)
-                       struct {
-                               __le16 status, len;
-                               u8 rssi[2];
-                               u8 rate;
-                               u8 freq;
-                               __le16 tmp[4];
-                       } hdr;
-#pragma pack()
-                       u16 gap;
-                       __le16 tmpbuf[4];
-                       __le16 *buffer;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               if (test_bit(FLAG_802_11, &apriv->flags))
-                                       mpi_receive_802_11(apriv);
-                               else
-                                       mpi_receive_802_3(apriv);
-                               OUT4500(apriv, EVACK, EV_RX);
-                               goto exitrx;
-                       }
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               if (test_bit(FLAG_802_11, &ai->flags))
+                       mpi_receive_802_11(ai);
+               else
+                       mpi_receive_802_3(ai);
+               OUT4500(ai, EVACK, EV_RX);
+               return;
+       }
 
-                       fid = IN4500( apriv, RXFID );
-
-                       /* Get the packet length */
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_setup (apriv, fid, 4, BAP0);
-                               bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0);
-                               /* Bad CRC. Ignore packet */
-                               if (le16_to_cpu(hdr.status) & 2)
-                                       hdr.len = 0;
-                               if (apriv->wifidev == NULL)
-                                       hdr.len = 0;
-                       } else {
-                               bap_setup (apriv, fid, 0x36, BAP0);
-                               bap_read (apriv, &hdr.len, 2, BAP0);
-                       }
-                       len = le16_to_cpu(hdr.len);
+       fid = IN4500(ai, RXFID);
 
-                       if (len > AIRO_DEF_MTU) {
-                               airo_print_err(apriv->dev->name, "Bad size %d", len);
-                               goto badrx;
-                       }
-                       if (len == 0)
-                               goto badrx;
+       /* Get the packet length */
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_setup (ai, fid, 4, BAP0);
+               bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0);
+               /* Bad CRC. Ignore packet */
+               if (le16_to_cpu(hdr.status) & 2)
+                       hdr.len = 0;
+               if (ai->wifidev == NULL)
+                       hdr.len = 0;
+       } else {
+               bap_setup(ai, fid, 0x36, BAP0);
+               bap_read(ai, &hdr.len, 2, BAP0);
+       }
+       len = le16_to_cpu(hdr.len);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_read (apriv, &fc, sizeof(fc), BAP0);
-                               hdrlen = header_len(fc);
-                       } else
-                               hdrlen = ETH_ALEN * 2;
+       if (len > AIRO_DEF_MTU) {
+               airo_print_err(ai->dev->name, "Bad size %d", len);
+               goto done;
+       }
+       if (len == 0)
+               goto done;
 
-                       skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
-                       if ( !skb ) {
-                               dev->stats.rx_dropped++;
-                               goto badrx;
-                       }
-                       skb_reserve(skb, 2); /* This way the IP header is aligned */
-                       buffer = (__le16*)skb_put (skb, len + hdrlen);
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               buffer[0] = fc;
-                               bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
-                               if (hdrlen == 24)
-                                       bap_read (apriv, tmpbuf, 6, BAP0);
-
-                               bap_read (apriv, &v, sizeof(v), BAP0);
-                               gap = le16_to_cpu(v);
-                               if (gap) {
-                                       if (gap <= 8) {
-                                               bap_read (apriv, tmpbuf, gap, BAP0);
-                                       } else {
-                                               airo_print_err(apriv->dev->name, "gaplen too "
-                                                       "big. Problems will follow...");
-                                       }
-                               }
-                               bap_read (apriv, buffer + hdrlen/2, len, BAP0);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_read(ai, &fc, sizeof (fc), BAP0);
+               hdrlen = header_len(fc);
+       } else
+               hdrlen = ETH_ALEN * 2;
+
+       skb = dev_alloc_skb(len + hdrlen + 2 + 2);
+       if (!skb) {
+               ai->dev->stats.rx_dropped++;
+               goto done;
+       }
+
+       skb_reserve(skb, 2); /* This way the IP header is aligned */
+       buffer = (__le16 *) skb_put(skb, len + hdrlen);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               buffer[0] = fc;
+               bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
+               if (hdrlen == 24)
+                       bap_read(ai, tmpbuf, 6, BAP0);
+
+               bap_read(ai, &v, sizeof(v), BAP0);
+               gap = le16_to_cpu(v);
+               if (gap) {
+                       if (gap <= 8) {
+                               bap_read(ai, tmpbuf, gap, BAP0);
                        } else {
-                               MICBuffer micbuf;
-                               bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-                               if (apriv->micstats.enabled) {
-                                       bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0);
-                                       if (ntohs(micbuf.typelen) > 0x05DC)
-                                               bap_setup (apriv, fid, 0x44, BAP0);
-                                       else {
-                                               if (len <= sizeof(micbuf))
-                                                       goto badmic;
-
-                                               len -= sizeof(micbuf);
-                                               skb_trim (skb, len + hdrlen);
-                                       }
-                               }
-                               bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-                               if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
-badmic:
-                                       dev_kfree_skb_irq (skb);
-badrx:
-                                       OUT4500( apriv, EVACK, EV_RX);
-                                       goto exitrx;
+                               airo_print_err(ai->dev->name, "gaplen too "
+                                       "big. Problems will follow...");
+                       }
+               }
+               bap_read(ai, buffer + hdrlen/2, len, BAP0);
+       } else {
+               MICBuffer micbuf;
+
+               bap_read(ai, buffer, ETH_ALEN * 2, BAP0);
+               if (ai->micstats.enabled) {
+                       bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0);
+                       if (ntohs(micbuf.typelen) > 0x05DC)
+                               bap_setup(ai, fid, 0x44, BAP0);
+                       else {
+                               if (len <= sizeof (micbuf)) {
+                                       dev_kfree_skb_irq(skb);
+                                       goto done;
                                }
+
+                               len -= sizeof(micbuf);
+                               skb_trim(skb, len + hdrlen);
                        }
+               }
+
+               bap_read(ai, buffer + ETH_ALEN, len, BAP0);
+               if (decapsulate(ai, &micbuf, (etherHead*) buffer, len))
+                       dev_kfree_skb_irq (skb);
+               else
+                       success = 1;
+       }
+
 #ifdef WIRELESS_SPY
-                       if (apriv->spy_data.spy_number > 0) {
-                               char *sa;
-                               struct iw_quality wstats;
-                               /* Prepare spy data : addr + qual */
-                               if (!test_bit(FLAG_802_11, &apriv->flags)) {
-                                       sa = (char*)buffer + 6;
-                                       bap_setup (apriv, fid, 8, BAP0);
-                                       bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0);
-                               } else
-                                       sa = (char*)buffer + 10;
-                               wstats.qual = hdr.rssi[0];
-                               if (apriv->rssi)
-                                       wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
-                               else
-                                       wstats.level = (hdr.rssi[1] + 321) / 2;
-                               wstats.noise = apriv->wstats.qual.noise;
-                               wstats.updated = IW_QUAL_LEVEL_UPDATED
-                                       | IW_QUAL_QUAL_UPDATED
-                                       | IW_QUAL_DBM;
-                               /* Update spy records */
-                               wireless_spy_update(dev, sa, &wstats);
-                       }
+       if (success && (ai->spy_data.spy_number > 0)) {
+               char *sa;
+               struct iw_quality wstats;
+
+               /* Prepare spy data : addr + qual */
+               if (!test_bit(FLAG_802_11, &ai->flags)) {
+                       sa = (char *) buffer + 6;
+                       bap_setup(ai, fid, 8, BAP0);
+                       bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0);
+               } else
+                       sa = (char *) buffer + 10;
+               wstats.qual = hdr.rssi[0];
+               if (ai->rssi)
+                       wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
+               else
+                       wstats.level = (hdr.rssi[1] + 321) / 2;
+               wstats.noise = ai->wstats.qual.noise;
+               wstats.updated =  IW_QUAL_LEVEL_UPDATED
+                               | IW_QUAL_QUAL_UPDATED
+                               | IW_QUAL_DBM;
+               /* Update spy records */
+               wireless_spy_update(ai->dev, sa, &wstats);
+       }
 #endif /* WIRELESS_SPY */
-                       OUT4500( apriv, EVACK, EV_RX);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               skb_reset_mac_header(skb);
-                               skb->pkt_type = PACKET_OTHERHOST;
-                               skb->dev = apriv->wifidev;
-                               skb->protocol = htons(ETH_P_802_2);
-                       } else
-                               skb->protocol = eth_type_trans(skb,dev);
-                       skb->ip_summed = CHECKSUM_NONE;
+done:
+       OUT4500(ai, EVACK, EV_RX);
+
+       if (success) {
+               if (test_bit(FLAG_802_11, &ai->flags)) {
+                       skb_reset_mac_header(skb);
+                       skb->pkt_type = PACKET_OTHERHOST;
+                       skb->dev = ai->wifidev;
+                       skb->protocol = htons(ETH_P_802_2);
+               } else
+                       skb->protocol = eth_type_trans(skb, ai->dev);
+               skb->ip_summed = CHECKSUM_NONE;
+
+               netif_rx(skb);
+       }
+}
+
+static void airo_handle_tx(struct airo_info *ai, u16 status)
+{
+       int i, len = 0, index = -1;
+       u16 fid;
 
-                       netif_rx( skb );
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               unsigned long flags;
+
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, -1);
+
+               spin_lock_irqsave(&ai->aux_lock, flags);
+               if (!skb_queue_empty(&ai->txq)) {
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       mpi_send_packet(ai->dev);
+               } else {
+                       clear_bit(FLAG_PENDING_XMIT, &ai->flags);
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       netif_wake_queue(ai->dev);
                }
-exitrx:
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               return;
+       }
 
-               /* Check to see if a packet has been transmitted */
-               if (  status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) {
-                       int i;
-                       int len = 0;
-                       int index = -1;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               unsigned long flags;
-
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, -1);
-                               spin_lock_irqsave(&apriv->aux_lock, flags);
-                               if (!skb_queue_empty(&apriv->txq)) {
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       mpi_send_packet (dev);
-                               } else {
-                                       clear_bit(FLAG_PENDING_XMIT, &apriv->flags);
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       netif_wake_queue (dev);
-                               }
-                               OUT4500( apriv, EVACK,
-                                       status & (EV_TX|EV_TXCPY|EV_TXEXC));
-                               goto exittx;
-                       }
+       fid = IN4500(ai, TXCOMPLFID);
 
-                       fid = IN4500(apriv, TXCOMPLFID);
+       for(i = 0; i < MAX_FIDS; i++) {
+               if ((ai->fids[i] & 0xffff) == fid) {
+                       len = ai->fids[i] >> 16;
+                       index = i;
+               }
+       }
 
-                       for( i = 0; i < MAX_FIDS; i++ ) {
-                               if ( ( apriv->fids[i] & 0xffff ) == fid ) {
-                                       len = apriv->fids[i] >> 16;
-                                       index = i;
-                               }
-                       }
-                       if (index != -1) {
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, index);
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
-                               /* Set up to be used again */
-                               apriv->fids[index] &= 0xffff;
-                               if (index < MAX_FIDS / 2) {
-                                       if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
-                                               netif_wake_queue(dev);
-                               } else {
-                                       if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
-                                               netif_wake_queue(apriv->wifidev);
-                               }
-                       } else {
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
-                               airo_print_err(apriv->dev->name, "Unallocated FID was "
-                                       "used to xmit" );
-                       }
+       if (index != -1) {
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, index);
+
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC));
+
+               /* Set up to be used again */
+               ai->fids[index] &= 0xffff;
+               if (index < MAX_FIDS / 2) {
+                       if (!test_bit(FLAG_PENDING_XMIT, &ai->flags))
+                               netif_wake_queue(ai->dev);
+               } else {
+                       if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags))
+                               netif_wake_queue(ai->wifidev);
+               }
+       } else {
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               airo_print_err(ai->dev->name, "Unallocated FID was used to xmit");
+       }
+}
+
+static irqreturn_t airo_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       u16 status, savedInterrupts = 0;
+       struct airo_info *ai = dev->ml_priv;
+       int handled = 0;
+
+       if (!netif_device_present(dev))
+               return IRQ_NONE;
+
+       for (;;) {
+               status = IN4500(ai, EVSTAT);
+               if (!(status & STATUS_INTS) || (status == 0xffff))
+                       break;
+
+               handled = 1;
+
+               if (status & EV_AWAKE) {
+                       OUT4500(ai, EVACK, EV_AWAKE);
+                       OUT4500(ai, EVACK, EV_AWAKE);
+               }
+
+               if (!savedInterrupts) {
+                       savedInterrupts = IN4500(ai, EVINTEN);
+                       OUT4500(ai, EVINTEN, 0);
+               }
+
+               if (status & EV_MIC) {
+                       OUT4500(ai, EVACK, EV_MIC);
+                       airo_handle_cisco_mic(ai);
                }
-exittx:
-               if ( status & ~STATUS_INTS & ~IGNORE_INTS )
-                       airo_print_warn(apriv->dev->name, "Got weird status %x",
+
+               if (status & EV_LINK) {
+                       /* Link status changed */
+                       airo_handle_link(ai);
+               }
+
+               /* Check to see if there is something to receive */
+               if (status & EV_RX)
+                       airo_handle_rx(ai);
+
+               /* Check to see if a packet has been transmitted */
+               if (status & (EV_TX | EV_TXCPY | EV_TXEXC))
+                       airo_handle_tx(ai, status);
+
+               if ( status & ~STATUS_INTS & ~IGNORE_INTS ) {
+                       airo_print_warn(ai->dev->name, "Got weird status %x",
                                status & ~STATUS_INTS & ~IGNORE_INTS );
+               }
        }
 
        if (savedInterrupts)
-               OUT4500( apriv, EVINTEN, savedInterrupts );
+               OUT4500(ai, EVINTEN, savedInterrupts);
 
-       /* done.. */
        return IRQ_RETVAL(handled);
 }
 
@@ -3613,18 +3663,10 @@ static void mpi_receive_802_11(struct airo_info *ai)
        struct sk_buff *skb = NULL;
        u16 len, hdrlen = 0;
        __le16 fc;
-#pragma pack(1)
-       struct {
-               __le16 status, len;
-               u8 rssi[2];
-               u8 rate;
-               u8 freq;
-               __le16 tmp[4];
-       } hdr;
-#pragma pack()
+       struct rx_hdr hdr;
        u16 gap;
        u16 *buffer;
-       char *ptr = ai->rxfids[0].virtual_host_addr+4;
+       char *ptr = ai->rxfids[0].virtual_host_addr + 4;
 
        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
        memcpy ((char *)&hdr, ptr, sizeof(hdr));
@@ -3691,6 +3733,7 @@ static void mpi_receive_802_11(struct airo_info *ai)
        skb->protocol = htons(ETH_P_802_2);
        skb->ip_summed = CHECKSUM_NONE;
        netif_rx( skb );
+
 badrx:
        if (rxd.valid == 0) {
                rxd.valid = 1;
@@ -5131,55 +5174,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
        return rc;
 }
 
-/* Returns the length of the key at the index.  If index == 0xffff
- * the index of the transmit key is returned.  If the key doesn't exist,
- * -1 will be returned.
+/* Returns the WEP key at the specified index, or -1 if that key does
+ * not exist.  The buffer is assumed to be at least 16 bytes in length.
  */
-static int get_wep_key(struct airo_info *ai, u16 index) {
+static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen)
+{
        WepKeyRid wkr;
        int rc;
        __le16 lastindex;
 
        rc = readWepKeyRid(ai, &wkr, 1, 1);
-       if (rc == SUCCESS) do {
+       if (rc != SUCCESS)
+               return -1;
+       do {
                lastindex = wkr.kindex;
-               if (wkr.kindex == cpu_to_le16(index)) {
-                       if (index == 0xffff) {
-                               return wkr.mac[0];
-                       }
-                       return le16_to_cpu(wkr.klen);
+               if (le16_to_cpu(wkr.kindex) == index) {
+                       int klen = min_t(int, buflen, le16_to_cpu(wkr.klen));
+                       memcpy(buf, wkr.key, klen);
+                       return klen;
                }
-               readWepKeyRid(ai, &wkr, 0, 1);
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
        } while (lastindex != wkr.kindex);
        return -1;
 }
 
-static int set_wep_key(struct airo_info *ai, u16 index,
-                      const char *key, u16 keylen, int perm, int lock )
+static int get_wep_tx_idx(struct airo_info *ai)
+{
+       WepKeyRid wkr;
+       int rc;
+       __le16 lastindex;
+
+       rc = readWepKeyRid(ai, &wkr, 1, 1);
+       if (rc != SUCCESS)
+               return -1;
+       do {
+               lastindex = wkr.kindex;
+               if (wkr.kindex == cpu_to_le16(0xffff))
+                       return wkr.mac[0];
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
+       } while (lastindex != wkr.kindex);
+       return -1;
+}
+
+static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
+                      u16 keylen, int perm, int lock)
 {
        static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
        WepKeyRid wkr;
+       int rc;
 
-       memset(&wkr, 0, sizeof(wkr));
        if (keylen == 0) {
-// We are selecting which key to use
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(0xffff);
-               wkr.mac[0] = (char)index;
-               if (perm) ai->defindex = (char)index;
-       } else {
-// We are actually setting the key
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(index);
-               wkr.klen = cpu_to_le16(keylen);
-               memcpy( wkr.key, key, keylen );
-               memcpy( wkr.mac, macaddr, ETH_ALEN );
+               airo_print_err(ai->dev->name, "%s: key length to set was zero",
+                              __func__);
+               return -1;
        }
 
+       memset(&wkr, 0, sizeof(wkr));
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(index);
+       wkr.klen = cpu_to_le16(keylen);
+       memcpy(wkr.key, key, keylen);
+       memcpy(wkr.mac, macaddr, ETH_ALEN);
+
        if (perm) disable_MAC(ai, lock);
-       writeWepKeyRid(ai, &wkr, perm, lock);
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
        if (perm) enable_MAC(ai, lock);
-       return 0;
+       return rc;
+}
+
+static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
+{
+       WepKeyRid wkr;
+       int rc;
+
+       memset(&wkr, 0, sizeof(wkr));
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(0xffff);
+       wkr.mac[0] = (char)index;
+
+       if (perm) {
+               ai->defindex = (char)index;
+               disable_MAC(ai, lock);
+       }
+
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
+
+       if (perm)
+               enable_MAC(ai, lock);
+       return rc;
 }
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
@@ -5187,7 +5273,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
        struct airo_info *ai = dev->ml_priv;
-       int i;
+       int i, rc;
        char key[16];
        u16 index = 0;
        int j = 0;
@@ -5201,7 +5287,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
            (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
                index = data->wbuffer[0] - '0';
                if (data->wbuffer[1] == '\n') {
-                       set_wep_key(ai, index, NULL, 0, 1, 1);
+                       rc = set_wep_tx_idx(ai, index, 1, 1);
+                       if (rc < 0) {
+                               airo_print_err(ai->dev->name, "failed to set "
+                                              "WEP transmit index to %d: %d.",
+                                              index, rc);
+                       }
                        return;
                }
                j = 2;
@@ -5220,7 +5311,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
                        break;
                }
        }
-       set_wep_key(ai, index, key, i/3, 1, 1);
+
+       rc = set_wep_key(ai, index, key, i/3, 1, 1);
+       if (rc < 0) {
+               airo_print_err(ai->dev->name, "failed to set WEP key at index "
+                              "%d: %d.", index, rc);
+       }
 }
 
 static int proc_wepkey_open( struct inode *inode, struct file *file )
@@ -5451,13 +5547,13 @@ static void timer_func( struct net_device *dev ) {
                        break;
                case AUTH_SHAREDKEY:
                        if (apriv->keyindex < auto_wep) {
-                               set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->keyindex, 0, 0);
                                apriv->config.authType = AUTH_SHAREDKEY;
                                apriv->keyindex++;
                        } else {
                                /* Drop to ENCRYPT */
                                apriv->keyindex = 0;
-                               set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->defindex, 0, 0);
                                apriv->config.authType = AUTH_ENCRYPT;
                        }
                        break;
@@ -5725,16 +5821,12 @@ static int airo_set_freq(struct net_device *dev,
        int rc = -EINPROGRESS;          /* Call commit handler */
 
        /* If setting by frequency, convert to a channel */
-       if((fwrq->e == 1) &&
-          (fwrq->m >= (int) 2.412e8) &&
-          (fwrq->m <= (int) 2.487e8)) {
+       if(fwrq->e == 1) {
                int f = fwrq->m / 100000;
-               int c = 0;
-               while((c < 14) && (f != frequency_list[c]))
-                       c++;
+
                /* Hack to fall through... */
                fwrq->e = 0;
-               fwrq->m = c + 1;
+               fwrq->m = ieee80211_freq_to_dsss_chan(f);
        }
        /* Setting by channel number */
        if((fwrq->m > 1000) || (fwrq->e > 0))
@@ -5778,7 +5870,7 @@ static int airo_get_freq(struct net_device *dev,
 
        ch = le16_to_cpu(status_rid.channel);
        if((ch > 0) && (ch < 15)) {
-               fwrq->m = frequency_list[ch - 1] * 100000;
+               fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000;
                fwrq->e = 1;
        } else {
                fwrq->m = ch;
@@ -6234,11 +6326,9 @@ static int airo_get_mode(struct net_device *dev,
        return 0;
 }
 
-static inline int valid_index(CapabilityRid *p, int index)
+static inline int valid_index(struct airo_info *ai, int index)
 {
-       if (index < 0)
-               return 0;
-       return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
+       return (index >= 0) && (index <= ai->max_wep_idx);
 }
 
 /*------------------------------------------------------------------*/
@@ -6251,16 +6341,13 @@ static int airo_set_encode(struct net_device *dev,
                           char *extra)
 {
        struct airo_info *local = dev->ml_priv;
-       CapabilityRid cap_rid;          /* Card capability info */
-       int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1);
        __le16 currentAuthType = local->config.authType;
+       int rc = 0;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Basic checking: do we have a key to set ?
@@ -6272,14 +6359,21 @@ static int airo_set_encode(struct net_device *dev,
        if (dwrq->length > 0) {
                wep_key_t key;
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               int current_index = get_wep_key(local, 0xffff);
+               int current_index;
+
                /* Check the size of the key */
                if (dwrq->length > MAX_KEY_SIZE) {
                        return -EINVAL;
                }
+
+               current_index = get_wep_tx_idx(local);
+               if (current_index < 0)
+                       current_index = 0;
+
                /* Check the index (none -> use current) */
-               if (!valid_index(&cap_rid, index))
+               if (!valid_index(local, index))
                        index = current_index;
+
                /* Set the length */
                if (dwrq->length > MIN_KEY_SIZE)
                        key.len = MAX_KEY_SIZE;
@@ -6296,7 +6390,13 @@ static int airo_set_encode(struct net_device *dev,
                        /* Copy the key in the driver */
                        memcpy(key.key, extra, dwrq->length);
                        /* Send the key to the card */
-                       set_wep_key(local, index, key.key, key.len, perm, 1);
+                       rc = set_wep_key(local, index, key.key, key.len, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP key at index %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
                }
                /* WE specify that if a valid key is set, encryption
                 * should be enabled (user may turn it off later)
@@ -6308,12 +6408,19 @@ static int airo_set_encode(struct net_device *dev,
        } else {
                /* Do we want to just set the transmit key index ? */
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               if (valid_index(&cap_rid, index)) {
-                       set_wep_key(local, index, NULL, 0, perm, 1);
-               } else
+               if (valid_index(local, index)) {
+                       rc = set_wep_tx_idx(local, index, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP transmit index to %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
+               } else {
                        /* Don't complain if only change the mode */
                        if (!(dwrq->flags & IW_ENCODE_MODE))
                                return -EINVAL;
+               }
        }
        /* Read the flags */
        if(dwrq->flags & IW_ENCODE_DISABLED)
@@ -6339,14 +6446,13 @@ static int airo_get_encode(struct net_device *dev,
 {
        struct airo_info *local = dev->ml_priv;
        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-       CapabilityRid cap_rid;          /* Card capability info */
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
+
        /* Check encryption mode */
        switch(local->config.authType)  {
                case AUTH_ENCRYPT:
@@ -6365,14 +6471,17 @@ static int airo_get_encode(struct net_device *dev,
        memset(extra, 0, 16);
 
        /* Which key do we want ? -1 -> tx index */
-       if (!valid_index(&cap_rid, index))
-               index = get_wep_key(local, 0xffff);
+       if (!valid_index(local, index)) {
+               index = get_wep_tx_idx(local);
+               if (index < 0)
+                       index = 0;
+       }
        dwrq->flags |= index + 1;
+
        /* Copy the key to the user buffer */
-       dwrq->length = get_wep_key(local, index);
-       if (dwrq->length > 16) {
-               dwrq->length=0;
-       }
+       dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf));
+       memcpy(extra, buf, dwrq->length);
+
        return 0;
 }
 
@@ -6388,28 +6497,27 @@ static int airo_set_encodeext(struct net_device *dev,
        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 */
        int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
        __le16 currentAuthType = local->config.authType;
-       int idx, key_len, alg = ext->alg, set_key = 1;
+       int idx, key_len, alg = ext->alg, set_key = 1, rc;
        wep_key_t key;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Determine and validate the key index */
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        if (encoding->flags & IW_ENCODE_DISABLED)
                alg = IW_ENCODE_ALG_NONE;
@@ -6418,7 +6526,13 @@ static int airo_set_encodeext(struct net_device *dev,
                /* Only set transmit key index here, actual
                 * key is set below if needed.
                 */
-               set_wep_key(local, idx, NULL, 0, perm, 1);
+               rc = set_wep_tx_idx(local, idx, perm, 1);
+               if (rc < 0) {
+                       airo_print_err(local->dev->name, "failed to set "
+                                      "WEP transmit index to %d: %d.",
+                                      idx, rc);
+                       return rc;
+               }
                set_key = ext->key_len > 0 ? 1 : 0;
        }
 
@@ -6444,7 +6558,12 @@ static int airo_set_encodeext(struct net_device *dev,
                        return -EINVAL;
                }
                /* Send the key to the card */
-               set_wep_key(local, idx, key.key, key.len, perm, 1);
+               rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+               if (rc < 0) {
+                       airo_print_err(local->dev->name, "failed to set WEP key"
+                                      " at index %d: %d.", idx, rc);
+                       return rc;
+               }
        }
 
        /* Read the flags */
@@ -6474,14 +6593,12 @@ static int airo_get_encodeext(struct net_device *dev,
        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 */
        int idx, max_key_len;
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
 
        max_key_len = encoding->length - sizeof(*ext);
@@ -6490,11 +6607,14 @@ static int airo_get_encodeext(struct net_device *dev,
 
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        encoding->flags = idx + 1;
        memset(ext, 0, sizeof(*ext));
@@ -6517,10 +6637,8 @@ static int airo_get_encodeext(struct net_device *dev,
        memset(extra, 0, 16);
        
        /* Copy the key to the user buffer */
-       ext->key_len = get_wep_key(local, idx);
-       if (ext->key_len > 16) {
-               ext->key_len=0;
-       }
+       ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
+       memcpy(extra, buf, ext->key_len);
 
        return 0;
 }
@@ -6795,8 +6913,8 @@ static int airo_get_range(struct net_device *dev,
        k = 0;
        for(i = 0; i < 14; i++) {
                range->freq[k].i = i + 1; /* List index */
-               range->freq[k].m = frequency_list[i] * 100000;
-               range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+               range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
+               range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */
        }
        range->num_frequency = k;
 
@@ -7189,10 +7307,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
        /* Add frequency */
        iwe.cmd = SIOCGIWFREQ;
        iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
-       /* iwe.u.freq.m containt the channel (starting 1), our 
-        * frequency_list array start at index 0...
-        */
-       iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
+       iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000;
        iwe.u.freq.e = 1;
        current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                          &iwe, IW_EV_FREQ_LEN);
index 183ffc8e62cadc4b6b78c339d7a8ec0c4febf481..0eda785fe62f8ec1a124113c01a3eeb183c19553 100644 (file)
@@ -1206,6 +1206,7 @@ extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
 /* Beacon control functions */
 extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
 extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
+extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
 extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
 extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
 #if 0
index a533ed60bb4d739da8a5cc41318b9de8b4b98c27..bd2c580d1f190e27690add916679555720cf4d06 100644 (file)
@@ -232,13 +232,14 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
                int mc_count, struct dev_mc_list *mclist);
 static int ath5k_set_key(struct ieee80211_hw *hw,
                enum set_key_cmd cmd,
-               const u8 *local_addr, const u8 *addr,
+               struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                struct ieee80211_key_conf *key);
 static int ath5k_get_stats(struct ieee80211_hw *hw,
                struct ieee80211_low_level_stats *stats);
 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_set_tsf(struct ieee80211_hw *hw, u64 tsf);
 static void ath5k_reset_tsf(struct ieee80211_hw *hw);
 static int ath5k_beacon_update(struct ath5k_softc *sc,
                struct sk_buff *skb);
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
        .conf_tx        = NULL,
        .get_tx_stats   = ath5k_get_tx_stats,
        .get_tsf        = ath5k_get_tsf,
+       .set_tsf        = ath5k_set_tsf,
        .reset_tsf      = ath5k_reset_tsf,
        .bss_info_changed = ath5k_bss_info_changed,
 };
@@ -347,9 +349,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 }
 
 /* Interrupt handling */
-static int     ath5k_init(struct ath5k_softc *sc, bool is_resume);
+static int     ath5k_init(struct ath5k_softc *sc);
 static int     ath5k_stop_locked(struct ath5k_softc *sc);
-static int     ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
+static int     ath5k_stop_hw(struct ath5k_softc *sc);
 static irqreturn_t ath5k_intr(int irq, void *dev_id);
 static void    ath5k_tasklet_reset(unsigned long data);
 
@@ -653,8 +655,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 
        ath5k_led_off(sc);
 
-       ath5k_stop_hw(sc, true);
-
        free_irq(pdev->irq, sc);
        pci_save_state(pdev);
        pci_disable_device(pdev);
@@ -689,14 +689,9 @@ ath5k_pci_resume(struct pci_dev *pdev)
                goto err_no_irq;
        }
 
-       err = ath5k_init(sc, true);
-       if (err)
-               goto err_irq;
        ath5k_led_enable(sc);
-
        return 0;
-err_irq:
-       free_irq(pdev->irq, sc);
+
 err_no_irq:
        pci_disable_device(pdev);
        return err;
@@ -1098,6 +1093,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
 * Buffers setup *
 \***************/
 
+static
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+{
+       struct sk_buff *skb;
+       unsigned int off;
+
+       /*
+        * Allocate buffer with headroom_needed space for the
+        * fake physical layer header at the start.
+        */
+       skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
+
+       if (!skb) {
+               ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+                               sc->rxbufsize + sc->cachelsz - 1);
+               return NULL;
+       }
+       /*
+        * Cache-line-align.  This is important (for the
+        * 5210 at least) as not doing so causes bogus data
+        * in rx'd frames.
+        */
+       off = ((unsigned long)skb->data) % sc->cachelsz;
+       if (off != 0)
+               skb_reserve(skb, sc->cachelsz - off);
+
+       *skb_addr = pci_map_single(sc->pdev,
+               skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
+       if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
+               ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+               dev_kfree_skb(skb);
+               return NULL;
+       }
+       return skb;
+}
+
 static int
 ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
@@ -1105,37 +1136,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        struct sk_buff *skb = bf->skb;
        struct ath5k_desc *ds;
 
-       if (likely(skb == NULL)) {
-               unsigned int off;
-
-               /*
-                * Allocate buffer with headroom_needed space for the
-                * fake physical layer header at the start.
-                */
-               skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
-               if (unlikely(skb == NULL)) {
-                       ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
-                                       sc->rxbufsize + sc->cachelsz - 1);
+       if (!skb) {
+               skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+               if (!skb)
                        return -ENOMEM;
-               }
-               /*
-                * Cache-line-align.  This is important (for the
-                * 5210 at least) as not doing so causes bogus data
-                * in rx'd frames.
-                */
-               off = ((unsigned long)skb->data) % sc->cachelsz;
-               if (off != 0)
-                       skb_reserve(skb, sc->cachelsz - off);
-
                bf->skb = skb;
-               bf->skbaddr = pci_map_single(sc->pdev,
-                       skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
-               if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
-                       ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
-                       dev_kfree_skb(skb);
-                       bf->skb = NULL;
-                       return -ENOMEM;
-               }
        }
 
        /*
@@ -1178,6 +1183,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        struct ieee80211_rate *rate;
        unsigned int mrr_rate[3], mrr_tries[3];
        int i, ret;
+       u16 hw_rate;
+       u16 cts_rate = 0;
+       u16 duration = 0;
+       u8 rc_flags;
 
        flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
 
@@ -1185,11 +1194,30 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
                        PCI_DMA_TODEVICE);
 
+       rate = ieee80211_get_tx_rate(sc->hw, info);
+
        if (info->flags & IEEE80211_TX_CTL_NO_ACK)
                flags |= AR5K_TXDESC_NOACK;
 
+       rc_flags = info->control.rates[0].flags;
+       hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
+               rate->hw_value_short : rate->hw_value;
+
        pktlen = skb->len;
 
+       if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+               flags |= AR5K_TXDESC_RTSENA;
+               cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
+               duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
+                       sc->vif, pktlen, info));
+       }
+       if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+               flags |= AR5K_TXDESC_CTSENA;
+               cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
+               duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
+                       sc->vif, pktlen, info));
+       }
+
        if (info->control.hw_key) {
                keyidx = info->control.hw_key->hw_key_idx;
                pktlen += info->control.hw_key->icv_len;
@@ -1197,8 +1225,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
                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.rates[0].count, keyidx, 0, flags, 0, 0);
+               hw_rate,
+               info->control.rates[0].count, keyidx, 0, flags,
+               cts_rate, duration);
        if (ret)
                goto err_unmap;
 
@@ -1664,7 +1693,8 @@ ath5k_tasklet_rx(unsigned long data)
 {
        struct ieee80211_rx_status rxs = {};
        struct ath5k_rx_status rs = {};
-       struct sk_buff *skb;
+       struct sk_buff *skb, *next_skb;
+       dma_addr_t next_skb_addr;
        struct ath5k_softc *sc = (void *)data;
        struct ath5k_buf *bf, *bf_last;
        struct ath5k_desc *ds;
@@ -1749,10 +1779,17 @@ ath5k_tasklet_rx(unsigned long data)
                                goto next;
                }
 accept:
+               next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+
+               /*
+                * If we can't replace bf->skb with a new skb under memory
+                * pressure, just skip this packet
+                */
+               if (!next_skb)
+                       goto next;
+
                pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
                                PCI_DMA_FROMDEVICE);
-               bf->skb = NULL;
-
                skb_put(skb, rs.rs_datalen);
 
                /* The MAC header is padded to have 32-bit boundary if the
@@ -1825,6 +1862,9 @@ accept:
                        ath5k_check_ibss_tsf(sc, skb, &rxs);
 
                __ieee80211_rx(sc->hw, skb, &rxs);
+
+               bf->skb = next_skb;
+               bf->skbaddr = next_skb_addr;
 next:
                list_move_tail(&bf->list, &sc->rxbuf);
        } while (ath5k_rxbuf_setup(sc, bf) == 0);
@@ -2207,18 +2247,13 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 \********************/
 
 static int
-ath5k_init(struct ath5k_softc *sc, bool is_resume)
+ath5k_init(struct ath5k_softc *sc)
 {
        struct ath5k_hw *ah = sc->ah;
        int ret, i;
 
        mutex_lock(&sc->lock);
 
-       if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
-               goto out_ok;
-
-       __clear_bit(ATH_STAT_STARTED, sc->status);
-
        ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
 
        /*
@@ -2250,15 +2285,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
        for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
                ath5k_hw_reset_key(ah, i);
 
-       __set_bit(ATH_STAT_STARTED, sc->status);
-
        /* Set ack to be sent at low bit-rates */
        ath5k_hw_set_ack_bitrate_high(ah, false);
 
        mod_timer(&sc->calib_tim, round_jiffies(jiffies +
                        msecs_to_jiffies(ath5k_calinterval * 1000)));
 
-out_ok:
        ret = 0;
 done:
        mmiowb();
@@ -2313,7 +2345,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
  * stop is preempted).
  */
 static int
-ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
+ath5k_stop_hw(struct ath5k_softc *sc)
 {
        int ret;
 
@@ -2344,8 +2376,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
                }
        }
        ath5k_txbuf_free(sc, sc->bbuf);
-       if (!is_suspend)
-               __clear_bit(ATH_STAT_STARTED, sc->status);
 
        mmiowb();
        mutex_unlock(&sc->lock);
@@ -2598,6 +2628,17 @@ ath5k_init_leds(struct ath5k_softc *sc)
                sc->led_pin = 1;
                sc->led_on = 1;  /* active high */
        }
+       /*
+        * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and
+        * in emachines notebooks with AMBIT subsystem.
+        */
+       if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN ||
+           pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) {
+               __set_bit(ATH_STAT_LEDSOFT, sc->status);
+               sc->led_pin = 3;
+               sc->led_on = 0;  /* active low */
+       }
+
        if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
                goto out;
 
@@ -2745,12 +2786,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
 
 static int ath5k_start(struct ieee80211_hw *hw)
 {
-       return ath5k_init(hw->priv, false);
+       return ath5k_init(hw->priv);
 }
 
 static void ath5k_stop(struct ieee80211_hw *hw)
 {
-       ath5k_stop_hw(hw->priv, false);
+       ath5k_stop_hw(hw->priv);
 }
 
 static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -2999,8 +3040,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
 
 static int
 ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-               const u8 *local_addr, const u8 *addr,
-               struct ieee80211_key_conf *key)
+             struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+             struct ieee80211_key_conf *key)
 {
        struct ath5k_softc *sc = hw->priv;
        int ret = 0;
@@ -3023,7 +3064,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        switch (cmd) {
        case SET_KEY:
-               ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
+               ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
+                                      sta ? sta->addr : NULL);
                if (ret) {
                        ATH5K_ERR(sc, "can't set the key\n");
                        goto unlock;
@@ -3082,6 +3124,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
        return ath5k_hw_get_tsf64(sc->ah);
 }
 
+static void
+ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+       struct ath5k_softc *sc = hw->priv;
+
+       ath5k_hw_set_tsf64(sc->ah, tsf);
+}
+
 static void
 ath5k_reset_tsf(struct ieee80211_hw *hw)
 {
index facc60ddada2824ceba476c8efcda1a66a398a1d..c0fb8b5c42fe75d783aac07fa9551658728a82ab 100644 (file)
@@ -148,8 +148,7 @@ struct ath5k_softc {
        u8                      bssidmask[ETH_ALEN];
 
        unsigned int            led_pin,        /* GPIO pin for driving LED */
-                               led_on,         /* pin setting for LED on */
-                               led_off;        /* off time for current blink */
+                               led_on;         /* pin setting for LED on */
 
        struct tasklet_struct   restq;          /* reset tasklet */
 
index 150f5ed204a01605a024703d5b8e9fb244e95a7a..367a6c7d3cc7dd493f93103ed980749011a158ad 100644 (file)
@@ -85,7 +85,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
                /* Enable  802.11b if a 2GHz capable radio (2111/5112) is
                 * connected */
                if (AR5K_EEPROM_HDR_11B(ee_header) ||
-                               AR5K_EEPROM_HDR_11G(ee_header)) {
+                   (AR5K_EEPROM_HDR_11G(ee_header) &&
+                    ah->ah_version != AR5K_AR5211)) {
                        /* 2312 */
                        ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
                        ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
@@ -94,7 +95,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
                                __set_bit(AR5K_MODE_11B,
                                                ah->ah_capabilities.cap_mode);
 
-                       if (AR5K_EEPROM_HDR_11G(ee_header))
+                       if (AR5K_EEPROM_HDR_11G(ee_header) &&
+                           ah->ah_version != AR5K_AR5211)
                                __set_bit(AR5K_MODE_11G,
                                                ah->ah_capabilities.cap_mode);
                }
index ccaeb5c219d2ddda8ea8e7f160a8f9a472c8c89a..413ed689cd5fe177527bae6414b8ac7a23ac5740 100644 (file)
@@ -165,7 +165,7 @@ static int reg_show(struct seq_file *seq, void *p)
        return 0;
 }
 
-static struct seq_operations register_seq_ops = {
+static const struct seq_operations register_seq_ops = {
        .start = reg_start,
        .next  = reg_next,
        .stop  = reg_stop,
@@ -193,43 +193,6 @@ static const struct file_operations fops_registers = {
 };
 
 
-/* debugfs: TSF */
-
-static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
-                                  size_t count, loff_t *ppos)
-{
-       struct ath5k_softc *sc = file->private_data;
-       char buf[100];
-       snprintf(buf, sizeof(buf), "0x%016llx\n",
-                (unsigned long long)ath5k_hw_get_tsf64(sc->ah));
-       return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
-}
-
-static ssize_t write_file_tsf(struct file *file,
-                                const char __user *userbuf,
-                                size_t count, loff_t *ppos)
-{
-       struct ath5k_softc *sc = file->private_data;
-       char buf[20];
-
-       if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
-               return -EFAULT;
-
-       if (strncmp(buf, "reset", 5) == 0) {
-               ath5k_hw_reset_tsf(sc->ah);
-               printk(KERN_INFO "debugfs reset TSF\n");
-       }
-       return count;
-}
-
-static const struct file_operations fops_tsf = {
-       .read = read_file_tsf,
-       .write = write_file_tsf,
-       .open = ath5k_debugfs_open,
-       .owner = THIS_MODULE,
-};
-
-
 /* debugfs: beacons */
 
 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
@@ -423,9 +386,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
        sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
                                sc->debug.debugfs_phydir, sc, &fops_registers);
 
-       sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO,
-                               sc->debug.debugfs_phydir, sc, &fops_tsf);
-
        sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
                                sc->debug.debugfs_phydir, sc, &fops_beacon);
 
@@ -444,7 +404,6 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
 {
        debugfs_remove(sc->debug.debugfs_debug);
        debugfs_remove(sc->debug.debugfs_registers);
-       debugfs_remove(sc->debug.debugfs_tsf);
        debugfs_remove(sc->debug.debugfs_beacon);
        debugfs_remove(sc->debug.debugfs_reset);
        debugfs_remove(sc->debug.debugfs_phydir);
index ffc529393306175cd0686f5c8da25099d74b0d10..66f69f04e55efbed331099d7b7fd5e26f0b61db1 100644 (file)
@@ -72,7 +72,6 @@ struct ath5k_dbg_info {
        struct dentry           *debugfs_phydir;
        struct dentry           *debugfs_debug;
        struct dentry           *debugfs_registers;
-       struct dentry           *debugfs_tsf;
        struct dentry           *debugfs_beacon;
        struct dentry           *debugfs_reset;
 };
index 1cb7edfae625cca6076f45d6b11afa8463ae47cb..b4ec539c464bdf30de219d7cfde0b41d795f401a 100644 (file)
@@ -137,6 +137,18 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
        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);
+
+               /* XXX: Don't know which versions include these two */
+               AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+
+               if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
+
+               if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
+               }
        }
 
        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
@@ -213,7 +225,8 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
 }
 
 /*
- * Read supported modes from eeprom
+ * Read supported modes and some mode-specific calibration data
+ * from eeprom
  */
 static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
                unsigned int mode)
@@ -315,6 +328,9 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
                goto done;
 
+       /* Note: >= v5 have bg freq piers on another location
+        * so these freq piers are ignored for >= v5 (should be 0xff
+        * anyway) */
        switch(mode) {
        case AR5K_EEPROM_MODE_11A:
                if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
@@ -442,7 +458,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
        return 0;
 }
 
-
+/* Read mode-specific data (except power calibration data) */
 static int
 ath5k_eeprom_init_modes(struct ath5k_hw *ah)
 {
@@ -488,6 +504,16 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
        return 0;
 }
 
+/* Used to match PCDAC steps with power values on RF5111 chips
+ * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC
+ * steps that match with the power values we read from eeprom. On
+ * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
+ * these 10 steps are spaced in a different way. This function returns
+ * the pcdac steps based on eeprom version and curve min/max so that we
+ * can have  pcdac/pwr points.
+ */
 static inline void
 ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
 {
@@ -507,37 +533,48 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
                *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100;
 }
 
+/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
+ * frequency mask) */
 static inline int
 ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
-                            struct ath5k_chan_pcal_info *pc, u8 *count)
+                       struct ath5k_chan_pcal_info *pc, unsigned int mode)
 {
+       struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
        int o = *offset;
        int i = 0;
-       u8 f1, f2;
+       u8 freq1, freq2;
        int ret;
        u16 val;
 
        while(i < max) {
                AR5K_EEPROM_READ(o++, val);
 
-               f1 = (val >> 8) & 0xff;
-               f2 = val & 0xff;
+               freq1 = (val >> 8) & 0xff;
+               freq2 = val & 0xff;
 
-               if (f1)
-                       pc[i++].freq = f1;
+               if (freq1) {
+                       pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+                                       freq1, mode);
+                       ee->ee_n_piers[mode]++;
+               }
 
-               if (f2)
-                       pc[i++].freq = f2;
+               if (freq2) {
+                       pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+                                       freq2, mode);
+                       ee->ee_n_piers[mode]++;
+               }
 
-               if (!f1 || !f2)
+               if (!freq1 || !freq2)
                        break;
        }
+
+       /* return new offset */
        *offset = o;
-       *count = i;
 
        return 0;
 }
 
+/* Read frequency piers for 802.11a */
 static int
 ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
 {
@@ -550,7 +587,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
        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]);
+                       AR5K_EEPROM_MODE_11A);
        } else {
                mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
 
@@ -577,23 +614,25 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
 
                AR5K_EEPROM_READ(offset++, val);
                pcal[9].freq |= (val >> 10) & 0x3f;
+
+               /* Fixed number of piers */
                ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
-       }
 
-       for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) {
-               pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+               for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
+                       pcal[i].freq = ath5k_eeprom_bin2freq(ee,
                                pcal[i].freq, AR5K_EEPROM_MODE_11A);
+               }
        }
 
        return 0;
 }
 
+/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
 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:
@@ -608,23 +647,25 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
 
        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);
-       }
+               mode);
 
        return 0;
 }
 
-
+/* Read power calibration for RF5111 chips
+ * For RF5111 we have an XPD -eXternal Power Detector- curve
+ * for each calibrated channel. Each curve has PCDAC steps on
+ * x axis and power on y axis and looks like a logarithmic
+ * function. To recreate the curve and pass the power values
+ * on the pcdac table, we read 10 points here and interpolate later.
+ */
 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;
+       int i;
        u16 val;
 
        offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
@@ -704,16 +745,22 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
 
                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]);
-               }
        }
 
        return 0;
 }
 
+/* Read power calibration for RF5112 chips
+ * For RF5112 we have 4 XPD -eXternal Power Detector- curves
+ * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * use the higher (3) and the lower (0) curves. Each curve has PCDAC
+ * steps on x axis and power on y axis and looks like a linear
+ * function. To recreate the curve and pass the power values
+ * on the pcdac table, we read 4 points for xpd 0 and 3 points
+ * for xpd 3 here and interpolate later.
+ *
+ * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
+ */
 static int
 ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
 {
@@ -790,7 +837,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
 
                /* PCDAC steps
                 * corresponding to the above power
-                * measurements (static) */
+                * measurements (fixed) */
                chan_pcal_info->pcdac_x3[0] = 20;
                chan_pcal_info->pcdac_x3[1] = 35;
                chan_pcal_info->pcdac_x3[2] = 63;
@@ -814,6 +861,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
        return 0;
 }
 
+/* For RF2413 power calibration data doesn't start on a fixed location and
+ * if a mode is not supported, it's section is missing -not zeroed-.
+ * So we need to calculate the starting offset for each section by using
+ * these two functions */
+
+/* Return the size of each section based on the mode and the number of pd
+ * gains available (maximum 4). */
 static inline unsigned int
 ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
 {
@@ -826,6 +880,8 @@ ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
        return sz;
 }
 
+/* Return the starting offset for a section based on the modes supported
+ * and each section's size. */
 static unsigned int
 ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
 {
@@ -834,11 +890,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
        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;
+                       offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) +
+                                                       AR5K_EEPROM_N_2GHZ_CHAN_2413 / 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;
+                       offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) +
+                                                       AR5K_EEPROM_N_5GHZ_CHAN / 2;
                /* fall through */
        case AR5K_EEPROM_MODE_11A:
                break;
@@ -849,6 +907,17 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
        return offset;
 }
 
+/* Read power calibration for RF2413 chips
+ * For RF2413 we have a PDDAC table (Power Detector) instead
+ * of a PCDAC and 4 pd gain curves for each calibrated channel.
+ * Each curve has PDDAC steps on x axis and power on y axis and
+ * looks like an exponential function. To recreate the curves
+ * we read here the points and interpolate later. Note that
+ * in most cases only higher and lower curves are used (like
+ * RF5112) but vendors have the oportunity to include all 4
+ * curves on eeprom. The final curve (higher power) has an extra
+ * point for better accuracy like RF5112.
+ */
 static int
 ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
 {
@@ -868,6 +937,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
        ee->ee_pd_gains[mode] = pd_gains;
 
        offset = ath5k_cal_data_offset_2413(ee, mode);
+       ee->ee_n_piers[mode] = 0;
        switch (mode) {
        case AR5K_EEPROM_MODE_11A:
                if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
@@ -1163,6 +1233,20 @@ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned
        return 0;
 }
 
+/*
+ * Read per channel calibration info from EEPROM
+ *
+ * This info is used to calibrate the baseband power table. Imagine
+ * that for each channel there is a power curve that's hw specific
+ * (depends on amplifier etc) and we try to "correct" this curve using
+ * offests we pass on to phy chip (baseband -> before amplifier) so that
+ * it can use accurate power values when setting tx power (takes amplifier's
+ * performance on each channel into account).
+ *
+ * EEPROM provides us with the offsets for some pre-calibrated channels
+ * and we have to interpolate to create the full table for these channels and
+ * also the table for any channel.
+ */
 static int
 ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
 {
@@ -1193,7 +1277,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
        return 0;
 }
 
-/* Read conformance test limits */
+/* Read conformance test limits used for regulatory control */
 static int
 ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
 {
index b77205adc18025278f06d5adc84ee694a5fea03f..64a27e73d02ed6f87cc9299ea78aa56603ad5a58 100644 (file)
@@ -83,7 +83,7 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
 int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
 {
        ATH5K_TRACE(ah->ah_sc);
-       if (gpio > AR5K_NUM_GPIO)
+       if (gpio >= AR5K_NUM_GPIO)
                return -EINVAL;
 
        ath5k_hw_reg_write(ah,
@@ -99,7 +99,7 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
 int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
 {
        ATH5K_TRACE(ah->ah_sc);
-       if (gpio > AR5K_NUM_GPIO)
+       if (gpio >= AR5K_NUM_GPIO)
                return -EINVAL;
 
        ath5k_hw_reg_write(ah,
@@ -115,7 +115,7 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
 u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
 {
        ATH5K_TRACE(ah->ah_sc);
-       if (gpio > AR5K_NUM_GPIO)
+       if (gpio >= AR5K_NUM_GPIO)
                return 0xffffffff;
 
        /* GPIO input magic */
@@ -131,7 +131,7 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
        u32 data;
        ATH5K_TRACE(ah->ah_sc);
 
-       if (gpio > AR5K_NUM_GPIO)
+       if (gpio >= AR5K_NUM_GPIO)
                return -EINVAL;
 
        /* GPIO output magic */
@@ -154,7 +154,7 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
        u32 data;
 
        ATH5K_TRACE(ah->ah_sc);
-       if (gpio > AR5K_NUM_GPIO)
+       if (gpio >= AR5K_NUM_GPIO)
                return;
 
        /*
index 75eb9f43c7417980266d2eb652f7ac5a9ad70580..f8a4a69602707bc95256ba4c9d252cc1585fc970 100644 (file)
@@ -645,6 +645,23 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
        return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
 }
 
+/**
+ * ath5k_hw_set_tsf64 - Set a new 64bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ * @tsf64: The new 64bit TSF
+ *
+ * Sets the new TSF
+ */
+void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
+{
+       ATH5K_TRACE(ah->ah_sc);
+
+       ath5k_hw_reg_write(ah, 0x00000000, AR5K_TSF_L32);
+       ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
+       ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
+}
+
 /**
  * ath5k_hw_reset_tsf - Force a TSF reset
  *
@@ -1026,6 +1043,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key)
                        return AR5K_KEYTABLE_TYPE_40;
                else if (key->keylen == LEN_WEP104)
                        return AR5K_KEYTABLE_TYPE_104;
+               return -EINVAL;
+       default:
+               return -EINVAL;
        }
        return -EINVAL;
 }
@@ -1041,7 +1061,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
        __le32 key_v[5] = {};
        __le32 key0 = 0, key1 = 0;
        __le32 *rxmic, *txmic;
-       u32 keytype;
+       int keytype;
        u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
        bool is_tkip;
        const u8 *key_ptr;
@@ -1139,7 +1159,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
 
        /* MAC may be NULL if it's a broadcast key. In this case no need to
         * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
-       if (unlikely(mac == NULL)) {
+       if (!mac) {
                low_id = 0xffffffff;
                high_id = 0xffff | AR5K_KEYTABLE_VALID;
        } else {
index 1b7bc50ea8eb212b68fdd51f96283de34998e693..5094c394a4b2c9b1270e7a8c664540b02e0a2bf0 100644 (file)
@@ -148,6 +148,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
  */
 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
 {
+       u32 pending;
        ATH5K_TRACE(ah->ah_sc);
        AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
@@ -159,7 +160,15 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
        if (ah->ah_version == AR5K_AR5210)
                return false;
 
-       return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
+       pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT);
+
+       /* It's possible to have no frames pending even if TXE
+        * is set. To indicate that q has not stopped return
+        * true */
+       if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+               return true;
+
+       return pending;
 }
 
 /*
@@ -324,8 +333,18 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                /*
                 * Set misc registers
                 */
-               ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
-                       AR5K_QUEUE_MISC(queue));
+               /* Enable DCU early termination for this queue */
+               AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+                                       AR5K_QCU_MISC_DCU_EARLY);
+
+               /* Enable DCU to wait for next fragment from QCU */
+               AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+                                       AR5K_DCU_MISC_FRAG_WAIT);
+
+               /* On Maui and Spirit use the global seqnum on DCU */
+               if (ah->ah_mac_version < AR5K_SREV_AR5211)
+                       AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+                                               AR5K_DCU_MISC_SEQNUM_CTL);
 
                if (tq->tqi_cbr_period) {
                        ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
@@ -341,7 +360,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                                        AR5K_QCU_MISC_CBR_THRES_ENABLE);
                }
 
-               if (tq->tqi_ready_time)
+               if (tq->tqi_ready_time &&
+               (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
                        ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
                                AR5K_QCU_RDYTIMECFG_INTVAL) |
                                AR5K_QCU_RDYTIMECFG_ENABLE,
@@ -383,13 +403,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                                AR5K_DCU_MISC_ARBLOCK_CTL_S) |
                                AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
                                AR5K_DCU_MISC_BCN_ENABLE);
-
-                       ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
-                               (AR5K_TUNE_SW_BEACON_RESP -
-                               AR5K_TUNE_DMA_BEACON_RESP) -
-                               AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
-                               AR5K_QCU_RDYTIMECFG_ENABLE,
-                               AR5K_QUEUE_RDYTIMECFG(queue));
                        break;
 
                case AR5K_TX_QUEUE_CAB:
@@ -398,6 +411,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                                AR5K_QCU_MISC_CBREXP_DIS |
                                AR5K_QCU_MISC_CBREXP_BCN_DIS);
 
+                       ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
+                               (AR5K_TUNE_SW_BEACON_RESP -
+                               AR5K_TUNE_DMA_BEACON_RESP) -
+                               AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
+                               AR5K_QCU_RDYTIMECFG_ENABLE,
+                               AR5K_QUEUE_RDYTIMECFG(queue));
+
                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
                                (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
                                AR5K_DCU_MISC_ARBLOCK_CTL_S));
@@ -413,6 +433,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                        break;
                }
 
+               /* TODO: Handle frame compression */
+
                /*
                 * Enable interrupts for this tx queue
                 * in the secondary interrupt mask registers
@@ -483,6 +505,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
                 * by setting AR5K_TXNOFRM to zero */
                if (ah->ah_txq_imr_nofrm == 0)
                        ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+               /* Set QCU mask for this DCU to save power */
+               AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
        }
 
        return 0;
index 1209d14613ac49cbdabf8e10fd17cf4257e2b440..00629587b790f8cc037ea643ad52ba7a66d6a1f9 100644 (file)
@@ -11,6 +11,8 @@ ath9k-y +=    hw.o \
                xmit.o \
                rc.o
 
+ath9k-$(CONFIG_PCI) += pci.o
+ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c
new file mode 100644 (file)
index 0000000..7f2c3a0
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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 <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+#include "core.h"
+#include "reg.h"
+#include "hw.h"
+
+/* return bus cachesize in 4B word units */
+static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
+{
+       *csz = L1_CACHE_BYTES >> 2;
+}
+
+static void ath_ahb_cleanup(struct ath_softc *sc)
+{
+       iounmap(sc->mem);
+}
+
+static bool ath_ahb_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+       struct ath_softc *sc = ah->ah_sc;
+       struct platform_device *pdev = to_platform_device(sc->dev);
+       struct ath9k_platform_data *pdata;
+
+       pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
+       if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+               DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+                       "%s: flash read failed, offset %08x is out of range\n",
+                               __func__, off);
+               return false;
+       }
+
+       *data = pdata->eeprom_data[off];
+       return true;
+}
+
+static struct ath_bus_ops ath_ahb_bus_ops  = {
+       .read_cachesize = ath_ahb_read_cachesize,
+       .cleanup = ath_ahb_cleanup,
+
+       .eeprom_read = ath_ahb_eeprom_read,
+};
+
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+       void __iomem *mem;
+       struct ath_softc *sc;
+       struct ieee80211_hw *hw;
+       struct resource *res;
+       int irq;
+       int ret = 0;
+       struct ath_hal *ah;
+
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "no platform data specified\n");
+               ret = -EINVAL;
+               goto err_out;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no memory resource found\n");
+               ret = -ENXIO;
+               goto err_out;
+       }
+
+       mem = ioremap_nocache(res->start, res->end - res->start + 1);
+       if (mem == NULL) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               ret = -ENOMEM;
+               goto err_out;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no IRQ resource found\n");
+               ret = -ENXIO;
+               goto err_iounmap;
+       }
+
+       irq = res->start;
+
+       hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
+       if (hw == NULL) {
+               dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+               ret = -ENOMEM;
+               goto err_iounmap;
+       }
+
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+       platform_set_drvdata(pdev, hw);
+
+       sc = hw->priv;
+       sc->hw = hw;
+       sc->dev = &pdev->dev;
+       sc->mem = mem;
+       sc->bus_ops = &ath_ahb_bus_ops;
+       sc->irq = irq;
+
+       ret = ath_attach(AR5416_AR9100_DEVID, sc);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
+               ret = -ENODEV;
+               goto err_free_hw;
+       }
+
+       ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
+               ret = -EIO;
+               goto err_detach;
+       }
+
+       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),
+              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, irq);
+
+       return 0;
+
+ err_detach:
+       ath_detach(sc);
+ err_free_hw:
+       ieee80211_free_hw(hw);
+       platform_set_drvdata(pdev, NULL);
+ err_iounmap:
+       iounmap(mem);
+ err_out:
+       return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+
+       if (hw) {
+               struct ath_softc *sc = hw->priv;
+
+               ath_cleanup(sc);
+               platform_set_drvdata(pdev, NULL);
+       }
+
+       return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+       .probe      = ath_ahb_probe,
+       .remove     = ath_ahb_remove,
+       .driver         = {
+               .name   = "ath9k",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int ath_ahb_init(void)
+{
+       return platform_driver_register(&ath_ahb_driver);
+}
+
+void ath_ahb_exit(void)
+{
+       platform_driver_unregister(&ath_ahb_driver);
+}
index 251e2d9a7a4a6d20e772325f6d7449a757f91984..42197fff2a471c0cb79c27d9603bee91e5b93418 100644 (file)
@@ -279,9 +279,8 @@ static void ath9k_ani_restart(struct ath_hal *ah)
 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 ieee80211_conf *conf = &ah->ah_sc->hw->conf;
        struct ar5416AniState *aniState;
-       enum wireless_mode mode;
        int32_t rssi;
 
        if (!DO_ANI(ah))
@@ -336,8 +335,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
                                             aniState->firstepLevel + 1);
                return;
        } else {
-               mode = ath9k_hw_chan2wmode(ah, chan);
-               if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+               if (conf->channel->band == IEEE80211_BAND_2GHZ) {
                        if (!aniState->ofdmWeakSigDetectOff)
                                ath9k_hw_ani_control(ah,
                                     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
@@ -353,9 +351,8 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
 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 ieee80211_conf *conf = &ah->ah_sc->hw->conf;
        struct ar5416AniState *aniState;
-       enum wireless_mode mode;
        int32_t rssi;
 
        if (!DO_ANI(ah))
@@ -381,8 +378,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
                        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 (conf->channel->band == IEEE80211_BAND_2GHZ) {
                        if (aniState->firstepLevel > 0)
                                ath9k_hw_ani_control(ah,
                                             ATH9K_ANI_FIRSTEP_LEVEL, 0);
@@ -555,6 +551,9 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah,
        struct ar5416AniState *aniState;
        int32_t listenTime;
 
+       if (!DO_ANI(ah))
+               return;
+
        aniState = ahp->ah_curani;
        ahp->ah_stats.ast_nodestats = *stats;
 
@@ -614,9 +613,6 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah,
                aniState->cckPhyErrCount = cckPhyErrCnt;
        }
 
-       if (!DO_ANI(ah))
-               return;
-
        if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
                if (aniState->ofdmPhyErrCount <= aniState->listenTime *
                    aniState->ofdmTrigLow / 1000 &&
index d2781350295348f850c7b0501044a904c8a3ce65..5289d287811177409518eff624063709d8caf77e 100644 (file)
@@ -198,6 +198,7 @@ enum ath9k_hw_caps {
        ATH9K_HW_CAP_AUTOSLEEP                  = BIT(19),
        ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(20),
        ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT     = BIT(21),
+       ATH9K_HW_CAP_BT_COEX                    = BIT(22)
 };
 
 enum ath9k_capability_type {
@@ -453,24 +454,15 @@ struct ath9k_11n_rate_series {
         CHANNEL_HT40MINUS)
 
 struct ath9k_channel {
+       struct ieee80211_channel *chan;
        u16 channel;
        u32 channelFlags;
-       u8 privFlags;
-       int8_t maxRegTxPower;
-       int8_t maxTxPower;
-       int8_t minTxPower;
        u32 chanmode;
        int32_t CalValid;
        bool oneTimeCalsDone;
        int8_t iCoff;
        int8_t qCoff;
        int16_t rawNoiseFloor;
-       int8_t antennaMax;
-       u32 regDmnFlags;
-       u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */
-#ifdef ATH_NF_PER_CHAN
-       struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
-#endif
 };
 
 #define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
@@ -498,7 +490,6 @@ struct ath9k_channel {
                          ((_c)->chanmode == CHANNEL_G_HT40MINUS))
 #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
 
-#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
 #define IS_CHAN_A_5MHZ_SPACED(_c)                      \
        ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&  \
         (((_c)->channel % 20) != 0) &&                 \
@@ -751,6 +742,7 @@ struct ath9k_node_stats {
 #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME           3
 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
 
@@ -787,23 +779,24 @@ struct ath_hal {
        u16 ah_currentRD;
        u16 ah_currentRDExt;
        u16 ah_currentRDInUse;
-       u16 ah_currentRD5G;
-       u16 ah_currentRD2G;
-       char ah_iso[4];
+       char alpha2[2];
+       struct reg_dmn_pair_mapping *regpair;
+       enum ath9k_power_mode ah_power_mode;
+       enum ath9k_power_mode ah_restore_mode;
 
-       struct ath9k_channel ah_channels[150];
+       struct ath9k_channel ah_channels[38];
        struct ath9k_channel *ah_curchan;
-       u32 ah_nchan;
 
        bool ah_isPciExpress;
        u16 ah_txTrigLevel;
        u16 ah_rfsilent;
        u32 ah_rfkill_gpio;
        u32 ah_rfkill_polarity;
-
-#ifndef ATH_NF_PER_CHAN
+       u32 ah_btactive_gpio;
+       u32 ah_wlanactive_gpio;
        struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
-#endif
+
+       bool sw_mgmt_crypto;
 };
 
 struct chan_centers {
@@ -816,8 +809,6 @@ 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,
@@ -827,7 +818,6 @@ 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);
 void ath9k_hw_get_channel_centers(struct ath_hal *ah,
                                  struct ath9k_channel *chan,
                                  struct chan_centers *centers);
@@ -843,11 +833,8 @@ 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);
+int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
+                   bool bChannelChange);
 
 /* Key Cache Management */
 
@@ -887,7 +874,6 @@ 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);
 void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
 bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
@@ -912,23 +898,25 @@ 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_settsf64(struct ath_hal *ah, u64 tsf64);
 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 */
+u16 ath9k_regd_get_rd(struct ath_hal *ah);
+bool ath9k_is_world_regd(struct ath_hal *ah);
+const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah);
+const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
+
+void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby);
+void ath9k_reg_apply_radar_flags(struct wiphy *wiphy);
 
-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);
+int ath9k_regd_init(struct ath_hal *ah);
+bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah);
 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);
+int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
 
 /* ANI */
 
@@ -951,8 +939,7 @@ 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);
+bool ath9k_hw_reset_calvalid(struct ath_hal *ah);
 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,
@@ -987,9 +974,8 @@ bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
                                  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);
+u16 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+                                   struct ath9k_channel *chan);
 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);
@@ -1053,5 +1039,6 @@ void ath9k_hw_rxena(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);
+void ath9k_hw_btcoex_enable(struct ath_hal *ah);
 
 #endif
index 3ab0b43aaf93f79c6b8af3859f7cf0ea9990e3db..61d37be9717e1784edffe0847569d267d2a43da0 100644 (file)
@@ -164,9 +164,9 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
        bf = avp->av_bcbuf;
        skb = (struct sk_buff *)bf->bf_mpdu;
        if (skb) {
-               pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+               dma_unmap_single(sc->dev, bf->bf_dmacontext,
                                 skb->len,
-                                PCI_DMA_TODEVICE);
+                                DMA_TO_DEVICE);
                dev_kfree_skb_any(skb);
        }
 
@@ -188,14 +188,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
        }
 
        bf->bf_buf_addr = bf->bf_dmacontext =
-               pci_map_single(sc->pdev, skb->data,
+               dma_map_single(sc->dev, skb->data,
                               skb->len,
-                              PCI_DMA_TODEVICE);
-       if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
+                              DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, 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");
+                       "dma_mapping_error() on beaconing\n");
                return NULL;
        }
 
@@ -220,7 +220,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
                 * acquires txq lock inside.
                 */
                if (sc->sc_nvaps > 1) {
-                       ath_tx_draintxq(sc, cabq, false);
+                       ath_draintxq(sc, cabq, false);
                        DPRINTF(sc, ATH_DBG_BEACON,
                                "flush previous cabq traffic\n");
                }
@@ -343,9 +343,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
        bf = avp->av_bcbuf;
        if (bf->bf_mpdu != NULL) {
                skb = (struct sk_buff *)bf->bf_mpdu;
-               pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+               dma_unmap_single(sc->dev, bf->bf_dmacontext,
                                 skb->len,
-                                PCI_DMA_TODEVICE);
+                                DMA_TO_DEVICE);
                dev_kfree_skb_any(skb);
                bf->bf_mpdu = NULL;
        }
@@ -402,14 +402,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
 
        bf->bf_mpdu = skb;
        bf->bf_buf_addr = bf->bf_dmacontext =
-               pci_map_single(sc->pdev, skb->data,
+               dma_map_single(sc->dev, skb->data,
                               skb->len,
-                              PCI_DMA_TODEVICE);
-       if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
+                              DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, 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");
+                       "dma_mapping_error() on beacon alloc\n");
                return -ENOMEM;
        }
 
@@ -429,9 +429,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
                bf = avp->av_bcbuf;
                if (bf->bf_mpdu != NULL) {
                        struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
-                       pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+                       dma_unmap_single(sc->dev, bf->bf_dmacontext,
                                         skb->len,
-                                        PCI_DMA_TODEVICE);
+                                        DMA_TO_DEVICE);
                        dev_kfree_skb_any(skb);
                        bf->bf_mpdu = NULL;
                }
index 3c7454fc51bdf0f24f1c70475352c85443236818..69ff01ce968b4a9b330fdfc697bf69b0dbb1dfca 100644 (file)
@@ -19,8 +19,6 @@
 #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
 
@@ -107,27 +105,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
                "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 (!AR_SREV_9285(ah)) {
+               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;
+                               "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))
@@ -143,51 +143,45 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
                "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_9285(ah)) {
+               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 (!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;
+                               "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,
+                               enum ieee80211_band band,
                                int16_t *nft)
 {
-       switch (chan->chanmode) {
-       case CHANNEL_A:
-       case CHANNEL_A_HT20:
-       case CHANNEL_A_HT40PLUS:
-       case CHANNEL_A_HT40MINUS:
+       switch (band) {
+       case IEEE80211_BAND_5GHZ:
                *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:
+       case IEEE80211_BAND_2GHZ:
                *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);
+               BUG_ON(1);
                return false;
        }
 
@@ -285,27 +279,24 @@ static void ath9k_hw_per_calibration(struct ath_hal *ah,
        }
 }
 
+/* Assumes you are talking about the currently configured channel */
 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;
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
 
        switch (calType & ahp->ah_suppCals) {
-       case IQ_MISMATCH_CAL:
-               if (!IS_CHAN_B(chan))
-                       retval = true;
-               break;
+       case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
+               return true;
        case ADC_GAIN_CAL:
        case ADC_DC_CAL:
-               if (!IS_CHAN_B(chan)
-                   && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
-                       retval = true;
+               if (conf->channel->band == IEEE80211_BAND_5GHZ &&
+                 conf_is_ht20(conf))
+                       return true;
                break;
        }
-
-       return retval;
+       return false;
 }
 
 static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
@@ -573,50 +564,40 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
                  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
 }
 
-void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
-                            bool *isCalDone)
+/* This is done for the currently configured channel */
+bool ath9k_hw_reset_calvalid(struct ath_hal *ah)
 {
        struct ath_hal_5416 *ahp = AH5416(ah);
-       struct ath9k_channel *ichan =
-               ath9k_regd_check_channel(ah, chan);
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
        struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
 
-       *isCalDone = true;
+       if (!ah->ah_curchan)
+               return true;
 
        if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
-               return;
+               return true;
 
        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;
-       }
-
+               return true;
 
        if (currCal->calState != CAL_DONE) {
                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
                        "Calibration state incorrect, %d\n",
                        currCal->calState);
-               return;
+               return true;
        }
 
-
-       if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
-               return;
+       if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
+               return true;
 
        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-               "Resetting Cal %d state for channel %u/0x%x\n",
-               currCal->calData->calType, chan->channel,
-               chan->channelFlags);
+               "Resetting Cal %d state for channel %u\n",
+               currCal->calData->calType, conf->channel->center_freq);
 
-       ichan->CalValid &= ~currCal->calData->calType;
+       ah->ah_curchan->CalValid &= ~currCal->calData->calType;
        currCal->calState = CAL_WAITING;
 
-       *isCalDone = false;
+       return false;
 }
 
 void ath9k_hw_start_nfcal(struct ath_hal *ah)
@@ -643,16 +624,14 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
        };
        u8 chainmask;
 
-       if (AR_SREV_9280(ah))
+       if (AR_SREV_9285(ah))
+               chainmask = 0x9;
+       else 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)) {
@@ -692,12 +671,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
        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;
+       struct ieee80211_channel *c = chan->chan;
 
        chan->channelFlags &= (~CHANNEL_CW_INT);
        if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
@@ -709,7 +683,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
        } else {
                ath9k_hw_do_getnf(ah, nfarray);
                nf = nfarray[0];
-               if (getNoiseFloorThresh(ah, chan, &nfThresh)
+               if (getNoiseFloorThresh(ah, c->band, &nfThresh)
                    && nf > nfThresh) {
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
                                "noise floor failed detected; "
@@ -719,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
                }
        }
 
-#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;
@@ -750,21 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
 
 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 (chan->rawNoiseFloor == 0)
+               nf = -96;
+       else
+               nf = chan->rawNoiseFloor;
 
        if (!ath9k_hw_nf_in_range(ah, nf))
                nf = ATH_DEFAULT_NOISE_FLOOR;
@@ -778,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
 {
        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,
+               ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
                                         isCalDone);
                if (*isCalDone) {
                        ahp->ah_cal_list_curr = currCal = currCal->calNext;
@@ -805,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
        }
 
        if (longcal) {
-               ath9k_hw_getnf(ah, ichan);
+               ath9k_hw_getnf(ah, chan);
                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;
-               }
+               if (chan->channelFlags & CHANNEL_CW_INT)
+                       chan->channelFlags &= ~CHANNEL_CW_INT;
        }
 
        return true;
@@ -917,7 +868,6 @@ 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) |
@@ -940,19 +890,19 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
        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)) {
+               if (ath9k_hw_iscal_supported(ah, 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)) {
+               if (ath9k_hw_iscal_supported(ah, 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)) {
+               if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
                        INIT_CAL(&ahp->ah_iqCalData);
                        INSERT_CAL(ahp, &ahp->ah_iqCalData);
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
@@ -965,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
                        ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
        }
 
-       ichan->CalValid = 0;
+       chan->CalValid = 0;
 
        return true;
 }
index 4ca2aed236e090d081e6649f019cf81da86273c0..29251f8dabb07a0417b2f0f8fdc4d8a4d61ec47a 100644 (file)
@@ -18,7 +18,7 @@
 #define CORE_H
 
 #include <linux/etherdevice.h>
-#include <linux/pci.h>
+#include <linux/device.h>
 #include <net/mac80211.h>
 #include <linux/leds.h>
 #include <linux/rfkill.h>
@@ -187,7 +187,6 @@ struct ath_config {
 #define ATH_TXBUF_RESET(_bf) do {                              \
                (_bf)->bf_status = 0;                           \
                (_bf)->bf_lastbf = NULL;                        \
-               (_bf)->bf_lastfrm = NULL;                       \
                (_bf)->bf_next = NULL;                          \
                memset(&((_bf)->bf_state), 0,                   \
                            sizeof(struct ath_buf_state));      \
@@ -245,10 +244,8 @@ struct ath_buf_state {
  */
 struct ath_buf {
        struct list_head list;
-       struct list_head *last;
        struct ath_buf *bf_lastbf;      /* last buf of this unit (a frame or
                                           an aggregate) */
-       struct ath_buf *bf_lastfrm;     /* last buf of this frame */
        struct ath_buf *bf_next;        /* next subframe in the aggregate */
        void *bf_mpdu;                  /* enclosing frame structure */
        struct ath_desc *bf_desc;       /* virtual addr of desc */
@@ -261,13 +258,7 @@ struct ath_buf {
 };
 
 #define ATH_RXBUF_RESET(_bf)    ((_bf)->bf_status = 0)
-
-/* hw processing complete, desc processed by hal */
-#define ATH_BUFSTATUS_DONE      0x00000001
-/* hw processing complete, desc hold for hw */
 #define ATH_BUFSTATUS_STALE     0x00000002
-/* Rx-only: OS is done with this packet and it's ok to queued it to hw */
-#define ATH_BUFSTATUS_FREE      0x00000004
 
 /* DMA state for tx/rx descriptors */
 
@@ -360,7 +351,6 @@ struct ath_txq {
        u32 *axq_link;                  /* link ptr in last TX desc */
        struct list_head axq_q;         /* transmit queue */
        spinlock_t axq_lock;
-       unsigned long axq_lockflags;    /* intr state when must cli */
        u32 axq_depth;                  /* queue depth */
        u8 axq_aggr_depth;              /* aggregates queued */
        u32 axq_totalqueued;            /* total ever queued */
@@ -485,28 +475,22 @@ 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);
-void ath_draintxq(struct ath_softc *sc, bool retry_tx);
-void ath_tx_draintxq(struct ath_softc *sc,
+void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+void ath_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);
-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,
                 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_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);
@@ -692,14 +676,22 @@ enum PROT_MODE {
 #define SC_OP_RFKILL_REGISTERED        BIT(11)
 #define SC_OP_RFKILL_SW_BLOCKED        BIT(12)
 #define SC_OP_RFKILL_HW_BLOCKED        BIT(13)
+#define SC_OP_WAIT_FOR_BEACON  BIT(14)
+
+struct ath_bus_ops {
+       void            (*read_cachesize)(struct ath_softc *sc, int *csz);
+       void            (*cleanup)(struct ath_softc *sc);
+       bool            (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data);
+};
 
 struct ath_softc {
        struct ieee80211_hw *hw;
-       struct pci_dev *pdev;
+       struct device *dev;
        struct tasklet_struct intr_tq;
        struct tasklet_struct bcon_tasklet;
        struct ath_hal *sc_ah;
        void __iomem *mem;
+       int irq;
        spinlock_t sc_resetlock;
        struct mutex mutex;
 
@@ -718,7 +710,7 @@ struct ath_softc {
        u32 sc_keymax;
        DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);
        u8 sc_splitmic;
-       u8 sc_protrix;
+       atomic_t ps_usecount;
        enum ath9k_int sc_imask;
        enum PROT_MODE sc_protmode;
        enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
@@ -732,7 +724,6 @@ struct ath_softc {
        struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
        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];
        struct ath_led radio_led;
        struct ath_led assoc_led;
@@ -744,6 +735,7 @@ struct ath_softc {
 #ifdef CONFIG_ATH9K_DEBUG
        struct ath9k_debug sc_debug;
 #endif
+       struct ath_bus_ops *bus_ops;
 };
 
 int ath_reset(struct ath_softc *sc, bool retry_tx);
@@ -751,4 +743,55 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
 int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
 
+static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
+{
+       sc->bus_ops->read_cachesize(sc, csz);
+}
+
+static inline void ath_bus_cleanup(struct ath_softc *sc)
+{
+       sc->bus_ops->cleanup(sc);
+}
+
+extern struct ieee80211_ops ath9k_ops;
+
+irqreturn_t ath_isr(int irq, void *dev);
+void ath_cleanup(struct ath_softc *sc);
+int ath_attach(u16 devid, struct ath_softc *sc);
+void ath_detach(struct ath_softc *sc);
+const char *ath_mac_bb_name(u32 mac_bb_version);
+const char *ath_rf_name(u16 rf_version);
+
+#ifdef CONFIG_PCI
+int ath_pci_init(void);
+void ath_pci_exit(void);
+#else
+static inline int ath_pci_init(void) { return 0; };
+static inline void ath_pci_exit(void) {};
+#endif
+
+#ifdef CONFIG_ATHEROS_AR71XX
+int ath_ahb_init(void);
+void ath_ahb_exit(void);
+#else
+static inline int ath_ahb_init(void) { return 0; };
+static inline void ath_ahb_exit(void) {};
+#endif
+
+static inline void ath9k_ps_wakeup(struct ath_softc *sc)
+{
+       if (atomic_inc_return(&sc->ps_usecount) == 1)
+               if (sc->sc_ah->ah_power_mode !=  ATH9K_PM_AWAKE) {
+                       sc->sc_ah->ah_restore_mode = sc->sc_ah->ah_power_mode;
+                       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+               }
+}
+
+static inline void ath9k_ps_restore(struct ath_softc *sc)
+{
+       if (atomic_dec_and_test(&sc->ps_usecount))
+               if (sc->hw->conf.flags & IEEE80211_CONF_PS)
+                       ath9k_hw_setpower(sc->sc_ah,
+                                         sc->sc_ah->ah_restore_mode);
+}
 #endif /* CORE_H */
index a80ed576830f0238f07ac003a8c8c579d52c86cc..1680164b4adb2cc089763ab1aac4b2df2644ab2b 100644 (file)
@@ -222,6 +222,7 @@ static const struct file_operations fops_interrupt = {
        .owner = THIS_MODULE
 };
 
+
 int ath9k_init_debug(struct ath_softc *sc)
 {
        sc->sc_debug.debug_mask = ath9k_debug;
index acd6c5374d44c1cca46ecaca40009f9051ec11cf..5038907e74323756188539c556eff0c34b445525 100644 (file)
@@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
        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);
+       struct ath_softc *sc = ah->ah_sc;
+
+       return sc->bus_ops->eeprom_read(ah, off, data);
 }
 
 static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
@@ -2121,19 +2079,19 @@ void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
 static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
                                      struct ath9k_channel *chan)
 {
+#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
        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);
+       REG_WRITE(ah, AR_PHY_SWITCH_COM,
+                 ath9k_hw_get_eeprom_antenna_cfg(ah, chan));
 
        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
                if (AR_SREV_9280(ah)) {
@@ -2163,9 +2121,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
                             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) {
+                       if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
                                txRxAttenLocal = pModal->txRxAttenCh[i];
                                if (AR_SREV_9280_10_OR_LATER(ah)) {
                                        REG_RMW_FIELD(ah,
@@ -2332,8 +2288,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
                              pModal->thresh62);
        }
 
-       if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-           AR5416_EEP_MINOR_VER_2) {
+       if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
                REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
                              AR_PHY_TX_END_DATA_START,
                              pModal->txFrameToDataStart);
@@ -2341,15 +2296,29 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
                              pModal->txFrameToPaOn);
        }
 
-       if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-           AR5416_EEP_MINOR_VER_3) {
+       if (AR5416_VER_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 (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
+               if (IS_CHAN_HT20(chan))
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+                                       eep->baseEepHeader.dacLpMode);
+               else if (eep->baseEepHeader.dacHiPwrMode_5G)
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
+               else
+                       REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+                                       eep->baseEepHeader.dacLpMode);
+
+               REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
+                               pModal->miscBits >> 2);
+       }
+
        return true;
+#undef AR5416_VER_MASK
 }
 
 static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
@@ -2360,7 +2329,6 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *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;
@@ -2370,8 +2338,8 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
 
        txRxAttenLocal = 23;
 
-       ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
-       REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+       REG_WRITE(ah, AR_PHY_SWITCH_COM,
+                 ath9k_hw_get_eeprom_antenna_cfg(ah, chan));
 
        regChainOffset = 0;
        REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
@@ -2554,70 +2522,39 @@ bool ath9k_hw_eeprom_set_board_values(struct ath_hal *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)
+static u16 ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
+                                              struct ath9k_channel *chan)
 {
        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;
+       return pModal->antCtrlCommon & 0xFFFF;
 }
 
-static int ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
-                                   struct ath9k_channel *chan,
-                                   u8 index, u16 *config)
+static u16 ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
+                                             struct ath9k_channel *chan)
 {
        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;
+       return pModal->antCtrlCommon & 0xFFFF;
 }
 
-static int (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *,
-                                            struct ath9k_channel *,
-                                            u8, u16 *) = {
+static u16 (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *,
+                                            struct ath9k_channel *) = {
        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)
+u16 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+                                   struct ath9k_channel *chan)
 {
        struct ath_hal_5416 *ahp = AH5416(ah);
 
-       return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan,
-                                                            index, config);
+       return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan);
 }
 
 static u8 ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
@@ -2739,6 +2676,7 @@ static u32 ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
 static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
                                   enum eeprom_param param)
 {
+#define AR5416_VER_MASK (pBase->version & AR5416_EEP_VER_MINOR_MASK)
        struct ath_hal_5416 *ahp = AH5416(ah);
        struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
        struct modal_eep_header *pModal = eep->modalHeader;
@@ -2774,7 +2712,7 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
        case EEP_DB_2:
                return pModal[1].db;
        case EEP_MINOR_REV:
-               return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+               return AR5416_VER_MASK;
        case EEP_TX_MASK:
                return pBase->txMask;
        case EEP_RX_MASK:
@@ -2783,10 +2721,15 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
                return pBase->rxGainType;
        case EEP_TXGAIN_TYPE:
                return pBase->txGainType;
-
+       case EEP_DAC_HPWR_5G:
+               if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
+                       return pBase->dacHiPwrMode_5G;
+               else
+                       return 0;
        default:
                return 0;
        }
+#undef AR5416_VER_MASK
 }
 
 static u32 (*ath9k_get_eeprom[])(struct ath_hal *, enum eeprom_param) = {
@@ -2807,9 +2750,6 @@ 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
index 34474edefc97ee4ff472be082d15ebbcad7c9a20..77282345efc1748c00ed25acf90fec95d9a94532 100644 (file)
 #include "phy.h"
 #include "initvals.h"
 
-static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 };
+static int btcoex_enable;
+module_param(btcoex_enable, bool, 0);
+MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support");
 
-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;
+#define ATH9K_CLOCK_RATE_CCK           22
+#define ATH9K_CLOCK_RATE_5GHZ_OFDM     40
+#define ATH9K_CLOCK_RATE_2GHZ_OFDM     44
 
 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,
@@ -48,17 +46,18 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha
 
 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];
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+       if (!ah->ah_curchan) /* should really check for CCK instead */
+               return clks / ATH9K_CLOCK_RATE_CCK;
+       if (conf->channel->band == IEEE80211_BAND_2GHZ)
+               return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
+       return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
 }
 
 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))
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+       if (conf_is_ht40(conf))
                return ath9k_hw_mac_usec(ah, clks) / 2;
        else
                return ath9k_hw_mac_usec(ah, clks);
@@ -66,34 +65,23 @@ static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 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];
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+       if (!ah->ah_curchan) /* should really check for CCK instead */
+               return usecs *ATH9K_CLOCK_RATE_CCK;
+       if (conf->channel->band == IEEE80211_BAND_2GHZ)
+               return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
+       return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
 }
 
 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))
+       struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+       if (conf_is_ht40(conf))
                return ath9k_hw_mac_clks(ah, usecs) * 2;
        else
                return ath9k_hw_mac_clks(ah, usecs);
 }
 
-enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
-                              const struct ath9k_channel *chan)
-{
-       if (IS_CHAN_B(chan))
-               return ATH9K_MODE_11B;
-       if (IS_CHAN_G(chan))
-               return ATH9K_MODE_11G;
-
-       return ATH9K_MODE_11A;
-}
-
 bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val)
 {
        int i;
@@ -199,46 +187,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah,
        return txTime;
 }
 
-u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
-{
-       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;
-       }
-}
-
 void ath9k_hw_get_channel_centers(struct ath_hal *ah,
                                  struct ath9k_channel *chan,
                                  struct chan_centers *centers)
@@ -389,6 +337,8 @@ static const char *ath9k_hw_devname(u16 devid)
                return "Atheros 5418";
        case AR9160_DEVID_PCI:
                return "Atheros 9160";
+       case AR5416_AR9100_DEVID:
+               return "Atheros 9100";
        case AR9280_DEVID_PCI:
        case AR9280_DEVID_PCIE:
                return "Atheros 9280";
@@ -1023,7 +973,7 @@ static void ath9k_hw_init_pll(struct ath_hal *ah,
                                pll |= SM(0xb, AR_RTC_PLL_DIV);
                }
        }
-       REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
+       REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
        udelay(RTC_PLL_SETTLE_DELAY);
 
@@ -1191,6 +1141,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
        switch (devid) {
        case AR5416_DEVID_PCI:
        case AR5416_DEVID_PCIE:
+       case AR5416_AR9100_DEVID:
        case AR9160_DEVID_PCI:
        case AR9280_DEVID_PCI:
        case AR9280_DEVID_PCIE:
@@ -1279,6 +1230,7 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
 {
        int i, regWrites = 0;
        struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ieee80211_channel *channel = chan->chan;
        u32 modesIndex, freqIndex;
        int status;
 
@@ -1383,9 +1335,8 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
 
        status = ath9k_hw_set_txpower(ah, chan,
                                      ath9k_regd_get_ctl(ah, chan),
-                                     ath9k_regd_get_antenna_allowed(ah,
-                                                                    chan),
-                                     chan->maxRegTxPower * 2,
+                                     channel->max_antenna_gain * 2,
+                                     channel->max_power * 2,
                                      min((u32) MAX_RATE_POWER,
                                          (u32) ah->ah_powerLimit));
        if (status != 0) {
@@ -1562,11 +1513,11 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
                        rst_flags |= AR_RTC_RC_MAC_COLD;
        }
 
-       REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
+       REG_WRITE(ah, 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)) {
+       REG_WRITE(ah, AR_RTC_RC, 0);
+       if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
                DPRINTF(ah->ah_sc, ATH_DBG_RESET,
                        "RTC stuck in MAC reset\n");
                return false;
@@ -1588,8 +1539,8 @@ 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);
+       REG_WRITE(ah, AR_RTC_RESET, 0);
+       REG_WRITE(ah, AR_RTC_RESET, 1);
 
        if (!ath9k_hw_wait(ah,
                           AR_RTC_STATUS,
@@ -1674,34 +1625,11 @@ static bool ath9k_hw_chip_reset(struct ath_hal *ah,
        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)
 {
+       struct ieee80211_channel *channel = chan->chan;
        u32 synthDelay, qnum;
 
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
@@ -1738,8 +1666,8 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah,
 
        if (ath9k_hw_set_txpower(ah, chan,
                                 ath9k_regd_get_ctl(ah, chan),
-                                ath9k_regd_get_antenna_allowed(ah, chan),
-                                chan->maxRegTxPower * 2,
+                                channel->max_antenna_gain * 2,
+                                channel->max_power * 2,
                                 min((u32) MAX_RATE_POWER,
                                     (u32) ah->ah_powerLimit)) != 0) {
                DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
@@ -1918,9 +1846,9 @@ static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel
                if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
 
                        /* workaround for gcc bug #37014 */
-                       volatile int tmp = abs(cur_vit_mask - bin);
+                       volatile int tmp_v = abs(cur_vit_mask - bin);
 
-                       if (tmp < 75)
+                       if (tmp_v < 75)
                                mask_amt = 1;
                        else
                                mask_amt = 0;
@@ -2119,9 +2047,9 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha
                if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
 
                        /* workaround for gcc bug #37014 */
-                       volatile int tmp = abs(cur_vit_mask - bin);
+                       volatile int tmp_v = abs(cur_vit_mask - bin);
 
-                       if (tmp < 75)
+                       if (tmp_v < 75)
                                mask_amt = 1;
                        else
                                mask_amt = 0;
@@ -2222,41 +2150,31 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha
        REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
 }
 
-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)
+int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
+                   bool bChannelChange)
 {
        u32 saveLedState;
+       struct ath_softc *sc = ah->ah_sc;
        struct ath_hal_5416 *ahp = AH5416(ah);
        struct ath9k_channel *curchan = ah->ah_curchan;
        u32 saveDefAntenna;
        u32 macStaId1;
-       int ecode;
-       int i, rx_chainmask;
+       int i, rx_chainmask, r;
 
-       ahp->ah_extprotspacing = extprotspacing;
-       ahp->ah_txchainmask = txchainmask;
-       ahp->ah_rxchainmask = rxchainmask;
+       ahp->ah_extprotspacing = sc->sc_ht_extprotspacing;
+       ahp->ah_txchainmask = sc->sc_tx_chainmask;
+       ahp->ah_rxchainmask = sc->sc_rx_chainmask;
 
-       if (AR_SREV_9280(ah)) {
+       if (AR_SREV_9285(ah)) {
+               ahp->ah_txchainmask &= 0x1;
+               ahp->ah_rxchainmask &= 0x1;
+       } else if (AR_SREV_9280(ah)) {
                ahp->ah_txchainmask &= 0x3;
                ahp->ah_rxchainmask &= 0x3;
        }
 
-       if (ath9k_hw_check_chan(ah, chan) == NULL) {
-               DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-                       "invalid channel %u/0x%x; no mapping\n",
-                       chan->channel, chan->channelFlags);
-               ecode = -EINVAL;
-               goto bad;
-       }
-
-       if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
-               ecode = -EIO;
-               goto bad;
-       }
+       if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+               return -EIO;
 
        if (curchan)
                ath9k_hw_getnf(ah, curchan);
@@ -2270,10 +2188,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
            (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
                                   !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) {
 
-               if (ath9k_hw_channel_change(ah, chan, macmode)) {
+               if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
                        ath9k_hw_loadnf(ah, ah->ah_curchan);
                        ath9k_hw_start_nfcal(ah);
-                       return true;
+                       return 0;
                }
        }
 
@@ -2291,28 +2209,32 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
 
        if (!ath9k_hw_chip_reset(ah, chan)) {
                DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n");
-               ecode = -EINVAL;
-               goto bad;
+               return -EINVAL;
        }
 
-       if (AR_SREV_9280(ah)) {
-               REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-                           AR_GPIO_JTAG_DISABLE);
+       if (AR_SREV_9280_10_OR_LATER(ah))
+               REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 
-               if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) {
-                       if (IS_CHAN_5GHZ(chan))
-                               ath9k_hw_set_gpio(ah, 9, 0);
-                       else
-                               ath9k_hw_set_gpio(ah, 9, 1);
-               }
-               ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-       }
+       r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
+       if (r)
+               return r;
 
-       ecode = ath9k_hw_process_ini(ah, chan, macmode);
-       if (ecode != 0) {
-               ecode = -EINVAL;
-               goto bad;
-       }
+       /* Setup MFP options for CCMP */
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+               /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+                * frames when constructing CCMP AAD. */
+               REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+                             0xc7ff);
+               ah->sw_mgmt_crypto = false;
+       } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+               /* Disable hardware crypto for management frames */
+               REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+                           AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+               REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+                           AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+               ah->sw_mgmt_crypto = true;
+       } else
+               ah->sw_mgmt_crypto = true;
 
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
                ath9k_hw_set_delta_slope(ah, chan);
@@ -2325,8 +2247,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
        if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
                DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
                        "error setting board options\n");
-               ecode = -EIO;
-               goto bad;
+               return -EIO;
        }
 
        ath9k_hw_decrease_chain_power(ah, chan);
@@ -2354,15 +2275,11 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
        REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
 
        if (AR_SREV_9280_10_OR_LATER(ah)) {
-               if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
-                       ecode = -EIO;
-                       goto bad;
-               }
+               if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
+                       return -EIO;
        } else {
-               if (!(ath9k_hw_set_channel(ah, chan))) {
-                       ecode = -EIO;
-                       goto bad;
-               }
+               if (!(ath9k_hw_set_channel(ah, chan)))
+                       return -EIO;
        }
 
        for (i = 0; i < AR_NUM_DCU; i++)
@@ -2396,10 +2313,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
 
        ath9k_hw_init_bb(ah, chan);
 
-       if (!ath9k_hw_init_cal(ah, chan)){
-               ecode = -EIO;;
-               goto bad;
-       }
+       if (!ath9k_hw_init_cal(ah, chan))
+               return -EIO;;
 
        rx_chainmask = ahp->ah_rxchainmask;
        if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
@@ -2428,11 +2343,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
 #endif
        }
 
-       return true;
-bad:
-       if (status)
-               *status = ecode;
-       return false;
+       return 0;
 }
 
 /************************/
@@ -2658,7 +2569,7 @@ static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
                if (!AR_SREV_9100(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
 
-               REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
+               REG_CLR_BIT(ah, (AR_RTC_RESET),
                            AR_RTC_RESET_EN);
        }
 }
@@ -2734,7 +2645,7 @@ bool ath9k_hw_setpower(struct ath_hal *ah,
        int status = true, setChip = true;
 
        DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n",
-               modes[ahp->ah_powerMode], modes[mode],
+               modes[ah->ah_power_mode], modes[mode],
                setChip ? "set chip " : "");
 
        switch (mode) {
@@ -2753,7 +2664,7 @@ bool ath9k_hw_setpower(struct ath_hal *ah,
                        "Unknown power mode %u\n", mode);
                return false;
        }
-       ahp->ah_powerMode = mode;
+       ah->ah_power_mode = mode;
 
        return status;
 }
@@ -3332,7 +3243,9 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
        pCap->num_mr_retries = 4;
        pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
 
-       if (AR_SREV_9280_10_OR_LATER(ah))
+       if (AR_SREV_9285_10_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9285_NUM_GPIO;
+       else if (AR_SREV_9280_10_OR_LATER(ah))
                pCap->num_gpio_pins = AR928X_NUM_GPIO;
        else
                pCap->num_gpio_pins = AR_NUM_GPIO;
@@ -3399,6 +3312,12 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
        pCap->num_antcfg_2ghz =
                ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
 
+       if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
+               pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
+               ah->ah_btactive_gpio = 6;
+               ah->ah_wlanactive_gpio = 5;
+       }
+
        return true;
 }
 
@@ -3577,17 +3496,18 @@ void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
 
 u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
 {
+#define MS_REG_READ(x, y) \
+       (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
+
        if (gpio >= ah->ah_caps.num_gpio_pins)
                return 0xffffffff;
 
-       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 (AR_SREV_9285_10_OR_LATER(ah))
+               return MS_REG_READ(AR9285, gpio) != 0;
+       else if (AR_SREV_9280_10_OR_LATER(ah))
+               return MS_REG_READ(AR928X, gpio) != 0;
+       else
+               return MS_REG_READ(AR, gpio) != 0;
 }
 
 void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
@@ -3625,27 +3545,6 @@ void ath9k_enable_rfkill(struct ath_hal *ah)
 }
 #endif
 
-int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg)
-{
-       struct ath9k_channel *chan = ah->ah_curchan;
-       const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-       u16 ant_config;
-       u32 halNumAntConfig;
-
-       halNumAntConfig = IS_CHAN_2GHZ(chan) ?
-               pCap->num_antcfg_2ghz : pCap->num_antcfg_5ghz;
-
-       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;
-               }
-       }
-
-       return -EINVAL;
-}
-
 u32 ath9k_hw_getdefantenna(struct ath_hal *ah)
 {
        return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
@@ -3755,13 +3654,14 @@ bool ath9k_hw_disable(struct ath_hal *ah)
 bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
 {
        struct ath9k_channel *chan = ah->ah_curchan;
+       struct ieee80211_channel *channel = chan->chan;
 
        ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
 
        if (ath9k_hw_set_txpower(ah, chan,
                                 ath9k_regd_get_ctl(ah, chan),
-                                ath9k_regd_get_antenna_allowed(ah, chan),
-                                chan->maxRegTxPower * 2,
+                                channel->max_antenna_gain * 2,
+                                channel->max_power * 2,
                                 min((u32) MAX_RATE_POWER,
                                     (u32) ah->ah_powerLimit)) != 0)
                return false;
@@ -3837,6 +3737,13 @@ u64 ath9k_hw_gettsf64(struct ath_hal *ah)
        return tsf;
 }
 
+void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64)
+{
+       REG_WRITE(ah, AR_TSF_L32, 0x00000000);
+       REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+       REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+}
+
 void ath9k_hw_reset_tsf(struct ath_hal *ah)
 {
        int count;
@@ -3893,3 +3800,30 @@ void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
 
        REG_WRITE(ah, AR_2040_MODE, macmode);
 }
+
+/***************************/
+/*  Bluetooth Coexistence  */
+/***************************/
+
+void ath9k_hw_btcoex_enable(struct ath_hal *ah)
+{
+       /* connect bt_active to baseband */
+       REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+                        AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
+
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+       /* Set input mux for bt_active to gpio pin */
+       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                       AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                       ah->ah_btactive_gpio);
+
+       /* Configure the desired gpio port for input */
+       ath9k_hw_cfg_gpio_input(ah, ah->ah_btactive_gpio);
+
+       /* Configure the desired GPIO port for TX_FRAME output */
+       ath9k_hw_cfg_output(ah, ah->ah_wlanactive_gpio,
+                           AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+}
index 91d8f594af813a9d1d5100ea117c4ffef0e841d7..087c5718707b9ee2f0a6525dec48e5eb1366cb93 100644 (file)
 #include <linux/if_ether.h>
 #include <linux/delay.h>
 
+extern const struct hal_percal_data iq_cal_multi_sample;
+extern const struct hal_percal_data iq_cal_single_sample;
+extern const struct hal_percal_data adc_gain_cal_multi_sample;
+extern const struct hal_percal_data adc_gain_cal_single_sample;
+extern const struct hal_percal_data adc_dc_cal_multi_sample;
+extern const struct hal_percal_data adc_dc_cal_single_sample;
+extern const struct hal_percal_data adc_init_dc_cal;
+
 struct ar5416_desc {
        u32 ds_link;
        u32 ds_data;
@@ -418,6 +426,7 @@ struct ar5416Stats {
 #define AR5416_EEP_MINOR_VER_16      0x10
 #define AR5416_EEP_MINOR_VER_17      0x11
 #define AR5416_EEP_MINOR_VER_19      0x13
+#define AR5416_EEP_MINOR_VER_20      0x14
 
 #define AR5416_NUM_5G_CAL_PIERS         8
 #define AR5416_NUM_2G_CAL_PIERS         4
@@ -480,6 +489,7 @@ enum eeprom_param {
        EEP_RX_MASK,
        EEP_RXGAIN_TYPE,
        EEP_TXGAIN_TYPE,
+       EEP_DAC_HPWR_5G,
 };
 
 enum ar5416_rates {
@@ -518,9 +528,13 @@ struct base_eep_header {
        u8 pwdclkind;
        u8 futureBase_1[2];
        u8 rxGainType;
-       u8 futureBase_2[3];
+       u8 dacHiPwrMode_5G;
+       u8 futureBase_2;
+       u8 dacLpMode;
        u8 txGainType;
-       u8 futureBase_3[25];
+       u8 rcChainMask;
+       u8 desiredScaleCCK;
+       u8 futureBase_3[23];
 } __packed;
 
 struct base_eep_header_4k {
@@ -587,7 +601,7 @@ struct modal_eep_header {
            force_xpaon:1,
            local_bias:1,
            femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
-       u8 futureModalar9280;
+       u8 miscBits;
        u16 xpaBiasLvlFreq[3];
        u8 futureModal[6];
 
@@ -830,7 +844,6 @@ struct ath_hal_5416 {
        bool ah_chipFullSleep;
        u32 ah_atimWindow;
        u16 ah_antennaSwitchSwap;
-       enum ath9k_power_mode ah_powerMode;
        enum ath9k_ant_setting ah_diversityControl;
 
        /* Calibration */
index f3cfa16525e42d029c98be3d8d681a4bd39a2096..d49236368a1c7e866df2f273517c1230e1ea5893 100644 (file)
@@ -14,7 +14,6 @@
  * 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 },
@@ -659,10 +658,9 @@ static const u32 ar5416Addac_9100[][2] = {
     {0x0000989c,  0x00000000 },
     {0x0000989c,  0x00000000 },
     {0x0000989c,  0x00000000 },
-    {0x000098c4,  0x00000000 },
+    {0x000098cc,  0x00000000 },
 };
 
-/* ar5416 - howl ar5416_howl.ini */
 static const u32 ar5416Modes[][6] = {
     { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
     { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -1313,7 +1311,6 @@ 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 },
@@ -2549,6 +2546,8 @@ static const u32 ar9280Modes_9280_2[][6] = {
     { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
     { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
     { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+    { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
+    { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
     { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
     { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
     { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
@@ -2587,7 +2586,6 @@ static const u32 ar9280Modes_9280_2[][6] = {
     { 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 },
@@ -2719,7 +2717,6 @@ static const u32 ar9280Common_9280_2[][2] = {
     { 0x00008110, 0x00000168 },
     { 0x00008118, 0x000100aa },
     { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
     { 0x00008124, 0x00000000 },
     { 0x00008128, 0x00000000 },
     { 0x0000812c, 0x00000000 },
@@ -2735,7 +2732,6 @@ static const u32 ar9280Common_9280_2[][2] = {
     { 0x00008178, 0x00000100 },
     { 0x0000817c, 0x00000000 },
     { 0x000081c0, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
     { 0x000081ec, 0x00000000 },
     { 0x000081f0, 0x00000000 },
     { 0x000081f4, 0x00000000 },
@@ -2817,7 +2813,7 @@ static const u32 ar9280Common_9280_2[][2] = {
     { 0x00009958, 0x2108ecff },
     { 0x00009940, 0x14750604 },
     { 0x0000c95c, 0x004b6a8e },
-    { 0x00009968, 0x000003ce },
+    { 0x0000c968, 0x000003ce },
     { 0x00009970, 0x190fb515 },
     { 0x00009974, 0x00000000 },
     { 0x00009978, 0x00000001 },
@@ -2909,16 +2905,12 @@ static const u32 ar9280Common_9280_2[][2] = {
     { 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 },
@@ -2954,7 +2946,6 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
     { 0x00009844, 0x03721821, 0x03721821 },
     { 0x00009914, 0x00000898, 0x00001130 },
     { 0x00009918, 0x0000000b, 0x00000016 },
-    { 0x00009944, 0xdfbc1210, 0xdfbc1210 },
 };
 
 static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
@@ -3366,21 +3357,26 @@ static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
     { 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 },
+    { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 },
+    { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 },
+    { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 },
+    { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 },
+    { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
+    { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 },
+    { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
+    { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
+    { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 },
+    { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
+    { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
+    { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
+    { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 },
     { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
     { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+    { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
+    { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
+    { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
+    { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
+    { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
     { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
 };
 
@@ -3409,6 +3405,11 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
     { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
     { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
     { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+    { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
+    { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
+    { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
+    { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
+    { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
     { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
 };
 
@@ -4135,11 +4136,11 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
     { 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 },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
+    { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
     { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
     { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
-    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
     { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
     { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
     { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
@@ -4159,264 +4160,264 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
     { 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 },
+    { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+    { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+    { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+    { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+    { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+    { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+    { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+    { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+    { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+    { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+    { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+    { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+    { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+    { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+    { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+    { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+    { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+    { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+    { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+    { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+    { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+    { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+    { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+    { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+    { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+    { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+    { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 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 },
+    { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+    { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+    { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+    { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+    { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+    { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+    { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+    { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+    { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+    { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+    { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+    { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+    { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+    { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+    { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+    { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+    { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+    { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+    { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+    { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+    { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+    { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+    { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+    { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+    { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+    { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+    { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+    { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+    { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+    { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+    { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+    { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+    { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+    { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+    { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+    { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+    { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+    { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+    { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+    { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+    { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+    { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+    { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+    { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+    { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+    { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+    { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+    { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+    { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+    { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+    { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+    { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+    { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+    { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+    { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+    { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+    { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+    { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+    { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+    { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+    { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+    { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+    { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+    { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+    { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+    { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+    { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+    { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+    { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+    { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+    { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+    { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+    { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+    { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+    { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+    { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+    { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+    { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+    { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+    { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+    { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
+    { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+    { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+    { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+    { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+    { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+    { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+    { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+    { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+    { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+    { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+    { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+    { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+    { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+    { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+    { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+    { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+    { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+    { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+    { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+    { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+    { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+    { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+    { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+    { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+    { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+    { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+    { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+    { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+    { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+    { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+    { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+    { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+    { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+    { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+    { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+    { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+    { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+    { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+    { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+    { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+    { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+    { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+    { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+    { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+    { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+    { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+    { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+    { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+    { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+    { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+    { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+    { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+    { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+    { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+    { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+    { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+    { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+    { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+    { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+    { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
     { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
-    { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
+    { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
     { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
     { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
     { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
@@ -4679,7 +4680,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
     { 0x000099a0, 0x00000000 },
     { 0x000099a4, 0x00000001 },
     { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x2def1000 },
+    { 0x000099ac, 0x2def0400 },
     { 0x000099b0, 0x03051000 },
     { 0x000099b4, 0x00000820 },
     { 0x000099dc, 0x00000000 },
@@ -4688,7 +4689,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
     { 0x000099e8, 0x3c466478 },
     { 0x000099ec, 0x0cc80caa },
     { 0x000099f0, 0x00000000 },
-    { 0x0000a208, 0x803e6788 },
+    { 0x0000a208, 0x803e68c8 },
     { 0x0000a210, 0x4080a333 },
     { 0x0000a214, 0x00206c10 },
     { 0x0000a218, 0x009c4060 },
index af32d091dc38231b4d77ba321d56711e93297c7e..ef832a5ebbd8f2d6b86f9d473a8aa27df5e030ea 100644 (file)
@@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
 
 bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
 {
+#define ATH9K_TX_STOP_DMA_TIMEOUT      4000    /* usec */
+#define ATH9K_TIME_QUANTUM             100     /* usec */
+
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+       struct ath9k_tx_queue_info *qi;
        u32 tsfLow, j, wait;
+       u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+
+       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;
+       }
 
        REG_WRITE(ah, AR_Q_TXD, 1 << q);
 
-       for (wait = 1000; wait != 0; wait--) {
+       for (wait = wait_time; wait != 0; wait--) {
                if (ath9k_hw_numtxpending(ah, q) == 0)
                        break;
-               udelay(100);
+               udelay(ATH9K_TIME_QUANTUM);
        }
 
        if (ath9k_hw_numtxpending(ah, q)) {
@@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
                udelay(200);
                REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
 
-               wait = 1000;
-
+               wait = wait_time;
                while (ath9k_hw_numtxpending(ah, q)) {
                        if ((--wait) == 0) {
                                DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
@@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
                                        "msec after killing last frame\n");
                                break;
                        }
-                       udelay(100);
+                       udelay(ATH9K_TIME_QUANTUM);
                }
 
                REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
        }
 
        REG_WRITE(ah, AR_Q_TXD, 0);
-
        return wait != 0;
+
+#undef ATH9K_TX_STOP_DMA_TIMEOUT
+#undef ATH9K_TIME_QUANTUM
 }
 
 bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
index 727f067aca4f8a764cbf9284c287b20ad96b73e4..d8e826659c150cbee40e085dad714bd137ffe685 100644 (file)
@@ -28,72 +28,113 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
 MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static struct pci_device_id ath_pci_id_table[] __devinitdata = {
-       { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
-       { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
-       { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
-       { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
-       { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
-       { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
-       { 0 }
+/* We use the hw_value as an index into our private channel structure */
+
+#define CHAN2G(_freq, _idx)  { \
+       .center_freq = (_freq), \
+       .hw_value = (_idx), \
+       .max_power = 30, \
+}
+
+#define CHAN5G(_freq, _idx) { \
+       .band = IEEE80211_BAND_5GHZ, \
+       .center_freq = (_freq), \
+       .hw_value = (_idx), \
+       .max_power = 30, \
+}
+
+/* Some 2 GHz radios are actually tunable on 2312-2732
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+       CHAN2G(2412, 0), /* Channel 1 */
+       CHAN2G(2417, 1), /* Channel 2 */
+       CHAN2G(2422, 2), /* Channel 3 */
+       CHAN2G(2427, 3), /* Channel 4 */
+       CHAN2G(2432, 4), /* Channel 5 */
+       CHAN2G(2437, 5), /* Channel 6 */
+       CHAN2G(2442, 6), /* Channel 7 */
+       CHAN2G(2447, 7), /* Channel 8 */
+       CHAN2G(2452, 8), /* Channel 9 */
+       CHAN2G(2457, 9), /* Channel 10 */
+       CHAN2G(2462, 10), /* Channel 11 */
+       CHAN2G(2467, 11), /* Channel 12 */
+       CHAN2G(2472, 12), /* Channel 13 */
+       CHAN2G(2484, 13), /* Channel 14 */
 };
 
-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);
-}
+/* Some 5 GHz radios are actually tunable on XXXX-YYYY
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+       /* _We_ call this UNII 1 */
+       CHAN5G(5180, 14), /* Channel 36 */
+       CHAN5G(5200, 15), /* Channel 40 */
+       CHAN5G(5220, 16), /* Channel 44 */
+       CHAN5G(5240, 17), /* Channel 48 */
+       /* _We_ call this UNII 2 */
+       CHAN5G(5260, 18), /* Channel 52 */
+       CHAN5G(5280, 19), /* Channel 56 */
+       CHAN5G(5300, 20), /* Channel 60 */
+       CHAN5G(5320, 21), /* Channel 64 */
+       /* _We_ call this "Middle band" */
+       CHAN5G(5500, 22), /* Channel 100 */
+       CHAN5G(5520, 23), /* Channel 104 */
+       CHAN5G(5540, 24), /* Channel 108 */
+       CHAN5G(5560, 25), /* Channel 112 */
+       CHAN5G(5580, 26), /* Channel 116 */
+       CHAN5G(5600, 27), /* Channel 120 */
+       CHAN5G(5620, 28), /* Channel 124 */
+       CHAN5G(5640, 29), /* Channel 128 */
+       CHAN5G(5660, 30), /* Channel 132 */
+       CHAN5G(5680, 31), /* Channel 136 */
+       CHAN5G(5700, 32), /* Channel 140 */
+       /* _We_ call this UNII 3 */
+       CHAN5G(5745, 33), /* Channel 149 */
+       CHAN5G(5765, 34), /* Channel 153 */
+       CHAN5G(5785, 35), /* Channel 157 */
+       CHAN5G(5805, 36), /* Channel 161 */
+       CHAN5G(5825, 37), /* Channel 165 */
+};
 
-static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
+static void ath_cache_conf_rate(struct ath_softc *sc,
+                               struct ieee80211_conf *conf)
 {
-       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;
+       switch (conf->channel->band) {
+       case IEEE80211_BAND_2GHZ:
+               if (conf_is_ht20(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
+               else if (conf_is_ht40_minus(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
+               else if (conf_is_ht40_plus(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
+               else
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11G];
+               break;
+       case IEEE80211_BAND_5GHZ:
+               if (conf_is_ht20(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
+               else if (conf_is_ht40_minus(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
+               else if (conf_is_ht40_plus(conf))
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
+               else
+                       sc->cur_rate_table =
+                         sc->hw_rate_table[ATH9K_MODE_11A];
+               break;
+       default:
+               BUG_ON(1);
+               break;
+       }
 }
 
 static void ath_update_txpow(struct ath_softc *sc)
@@ -176,79 +217,18 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
        for (i = 0; i < maxrates; i++) {
                rate[i].bitrate = rate_table->info[i].ratekbps / 100;
                rate[i].hw_value = rate_table->info[i].ratecode;
+               if (rate_table->info[i].short_preamble) {
+                       rate[i].hw_value_short = rate_table->info[i].ratecode |
+                               rate_table->info[i].short_preamble;
+                       rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
+               }
                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
@@ -258,68 +238,66 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
 {
        struct ath_hal *ah = sc->sc_ah;
        bool fastcc = true, stopped;
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_channel *channel = hw->conf.channel;
+       int r;
 
        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);
+       ath9k_ps_wakeup(sc);
 
-               sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
-               sc->sc_flags &= ~SC_OP_FULL_RESET;
+       /*
+        * 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_drain_all_txq(sc, false);
+       stopped = ath_stoprecv(sc);
 
-               if (ath_startrecv(sc) != 0) {
-                       DPRINTF(sc, ATH_DBG_FATAL,
-                               "Unable to restart recv logic\n");
-                       return -EIO;
-               }
+       /* XXX: do not flush receive queue here. We don't want
+        * to flush data frames already in queue because of
+        * changing channel. */
 
-               ath_setcurmode(sc, ath_chan2mode(hchan));
-               ath_update_txpow(sc);
-               ath9k_hw_set_interrupts(ah, sc->sc_imask);
+       if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
+               fastcc = false;
+
+       DPRINTF(sc, ATH_DBG_CONFIG,
+               "(%u MHz) -> (%u MHz), chanwidth: %d\n",
+               sc->sc_ah->ah_curchan->channel,
+               channel->center_freq, sc->tx_chan_width);
+
+       spin_lock_bh(&sc->sc_resetlock);
+
+       r = ath9k_hw_reset(ah, hchan, fastcc);
+       if (r) {
+               DPRINTF(sc, ATH_DBG_FATAL,
+                       "Unable to reset channel (%u Mhz) "
+                       "reset status %u\n",
+                       channel->center_freq, r);
+               spin_unlock_bh(&sc->sc_resetlock);
+               return r;
+       }
+       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_cache_conf_rate(sc, &hw->conf);
+       ath_update_txpow(sc);
+       ath9k_hw_set_interrupts(ah, sc->sc_imask);
+       ath9k_ps_restore(sc);
        return 0;
 }
 
@@ -369,8 +347,7 @@ static void ath_ani_calibrate(unsigned long data)
        } 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);
+                       sc->sc_ani.sc_caldone = ath9k_hw_reset_calvalid(ah);
                        if (sc->sc_ani.sc_caldone)
                                sc->sc_ani.sc_resetcal_timer = timestamp;
                }
@@ -434,12 +411,14 @@ static void ath_ani_calibrate(unsigned long data)
 /*
  * Update tx/rx chainmask. For legacy association,
  * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration.
+ * the chainmask configuration, for bt coexistence, use
+ * the chainmask configuration even in legacy mode.
  */
 static void ath_update_chainmask(struct ath_softc *sc, int is_ht)
 {
        sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
-       if (is_ht) {
+       if (is_ht ||
+           (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
                sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
                sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
        } else {
@@ -499,7 +478,7 @@ static void ath9k_tasklet(unsigned long data)
        ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
 }
 
-static irqreturn_t ath_isr(int irq, void *dev)
+irqreturn_t ath_isr(int irq, void *dev)
 {
        struct ath_softc *sc = dev;
        struct ath_hal *ah = sc->sc_ah;
@@ -591,8 +570,10 @@ static irqreturn_t ath_isr(int irq, void *dev)
                                      ATH9K_HW_CAP_AUTOSLEEP)) {
                                        /* Clear RxAbort bit so that we can
                                         * receive frames */
+                                       ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
                                        ath9k_hw_setrxabort(ah, 0);
                                        sched = true;
+                                       sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
                                }
                        }
                }
@@ -609,19 +590,6 @@ static irqreturn_t ath_isr(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static int ath_get_channel(struct ath_softc *sc,
-                          struct ieee80211_channel *chan)
-{
-       int i;
-
-       for (i = 0; i < sc->sc_ah->ah_nchan; i++) {
-               if (sc->sc_ah->ah_channels[i].channel == chan->center_freq)
-                       return i;
-       }
-
-       return -1;
-}
-
 static u32 ath_get_extchanmode(struct ath_softc *sc,
                               struct ieee80211_channel *chan,
                               enum nl80211_channel_type channel_type)
@@ -797,7 +765,7 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc)
 }
 
 static int ath_key_config(struct ath_softc *sc,
-                         const u8 *addr,
+                         struct ieee80211_sta *sta,
                          struct ieee80211_key_conf *key)
 {
        struct ath9k_keyval hk;
@@ -818,7 +786,7 @@ static int ath_key_config(struct ath_softc *sc,
                hk.kv_type = ATH9K_CIPHER_AES_CCM;
                break;
        default:
-               return -EINVAL;
+               return -EOPNOTSUPP;
        }
 
        hk.kv_len = key->keylen;
@@ -831,7 +799,10 @@ static int ath_key_config(struct ath_softc *sc,
        } else if (key->keyidx) {
                struct ieee80211_vif *vif;
 
-               mac = addr;
+               if (WARN_ON(!sta))
+                       return -EOPNOTSUPP;
+               mac = sta->addr;
+
                vif = sc->sc_vaps[0];
                if (vif->type != NL80211_IFTYPE_AP) {
                        /* Only keyidx 0 should be used with unicast key, but
@@ -840,13 +811,16 @@ static int ath_key_config(struct ath_softc *sc,
                } else
                        return -EIO;
        } else {
-               mac = addr;
+               if (WARN_ON(!sta))
+                       return -EOPNOTSUPP;
+               mac = sta->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 */
+                       return -ENOSPC; /* no free key cache entries */
        }
 
        if (key->alg == ALG_TKIP)
@@ -886,7 +860,8 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
        }
 }
 
-static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
+static void setup_ht_cap(struct ath_softc *sc,
+                        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 */
@@ -899,10 +874,23 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
 
        ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
        ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
+
        /* 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;
+
+       switch(sc->sc_rx_chainmask) {
+       case 1:
+               ht_info->mcs.rx_mask[0] = 0xff;
+               break;
+       case 3:
+       case 5:
+       case 7:
+       default:
+               ht_info->mcs.rx_mask[0] = 0xff;
+               ht_info->mcs.rx_mask[1] = 0xff;
+               break;
+       }
+
        ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 }
 
@@ -1067,23 +1055,19 @@ fail:
 static void ath_radio_enable(struct ath_softc *sc)
 {
        struct ath_hal *ah = sc->sc_ah;
-       int status;
+       struct ieee80211_channel *channel = sc->hw->conf.channel;
+       int r;
 
+       ath9k_ps_wakeup(sc);
        spin_lock_bh(&sc->sc_resetlock);
-       if (!ath9k_hw_reset(ah, ah->ah_curchan,
-                           sc->tx_chan_width,
-                           sc->sc_tx_chainmask,
-                           sc->sc_rx_chainmask,
-                           sc->sc_ht_extprotspacing,
-                           false, &status)) {
+
+       r = ath9k_hw_reset(ah, ah->ah_curchan, false);
+
+       if (r) {
                DPRINTF(sc, ATH_DBG_FATAL,
-                       "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),
-                       ah->ah_curchan->channel,
-                       ah->ah_curchan->channelFlags, status);
+                       "Unable to reset channel %u (%uMhz) ",
+                       "reset status %u\n",
+                       channel->center_freq, r);
        }
        spin_unlock_bh(&sc->sc_resetlock);
 
@@ -1106,14 +1090,16 @@ static void ath_radio_enable(struct ath_softc *sc)
        ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
 
        ieee80211_wake_queues(sc->hw);
+       ath9k_ps_restore(sc);
 }
 
 static void ath_radio_disable(struct ath_softc *sc)
 {
        struct ath_hal *ah = sc->sc_ah;
-       int status;
-
+       struct ieee80211_channel *channel = sc->hw->conf.channel;
+       int r;
 
+       ath9k_ps_wakeup(sc);
        ieee80211_stop_queues(sc->hw);
 
        /* Disable LED */
@@ -1123,30 +1109,23 @@ static void ath_radio_disable(struct ath_softc *sc)
        /* Disable interrupts */
        ath9k_hw_set_interrupts(ah, 0);
 
-       ath_draintxq(sc, false);        /* clear pending tx frames */
+       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
        ath_stoprecv(sc);               /* turn off frame recv */
        ath_flushrecv(sc);              /* flush recv queue */
 
        spin_lock_bh(&sc->sc_resetlock);
-       if (!ath9k_hw_reset(ah, ah->ah_curchan,
-                           sc->tx_chan_width,
-                           sc->sc_tx_chainmask,
-                           sc->sc_rx_chainmask,
-                           sc->sc_ht_extprotspacing,
-                           false, &status)) {
+       r = ath9k_hw_reset(ah, ah->ah_curchan, false);
+       if (r) {
                DPRINTF(sc, ATH_DBG_FATAL,
                        "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),
-                       ah->ah_curchan->channel,
-                       ah->ah_curchan->channelFlags, status);
+                       "reset status %u\n",
+                       channel->center_freq, r);
        }
        spin_unlock_bh(&sc->sc_resetlock);
 
        ath9k_hw_phy_disable(ah);
        ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+       ath9k_ps_restore(sc);
 }
 
 static bool ath_is_rfkill_set(struct ath_softc *sc)
@@ -1274,13 +1253,7 @@ static int ath_start_rfkill_poll(struct ath_softc *sc)
                        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);
+                       ath_cleanup(sc);
                        return -EIO;
                } else {
                        sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
@@ -1291,11 +1264,21 @@ static int ath_start_rfkill_poll(struct ath_softc *sc)
 }
 #endif /* CONFIG_RFKILL */
 
-static void ath_detach(struct ath_softc *sc)
+void ath_cleanup(struct ath_softc *sc)
+{
+       ath_detach(sc);
+       free_irq(sc->irq, sc);
+       ath_bus_cleanup(sc);
+       ieee80211_free_hw(sc->hw);
+}
+
+void ath_detach(struct ath_softc *sc)
 {
        struct ieee80211_hw *hw = sc->hw;
        int i = 0;
 
+       ath9k_ps_wakeup(sc);
+
        DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
 
 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
@@ -1320,6 +1303,7 @@ static void ath_detach(struct ath_softc *sc)
 
        ath9k_hw_detach(sc->sc_ah);
        ath9k_exit_debug(sc);
+       ath9k_ps_restore(sc);
 }
 
 static int ath_init(u16 devid, struct ath_softc *sc)
@@ -1345,14 +1329,14 @@ static int ath_init(u16 devid, struct ath_softc *sc)
         * Cache line size is used to size and align various
         * structures used to communicate with the hardware.
         */
-       bus_read_cachesize(sc, &csz);
+       ath_read_cachesize(sc, &csz);
        /* XXX assert csz is non-zero */
        sc->sc_cachelsz = csz << 2;     /* convert to bytes */
 
        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);
+                       "Unable to attach hardware; HAL status %d\n", status);
                error = -ENXIO;
                goto bad;
        }
@@ -1374,16 +1358,12 @@ static int ath_init(u16 devid, struct ath_softc *sc)
        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)
+       if (ath9k_regd_init(sc->sc_ah))
                goto bad;
 
        /* default to MONITOR mode */
        sc->sc_ah->ah_opmode = NL80211_IFTYPE_MONITOR;
 
-
        /* Setup rate tables */
 
        ath_rate_attach(sc);
@@ -1515,20 +1495,25 @@ static int ath_init(u16 devid, struct ath_softc *sc)
 
        /* setup channels and rates */
 
-       sc->sbands[IEEE80211_BAND_2GHZ].channels =
-               sc->channels[IEEE80211_BAND_2GHZ];
+       sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
        sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
                sc->rates[IEEE80211_BAND_2GHZ];
        sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+       sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+               ARRAY_SIZE(ath9k_2ghz_chantable);
 
        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].channels = ath9k_5ghz_chantable;
                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].n_channels =
+                       ARRAY_SIZE(ath9k_5ghz_chantable);
        }
 
+       if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
+               ath9k_hw_btcoex_enable(sc->sc_ah);
+
        return 0;
 bad2:
        /* cleanup tx queues */
@@ -1542,7 +1527,7 @@ bad:
        return error;
 }
 
-static int ath_attach(u16 devid, struct ath_softc *sc)
+int ath_attach(u16 devid, struct ath_softc *sc)
 {
        struct ieee80211_hw *hw = sc->hw;
        int error = 0;
@@ -1560,13 +1545,21 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
                IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
                IEEE80211_HW_SIGNAL_DBM |
-               IEEE80211_HW_AMPDU_AGGREGATION;
+               IEEE80211_HW_AMPDU_AGGREGATION |
+               IEEE80211_HW_SUPPORTS_PS |
+               IEEE80211_HW_PS_NULLFUNC_STACK;
+
+       if (AR_SREV_9160_10_OR_LATER(sc->sc_ah))
+               hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
 
+       hw->wiphy->reg_notifier = ath9k_reg_notifier;
+       hw->wiphy->strict_regulatory = true;
+
        hw->queues = 4;
        hw->max_rates = 4;
        hw->max_rate_tries = ATH_11N_TXMAXTRY;
@@ -1576,9 +1569,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
        hw->rate_control_algorithm = "ath9k_rate_control";
 
        if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
-               setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+               setup_ht_cap(sc, &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);
+                       setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
        }
 
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ];
@@ -1605,11 +1598,36 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
                goto detach;
 #endif
 
+       if (ath9k_is_world_regd(sc->sc_ah)) {
+               /* Anything applied here (prior to wiphy registratoin) gets
+                * saved on the wiphy orig_* parameters */
+               const struct ieee80211_regdomain *regd =
+                       ath9k_world_regdomain(sc->sc_ah);
+               hw->wiphy->custom_regulatory = true;
+               hw->wiphy->strict_regulatory = false;
+               wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
+               ath9k_reg_apply_radar_flags(hw->wiphy);
+               ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
+       } else {
+               /* This gets applied in the case of the absense of CRDA,
+                * its our own custom world regulatory domain, similar to
+                * cfg80211's but we enable passive scanning */
+               const struct ieee80211_regdomain *regd =
+                       ath9k_default_world_regdomain();
+               wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
+               ath9k_reg_apply_radar_flags(hw->wiphy);
+               ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
+       }
+
        error = ieee80211_register_hw(hw);
 
+       if (!ath9k_is_world_regd(sc->sc_ah))
+               regulatory_hint(hw->wiphy, sc->sc_ah->alpha2);
+
        /* Initialize LED control */
        ath_init_leds(sc);
 
+
        return 0;
 detach:
        ath_detach(sc);
@@ -1619,23 +1637,19 @@ detach:
 int ath_reset(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hal *ah = sc->sc_ah;
-       int status;
-       int error = 0;
+       struct ieee80211_hw *hw = sc->hw;
+       int r;
 
        ath9k_hw_set_interrupts(ah, 0);
-       ath_draintxq(sc, retry_tx);
+       ath_drain_all_txq(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)) {
+       r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, false);
+       if (r)
                DPRINTF(sc, ATH_DBG_FATAL,
-                       "Unable to reset hardware; hal status %u\n", status);
-               error = -EIO;
-       }
+                       "Unable to reset hardware; reset status %u\n", r);
        spin_unlock_bh(&sc->sc_resetlock);
 
        if (ath_startrecv(sc) != 0)
@@ -1646,7 +1660,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
         * 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_cache_conf_rate(sc, &hw->conf);
 
        ath_update_txpow(sc);
 
@@ -1666,7 +1680,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       return error;
+       return r;
 }
 
 /*
@@ -1720,9 +1734,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
        }
 
        /* allocate descriptors */
-       dd->dd_desc = pci_alloc_consistent(sc->pdev,
-                             dd->dd_desc_len,
-                             &dd->dd_desc_paddr);
+       dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
+                                        &dd->dd_desc_paddr, GFP_ATOMIC);
        if (dd->dd_desc == NULL) {
                error = -ENOMEM;
                goto fail;
@@ -1768,8 +1781,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
        }
        return 0;
 fail2:
-       pci_free_consistent(sc->pdev,
-               dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
+       dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+                         dd->dd_desc_paddr);
 fail:
        memset(dd, 0, sizeof(*dd));
        return error;
@@ -1782,8 +1795,8 @@ 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);
+       dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+                         dd->dd_desc_paddr);
 
        INIT_LIST_HEAD(head);
        kfree(dd->dd_bufptr);
@@ -1840,6 +1853,37 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
        return qnum;
 }
 
+/* XXX: Remove me once we don't depend on ath9k_channel for all
+ * this redundant data */
+static void ath9k_update_ichannel(struct ath_softc *sc,
+                         struct ath9k_channel *ichan)
+{
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_channel *chan = hw->conf.channel;
+       struct ieee80211_conf *conf = &hw->conf;
+
+       ichan->channel = chan->center_freq;
+       ichan->chan = chan;
+
+       if (chan->band == IEEE80211_BAND_2GHZ) {
+               ichan->chanmode = CHANNEL_G;
+               ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
+       } else {
+               ichan->chanmode = CHANNEL_A;
+               ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
+       }
+
+       sc->tx_chan_width = ATH9K_HT_MACMODE_20;
+
+       if (conf_is_ht(conf)) {
+               if (conf_is_ht40(conf))
+                       sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
+
+               ichan->chanmode = ath_get_extchanmode(sc, chan,
+                                           conf->channel_type);
+       }
+}
+
 /**********************/
 /* mac80211 callbacks */
 /**********************/
@@ -1849,24 +1893,17 @@ static int ath9k_start(struct ieee80211_hw *hw)
        struct ath_softc *sc = hw->priv;
        struct ieee80211_channel *curchan = hw->conf.channel;
        struct ath9k_channel *init_channel;
-       int error = 0, pos, status;
+       int r, pos;
 
        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, "Invalid channel: %d\n", curchan->center_freq);
-               error = -EINVAL;
-               goto error;
-       }
+       pos = curchan->hw_value;
 
-       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];
+       ath9k_update_ichannel(sc, init_channel);
 
        /* Reset SERDES registers */
        ath9k_hw_configpcipowersave(sc->sc_ah, 0);
@@ -1879,17 +1916,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
         * 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)) {
+       r = ath9k_hw_reset(sc->sc_ah, init_channel, false);
+       if (r) {
                DPRINTF(sc, ATH_DBG_FATAL,
-                       "Unable to reset hardware; hal status %u "
-                       "(freq %u flags 0x%x)\n", status,
-                       init_channel->channel, init_channel->channelFlags);
-               error = -EIO;
+                       "Unable to reset hardware; reset status %u "
+                       "(freq %u MHz)\n", r,
+                       curchan->center_freq);
                spin_unlock_bh(&sc->sc_resetlock);
-               goto error;
+               return r;
        }
        spin_unlock_bh(&sc->sc_resetlock);
 
@@ -1909,8 +1943,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
        if (ath_startrecv(sc) != 0) {
                DPRINTF(sc, ATH_DBG_FATAL,
                        "Unable to start recv logic\n");
-               error = -EIO;
-               goto error;
+               return -EIO;
        }
 
        /* Setup our intr mask. */
@@ -1943,7 +1976,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
            !sc->sc_config.swBeaconProcess)
                sc->sc_imask |= ATH9K_INT_TIM;
 
-       ath_setcurmode(sc, ath_chan2mode(init_channel));
+       ath_cache_conf_rate(sc, &hw->conf);
 
        sc->sc_flags &= ~SC_OP_INVALID;
 
@@ -1954,11 +1987,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
        ieee80211_wake_queues(sc->hw);
 
 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-       error = ath_start_rfkill_poll(sc);
+       r = ath_start_rfkill_poll(sc);
 #endif
-
-error:
-       return error;
+       return r;
 }
 
 static int ath9k_tx(struct ieee80211_hw *hw,
@@ -2031,7 +2062,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
        ath9k_hw_set_interrupts(sc->sc_ah, 0);
 
        if (!(sc->sc_flags & SC_OP_INVALID)) {
-               ath_draintxq(sc, false);
+               ath_drain_all_txq(sc, false);
                ath_stoprecv(sc);
                ath9k_hw_phy_disable(sc->sc_ah);
        } else
@@ -2133,38 +2164,38 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
        struct ieee80211_conf *conf = &hw->conf;
 
        mutex_lock(&sc->mutex);
-       if (changed & (IEEE80211_CONF_CHANGE_CHANNEL |
-                      IEEE80211_CONF_CHANGE_HT)) {
+       if (changed & IEEE80211_CONF_CHANGE_PS) {
+               if (conf->flags & IEEE80211_CONF_PS) {
+                       if ((sc->sc_imask & ATH9K_INT_TIM_TIMER) == 0) {
+                               sc->sc_imask |= ATH9K_INT_TIM_TIMER;
+                               ath9k_hw_set_interrupts(sc->sc_ah,
+                                               sc->sc_imask);
+                       }
+                       ath9k_hw_setrxabort(sc->sc_ah, 1);
+                       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+               } else {
+                       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+                       ath9k_hw_setrxabort(sc->sc_ah, 0);
+                       sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
+                       if (sc->sc_imask & ATH9K_INT_TIM_TIMER) {
+                               sc->sc_imask &= ~ATH9K_INT_TIM_TIMER;
+                               ath9k_hw_set_interrupts(sc->sc_ah,
+                                               sc->sc_imask);
+                       }
+               }
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
                struct ieee80211_channel *curchan = hw->conf.channel;
-               int pos;
+               int pos = curchan->hw_value;
 
                DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
                        curchan->center_freq);
 
-               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;
-               }
-
-               sc->tx_chan_width = ATH9K_HT_MACMODE_20;
-               sc->sc_ah->ah_channels[pos].chanmode =
-                       (curchan->band == IEEE80211_BAND_2GHZ) ?
-                       CHANNEL_G : CHANNEL_A;
+               /* XXX: remove me eventualy */
+               ath9k_update_ichannel(sc, &sc->sc_ah->ah_channels[pos]);
 
-               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;
-
-                       sc->sc_ah->ah_channels[pos].chanmode =
-                               ath_get_extchanmode(sc, curchan,
-                                                   conf->ht.channel_type);
-               }
-
-               ath_update_chainmask(sc, conf->ht.enabled);
+               ath_update_chainmask(sc, conf_is_ht(conf));
 
                if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
                        DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
@@ -2228,24 +2259,27 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
                }
        }
 
-       if ((conf->changed & IEEE80211_IFCC_BEACON) &&
-           ((vif->type == NL80211_IFTYPE_ADHOC) ||
-            (vif->type == NL80211_IFTYPE_AP))) {
-               /*
-                * Allocate and setup the beacon frame.
-                *
-                * Stop any previous beacon DMA.  This may be
-                * necessary, for example, when an ibss merge
-                * causes reconfiguration; we may be called
-                * with beacon transmission active.
-                */
-               ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+       if ((vif->type == NL80211_IFTYPE_ADHOC) ||
+           (vif->type == NL80211_IFTYPE_AP)) {
+               if ((conf->changed & IEEE80211_IFCC_BEACON) ||
+                   (conf->changed & IEEE80211_IFCC_BEACON_ENABLED &&
+                    conf->enable_beacon)) {
+                       /*
+                        * Allocate and setup the beacon frame.
+                        *
+                        * Stop any previous beacon DMA.  This may be
+                        * necessary, for example, when an ibss merge
+                        * causes reconfiguration; we may be called
+                        * with beacon transmission active.
+                        */
+                       ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 
-               error = ath_beacon_alloc(sc, 0);
-               if (error != 0)
-                       return error;
+                       error = ath_beacon_alloc(sc, 0);
+                       if (error != 0)
+                               return error;
 
-               ath_beacon_sync(sc, 0);
+                       ath_beacon_sync(sc, 0);
+               }
        }
 
        /* Check for WLAN_CAPABILITY_PRIVACY ? */
@@ -2348,24 +2382,27 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
 
 static int ath9k_set_key(struct ieee80211_hw *hw,
                         enum set_key_cmd cmd,
-                        const u8 *local_addr,
-                        const u8 *addr,
+                        struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta,
                         struct ieee80211_key_conf *key)
 {
        struct ath_softc *sc = hw->priv;
        int ret = 0;
 
+       ath9k_ps_wakeup(sc);
        DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n");
 
        switch (cmd) {
        case SET_KEY:
-               ret = ath_key_config(sc, addr, key);
+               ret = ath_key_config(sc, sta, key);
                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;
+                       if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+                               key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
                        ret = 0;
                }
                break;
@@ -2376,6 +2413,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
                ret = -EINVAL;
        }
 
+       ath9k_ps_restore(sc);
        return ret;
 }
 
@@ -2423,6 +2461,14 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
        return tsf;
 }
 
+static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hal *ah = sc->sc_ah;
+
+       ath9k_hw_settsf64(ah, tsf);
+}
+
 static void ath9k_reset_tsf(struct ieee80211_hw *hw)
 {
        struct ath_softc *sc = hw->priv;
@@ -2472,7 +2518,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
        return ret;
 }
 
-static struct ieee80211_ops ath9k_ops = {
+struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
        .stop               = ath9k_stop,
@@ -2486,6 +2532,7 @@ static struct ieee80211_ops ath9k_ops = {
        .bss_info_changed   = ath9k_bss_info_changed,
        .set_key            = ath9k_set_key,
        .get_tsf            = ath9k_get_tsf,
+       .set_tsf            = ath9k_set_tsf,
        .reset_tsf          = ath9k_reset_tsf,
        .ampdu_action       = ath9k_ampdu_action,
 };
@@ -2516,7 +2563,7 @@ static struct {
 /*
  * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
  */
-static const char *
+const char *
 ath_mac_bb_name(u32 mac_bb_version)
 {
        int i;
@@ -2533,7 +2580,7 @@ ath_mac_bb_name(u32 mac_bb_version)
 /*
  * Return the RF name. "????" is returned if the RF is unknown.
  */
-static const char *
+const char *
 ath_rf_name(u16 rf_version)
 {
        int i;
@@ -2547,254 +2594,51 @@ ath_rf_name(u16 rf_version)
        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;
-       u8 csz;
-       u32 val;
-       int ret = 0;
-       struct ath_hal *ah;
-
-       if (pci_enable_device(pdev))
-               return -EIO;
-
-       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;
-       }
-
-       /*
-        * Cache line size is used to size and align various
-        * structures used to communicate with the hardware.
-        */
-       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
-       if (csz == 0) {
-               /*
-                * Linux 2.4.18 (at least) writes the cache line size
-                * register as a 16-bit wide register which is wrong.
-                * We must have this setup properly for rx buffer
-                * DMA to work so force a reasonable value here if it
-                * comes up zero.
-                */
-               csz = L1_CACHE_BYTES / sizeof(u32);
-               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
-       }
-       /*
-        * The default setting of latency timer yields poor results,
-        * set it to the value used by other systems. It may be worth
-        * tweaking this setting more.
-        */
-       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
-       pci_set_master(pdev);
-
-       /*
-        * Disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state.
-        */
-       pci_read_config_dword(pdev, 0x40, &val);
-       if ((val & 0x0000ff00) != 0)
-               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-       ret = pci_request_region(pdev, 0, "ath9k");
-       if (ret) {
-               dev_err(&pdev->dev, "PCI memory region reserve error\n");
-               ret = -ENODEV;
-               goto bad;
-       }
-
-       mem = pci_iomap(pdev, 0, 0);
-       if (!mem) {
-               printk(KERN_ERR "PCI memory map error\n") ;
-               ret = -EIO;
-               goto bad1;
-       }
-
-       hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
-       if (hw == NULL) {
-               printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
-               goto bad2;
-       }
-
-       SET_IEEE80211_DEV(hw, &pdev->dev);
-       pci_set_drvdata(pdev, hw);
-
-       sc = hw->priv;
-       sc->hw = hw;
-       sc->pdev = pdev;
-       sc->mem = mem;
-
-       if (ath_attach(id->device, sc) != 0) {
-               ret = -ENODEV;
-               goto bad3;
-       }
-
-       /* setup interrupt service routine */
-
-       if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
-               printk(KERN_ERR "%s: request_irq failed\n",
-                       wiphy_name(hw->wiphy));
-               ret = -EIO;
-               goto bad4;
-       }
-
-       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),
-              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;
-bad4:
-       ath_detach(sc);
-bad3:
-       ieee80211_free_hw(hw);
-bad2:
-       pci_iounmap(pdev, mem);
-bad1:
-       pci_release_region(pdev, 0);
-bad:
-       pci_disable_device(pdev);
-       return ret;
-}
-
-static void ath_pci_remove(struct pci_dev *pdev)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-       struct ath_softc *sc = hw->priv;
-
-       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);
-       ieee80211_free_hw(hw);
-}
-
-#ifdef CONFIG_PM
-
-static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-       struct ath_softc *sc = hw->priv;
-
-       ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-
-#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
-
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, 3);
-
-       return 0;
-}
-
-static int ath_pci_resume(struct pci_dev *pdev)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-       struct ath_softc *sc = hw->priv;
-       u32 val;
-       int err;
-
-       err = pci_enable_device(pdev);
-       if (err)
-               return err;
-       pci_restore_state(pdev);
-       /*
-        * Suspend/Resume resets the PCI configuration space, so we have to
-        * re-disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state
-        */
-       pci_read_config_dword(pdev, 0x40, &val);
-       if ((val & 0x0000ff00) != 0)
-               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-       /* Enable LED */
-       ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
-                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-       ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-       /*
-        * check the h/w rfkill state on resume
-        * and start the rfkill poll timer
-        */
-       if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-               queue_delayed_work(sc->hw->workqueue,
-                                  &sc->rf_kill.rfkill_poll, 0);
-#endif
-
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
-MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
-
-static struct pci_driver ath_pci_driver = {
-       .name       = "ath9k",
-       .id_table   = ath_pci_id_table,
-       .probe      = ath_pci_probe,
-       .remove     = ath_pci_remove,
-#ifdef CONFIG_PM
-       .suspend    = ath_pci_suspend,
-       .resume     = ath_pci_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init init_ath_pci(void)
+static int __init ath9k_init(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",
+                       "ath9k: Unable to register rate control "
+                       "algorithm: %d\n",
                        error);
-               ath_rate_control_unregister();
-               return error;
+               goto err_out;
        }
 
-       if (pci_register_driver(&ath_pci_driver) < 0) {
+       error = ath_pci_init();
+       if (error < 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;
+                       "ath9k: No PCI devices found, driver not installed.\n");
+               error = -ENODEV;
+               goto err_rate_unregister;
+       }
+
+       error = ath_ahb_init();
+       if (error < 0) {
+               error = -ENODEV;
+               goto err_pci_exit;
        }
 
        return 0;
+
+ err_pci_exit:
+       ath_pci_exit();
+
+ err_rate_unregister:
+       ath_rate_control_unregister();
+ err_out:
+       return error;
 }
-module_init(init_ath_pci);
+module_init(ath9k_init);
 
-static void __exit exit_ath_pci(void)
+static void __exit ath9k_exit(void)
 {
+       ath_ahb_exit();
+       ath_pci_exit();
        ath_rate_control_unregister();
-       pci_unregister_driver(&ath_pci_driver);
        printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
-module_exit(exit_ath_pci);
+module_exit(ath9k_exit);
diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c
new file mode 100644 (file)
index 0000000..05612bf
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * 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 <linux/nl80211.h>
+#include <linux/pci.h>
+#include "core.h"
+#include "reg.h"
+#include "hw.h"
+
+static struct pci_device_id ath_pci_id_table[] __devinitdata = {
+       { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
+       { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
+       { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
+       { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
+       { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+       { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
+       { 0 }
+};
+
+/* return bus cachesize in 4B word units */
+static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
+{
+       u8 u8tmp;
+
+       pci_read_config_byte(to_pci_dev(sc->dev), 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_pci_cleanup(struct ath_softc *sc)
+{
+       struct pci_dev *pdev = to_pci_dev(sc->dev);
+
+       pci_iounmap(pdev, sc->mem);
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
+}
+
+static bool ath_pci_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 struct ath_bus_ops ath_pci_bus_ops = {
+       .read_cachesize = ath_pci_read_cachesize,
+       .cleanup = ath_pci_cleanup,
+       .eeprom_read = ath_pci_eeprom_read,
+};
+
+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;
+       u8 csz;
+       u32 val;
+       int ret = 0;
+       struct ath_hal *ah;
+
+       if (pci_enable_device(pdev))
+               return -EIO;
+
+       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;
+       }
+
+       /*
+        * Cache line size is used to size and align various
+        * structures used to communicate with the hardware.
+        */
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+       if (csz == 0) {
+               /*
+                * Linux 2.4.18 (at least) writes the cache line size
+                * register as a 16-bit wide register which is wrong.
+                * We must have this setup properly for rx buffer
+                * DMA to work so force a reasonable value here if it
+                * comes up zero.
+                */
+               csz = L1_CACHE_BYTES / sizeof(u32);
+               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+       }
+       /*
+        * The default setting of latency timer yields poor results,
+        * set it to the value used by other systems. It may be worth
+        * tweaking this setting more.
+        */
+       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+       pci_set_master(pdev);
+
+       /*
+        * Disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
+       pci_read_config_dword(pdev, 0x40, &val);
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+       ret = pci_request_region(pdev, 0, "ath9k");
+       if (ret) {
+               dev_err(&pdev->dev, "PCI memory region reserve error\n");
+               ret = -ENODEV;
+               goto bad;
+       }
+
+       mem = pci_iomap(pdev, 0, 0);
+       if (!mem) {
+               printk(KERN_ERR "PCI memory map error\n") ;
+               ret = -EIO;
+               goto bad1;
+       }
+
+       hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
+       if (hw == NULL) {
+               printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
+               goto bad2;
+       }
+
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+       pci_set_drvdata(pdev, hw);
+
+       sc = hw->priv;
+       sc->hw = hw;
+       sc->dev = &pdev->dev;
+       sc->mem = mem;
+       sc->bus_ops = &ath_pci_bus_ops;
+
+       if (ath_attach(id->device, sc) != 0) {
+               ret = -ENODEV;
+               goto bad3;
+       }
+
+       /* setup interrupt service routine */
+
+       if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
+               printk(KERN_ERR "%s: request_irq failed\n",
+                       wiphy_name(hw->wiphy));
+               ret = -EIO;
+               goto bad4;
+       }
+
+       sc->irq = pdev->irq;
+
+       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),
+              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;
+bad4:
+       ath_detach(sc);
+bad3:
+       ieee80211_free_hw(hw);
+bad2:
+       pci_iounmap(pdev, mem);
+bad1:
+       pci_release_region(pdev, 0);
+bad:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void ath_pci_remove(struct pci_dev *pdev)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+
+       ath_cleanup(sc);
+}
+
+#ifdef CONFIG_PM
+
+static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+
+       ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+#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
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+
+static int ath_pci_resume(struct pci_dev *pdev)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ath_softc *sc = hw->priv;
+       u32 val;
+       int err;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
+       pci_restore_state(pdev);
+       /*
+        * Suspend/Resume resets the PCI configuration space, so we have to
+        * re-disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state
+        */
+       pci_read_config_dword(pdev, 0x40, &val);
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+       /* Enable LED */
+       ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
+                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+       /*
+        * check the h/w rfkill state on resume
+        * and start the rfkill poll timer
+        */
+       if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+               queue_delayed_work(sc->hw->workqueue,
+                                  &sc->rf_kill.rfkill_poll, 0);
+#endif
+
+       return 0;
+}
+
+#endif /* CONFIG_PM */
+
+MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
+
+static struct pci_driver ath_pci_driver = {
+       .name       = "ath9k",
+       .id_table   = ath_pci_id_table,
+       .probe      = ath_pci_probe,
+       .remove     = ath_pci_remove,
+#ifdef CONFIG_PM
+       .suspend    = ath_pci_suspend,
+       .resume     = ath_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+int __init ath_pci_init(void)
+{
+       return pci_register_driver(&ath_pci_driver);
+}
+
+void ath_pci_exit(void)
+{
+       pci_unregister_driver(&ath_pci_driver);
+}
index 1b71b934bb5eb07ac979cf06684d16cfc090be01..eb557add656749828c30647c62007593a6d57601 100644 (file)
 
 static struct ath_rate_table ar5416_11na_ratetable = {
        42,
-       {0},
        {
                { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
                        5400, 0x0b, 0x00, 12,
                        0, 2, 1, 0, 0, 0, 0, 0 },
-               { VALID,        VALID, WLAN_RC_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 },
                { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
@@ -158,7 +157,6 @@ static struct ath_rate_table ar5416_11na_ratetable = {
 
 static struct ath_rate_table ar5416_11ng_ratetable = {
        46,
-       {0},
        {
                { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
                        900, 0x1b, 0x00, 2,
@@ -306,7 +304,6 @@ static struct ath_rate_table ar5416_11ng_ratetable = {
 
 static struct ath_rate_table ar5416_11a_ratetable = {
        8,
-       {0},
        {
                { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
                        5400, 0x0b, 0x00, (0x80|12),
@@ -340,7 +337,6 @@ static struct ath_rate_table ar5416_11a_ratetable = {
 
 static struct ath_rate_table ar5416_11g_ratetable = {
        12,
-       {0},
        {
                { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
                        900, 0x1b, 0x00, 2,
@@ -386,7 +382,6 @@ static struct ath_rate_table ar5416_11g_ratetable = {
 
 static struct ath_rate_table ar5416_11b_ratetable = {
        4,
-       {0},
        {
                { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
                        900, 0x1b,  0x00, (0x80|2),
@@ -875,7 +870,7 @@ static void ath_rc_ratefind(struct ath_softc *sc,
         * above conditions.
         */
        if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
-           (sc->hw->conf.ht.enabled)) {
+           (conf_is_ht(&sc->hw->conf))) {
                u8 dot11rate = rate_table->info[rix].dot11rate;
                u8 phy = rate_table->info[rix].phy;
                if (i == 4 &&
@@ -1363,9 +1358,13 @@ static void ath_rc_init(struct ath_softc *sc,
        }
 
        if (sta->ht_cap.ht_supported) {
-               ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
+               ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG;
+               if (sc->sc_ah->ah_caps.tx_chainmask != 1)
+                       ath_rc_priv->ht_cap |= 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;
+               if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
+                       ath_rc_priv->ht_cap |= WLAN_RC_SGI_FLAG;
        }
 
        /* Initial rate table size. Will change depending
@@ -1511,7 +1510,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
                        tx_info, &is_probe, false);
 
        /* Check if aggregation has to be enabled for this tid */
-       if (hw->conf.ht.enabled) {
+       if (conf_is_ht(&hw->conf)) {
                if (ieee80211_is_data_qos(fc)) {
                        u8 *qc, tid;
                        struct ath_node *an;
@@ -1607,16 +1606,8 @@ static void ath_setup_rate_table(struct ath_softc *sc,
 {
        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,
index 97c60d12e8aa51cbfc7e34cff14869a556888908..a987cb9e74e257f55794d6da93002f48223560b5 100644 (file)
@@ -90,7 +90,6 @@ struct ath_softc;
  */
 struct ath_rate_table {
        int rate_cnt;
-       u8 rateCodeToIndex[256];
        struct {
                int valid;
                int valid_single_stream;
index 462e08c3d09dc4cf18693f4e39c383a7dc34c580..8da08f9b463ca6c583765c6828a59f64c785244f 100644 (file)
@@ -291,15 +291,15 @@ 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,
+                       bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
                                                         sc->rx.bufsize,
-                                                        PCI_DMA_FROMDEVICE);
-                       if (unlikely(pci_dma_mapping_error(sc->pdev,
+                                                        DMA_FROM_DEVICE);
+                       if (unlikely(dma_mapping_error(sc->dev,
                                  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");
+                                       "dma_mapping_error() on RX init\n");
                                error = -ENOMEM;
                                break;
                        }
@@ -524,9 +524,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
                 * 1. accessing the frame
                 * 2. requeueing the same buffer to h/w
                 */
-               pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
+               dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
                                sc->rx.bufsize,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
 
                /*
                 * If we're asked to flush receive queue, directly
@@ -557,9 +557,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
                        goto requeue;
 
                /* Unmap the frame */
-               pci_unmap_single(sc->pdev, bf->bf_buf_addr,
+               dma_unmap_single(sc->dev, bf->bf_buf_addr,
                                 sc->rx.bufsize,
-                                PCI_DMA_FROMDEVICE);
+                                DMA_FROM_DEVICE);
 
                skb_put(skb, ds->ds_rxstat.rs_datalen);
                skb->protocol = cpu_to_be16(ETH_P_CONTROL);
@@ -593,21 +593,27 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
                        if (test_bit(keyix, sc->sc_keymap))
                                rx_status.flag |= RX_FLAG_DECRYPTED;
                }
+               if (ah->sw_mgmt_crypto &&
+                   (rx_status.flag & RX_FLAG_DECRYPTED) &&
+                   ieee80211_is_mgmt(hdr->frame_control)) {
+                       /* Use software decrypt for management frames. */
+                       rx_status.flag &= ~RX_FLAG_DECRYPTED;
+               }
 
                /* Send the frame to mac80211 */
                __ieee80211_rx(sc->hw, skb, &rx_status);
 
                /* 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,
+               bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
                                         sc->rx.bufsize,
-                                        PCI_DMA_FROMDEVICE);
-               if (unlikely(pci_dma_mapping_error(sc->pdev,
+                                        DMA_FROM_DEVICE);
+               if (unlikely(dma_mapping_error(sc->dev,
                          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");
+                               "dma_mapping_error() on RX\n");
                        break;
                }
                bf->bf_dmacontext = bf->bf_buf_addr;
@@ -622,6 +628,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
                } else {
                        sc->rx.rxotherant = 0;
                }
+
+               if (ieee80211_is_beacon(hdr->frame_control) &&
+                               (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) {
+                       sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
+                       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+               }
 requeue:
                list_move_tail(&bf->list, &sc->rx.rxbuf);
                ath_rx_buf_link(sc, bf);
index 9fedb4911bc30b859ca87d907bdb8357c7a80178..150eda56055a6273309d512d376f24eea569fb2d 100644 (file)
@@ -875,12 +875,15 @@ enum {
 
 #define AR_NUM_GPIO                              14
 #define AR928X_NUM_GPIO                          10
+#define AR9285_NUM_GPIO                          12
 
 #define AR_GPIO_IN_OUT                           0x4048
 #define AR_GPIO_IN_VAL                           0x0FFFC000
 #define AR_GPIO_IN_VAL_S                         14
 #define AR928X_GPIO_IN_VAL                       0x000FFC00
 #define AR928X_GPIO_IN_VAL_S                     10
+#define AR9285_GPIO_IN_VAL                       0x00FFF000
+#define AR9285_GPIO_IN_VAL_S                     12
 
 #define AR_GPIO_OE_OUT                           0x404c
 #define AR_GPIO_OE_OUT_DRV                       0x3
@@ -894,14 +897,24 @@ enum {
 #define AR_GPIO_INTR_POL_VAL_S                   0
 
 #define AR_GPIO_INPUT_EN_VAL                     0x4054
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S      3
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF       0x00000010
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
 #define AR_GPIO_JTAG_DISABLE                     0x00020000
 
 #define AR_GPIO_INPUT_MUX1                       0x4058
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16
 
 #define AR_GPIO_INPUT_MUX2                       0x405c
 #define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f
@@ -940,7 +953,7 @@ enum {
 
 #define AR_RTC_BASE             0x00020000
 #define AR_RTC_RC \
-       (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
 #define AR_RTC_RC_M            0x00000003
 #define AR_RTC_RC_MAC_WARM      0x00000001
 #define AR_RTC_RC_MAC_COLD      0x00000002
@@ -948,7 +961,7 @@ enum {
 #define AR_RTC_RC_WARM_RESET    0x00000008
 
 #define AR_RTC_PLL_CONTROL \
-       (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014
+       ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
 
 #define AR_RTC_PLL_DIV          0x0000001f
 #define AR_RTC_PLL_DIV_S        0
@@ -1021,6 +1034,10 @@ enum {
 #define AR_AN_RF5G1_CH1_DB5     0x00380000
 #define AR_AN_RF5G1_CH1_DB5_S   19
 
+#define AR_AN_TOP1                  0x7890
+#define AR_AN_TOP1_DACIPMODE       0x00040000
+#define AR_AN_TOP1_DACIPMODE_S     18
+
 #define AR_AN_TOP2                  0x7894
 #define AR_AN_TOP2_XPABIAS_LVL      0xC0000000
 #define AR_AN_TOP2_XPABIAS_LVL_S    30
@@ -1236,6 +1253,8 @@ enum {
 
 #define AR_AES_MUTE_MASK1       0x8060
 #define AR_AES_MUTE_MASK1_SEQ   0x0000FFFF
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
 
 #define AR_GATED_CLKS       0x8064
 #define AR_GATED_CLKS_TX    0x00000002
@@ -1460,6 +1479,10 @@ enum {
 #define AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
 #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE   0x380
 
+#define AR_PCU_MISC_MODE2               0x8344
+#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE           0x00000002
+#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT   0x00000004
+
 #define AR_KEYTABLE_0           0x8800
 #define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
 #define AR_KEY_CACHE_SIZE       128
index 64043e99facff0faef1838b01ca214c2d2f7c9b8..ec88f78743e9ac06a83c52bfbd3a2aadfe6a6553 100644 (file)
 #include "regd.h"
 #include "regd_common.h"
 
-static int ath9k_regd_chansort(const void *a, const void *b)
-{
-       const struct ath9k_channel *ca = a;
-       const struct ath9k_channel *cb = b;
-
-       return (ca->channel == cb->channel) ?
-           (ca->channelFlags & CHAN_FLAGS) -
-           (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel;
-}
+/*
+ * This is a set of common rules used by our world regulatory domains.
+ * We have 12 world regulatory domains. To save space we consolidate
+ * the regulatory domains in 5 structures by frequency and change
+ * the flags on our reg_notifier() on a case by case basis.
+ */
 
-static void
-ath9k_regd_sort(void *a, u32 n, u32 size, ath_hal_cmp_t *cmp)
-{
-       u8 *aa = a;
-       u8 *ai, *t;
-
-       for (ai = aa + size; --n >= 1; ai += size)
-               for (t = ai; t > aa; t -= size) {
-                       u8 *u = t - size;
-                       if (cmp(u, t) <= 0)
-                               break;
-                       swap_array(u, t, size);
-               }
-}
+/* Only these channels all allow active scan on all world regulatory domains */
+#define ATH9K_2GHZ_CH01_11     REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+
+/* We enable active scan on these a case by case basis by regulatory domain */
+#define ATH9K_2GHZ_CH12_13     REG_RULE(2467-10, 2472+10, 40, 0, 20,\
+                                       NL80211_RRF_PASSIVE_SCAN)
+#define ATH9K_2GHZ_CH14                REG_RULE(2484-10, 2484+10, 40, 0, 20,\
+                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+
+/* We allow IBSS on these on a case by case basis by regulatory domain */
+#define ATH9K_5GHZ_5150_5350   REG_RULE(5150-10, 5350+10, 40, 0, 30,\
+                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5470_5850   REG_RULE(5470-10, 5850+10, 40, 0, 30,\
+                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5725_5850   REG_RULE(5725-10, 5850+10, 40, 0, 30,\
+                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+#define ATH9K_2GHZ_ALL         ATH9K_2GHZ_CH01_11, \
+                               ATH9K_2GHZ_CH12_13, \
+                               ATH9K_2GHZ_CH14
+
+#define ATH9K_5GHZ_ALL         ATH9K_5GHZ_5150_5350, \
+                               ATH9K_5GHZ_5470_5850
+/* This one skips what we call "mid band" */
+#define ATH9K_5GHZ_NO_MIDBAND  ATH9K_5GHZ_5150_5350, \
+                               ATH9K_5GHZ_5725_5850
+
+/* Can be used for:
+ * 0x60, 0x61, 0x62 */
+static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
+       .n_reg_rules = 5,
+       .alpha2 =  "99",
+       .reg_rules = {
+               ATH9K_2GHZ_ALL,
+               ATH9K_5GHZ_ALL,
+       }
+};
+
+/* Can be used by 0x63 and 0x65 */
+static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
+       .n_reg_rules = 4,
+       .alpha2 =  "99",
+       .reg_rules = {
+               ATH9K_2GHZ_CH01_11,
+               ATH9K_2GHZ_CH12_13,
+               ATH9K_5GHZ_NO_MIDBAND,
+       }
+};
+
+/* Can be used by 0x64 only */
+static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
+       .n_reg_rules = 3,
+       .alpha2 =  "99",
+       .reg_rules = {
+               ATH9K_2GHZ_CH01_11,
+               ATH9K_5GHZ_NO_MIDBAND,
+       }
+};
+
+/* Can be used by 0x66 and 0x69 */
+static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
+       .n_reg_rules = 3,
+       .alpha2 =  "99",
+       .reg_rules = {
+               ATH9K_2GHZ_CH01_11,
+               ATH9K_5GHZ_ALL,
+       }
+};
+
+/* Can be used by 0x67, 0x6A and 0x68 */
+static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = {
+       .n_reg_rules = 4,
+       .alpha2 =  "99",
+       .reg_rules = {
+               ATH9K_2GHZ_CH01_11,
+               ATH9K_2GHZ_CH12_13,
+               ATH9K_5GHZ_ALL,
+       }
+};
 
 static u16 ath9k_regd_get_eepromRD(struct ath_hal *ah)
 {
        return ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG;
 }
 
-static bool ath9k_regd_is_chan_bm_zero(u64 *bitmask)
+u16 ath9k_regd_get_rd(struct ath_hal *ah)
 {
-       int i;
+       return ath9k_regd_get_eepromRD(ah);
+}
 
-       for (i = 0; i < BMLEN; i++) {
-               if (bitmask[i] != 0)
-                       return false;
-       }
-       return true;
+bool ath9k_is_world_regd(struct ath_hal *ah)
+{
+       return isWwrSKU(ah);
 }
 
-static bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
+const struct ieee80211_regdomain *ath9k_default_world_regdomain(void)
 {
-       u16 rd = ath9k_regd_get_eepromRD(ah);
-       int i;
+       /* this is the most restrictive */
+       return &ath9k_world_regdom_64;
+}
 
-       if (rd & COUNTRY_ERD_FLAG) {
-               u16 cc = rd & ~COUNTRY_ERD_FLAG;
-               for (i = 0; i < ARRAY_SIZE(allCountries); i++)
-                       if (allCountries[i].countryCode == cc)
-                               return true;
-       } else {
-               for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
-                       if (regDomainPairs[i].regDmnEnum == rd)
-                               return true;
+const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah)
+{
+       switch (ah->regpair->regDmnEnum) {
+       case 0x60:
+       case 0x61:
+       case 0x62:
+               return &ath9k_world_regdom_60_61_62;
+       case 0x63:
+       case 0x65:
+               return &ath9k_world_regdom_63_65;
+       case 0x64:
+               return &ath9k_world_regdom_64;
+       case 0x66:
+       case 0x69:
+               return &ath9k_world_regdom_66_69;
+       case 0x67:
+       case 0x68:
+       case 0x6A:
+               return &ath9k_world_regdom_67_68_6A;
+       default:
+               WARN_ON(1);
+               return ath9k_default_world_regdomain();
        }
-       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                "invalid regulatory domain/country code 0x%x\n", rd);
-       return false;
 }
 
-static bool ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah)
+/* Enable adhoc on 5 GHz if allowed by 11d */
+static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy,
+                                            enum reg_set_by setby)
 {
-       u32 regcap;
-
-       regcap = ah->ah_caps.reg_cap;
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct ath_softc *sc = hw->priv;
+       struct ieee80211_supported_band *sband;
+       const struct ieee80211_reg_rule *reg_rule;
+       struct ieee80211_channel *ch;
+       unsigned int i;
+       u32 bandwidth = 0;
+       int r;
+
+       if (setby != REGDOM_SET_BY_COUNTRY_IE)
+               return;
+       if (!test_bit(ATH9K_MODE_11A,
+           sc->sc_ah->ah_caps.wireless_modes))
+               return;
 
-       if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND)
-               return true;
-       else
-               return false;
+       sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+       for (i = 0; i < sband->n_channels; i++) {
+               ch = &sband->channels[i];
+               r = freq_reg_info(wiphy, ch->center_freq,
+                       &bandwidth, &reg_rule);
+               if (r)
+                       continue;
+               /* If 11d had a rule for this channel ensure we enable adhoc
+                * if it allows us to use it. Note that we would have disabled
+                * it by applying our static world regdomain by default during
+                * probe */
+               if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
+                       ch->flags &= ~NL80211_RRF_NO_IBSS;
+       }
 }
 
-static bool ath9k_regd_is_ccode_valid(struct ath_hal *ah,
-                                     u16 cc)
+/* Allows active scan scan on Ch 12 and 13 */
+static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy,
+                                             enum reg_set_by setby)
 {
-       u16 rd;
-       int i;
-
-       if (cc == CTRY_DEFAULT)
-               return true;
-       if (cc == CTRY_DEBUG)
-               return true;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *ch;
+       const struct ieee80211_reg_rule *reg_rule;
+       u32 bandwidth = 0;
+       int r;
+
+       /* Force passive scan on Channels 12-13 */
+       sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+
+       /* If no country IE has been received always enable active scan
+        * on these channels */
+       if (setby != REGDOM_SET_BY_COUNTRY_IE) {
+               ch = &sband->channels[11]; /* CH 12 */
+               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               ch = &sband->channels[12]; /* CH 13 */
+               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               return;
+       }
 
-       rd = ath9k_regd_get_eepromRD(ah);
-       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "EEPROM regdomain 0x%x\n", rd);
+       /* If a country IE has been recieved check its rule for this
+        * channel first before enabling active scan. The passive scan
+        * would have been enforced by the initial probe processing on
+        * our custom regulatory domain. */
 
-       if (rd & COUNTRY_ERD_FLAG) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "EEPROM setting is country code %u\n",
-                       rd & ~COUNTRY_ERD_FLAG);
-               return cc == (rd & ~COUNTRY_ERD_FLAG);
+       ch = &sband->channels[11]; /* CH 12 */
+       r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
+       if (!r) {
+               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
        }
 
-       for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
-               if (cc == allCountries[i].countryCode) {
-#ifdef AH_SUPPORT_11D
-                       if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)
-                               return true;
-#endif
-                       if (allCountries[i].regDmnEnum == rd ||
-                           rd == DEBUG_REG_DMN || rd == NO_ENUMRD)
-                               return true;
-               }
+       ch = &sband->channels[12]; /* CH 13 */
+       r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
+       if (!r) {
+               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
        }
-       return false;
 }
 
-static void
-ath9k_regd_get_wmodes_nreg(struct ath_hal *ah,
-                          struct country_code_to_enum_rd *country,
-                          struct regDomain *rd5GHz,
-                          unsigned long *modes_allowed)
+/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
+void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
 {
-       bitmap_copy(modes_allowed, ah->ah_caps.wireless_modes, ATH9K_MODE_MAX);
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *ch;
+       unsigned int i;
 
-       if (test_bit(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) &&
-           (!country->allow11g))
-               clear_bit(ATH9K_MODE_11G, modes_allowed);
+       if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+               return;
 
-       if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) &&
-           (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a)))
-               clear_bit(ATH9K_MODE_11A, modes_allowed);
+       sband = wiphy->bands[IEEE80211_BAND_5GHZ];
 
-       if (test_bit(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes)
-           && (!country->allow11ng20))
-               clear_bit(ATH9K_MODE_11NG_HT20, modes_allowed);
+       for (i = 0; i < sband->n_channels; i++) {
+               ch = &sband->channels[i];
+               if (ch->center_freq < 5260)
+                       continue;
+               if (ch->center_freq > 5700)
+                       continue;
+               /* We always enable radar detection/DFS on this
+                * frequency range. Additionally we also apply on
+                * this frequency range:
+                * - If STA mode does not yet have DFS supports disable
+                *   active scanning
+                * - If adhoc mode does not support DFS yet then
+                *   disable adhoc in the frequency.
+                * - If AP mode does not yet support radar detection/DFS
+                *   do not allow AP mode
+                */
+               if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+                       ch->flags |= IEEE80211_CHAN_RADAR |
+                                    IEEE80211_CHAN_NO_IBSS |
+                                    IEEE80211_CHAN_PASSIVE_SCAN;
+       }
+}
 
-       if (test_bit(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes)
-           && (!country->allow11na20))
-               clear_bit(ATH9K_MODE_11NA_HT20, modes_allowed);
+void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby)
+{
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct ath_softc *sc = hw->priv;
+       struct ath_hal *ah = sc->sc_ah;
+
+       switch (ah->regpair->regDmnEnum) {
+       case 0x60:
+       case 0x63:
+       case 0x66:
+       case 0x67:
+               ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby);
+               break;
+       case 0x68:
+               ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby);
+               ath9k_reg_apply_active_scan_flags(wiphy, setby);
+               break;
+       }
+       return;
+}
 
-       if (test_bit(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) &&
-           (!country->allow11ng40))
-               clear_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed);
+int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+{
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct ath_softc *sc = hw->priv;
 
-       if (test_bit(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) &&
-           (!country->allow11ng40))
-               clear_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed);
+       /* We always apply this */
+       ath9k_reg_apply_radar_flags(wiphy);
 
-       if (test_bit(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) &&
-           (!country->allow11na40))
-               clear_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed);
+       switch (request->initiator) {
+       case REGDOM_SET_BY_DRIVER:
+       case REGDOM_SET_BY_INIT:
+       case REGDOM_SET_BY_CORE:
+       case REGDOM_SET_BY_USER:
+               break;
+       case REGDOM_SET_BY_COUNTRY_IE:
+               if (ath9k_is_world_regd(sc->sc_ah))
+                       ath9k_reg_apply_world_flags(wiphy, request->initiator);
+               break;
+       }
 
-       if (test_bit(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) &&
-           (!country->allow11na40))
-               clear_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed);
+       return 0;
 }
 
-bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah)
+bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
 {
-       u16 rd;
-
-       rd = ath9k_regd_get_eepromRD(ah);
+       u16 rd = ath9k_regd_get_eepromRD(ah);
+       int i;
 
-       switch (rd) {
-       case FCC4_FCCA:
-       case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG):
-               return true;
-       case DEBUG_REG_DMN:
-       case NO_ENUMRD:
-               if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49)
-                       return true;
-               break;
+       if (rd & COUNTRY_ERD_FLAG) {
+               /* EEPROM value is a country code */
+               u16 cc = rd & ~COUNTRY_ERD_FLAG;
+               for (i = 0; i < ARRAY_SIZE(allCountries); i++)
+                       if (allCountries[i].countryCode == cc)
+                               return true;
+       } else {
+               /* EEPROM value is a regpair value */
+               for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
+                       if (regDomainPairs[i].regDmnEnum == rd)
+                               return true;
        }
+       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
+                "invalid regulatory domain/country code 0x%x\n", rd);
        return false;
 }
 
+/* EEPROM country code to regpair mapping */
 static struct country_code_to_enum_rd*
 ath9k_regd_find_country(u16 countryCode)
 {
@@ -201,10 +350,23 @@ ath9k_regd_find_country(u16 countryCode)
        return NULL;
 }
 
+/* EEPROM rd code to regpair mapping */
+static struct country_code_to_enum_rd*
+ath9k_regd_find_country_by_rd(int regdmn)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+               if (allCountries[i].regDmnEnum == regdmn)
+                       return &allCountries[i];
+       }
+       return NULL;
+}
+
+/* Returns the map of the EEPROM set RD to a country code */
 static u16 ath9k_regd_get_default_country(struct ath_hal *ah)
 {
        u16 rd;
-       int i;
 
        rd = ath9k_regd_get_eepromRD(ah);
        if (rd & COUNTRY_ERD_FLAG) {
@@ -216,798 +378,104 @@ static u16 ath9k_regd_get_default_country(struct ath_hal *ah)
                        return cc;
        }
 
-       for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
-               if (regDomainPairs[i].regDmnEnum == rd) {
-                       if (regDomainPairs[i].singleCC != 0)
-                               return regDomainPairs[i].singleCC;
-                       else
-                               i = ARRAY_SIZE(regDomainPairs);
-               }
        return CTRY_DEFAULT;
 }
 
-static bool ath9k_regd_is_valid_reg_domain(int regDmn,
-                                          struct regDomain *rd)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(regDomains); i++) {
-               if (regDomains[i].regDmnEnum == regDmn) {
-                       if (rd != NULL) {
-                               memcpy(rd, &regDomains[i],
-                                      sizeof(struct regDomain));
-                       }
-                       return true;
-               }
-       }
-       return false;
-}
-
-static bool ath9k_regd_is_valid_reg_domainPair(int regDmnPair)
+static struct reg_dmn_pair_mapping*
+ath9k_get_regpair(int regdmn)
 {
        int i;
 
-       if (regDmnPair == NO_ENUMRD)
-               return false;
+       if (regdmn == NO_ENUMRD)
+               return NULL;
        for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
-               if (regDomainPairs[i].regDmnEnum == regDmnPair)
-                       return true;
+               if (regDomainPairs[i].regDmnEnum == regdmn)
+                       return &regDomainPairs[i];
        }
-       return false;
-}
-
-static bool
-ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
-                              u16 channelFlag, struct regDomain *rd)
-{
-       int i, found;
-       u64 flags = NO_REQ;
-       struct reg_dmn_pair_mapping *regPair = NULL;
-       int regOrg;
-
-       regOrg = regDmn;
-       if (regDmn == CTRY_DEFAULT) {
-               u16 rdnum;
-               rdnum = ath9k_regd_get_eepromRD(ah);
-
-               if (!(rdnum & COUNTRY_ERD_FLAG)) {
-                       if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) ||
-                           ath9k_regd_is_valid_reg_domainPair(rdnum)) {
-                               regDmn = rdnum;
-                       }
-               }
-       }
-
-       if ((regDmn & MULTI_DOMAIN_MASK) == 0) {
-               for (i = 0, found = 0;
-                    (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) {
-                       if (regDomainPairs[i].regDmnEnum == regDmn) {
-                               regPair = &regDomainPairs[i];
-                               found = 1;
-                       }
-               }
-               if (!found) {
-                       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                               "Failed to find reg domain pair %u\n", regDmn);
-                       return false;
-               }
-               if (!(channelFlag & CHANNEL_2GHZ)) {
-                       regDmn = regPair->regDmn5GHz;
-                       flags = regPair->flags5GHz;
-               }
-               if (channelFlag & CHANNEL_2GHZ) {
-                       regDmn = regPair->regDmn2GHz;
-                       flags = regPair->flags2GHz;
-               }
-       }
-
-       found = ath9k_regd_is_valid_reg_domain(regDmn, rd);
-       if (!found) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Failed to find unitary reg domain %u\n", regDmn);
-               return false;
-       } else {
-               rd->pscan &= regPair->pscanMask;
-               if (((regOrg & MULTI_DOMAIN_MASK) == 0) &&
-                   (flags != NO_REQ)) {
-                       rd->flags = flags;
-               }
-
-               rd->flags &= (channelFlag & CHANNEL_2GHZ) ?
-                   REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK;
-               return true;
-       }
-}
-
-static bool ath9k_regd_is_bit_set(int bit, u64 *bitmask)
-{
-       int byteOffset, bitnum;
-       u64 val;
-
-       byteOffset = bit / 64;
-       bitnum = bit - byteOffset * 64;
-       val = ((u64) 1) << bitnum;
-       if (bitmask[byteOffset] & val)
-               return true;
-       else
-               return false;
-}
-
-static void
-ath9k_regd_add_reg_classid(u8 *regclassids, u32 maxregids,
-                          u32 *nregids, u8 regclassid)
-{
-       int i;
-
-       if (regclassid == 0)
-               return;
-
-       for (i = 0; i < maxregids; i++) {
-               if (regclassids[i] == regclassid)
-                       return;
-               if (regclassids[i] == 0)
-                       break;
-       }
-
-       if (i == maxregids)
-               return;
-       else {
-               regclassids[i] = regclassid;
-               *nregids += 1;
-       }
-
-       return;
-}
-
-static bool
-ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah,
-                                  enum reg_ext_bitmap bit)
-{
-       return (ah->ah_currentRDExt & (1 << bit)) ? true : false;
-}
-
-#ifdef ATH_NF_PER_CHAN
-
-static void ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans,
-                                     int nchans)
-{
-       int i, j, next;
-
-       for (next = 0; next < nchans; next++) {
-               for (i = 0; i < NUM_NF_READINGS; i++) {
-                       ichans[next].nfCalHist[i].currIndex = 0;
-                       ichans[next].nfCalHist[i].privNF =
-                           AR_PHY_CCA_MAX_GOOD_VALUE;
-                       ichans[next].nfCalHist[i].invalidNFcount =
-                           AR_PHY_CCA_FILTERWINDOW_LENGTH;
-                       for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
-                               ichans[next].nfCalHist[i].nfCalBuffer[j] =
-                                   AR_PHY_CCA_MAX_GOOD_VALUE;
-                       }
-               }
-       }
-}
-#endif
-
-static int ath9k_regd_is_chan_present(struct ath_hal *ah,
-                                     u16 c)
-{
-       int i;
-
-       for (i = 0; i < 150; i++) {
-               if (!ah->ah_channels[i].channel)
-                       return -1;
-               else if (ah->ah_channels[i].channel == c)
-                       return i;
-       }
-
-       return -1;
-}
-
-static bool
-ath9k_regd_add_channel(struct ath_hal *ah,
-                      u16 c,
-                      u16 c_lo,
-                      u16 c_hi,
-                      u16 maxChan,
-                      u8 ctl,
-                      int pos,
-                      struct regDomain rd5GHz,
-                      struct RegDmnFreqBand *fband,
-                      struct regDomain *rd,
-                      const struct cmode *cm,
-                      struct ath9k_channel *ichans,
-                      bool enableExtendedChannels)
-{
-       struct ath9k_channel *chan;
-       int ret;
-       u32 channelFlags = 0;
-       u8 privFlags = 0;
-
-       if (!(c_lo <= c && c <= c_hi)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "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,
-                       "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,
-                       "Skipping %u quarter rate channel\n", c);
-               return false;
-       }
-
-       if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "c %u > maxChan %u\n", c, maxChan);
-               return false;
-       }
-
-       if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Skipping ecm channel\n");
-               return false;
-       }
-
-       if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == NL80211_IFTYPE_AP)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Skipping HOSTAP channel\n");
-               return false;
-       }
-
-       if (IS_HT40_MODE(cm->mode) &&
-           !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) &&
-           (fband->useDfs) &&
-           (rd->conformanceTestLimit != MKK)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n");
-               return false;
-       }
-
-       if (IS_HT40_MODE(cm->mode) &&
-           !(ath9k_regd_get_eeprom_reg_ext_bits(ah,
-                                                REG_EXT_JAPAN_NONDFS_HT40)) &&
-           !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Skipping HT40 channel (en_jap_ht40 = 0)\n");
-               return false;
-       }
-
-       if (IS_HT40_MODE(cm->mode) &&
-           !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) &&
-           (fband->useDfs) &&
-           (rd->conformanceTestLimit == MKK)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n");
-               return false;
-       }
-
-       /* Calculate channel flags */
-
-       channelFlags = cm->flags;
-
-       switch (fband->channelBW) {
-       case CHANNEL_HALF_BW:
-               channelFlags |= CHANNEL_HALF;
-               break;
-       case CHANNEL_QUARTER_BW:
-               channelFlags |= CHANNEL_QUARTER;
-               break;
-       }
-
-       if (fband->usePassScan & rd->pscan)
-               channelFlags |= CHANNEL_PASSIVE;
-       else
-               channelFlags &= ~CHANNEL_PASSIVE;
-       if (fband->useDfs & rd->dfsMask)
-               privFlags = CHANNEL_DFS;
-       else
-               privFlags = 0;
-       if (rd->flags & LIMIT_FRAME_4MS)
-               privFlags |= CHANNEL_4MS_LIMIT;
-       if (privFlags & CHANNEL_DFS)
-               privFlags |= CHANNEL_DISALLOW_ADHOC;
-       if (rd->flags & ADHOC_PER_11D)
-               privFlags |= CHANNEL_PER_11D_ADHOC;
-
-       if (channelFlags & CHANNEL_PASSIVE) {
-               if ((c < 2412) || (c > 2462)) {
-                       if (rd5GHz.regDmnEnum == MKK1 ||
-                           rd5GHz.regDmnEnum == MKK2) {
-                               u32 regcap = ah->ah_caps.reg_cap;
-                               if (!(regcap &
-                                     (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
-                                      AR_EEPROM_EEREGCAP_EN_KK_U2 |
-                                      AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) &&
-                                   isUNII1OddChan(c)) {
-                                       channelFlags &= ~CHANNEL_PASSIVE;
-                               } else {
-                                       privFlags |= CHANNEL_DISALLOW_ADHOC;
-                               }
-                       } else {
-                               privFlags |= CHANNEL_DISALLOW_ADHOC;
-                       }
-               }
-       }
-
-       if ((cm->mode == ATH9K_MODE_11A) ||
-           (cm->mode == ATH9K_MODE_11NA_HT20) ||
-           (cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
-           (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) {
-               if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A))
-                       privFlags |= CHANNEL_DISALLOW_ADHOC;
-       }
-
-       /* Fill in channel details */
-
-       ret = ath9k_regd_is_chan_present(ah, c);
-       if (ret == -1) {
-               chan = &ah->ah_channels[pos];
-               chan->channel = c;
-               chan->maxRegTxPower = fband->powerDfs;
-               chan->antennaMax = fband->antennaMax;
-               chan->regDmnFlags = rd->flags;
-               chan->maxTxPower = AR5416_MAX_RATE_POWER;
-               chan->minTxPower = AR5416_MAX_RATE_POWER;
-               chan->channelFlags = channelFlags;
-               chan->privFlags = privFlags;
-       } else {
-               chan = &ah->ah_channels[ret];
-               chan->channelFlags |= channelFlags;
-               chan->privFlags |= privFlags;
-       }
-
-       /* Set CTLs */
-
-       if ((cm->flags & CHANNEL_ALL) == CHANNEL_A)
-               chan->conformanceTestLimit[0] = ctl;
-       else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B)
-               chan->conformanceTestLimit[1] = ctl;
-       else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G)
-               chan->conformanceTestLimit[2] = ctl;
-
-       return (ret == -1) ? true : false;
-}
-
-static bool ath9k_regd_japan_check(struct ath_hal *ah,
-                                  int b,
-                                  struct regDomain *rd5GHz)
-{
-       bool skipband = false;
-       int i;
-       u32 regcap;
-
-       for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) {
-               if (j_bandcheck[i].freqbandbit == b) {
-                       regcap = ah->ah_caps.reg_cap;
-                       if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) {
-                               skipband = true;
-                       } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) ||
-                                 (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) {
-                               rd5GHz->dfsMask |= DFS_MKK4;
-                               rd5GHz->pscan |= PSCAN_MKK3;
-                       }
-                       break;
-               }
-       }
-
-       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-               "Skipping %d freq band\n", j_bandcheck[i].freqbandbit);
-
-       return skipband;
+       return NULL;
 }
 
-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)
+int ath9k_regd_init(struct ath_hal *ah)
 {
-       u16 maxChan = 7000;
        struct country_code_to_enum_rd *country = NULL;
-       struct regDomain rd5GHz, rd2GHz;
-       const struct cmode *cm;
-       struct ath9k_channel *ichans = &ah->ah_channels[0];
-       int next = 0, b;
-       u8 ctl;
        int regdmn;
-       u16 chanSep;
-       unsigned long *modes_avail;
-       DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX);
-
-       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,
-                       "Invalid country code %d\n", cc);
-               return false;
-       }
 
        if (!ath9k_regd_is_eeprom_valid(ah)) {
                DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
                        "Invalid EEPROM contents\n");
-               return false;
+               return -EINVAL;
        }
 
        ah->ah_countryCode = ath9k_regd_get_default_country(ah);
 
-       if (ah->ah_countryCode == CTRY_DEFAULT) {
-               ah->ah_countryCode = cc & COUNTRY_CODE_MASK;
-               if ((ah->ah_countryCode == CTRY_DEFAULT) &&
-                   (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) {
-                       ah->ah_countryCode = CTRY_UNITED_STATES;
-               }
-       }
+       if (ah->ah_countryCode == CTRY_DEFAULT &&
+           ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)
+               ah->ah_countryCode = CTRY_UNITED_STATES;
 
-#ifdef AH_SUPPORT_11D
        if (ah->ah_countryCode == CTRY_DEFAULT) {
                regdmn = ath9k_regd_get_eepromRD(ah);
                country = NULL;
        } else {
-#endif
                country = ath9k_regd_find_country(ah->ah_countryCode);
                if (country == NULL) {
                        DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
                                "Country is NULL!!!!, cc= %d\n",
                                ah->ah_countryCode);
-                       return false;
-               } else {
+                       return -EINVAL;
+               } else
                        regdmn = country->regDmnEnum;
-#ifdef AH_SUPPORT_11D
-                       if (((ath9k_regd_get_eepromRD(ah) &
-                             WORLD_SKU_MASK) == WORLD_SKU_PREFIX) &&
-                           (cc == CTRY_UNITED_STATES)) {
-                               if (!isWwrSKU_NoMidband(ah)
-                                   && ath9k_regd_is_fcc_midband_supported(ah))
-                                       regdmn = FCC3_FCCA;
-                               else
-                                       regdmn = FCC1_FCCA;
-                       }
-#endif
-               }
-#ifdef AH_SUPPORT_11D
-       }
-#endif
-       if (!ath9k_regd_get_wmode_regdomain(ah,
-                                           regdmn,
-                                           ~CHANNEL_2GHZ,
-                                           &rd5GHz)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Couldn't find unitary "
-                       "5GHz reg domain for country %u\n",
-                       ah->ah_countryCode);
-               return false;
-       }
-       if (!ath9k_regd_get_wmode_regdomain(ah,
-                                           regdmn,
-                                           CHANNEL_2GHZ,
-                                           &rd2GHz)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "Couldn't find unitary 2GHz "
-                       "reg domain for country %u\n",
-                       ah->ah_countryCode);
-               return false;
        }
 
-       if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) ||
-                             (rd5GHz.regDmnEnum == FCC2))) {
-               if (ath9k_regd_is_fcc_midband_supported(ah)) {
-                       if (!ath9k_regd_get_wmode_regdomain(ah,
-                                                           FCC3_FCCA,
-                                                           ~CHANNEL_2GHZ,
-                                                           &rd5GHz)) {
-                               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                                       "Couldn't find unitary 5GHz "
-                                       "reg domain for country %u\n",
-                                       ah->ah_countryCode);
-                               return false;
-                       }
-               }
-       }
-
-       if (country == NULL) {
-               modes_avail = ah->ah_caps.wireless_modes;
-       } else {
-               ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed);
-               modes_avail = modes_allowed;
-
-               if (!enableOutdoor)
-                       maxChan = country->outdoorChanStart;
-       }
-
-       next = 0;
-
-       if (maxchans > ARRAY_SIZE(ah->ah_channels))
-               maxchans = ARRAY_SIZE(ah->ah_channels);
-
-       for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) {
-               u16 c, c_hi, c_lo;
-               u64 *channelBM = NULL;
-               struct regDomain *rd = NULL;
-               struct RegDmnFreqBand *fband = NULL, *freqs;
-               int8_t low_adj = 0, hi_adj = 0;
-
-               if (!test_bit(cm->mode, modes_avail)) {
-                       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                               "!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,
-                               "channels 0x%x not supported "
-                               "by hardware\n", cm->flags);
-                       continue;
-               }
-
-               switch (cm->mode) {
-               case ATH9K_MODE_11A:
-               case ATH9K_MODE_11NA_HT20:
-               case ATH9K_MODE_11NA_HT40PLUS:
-               case ATH9K_MODE_11NA_HT40MINUS:
-                       rd = &rd5GHz;
-                       channelBM = rd->chan11a;
-                       freqs = &regDmn5GhzFreq[0];
-                       ctl = rd->conformanceTestLimit;
-                       break;
-               case ATH9K_MODE_11B:
-                       rd = &rd2GHz;
-                       channelBM = rd->chan11b;
-                       freqs = &regDmn2GhzFreq[0];
-                       ctl = rd->conformanceTestLimit | CTL_11B;
-                       break;
-               case ATH9K_MODE_11G:
-               case ATH9K_MODE_11NG_HT20:
-               case ATH9K_MODE_11NG_HT40PLUS:
-               case ATH9K_MODE_11NG_HT40MINUS:
-                       rd = &rd2GHz;
-                       channelBM = rd->chan11g;
-                       freqs = &regDmn2Ghz11gFreq[0];
-                       ctl = rd->conformanceTestLimit | CTL_11G;
-                       break;
-               default:
-                       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                               "Unknown HAL mode 0x%x\n", cm->mode);
-                       continue;
-               }
-
-               if (ath9k_regd_is_chan_bm_zero(channelBM))
-                       continue;
-
-               if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) ||
-                   (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) {
-                       hi_adj = -20;
-               }
-
-               if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) ||
-                   (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) {
-                       low_adj = 20;
-               }
-
-               /* XXX: Add a helper here instead */
-               for (b = 0; b < 64 * BMLEN; b++) {
-                       if (ath9k_regd_is_bit_set(b, channelBM)) {
-                               fband = &freqs[b];
-                               if (rd5GHz.regDmnEnum == MKK1
-                                   || rd5GHz.regDmnEnum == MKK2) {
-                                       if (ath9k_regd_japan_check(ah,
-                                                                  b,
-                                                                  &rd5GHz))
-                                               continue;
-                               }
-
-                               ath9k_regd_add_reg_classid(regclassids,
-                                                          maxregids,
-                                                          nregids,
-                                                          fband->
-                                                          regClassId);
-
-                               if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) {
-                                       chanSep = 40;
-                                       if (fband->lowChannel == 5280)
-                                               low_adj += 20;
-
-                                       if (fband->lowChannel == 5170)
-                                               continue;
-                               } else
-                                       chanSep = fband->channelSep;
-
-                               for (c = fband->lowChannel + low_adj;
-                                    ((c <= (fband->highChannel + hi_adj)) &&
-                                     (c >= (fband->lowChannel + low_adj)));
-                                    c += chanSep) {
-                                       if (next >= maxchans) {
-                                               DPRINTF(ah->ah_sc,
-                                                       ATH_DBG_REGULATORY,
-                                                       "too many channels "
-                                                       "for channel table\n");
-                                               goto done;
-                                       }
-                                       if (ath9k_regd_add_channel(ah,
-                                                  c, c_lo, c_hi,
-                                                  maxChan, ctl,
-                                                  next,
-                                                  rd5GHz,
-                                                  fband, rd, cm,
-                                                  ichans,
-                                                  enableExtendedChannels))
-                                               next++;
-                               }
-                               if (IS_HT40_MODE(cm->mode) &&
-                                   (fband->lowChannel == 5280)) {
-                                       low_adj -= 20;
-                               }
-                       }
-               }
-       }
-done:
-       if (next != 0) {
-               int i;
+       ah->ah_currentRDInUse = regdmn;
+       ah->regpair = ath9k_get_regpair(regdmn);
 
-               if (next > ARRAY_SIZE(ah->ah_channels)) {
-                       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                               "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
-               ath9k_regd_init_rf_buffer(ichans, next);
-#endif
-               ath9k_regd_sort(ichans, next,
-                               sizeof(struct ath9k_channel),
-                               ath9k_regd_chansort);
-
-               ah->ah_nchan = next;
-
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Channel list:\n");
-               for (i = 0; i < next; i++) {
-                       DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                               "chan: %d flags: 0x%x\n",
-                               ah->ah_channels[i].channel,
-                               ah->ah_channels[i].channelFlags);
-               }
+       if (!ah->regpair) {
+               DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+                       "No regulatory domain pair found, cannot continue\n");
+               return -EINVAL;
        }
-       *nchans = next;
 
-       ah->ah_countryCode = ah->ah_countryCode;
+       if (!country)
+               country = ath9k_regd_find_country_by_rd(regdmn);
 
-       ah->ah_currentRDInUse = regdmn;
-       ah->ah_currentRD5G = rd5GHz.regDmnEnum;
-       ah->ah_currentRD2G = rd2GHz.regDmnEnum;
-       if (country == NULL) {
-               ah->ah_iso[0] = 0;
-               ah->ah_iso[1] = 0;
+       if (country) {
+               ah->alpha2[0] = country->isoName[0];
+               ah->alpha2[1] = country->isoName[1];
        } else {
-               ah->ah_iso[0] = country->isoName[0];
-               ah->ah_iso[1] = country->isoName[1];
+               ah->alpha2[0] = '0';
+               ah->alpha2[1] = '0';
        }
 
-       return next != 0;
-}
-
-struct ath9k_channel*
-ath9k_regd_check_channel(struct ath_hal *ah,
-                        const struct ath9k_channel *c)
-{
-       struct ath9k_channel *base, *cc;
-
-       int flags = c->channelFlags & CHAN_FLAGS;
-       int n, lim;
-
        DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-               "channel %u/0x%x (0x%x) requested\n",
-               c->channel, c->channelFlags, flags);
-
-       cc = ah->ah_curchan;
-       if (cc != NULL && cc->channel == c->channel &&
-           (cc->channelFlags & CHAN_FLAGS) == flags) {
-               if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
-                   (cc->privFlags & CHANNEL_DFS))
-                       return NULL;
-               else
-                       return cc;
-       }
+               "Country alpha2 being used: %c%c\n"
+               "Regpair detected: 0x%0x\n",
+               ah->alpha2[0], ah->alpha2[1],
+               ah->regpair->regDmnEnum);
 
-       base = ah->ah_channels;
-       n = ah->ah_nchan;
-
-       for (lim = n; lim != 0; lim >>= 1) {
-               int d;
-               cc = &base[lim >> 1];
-               d = c->channel - cc->channel;
-               if (d == 0) {
-                       if ((cc->channelFlags & CHAN_FLAGS) == flags) {
-                               if ((cc->privFlags & CHANNEL_INTERFERENCE) &&
-                                   (cc->privFlags & CHANNEL_DFS))
-                                       return NULL;
-                               else
-                                       return cc;
-                       }
-                       d = flags - (cc->channelFlags & CHAN_FLAGS);
-               }
-               DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-                       "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, "no match for %u/0x%x\n",
-               c->channel, c->channelFlags);
-       return NULL;
-}
-
-u32
-ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
-                              struct ath9k_channel *chan)
-{
-       struct ath9k_channel *ichan = NULL;
-
-       ichan = ath9k_regd_check_channel(ah, chan);
-       if (!ichan)
-               return 0;
-
-       return ichan->antennaMax;
+       return 0;
 }
 
 u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan)
 {
        u32 ctl = NO_CTL;
-       struct ath9k_channel *ichan;
 
-       if (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) {
+       if (!ah->regpair ||
+           (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah))) {
                if (IS_CHAN_B(chan))
                        ctl = SD_NO_CTL | CTL_11B;
                else if (IS_CHAN_G(chan))
                        ctl = SD_NO_CTL | CTL_11G;
                else
                        ctl = SD_NO_CTL | CTL_11A;
-       } else {
-               ichan = ath9k_regd_check_channel(ah, chan);
-               if (ichan != NULL) {
-                       /* FIXME */
-                       if (IS_CHAN_A(ichan))
-                               ctl = ichan->conformanceTestLimit[0];
-                       else if (IS_CHAN_B(ichan))
-                               ctl = ichan->conformanceTestLimit[1];
-                       else if (IS_CHAN_G(ichan))
-                               ctl = ichan->conformanceTestLimit[2];
-
-                       if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B)
-                               ctl = (ctl & ~0xf) | CTL_11G;
-               }
+               return ctl;
        }
-       return ctl;
-}
 
-void ath9k_regd_get_current_country(struct ath_hal *ah,
-                                   struct ath9k_country_entry *ctry)
-{
-       u16 rd = ath9k_regd_get_eepromRD(ah);
+       if (IS_CHAN_B(chan))
+               ctl = ah->regpair->reg_2ghz_ctl | CTL_11B;
+       else if (IS_CHAN_G(chan))
+               ctl = ah->regpair->reg_5ghz_ctl | CTL_11G;
+       else
+               ctl = ah->regpair->reg_5ghz_ctl | CTL_11A;
 
-       ctry->isMultidomain = false;
-       if (rd == CTRY_DEFAULT)
-               ctry->isMultidomain = true;
-       else if (!(rd & COUNTRY_ERD_FLAG))
-               ctry->isMultidomain = isWwrSKU(ah);
-
-       ctry->countryCode = ah->ah_countryCode;
-       ctry->regDmnEnum = ah->ah_currentRD;
-       ctry->regDmn5G = ah->ah_currentRD5G;
-       ctry->regDmn2G = ah->ah_currentRD2G;
-       ctry->iso[0] = ah->ah_iso[0];
-       ctry->iso[1] = ah->ah_iso[1];
-       ctry->iso[2] = ah->ah_iso[2];
+       return ctl;
 }
index 512d990aa7ea352e44452158cb04742689add545..ba2d2dfb0d1f0aae1f4f4785ff8a05ff67dc1832 100644 (file)
 
 #include "ath9k.h"
 
-#define BMLEN 2
-#define BMZERO {(u64) 0, (u64) 0}
-
-#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \
-       {((((_fa >= 0) && (_fa < 64)) ? \
-               (((u64) 1) << _fa) : (u64) 0) | \
-       (((_fb >= 0) && (_fb < 64)) ? \
-               (((u64) 1) << _fb) : (u64) 0) | \
-       (((_fc >= 0) && (_fc < 64)) ? \
-               (((u64) 1) << _fc) : (u64) 0) | \
-       (((_fd >= 0) && (_fd < 64)) ? \
-               (((u64) 1) << _fd) : (u64) 0) | \
-       (((_fe >= 0) && (_fe < 64)) ? \
-               (((u64) 1) << _fe) : (u64) 0) | \
-       (((_ff >= 0) && (_ff < 64)) ? \
-               (((u64) 1) << _ff) : (u64) 0) | \
-       (((_fg >= 0) && (_fg < 64)) ? \
-               (((u64) 1) << _fg) : (u64) 0) | \
-       (((_fh >= 0) && (_fh < 64)) ? \
-               (((u64) 1) << _fh) : (u64) 0) | \
-       (((_fi >= 0) && (_fi < 64)) ? \
-               (((u64) 1) << _fi) : (u64) 0) | \
-       (((_fj >= 0) && (_fj < 64)) ? \
-               (((u64) 1) << _fj) : (u64) 0) | \
-       (((_fk >= 0) && (_fk < 64)) ? \
-               (((u64) 1) << _fk) : (u64) 0) | \
-       (((_fl >= 0) && (_fl < 64)) ? \
-               (((u64) 1) << _fl) : (u64) 0) | \
-                       ((((_fa > 63) && (_fa < 128)) ? \
-                       (((u64) 1) << (_fa - 64)) : (u64) 0) | \
-       (((_fb > 63) && (_fb < 128)) ? \
-               (((u64) 1) << (_fb - 64)) : (u64) 0) | \
-       (((_fc > 63) && (_fc < 128)) ? \
-               (((u64) 1) << (_fc - 64)) : (u64) 0) | \
-       (((_fd > 63) && (_fd < 128)) ? \
-               (((u64) 1) << (_fd - 64)) : (u64) 0) | \
-       (((_fe > 63) && (_fe < 128)) ? \
-               (((u64) 1) << (_fe - 64)) : (u64) 0) | \
-       (((_ff > 63) && (_ff < 128)) ? \
-               (((u64) 1) << (_ff - 64)) : (u64) 0) | \
-       (((_fg > 63) && (_fg < 128)) ? \
-               (((u64) 1) << (_fg - 64)) : (u64) 0) | \
-       (((_fh > 63) && (_fh < 128)) ? \
-               (((u64) 1) << (_fh - 64)) : (u64) 0) | \
-       (((_fi > 63) && (_fi < 128)) ? \
-               (((u64) 1) << (_fi - 64)) : (u64) 0) | \
-       (((_fj > 63) && (_fj < 128)) ? \
-               (((u64) 1) << (_fj - 64)) : (u64) 0) | \
-       (((_fk > 63) && (_fk < 128)) ? \
-               (((u64) 1) << (_fk - 64)) : (u64) 0) | \
-       (((_fl > 63) && (_fl < 128)) ? \
-               (((u64) 1) << (_fl - 64)) : (u64) 0)))}
-
-#define DEF_REGDMN      FCC1_FCCA
-#define DEF_DMN_5       FCC1
-#define DEF_DMN_2       FCCA
 #define COUNTRY_ERD_FLAG        0x8000
 #define WORLDWIDE_ROAMING_FLAG  0x4000
-#define SUPER_DOMAIN_MASK   0x0fff
-#define COUNTRY_CODE_MASK   0x3fff
-#define CF_INTERFERENCE     (CHANNEL_CW_INT | CHANNEL_RADAR_INT)
-#define CHANNEL_14      (2484)
-#define IS_11G_CH14(_ch,_cf) \
-    (((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G))
-
-#define NO_PSCAN    0x0ULL
-#define PSCAN_FCC   0x0000000000000001ULL
-#define PSCAN_FCC_T 0x0000000000000002ULL
-#define PSCAN_ETSI  0x0000000000000004ULL
-#define PSCAN_MKK1  0x0000000000000008ULL
-#define PSCAN_MKK2  0x0000000000000010ULL
-#define PSCAN_MKKA  0x0000000000000020ULL
-#define PSCAN_MKKA_G    0x0000000000000040ULL
-#define PSCAN_ETSIA 0x0000000000000080ULL
-#define PSCAN_ETSIB 0x0000000000000100ULL
-#define PSCAN_ETSIC 0x0000000000000200ULL
-#define PSCAN_WWR   0x0000000000000400ULL
-#define PSCAN_MKKA1 0x0000000000000800ULL
-#define PSCAN_MKKA1_G   0x0000000000001000ULL
-#define PSCAN_MKKA2 0x0000000000002000ULL
-#define PSCAN_MKKA2_G   0x0000000000004000ULL
-#define PSCAN_MKK3  0x0000000000008000ULL
-#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL
-#define IS_ECM_CHAN 0x8000000000000000ULL
 
 #define isWwrSKU(_ah) \
        (((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \
                WORLD_SKU_PREFIX) || \
                (ath9k_regd_get_eepromRD(_ah) == WORLD))
 
-#define isWwrSKU_NoMidband(_ah) \
-       ((ath9k_regd_get_eepromRD((_ah)) == WOR3_WORLD) || \
-       (ath9k_regd_get_eepromRD(_ah) == WOR4_WORLD) || \
-       (ath9k_regd_get_eepromRD(_ah) == WOR5_ETSIC))
-
-#define isUNII1OddChan(ch) \
-       ((ch == 5170) || (ch == 5190) || (ch == 5210) || (ch == 5230))
-
-#define IS_HT40_MODE(_mode)                                    \
-       (((_mode == ATH9K_MODE_11NA_HT40PLUS  ||                \
-          _mode == ATH9K_MODE_11NG_HT40PLUS    ||              \
-          _mode == ATH9K_MODE_11NA_HT40MINUS   ||              \
-          _mode == ATH9K_MODE_11NG_HT40MINUS) ? true : false))
-
-#define CHAN_FLAGS      (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
-
-#define swap_array(_a, _b, _size) {                   \
-       u8 *s = _b;                       \
-       int i = _size;                          \
-       do {                                    \
-               u8 tmp = *_a;             \
-               *_a++ = *s;                     \
-               *s++ = tmp;                     \
-       } while (--i);                          \
-       _a -= _size;                            \
-}
-
-
-#define HALF_MAXCHANBW          10
-
 #define MULTI_DOMAIN_MASK 0xFF00
 
 #define WORLD_SKU_MASK          0x00F0
 #define CHANNEL_HALF_BW         10
 #define CHANNEL_QUARTER_BW      5
 
-typedef int ath_hal_cmp_t(const void *, const void *);
-
 struct reg_dmn_pair_mapping {
        u16 regDmnEnum;
-       u16 regDmn5GHz;
-       u16 regDmn2GHz;
-       u32 flags5GHz;
-       u32 flags2GHz;
-       u64 pscanMask;
-       u16 singleCC;
-};
-
-struct ccmap {
-       char isoName[3];
-       u16 countryCode;
+       u16 reg_5ghz_ctl;
+       u16 reg_2ghz_ctl;
 };
 
 struct country_code_to_enum_rd {
        u16 countryCode;
        u16 regDmnEnum;
        const char *isoName;
-       const char *name;
-       bool allow11g;
-       bool allow11aTurbo;
-       bool allow11gTurbo;
-       bool allow11ng20;
-       bool allow11ng40;
-       bool allow11na20;
-       bool allow11na40;
-       u16 outdoorChanStart;
-};
-
-struct RegDmnFreqBand {
-       u16 lowChannel;
-       u16 highChannel;
-       u8 powerDfs;
-       u8 antennaMax;
-       u8 channelBW;
-       u8 channelSep;
-       u64 useDfs;
-       u64 usePassScan;
-       u8 regClassId;
-};
-
-struct regDomain {
-       u16 regDmnEnum;
-       u8 conformanceTestLimit;
-       u64 dfsMask;
-       u64 pscan;
-       u32 flags;
-       u64 chan11a[BMLEN];
-       u64 chan11a_turbo[BMLEN];
-       u64 chan11a_dyn_turbo[BMLEN];
-       u64 chan11b[BMLEN];
-       u64 chan11g[BMLEN];
-       u64 chan11g_turbo[BMLEN];
-};
-
-struct cmode {
-       u32 mode;
-       u32 flags;
-};
-
-#define YES true
-#define NO  false
-
-struct japan_bandcheck {
-       u16 freqbandbit;
-       u32 eepromflagtocheck;
-};
-
-struct common_mode_power {
-       u16 lchan;
-       u16 hchan;
-       u8 pwrlvl;
 };
 
 enum CountryCode {
index 6df1b3b77c253730a8e234ea954ae9ea568028cf..b41d0002f3fef4bad462be9ac2aa1544216d42e0 100644 (file)
@@ -150,1766 +150,324 @@ enum EnumRd {
        MKK9_MKKC = 0xFE,
        MKK9_MKKA2 = 0xFF,
 
-       APL1 = 0x0150,
-       APL2 = 0x0250,
-       APL3 = 0x0350,
-       APL4 = 0x0450,
-       APL5 = 0x0550,
-       APL6 = 0x0650,
-       APL7 = 0x0750,
-       APL8 = 0x0850,
-       APL9 = 0x0950,
-       APL10 = 0x1050,
-
-       ETSI1 = 0x0130,
-       ETSI2 = 0x0230,
-       ETSI3 = 0x0330,
-       ETSI4 = 0x0430,
-       ETSI5 = 0x0530,
-       ETSI6 = 0x0630,
-       ETSIA = 0x0A30,
-       ETSIB = 0x0B30,
-       ETSIC = 0x0C30,
-
-       FCC1 = 0x0110,
-       FCC2 = 0x0120,
-       FCC3 = 0x0160,
-       FCC4 = 0x0165,
-       FCC5 = 0x0510,
-       FCC6 = 0x0610,
-       FCCA = 0x0A10,
-
-       APLD = 0x0D50,
-
-       MKK1 = 0x0140,
-       MKK2 = 0x0240,
-       MKK3 = 0x0340,
-       MKK4 = 0x0440,
-       MKK5 = 0x0540,
-       MKK6 = 0x0640,
-       MKK7 = 0x0740,
-       MKK8 = 0x0840,
-       MKK9 = 0x0940,
-       MKK10 = 0x0B40,
-       MKK11 = 0x1140,
-       MKK12 = 0x1240,
-       MKK13 = 0x0C40,
-       MKK14 = 0x1440,
-       MKK15 = 0x1540,
-       MKKA = 0x0A40,
-       MKKC = 0x0A50,
-
-       NULL1 = 0x0198,
        WORLD = 0x0199,
        DEBUG_REG_DMN = 0x01ff,
 };
 
-enum {
-       FCC = 0x10,
-       MKK = 0x40,
-       ETSI = 0x30,
-};
-
-enum {
-       NO_REQ = 0x00000000,
-       DISALLOW_ADHOC_11A = 0x00000001,
-       DISALLOW_ADHOC_11A_TURB = 0x00000002,
-       NEED_NFC = 0x00000004,
-
-       ADHOC_PER_11D = 0x00000008,
-       ADHOC_NO_11A = 0x00000010,
-
-       PUBLIC_SAFETY_DOMAIN = 0x00000020,
-       LIMIT_FRAME_4MS = 0x00000040,
-
-       NO_HOSTAP = 0x00000080,
-
-       REQ_MASK = 0x000000FF,
+enum ctl_group {
+       CTL_FCC = 0x10,
+       CTL_MKK = 0x40,
+       CTL_ETSI = 0x30,
 };
 
-#define REG_DOMAIN_2GHZ_MASK    (REQ_MASK & \
-       (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
-#define REG_DOMAIN_5GHZ_MASK    REQ_MASK
-
+/* Regpair to CTL band mapping */
 static struct reg_dmn_pair_mapping regDomainPairs[] = {
-       {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ,
-        PSCAN_DEFER, 0},
-       {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-
-       {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC4_FCCA, FCC4, FCCA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {FCC5_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-
-       {ETSI1_WORLD, ETSI1, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {ETSI2_WORLD, ETSI2, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {ETSI3_WORLD, ETSI3, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {ETSI4_WORLD, ETSI4, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {ETSI5_WORLD, ETSI5, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {ETSI6_WORLD, ETSI6, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-
-       {ETSI3_ETSIA, ETSI3, WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-
-       {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-
-       {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER,},
-
-       {MKK1_MKKA, MKK1, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN},
-       {MKK1_MKKB, MKK1, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN1},
-       {MKK1_FCCA, MKK1, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1, CTRY_JAPAN2},
-       {MKK1_MKKA1, MKK1, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4},
-       {MKK1_MKKA2, MKK1, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5},
-       {MKK1_MKKC, MKK1, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1, CTRY_JAPAN6},
-
-       {MKK2_MKKA, MKK2, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN3},
-
-       {MKK3_MKKA, MKK3, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA, CTRY_JAPAN25},
-       {MKK3_MKKB, MKK3, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN7},
-       {MKK3_MKKA1, MKK3, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26},
-       {MKK3_MKKA2, MKK3, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8},
-       {MKK3_MKKC, MKK3, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN9},
-       {MKK3_FCCA, MKK3, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN27},
-
-       {MKK4_MKKA, MKK4, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN36},
-       {MKK4_MKKB, MKK4, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN10},
-       {MKK4_MKKA1, MKK4, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28},
-       {MKK4_MKKA2, MKK4, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11},
-       {MKK4_MKKC, MKK4, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN12},
-       {MKK4_FCCA, MKK4, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN29},
-
-       {MKK5_MKKB, MKK5, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN13},
-       {MKK5_MKKA2, MKK5, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14},
-       {MKK5_MKKC, MKK5, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN15},
-
-       {MKK6_MKKB, MKK6, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16},
-       {MKK6_MKKA1, MKK6, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30},
-       {MKK6_MKKA2, MKK6, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17},
-       {MKK6_MKKC, MKK6, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1, CTRY_JAPAN18},
-       {MKK6_FCCA, MKK6, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN31},
-
-       {MKK7_MKKB, MKK7, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN19},
-       {MKK7_MKKA1, MKK7, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32},
-       {MKK7_MKKA2, MKK7, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G,
-        CTRY_JAPAN20},
-       {MKK7_MKKC, MKK7, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21},
-       {MKK7_FCCA, MKK7, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33},
-
-       {MKK8_MKKB, MKK8, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN22},
-       {MKK8_MKKA2, MKK8, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G,
-        CTRY_JAPAN23},
-       {MKK8_MKKC, MKK8, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN24},
-
-       {MKK9_MKKA, MKK9, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK2 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN34},
-       {MKK9_FCCA, MKK9, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN37},
-       {MKK9_MKKA1, MKK9, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38},
-       {MKK9_MKKA2, MKK9, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40},
-       {MKK9_MKKC, MKK9, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN39},
-
-       {MKK10_MKKA, MKK10, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKK3, CTRY_JAPAN35},
-       {MKK10_FCCA, MKK10, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN41},
-       {MKK10_MKKA1, MKK10, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42},
-       {MKK10_MKKA2, MKK10, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44},
-       {MKK10_MKKC, MKK10, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        NO_PSCAN, CTRY_JAPAN43},
-
-       {MKK11_MKKA, MKK11, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN45},
-       {MKK11_FCCA, MKK11, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN46},
-       {MKK11_MKKA1, MKK11, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47},
-       {MKK11_MKKA2, MKK11, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49},
-       {MKK11_MKKC, MKK11, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK3, CTRY_JAPAN48},
-
-       {MKK12_MKKA, MKK12, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50},
-       {MKK12_FCCA, MKK12, FCCA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51},
-       {MKK12_MKKA1, MKK12, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G,
-        CTRY_JAPAN52},
-       {MKK12_MKKA2, MKK12, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G,
-        CTRY_JAPAN54},
-       {MKK12_MKKC, MKK12, MKKC,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53},
-
-       {MKK13_MKKB, MKK13, MKKA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC |
-        LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G,
-        CTRY_JAPAN57},
-
-       {MKK14_MKKA1, MKK14, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58},
-       {MKK15_MKKA1, MKK15, MKKA,
-        DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC,
-        PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59},
-
-       {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER,
-        0},
-       {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB,
-        NO_REQ, PSCAN_DEFER, 0},
-       {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER,
-        0},
-       {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ,
-        PSCAN_DEFER, 0},
-       {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ,
-        PSCAN_DEFER, 0},
-       {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
-       {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {WORA_WORLD, WORA_WORLD, WORA_WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
-       {WORB_WORLD, WORB_WORLD, WORB_WORLD,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER,
-        0},
+       /* regpair, 5 GHz CTL, 2 GHz CTL */
+       {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
+       {NULL1_WORLD, NO_CTL, CTL_ETSI},
+       {NULL1_ETSIB, NO_CTL, CTL_ETSI},
+       {NULL1_ETSIC, NO_CTL, CTL_ETSI},
+
+       {FCC2_FCCA, CTL_FCC, CTL_FCC},
+       {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+       {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+       {FCC3_FCCA, CTL_FCC, CTL_FCC},
+       {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+       {FCC4_FCCA, CTL_FCC, CTL_FCC},
+       {FCC5_FCCA, CTL_FCC, CTL_FCC},
+       {FCC6_FCCA, CTL_FCC, CTL_FCC},
+       {FCC6_WORLD, CTL_FCC, CTL_ETSI},
+
+       {ETSI1_WORLD, CTL_ETSI, CTL_ETSI},
+       {ETSI2_WORLD, CTL_ETSI, CTL_ETSI},
+       {ETSI3_WORLD, CTL_ETSI, CTL_ETSI},
+       {ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
+       {ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
+       {ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
+
+       /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
+       {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
+       {FRANCE_RES, CTL_ETSI, CTL_ETSI},
+
+       {FCC1_WORLD, CTL_FCC, CTL_ETSI},
+       {FCC1_FCCA, CTL_FCC, CTL_FCC},
+       {APL1_WORLD, CTL_FCC, CTL_ETSI},
+       {APL2_WORLD, CTL_FCC, CTL_ETSI},
+       {APL3_WORLD, CTL_FCC, CTL_ETSI},
+       {APL4_WORLD, CTL_FCC, CTL_ETSI},
+       {APL5_WORLD, CTL_FCC, CTL_ETSI},
+       {APL6_WORLD, CTL_ETSI, CTL_ETSI},
+       {APL8_WORLD, CTL_ETSI, CTL_ETSI},
+       {APL9_WORLD, CTL_ETSI, CTL_ETSI},
+
+       {APL3_FCCA, CTL_FCC, CTL_FCC},
+       {APL1_ETSIC, CTL_FCC, CTL_ETSI},
+       {APL2_ETSIC, CTL_FCC, CTL_ETSI},
+       {APL2_APLD, CTL_FCC, NO_CTL},
+
+       {MKK1_MKKA, CTL_MKK, CTL_MKK},
+       {MKK1_MKKB, CTL_MKK, CTL_MKK},
+       {MKK1_FCCA, CTL_MKK, CTL_FCC},
+       {MKK1_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK1_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK1_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK2_MKKA, CTL_MKK, CTL_MKK},
+       {MKK3_MKKA, CTL_MKK, CTL_MKK},
+       {MKK3_MKKB, CTL_MKK, CTL_MKK},
+       {MKK3_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK3_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK3_MKKC, CTL_MKK, CTL_MKK},
+       {MKK3_FCCA, CTL_MKK, CTL_FCC},
+
+       {MKK4_MKKA, CTL_MKK, CTL_MKK},
+       {MKK4_MKKB, CTL_MKK, CTL_MKK},
+       {MKK4_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK4_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK4_MKKC, CTL_MKK, CTL_MKK},
+       {MKK4_FCCA, CTL_MKK, CTL_FCC},
+
+       {MKK5_MKKB, CTL_MKK, CTL_MKK},
+       {MKK5_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK5_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK6_MKKB, CTL_MKK, CTL_MKK},
+       {MKK6_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK6_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK6_MKKC, CTL_MKK, CTL_MKK},
+       {MKK6_FCCA, CTL_MKK, CTL_FCC},
+
+       {MKK7_MKKB, CTL_MKK, CTL_MKK},
+       {MKK7_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK7_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK7_MKKC, CTL_MKK, CTL_MKK},
+       {MKK7_FCCA, CTL_MKK, CTL_FCC},
+
+       {MKK8_MKKB, CTL_MKK, CTL_MKK},
+       {MKK8_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK8_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK9_MKKA, CTL_MKK, CTL_MKK},
+       {MKK9_FCCA, CTL_MKK, CTL_FCC},
+       {MKK9_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK9_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK9_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK10_MKKA, CTL_MKK, CTL_MKK},
+       {MKK10_FCCA, CTL_MKK, CTL_FCC},
+       {MKK10_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK10_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK10_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK11_MKKA, CTL_MKK, CTL_MKK},
+       {MKK11_FCCA, CTL_MKK, CTL_FCC},
+       {MKK11_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK11_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK11_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK12_MKKA, CTL_MKK, CTL_MKK},
+       {MKK12_FCCA, CTL_MKK, CTL_FCC},
+       {MKK12_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK12_MKKA2, CTL_MKK, CTL_MKK},
+       {MKK12_MKKC, CTL_MKK, CTL_MKK},
+
+       {MKK13_MKKB, CTL_MKK, CTL_MKK},
+       {MKK14_MKKA1, CTL_MKK, CTL_MKK},
+       {MKK15_MKKA1, CTL_MKK, CTL_MKK},
+
+       {WOR0_WORLD, NO_CTL, NO_CTL},
+       {WOR1_WORLD, NO_CTL, NO_CTL},
+       {WOR2_WORLD, NO_CTL, NO_CTL},
+       {WOR3_WORLD, NO_CTL, NO_CTL},
+       {WOR4_WORLD, NO_CTL, NO_CTL},
+       {WOR5_ETSIC, NO_CTL, NO_CTL},
+       {WOR01_WORLD, NO_CTL, NO_CTL},
+       {WOR02_WORLD, NO_CTL, NO_CTL},
+       {EU1_WORLD, NO_CTL, NO_CTL},
+       {WOR9_WORLD, NO_CTL, NO_CTL},
+       {WORA_WORLD, NO_CTL, NO_CTL},
+       {WORB_WORLD, NO_CTL, NO_CTL},
 };
 
-#define        NO_INTERSECT_REQ        0xFFFFFFFF
-#define        NO_UNION_REQ            0
-
 static struct country_code_to_enum_rd allCountries[] = {
-       {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, NO,
-        NO, NO, 7000},
-       {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, NO,
-        NO, NO, 7000},
-       {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES,
-        NO, YES, NO, 7000},
-       {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_BELGIUM2, ETSI4_WORLD, "BL", "BELGIUM", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA_HERZGOWINA", YES, NO,
-        YES, YES, YES, YES, NO, 7000},
-       {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, NO,
-        YES, NO, 7000},
-       {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN", "BRUNEI DARUSSALAM",
-        YES, YES, YES, YES, YES, YES, YES, 7000},
-       {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES,
-        YES, YES, YES, NO, 7000},
-       {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC",
-        YES, YES, YES, YES, YES, YES, YES, 7000},
-       {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES,
-        YES, NO, 7000},
-       {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES,
-        YES, YES, YES, NO, 7000},
-       {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES,
-        YES, 7000},
-       {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAMAICA, ETSI1_WORLD, "JM", "JAMAICA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-
-       {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, YES, YES, YES,
-        YES, 7000},
-       {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-       {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES,
-        YES, YES, 7000},
-
-       {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES,
-        YES, YES, NO, NO, 7000},
-       {CTRY_KOREA_NORTH, APL9_WORLD, "KP", "NORTH KOREA", YES, NO, NO,
-        YES, YES, YES, YES, 7000},
-       {CTRY_KOREA_ROC, APL9_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO,
-        YES, NO, YES, NO, 7000},
-       {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2", YES, NO, NO,
-        YES, NO, YES, NO, 7000},
-       {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3", YES, NO, NO,
-        YES, NO, YES, NO, 7000},
-       {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO,
-        YES, YES, YES, YES, YES, 7000},
-       {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, NO,
-        YES, NO, 7000},
-       {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN",
-        "NETHERLANDS-ANTILLES", YES, NO, YES, YES, YES, YES, YES, 7000},
-       {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES,
-        YES, YES, YES, NO, 7000},
-       {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES,
-        NO, 7000},
-       {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES,
-        YES, YES, YES, YES, YES, YES, 7000},
-       {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES,
-        NO, 7000},
-       {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO,
-        YES, YES, YES, NO, NO, 7000},
-       {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS", "SERBIA & MONTENEGRO",
-        YES, NO, YES, YES, YES, YES, YES, 7000},
-       {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC", YES, NO, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES,
-        YES, YES, YES, 7000},
-       {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES,
-        YES, YES, YES, NO, 7000},
-       {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES,
-        YES, YES, 7000},
-       {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT", "TRINIDAD & TOBAGO",
-        YES, NO, YES, YES, YES, YES, NO, 7000},
-       {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES,
-        YES, YES, NO, NO, 7000},
-       {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO,
-        YES, YES, YES, YES, YES, 7000},
-       {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES,
-        YES, YES, YES, YES, YES, 5825},
-       {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS",
-        "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES,
-        YES, 7000},
-       {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES,
-        YES, NO, 7000},
-       {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES,
-        YES, YES, YES, YES, 7000},
-       {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, YES,
-        YES, YES, NO, 7000},
-       {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, YES,
-        YES, NO, NO, 7000},
-       {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES,
-        NO, NO, 7000},
-       {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES,
-        YES, NO, NO, 7000}
-};
-
-enum {
-       NO_DFS = 0x0000000000000000ULL,
-       DFS_FCC3 = 0x0000000000000001ULL,
-       DFS_ETSI = 0x0000000000000002ULL,
-       DFS_MKK4 = 0x0000000000000004ULL,
-};
-
-enum {
-       F1_4915_4925,
-       F1_4935_4945,
-       F1_4920_4980,
-       F1_4942_4987,
-       F1_4945_4985,
-       F1_4950_4980,
-       F1_5035_5040,
-       F1_5040_5080,
-       F1_5055_5055,
-
-       F1_5120_5240,
-
-       F1_5170_5230,
-       F2_5170_5230,
-
-       F1_5180_5240,
-       F2_5180_5240,
-       F3_5180_5240,
-       F4_5180_5240,
-       F5_5180_5240,
-       F6_5180_5240,
-       F7_5180_5240,
-       F8_5180_5240,
-
-       F1_5180_5320,
-
-       F1_5240_5280,
-
-       F1_5260_5280,
-
-       F1_5260_5320,
-       F2_5260_5320,
-       F3_5260_5320,
-       F4_5260_5320,
-       F5_5260_5320,
-       F6_5260_5320,
-
-       F1_5260_5700,
-
-       F1_5280_5320,
-
-       F1_5500_5580,
-
-       F1_5500_5620,
-
-       F1_5500_5700,
-       F2_5500_5700,
-       F3_5500_5700,
-       F4_5500_5700,
-       F5_5500_5700,
-
-       F1_5660_5700,
-
-       F1_5745_5805,
-       F2_5745_5805,
-       F3_5745_5805,
-
-       F1_5745_5825,
-       F2_5745_5825,
-       F3_5745_5825,
-       F4_5745_5825,
-       F5_5745_5825,
-       F6_5745_5825,
-
-       W1_4920_4980,
-       W1_5040_5080,
-       W1_5170_5230,
-       W1_5180_5240,
-       W1_5260_5320,
-       W1_5745_5825,
-       W1_5500_5700,
-       A_DEMO_ALL_CHANNELS
-};
-
-static struct RegDmnFreqBand regDmn5GhzFreq[] = {
-       {4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16},
-       {4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16},
-       {4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7},
-       {4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0},
-       {4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0},
-       {4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0},
-       {5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12},
-       {5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2},
-       {5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12},
-
-       {5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-
-       {5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1},
-       {5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1},
-
-       {5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
-       {5180, 5240, 17, 6, 20, 20, NO_DFS, NO_PSCAN, 1},
-       {5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
-       {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
-       {5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0},
-       {5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0},
-       {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK3, 0},
-       {5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-
-       {5180, 5320, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0},
-
-       {5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0},
-
-       {5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
-        PSCAN_FCC | PSCAN_ETSI, 0},
-
-       {5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
-        PSCAN_FCC | PSCAN_ETSI, 0},
-
-       {5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4,
-        PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3, 0},
-
-
-       {5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI,
-        PSCAN_FCC | PSCAN_ETSI, 2},
-       {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2},
-       {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0},
-       {5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
-
-       {5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0},
-
-       {5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0},
-
-       {5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0},
-
-       {5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0},
-
-       {5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4},
-       {5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
-        PSCAN_FCC | PSCAN_ETSI, 0},
-       {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI,
-        PSCAN_FCC | PSCAN_ETSI, 0},
-       {5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4,
-        PSCAN_MKK3 | PSCAN_FCC, 0},
-       {5500, 5700, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0},
-
-       {5660, 5700, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0},
-
-       {5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5805, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0},
-       {5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0},
-       {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3},
-       {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-
-
-       {4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
-       {5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
-       {5170, 5230, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
-       {5180, 5240, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
-       {5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
-       {5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0},
-       {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0},
-       {4920, 6100, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0},
-};
-
-enum {
-       T1_5130_5650,
-       T1_5150_5670,
-
-       T1_5200_5200,
-       T2_5200_5200,
-       T3_5200_5200,
-       T4_5200_5200,
-       T5_5200_5200,
-       T6_5200_5200,
-       T7_5200_5200,
-       T8_5200_5200,
-
-       T1_5200_5280,
-       T2_5200_5280,
-       T3_5200_5280,
-       T4_5200_5280,
-       T5_5200_5280,
-       T6_5200_5280,
-
-       T1_5200_5240,
-       T1_5210_5210,
-       T2_5210_5210,
-       T3_5210_5210,
-       T4_5210_5210,
-       T5_5210_5210,
-       T6_5210_5210,
-       T7_5210_5210,
-       T8_5210_5210,
-       T9_5210_5210,
-       T10_5210_5210,
-       T1_5240_5240,
-
-       T1_5210_5250,
-       T1_5210_5290,
-       T2_5210_5290,
-       T3_5210_5290,
-
-       T1_5280_5280,
-       T2_5280_5280,
-       T1_5290_5290,
-       T2_5290_5290,
-       T3_5290_5290,
-       T1_5250_5290,
-       T2_5250_5290,
-       T3_5250_5290,
-       T4_5250_5290,
-
-       T1_5540_5660,
-       T2_5540_5660,
-       T3_5540_5660,
-       T1_5760_5800,
-       T2_5760_5800,
-       T3_5760_5800,
-       T4_5760_5800,
-       T5_5760_5800,
-       T6_5760_5800,
-       T7_5760_5800,
-
-       T1_5765_5805,
-       T2_5765_5805,
-       T3_5765_5805,
-       T4_5765_5805,
-       T5_5765_5805,
-       T6_5765_5805,
-       T7_5765_5805,
-       T8_5765_5805,
-       T9_5765_5805,
-
-       WT1_5210_5250,
-       WT1_5290_5290,
-       WT1_5540_5660,
-       WT1_5760_5800,
-};
-
-enum {
-       F1_2312_2372,
-       F2_2312_2372,
-
-       F1_2412_2472,
-       F2_2412_2472,
-       F3_2412_2472,
-
-       F1_2412_2462,
-       F2_2412_2462,
-
-       F1_2432_2442,
-
-       F1_2457_2472,
-
-       F1_2467_2472,
-
-       F1_2484_2484,
-       F2_2484_2484,
-
-       F1_2512_2732,
-
-       W1_2312_2372,
-       W1_2412_2412,
-       W1_2417_2432,
-       W1_2437_2442,
-       W1_2447_2457,
-       W1_2462_2462,
-       W1_2467_2467,
-       W2_2467_2467,
-       W1_2472_2472,
-       W2_2472_2472,
-       W1_2484_2484,
-       W2_2484_2484,
-};
-
-static struct RegDmnFreqBand regDmn2GhzFreq[] = {
-       {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
-       {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0},
-
-       {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
-
-       {2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2484, 2484, 20, 0, 20, 5, NO_DFS,
-        PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0},
-
-       {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
-       {2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
-       {2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
-       {2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
-       {2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
-       {2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
-};
-
-enum {
-       G1_2312_2372,
-       G2_2312_2372,
-
-       G1_2412_2472,
-       G2_2412_2472,
-       G3_2412_2472,
-
-       G1_2412_2462,
-       G2_2412_2462,
-
-       G1_2432_2442,
-
-       G1_2457_2472,
-
-       G1_2512_2732,
-
-       G1_2467_2472,
-
-       WG1_2312_2372,
-       WG1_2412_2462,
-       WG1_2467_2472,
-       WG2_2467_2472,
-       G_DEMO_ALL_CHANNELS
-};
-
-static struct RegDmnFreqBand regDmn2Ghz11gFreq[] = {
-       {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
-       {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0},
-
-       {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-
-       {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0},
-
-       {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2412, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0},
-       {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0},
-       {2467, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0},
-       {2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0},
-};
-
-enum {
-       T1_2312_2372,
-       T1_2437_2437,
-       T2_2437_2437,
-       T3_2437_2437,
-       T1_2512_2732
+       {CTRY_DEBUG, NO_ENUMRD, "DB"},
+       {CTRY_DEFAULT, FCC1_FCCA, "CO"},
+       {CTRY_ALBANIA, NULL1_WORLD, "AL"},
+       {CTRY_ALGERIA, NULL1_WORLD, "DZ"},
+       {CTRY_ARGENTINA, APL3_WORLD, "AR"},
+       {CTRY_ARMENIA, ETSI4_WORLD, "AM"},
+       {CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
+       {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
+       {CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
+       {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
+       {CTRY_BAHRAIN, APL6_WORLD, "BH"},
+       {CTRY_BELARUS, ETSI1_WORLD, "BY"},
+       {CTRY_BELGIUM, ETSI1_WORLD, "BE"},
+       {CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
+       {CTRY_BELIZE, APL1_ETSIC, "BZ"},
+       {CTRY_BOLIVIA, APL1_ETSIC, "BO"},
+       {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
+       {CTRY_BRAZIL, FCC3_WORLD, "BR"},
+       {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
+       {CTRY_BULGARIA, ETSI6_WORLD, "BG"},
+       {CTRY_CANADA, FCC2_FCCA, "CA"},
+       {CTRY_CANADA2, FCC6_FCCA, "CA"},
+       {CTRY_CHILE, APL6_WORLD, "CL"},
+       {CTRY_CHINA, APL1_WORLD, "CN"},
+       {CTRY_COLOMBIA, FCC1_FCCA, "CO"},
+       {CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
+       {CTRY_CROATIA, ETSI3_WORLD, "HR"},
+       {CTRY_CYPRUS, ETSI1_WORLD, "CY"},
+       {CTRY_CZECH, ETSI3_WORLD, "CZ"},
+       {CTRY_DENMARK, ETSI1_WORLD, "DK"},
+       {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
+       {CTRY_ECUADOR, FCC1_WORLD, "EC"},
+       {CTRY_EGYPT, ETSI3_WORLD, "EG"},
+       {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"},
+       {CTRY_ESTONIA, ETSI1_WORLD, "EE"},
+       {CTRY_FINLAND, ETSI1_WORLD, "FI"},
+       {CTRY_FRANCE, ETSI1_WORLD, "FR"},
+       {CTRY_GEORGIA, ETSI4_WORLD, "GE"},
+       {CTRY_GERMANY, ETSI1_WORLD, "DE"},
+       {CTRY_GREECE, ETSI1_WORLD, "GR"},
+       {CTRY_GUATEMALA, FCC1_FCCA, "GT"},
+       {CTRY_HONDURAS, NULL1_WORLD, "HN"},
+       {CTRY_HONG_KONG, FCC2_WORLD, "HK"},
+       {CTRY_HUNGARY, ETSI1_WORLD, "HU"},
+       {CTRY_ICELAND, ETSI1_WORLD, "IS"},
+       {CTRY_INDIA, APL6_WORLD, "IN"},
+       {CTRY_INDONESIA, APL1_WORLD, "ID"},
+       {CTRY_IRAN, APL1_WORLD, "IR"},
+       {CTRY_IRELAND, ETSI1_WORLD, "IE"},
+       {CTRY_ISRAEL, NULL1_WORLD, "IL"},
+       {CTRY_ITALY, ETSI1_WORLD, "IT"},
+       {CTRY_JAMAICA, ETSI1_WORLD, "JM"},
+
+       {CTRY_JAPAN, MKK1_MKKA, "JP"},
+       {CTRY_JAPAN1, MKK1_MKKB, "JP"},
+       {CTRY_JAPAN2, MKK1_FCCA, "JP"},
+       {CTRY_JAPAN3, MKK2_MKKA, "JP"},
+       {CTRY_JAPAN4, MKK1_MKKA1, "JP"},
+       {CTRY_JAPAN5, MKK1_MKKA2, "JP"},
+       {CTRY_JAPAN6, MKK1_MKKC, "JP"},
+       {CTRY_JAPAN7, MKK3_MKKB, "JP"},
+       {CTRY_JAPAN8, MKK3_MKKA2, "JP"},
+       {CTRY_JAPAN9, MKK3_MKKC, "JP"},
+       {CTRY_JAPAN10, MKK4_MKKB, "JP"},
+       {CTRY_JAPAN11, MKK4_MKKA2, "JP"},
+       {CTRY_JAPAN12, MKK4_MKKC, "JP"},
+       {CTRY_JAPAN13, MKK5_MKKB, "JP"},
+       {CTRY_JAPAN14, MKK5_MKKA2, "JP"},
+       {CTRY_JAPAN15, MKK5_MKKC, "JP"},
+       {CTRY_JAPAN16, MKK6_MKKB, "JP"},
+       {CTRY_JAPAN17, MKK6_MKKA2, "JP"},
+       {CTRY_JAPAN18, MKK6_MKKC, "JP"},
+       {CTRY_JAPAN19, MKK7_MKKB, "JP"},
+       {CTRY_JAPAN20, MKK7_MKKA2, "JP"},
+       {CTRY_JAPAN21, MKK7_MKKC, "JP"},
+       {CTRY_JAPAN22, MKK8_MKKB, "JP"},
+       {CTRY_JAPAN23, MKK8_MKKA2, "JP"},
+       {CTRY_JAPAN24, MKK8_MKKC, "JP"},
+       {CTRY_JAPAN25, MKK3_MKKA, "JP"},
+       {CTRY_JAPAN26, MKK3_MKKA1, "JP"},
+       {CTRY_JAPAN27, MKK3_FCCA, "JP"},
+       {CTRY_JAPAN28, MKK4_MKKA1, "JP"},
+       {CTRY_JAPAN29, MKK4_FCCA, "JP"},
+       {CTRY_JAPAN30, MKK6_MKKA1, "JP"},
+       {CTRY_JAPAN31, MKK6_FCCA, "JP"},
+       {CTRY_JAPAN32, MKK7_MKKA1, "JP"},
+       {CTRY_JAPAN33, MKK7_FCCA, "JP"},
+       {CTRY_JAPAN34, MKK9_MKKA, "JP"},
+       {CTRY_JAPAN35, MKK10_MKKA, "JP"},
+       {CTRY_JAPAN36, MKK4_MKKA, "JP"},
+       {CTRY_JAPAN37, MKK9_FCCA, "JP"},
+       {CTRY_JAPAN38, MKK9_MKKA1, "JP"},
+       {CTRY_JAPAN39, MKK9_MKKC, "JP"},
+       {CTRY_JAPAN40, MKK9_MKKA2, "JP"},
+       {CTRY_JAPAN41, MKK10_FCCA, "JP"},
+       {CTRY_JAPAN42, MKK10_MKKA1, "JP"},
+       {CTRY_JAPAN43, MKK10_MKKC, "JP"},
+       {CTRY_JAPAN44, MKK10_MKKA2, "JP"},
+       {CTRY_JAPAN45, MKK11_MKKA, "JP"},
+       {CTRY_JAPAN46, MKK11_FCCA, "JP"},
+       {CTRY_JAPAN47, MKK11_MKKA1, "JP"},
+       {CTRY_JAPAN48, MKK11_MKKC, "JP"},
+       {CTRY_JAPAN49, MKK11_MKKA2, "JP"},
+       {CTRY_JAPAN50, MKK12_MKKA, "JP"},
+       {CTRY_JAPAN51, MKK12_FCCA, "JP"},
+       {CTRY_JAPAN52, MKK12_MKKA1, "JP"},
+       {CTRY_JAPAN53, MKK12_MKKC, "JP"},
+       {CTRY_JAPAN54, MKK12_MKKA2, "JP"},
+       {CTRY_JAPAN57, MKK13_MKKB, "JP"},
+       {CTRY_JAPAN58, MKK14_MKKA1, "JP"},
+       {CTRY_JAPAN59, MKK15_MKKA1, "JP"},
+
+       {CTRY_JORDAN, ETSI2_WORLD, "JO"},
+       {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
+       {CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
+       {CTRY_KOREA_ROC, APL9_WORLD, "KR"},
+       {CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
+       {CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
+       {CTRY_KUWAIT, NULL1_WORLD, "KW"},
+       {CTRY_LATVIA, ETSI1_WORLD, "LV"},
+       {CTRY_LEBANON, NULL1_WORLD, "LB"},
+       {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
+       {CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
+       {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
+       {CTRY_MACAU, FCC2_WORLD, "MO"},
+       {CTRY_MACEDONIA, NULL1_WORLD, "MK"},
+       {CTRY_MALAYSIA, APL8_WORLD, "MY"},
+       {CTRY_MALTA, ETSI1_WORLD, "MT"},
+       {CTRY_MEXICO, FCC1_FCCA, "MX"},
+       {CTRY_MONACO, ETSI4_WORLD, "MC"},
+       {CTRY_MOROCCO, NULL1_WORLD, "MA"},
+       {CTRY_NEPAL, APL1_WORLD, "NP"},
+       {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
+       {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
+       {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
+       {CTRY_NORWAY, ETSI1_WORLD, "NO"},
+       {CTRY_OMAN, APL6_WORLD, "OM"},
+       {CTRY_PAKISTAN, NULL1_WORLD, "PK"},
+       {CTRY_PANAMA, FCC1_FCCA, "PA"},
+       {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
+       {CTRY_PERU, APL1_WORLD, "PE"},
+       {CTRY_PHILIPPINES, APL1_WORLD, "PH"},
+       {CTRY_POLAND, ETSI1_WORLD, "PL"},
+       {CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
+       {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
+       {CTRY_QATAR, NULL1_WORLD, "QA"},
+       {CTRY_ROMANIA, NULL1_WORLD, "RO"},
+       {CTRY_RUSSIA, NULL1_WORLD, "RU"},
+       {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
+       {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
+       {CTRY_SINGAPORE, APL6_WORLD, "SG"},
+       {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
+       {CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
+       {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
+       {CTRY_SPAIN, ETSI1_WORLD, "ES"},
+       {CTRY_SRI_LANKA, FCC3_WORLD, "LK"},
+       {CTRY_SWEDEN, ETSI1_WORLD, "SE"},
+       {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
+       {CTRY_SYRIA, NULL1_WORLD, "SY"},
+       {CTRY_TAIWAN, APL3_FCCA, "TW"},
+       {CTRY_THAILAND, NULL1_WORLD, "TH"},
+       {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
+       {CTRY_TUNISIA, ETSI3_WORLD, "TN"},
+       {CTRY_TURKEY, ETSI3_WORLD, "TR"},
+       {CTRY_UKRAINE, NULL1_WORLD, "UA"},
+       {CTRY_UAE, NULL1_WORLD, "AE"},
+       {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+       {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
+       /* This "PS" is for US public safety actually... to support this we
+        * would need to assign new special alpha2 to CRDA db as with the world
+        * regdomain and use another alpha2 */
+       {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
+       {CTRY_URUGUAY, APL2_WORLD, "UY"},
+       {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
+       {CTRY_VENEZUELA, APL2_ETSIC, "VE"},
+       {CTRY_VIET_NAM, NULL1_WORLD, "VN"},
+       {CTRY_YEMEN, NULL1_WORLD, "YE"},
+       {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
 };
 
-static struct regDomain regDomains[] = {
-
-       {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ,
-        BM(A_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5130_5650, T1_5150_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(G_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1)},
-
-       {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC, NO_REQ,
-        BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL7, ETSI, DFS_ETSI, PSCAN_ETSI, NO_REQ,
-        BM(F1_5280_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL8, ETSI, NO_DFS, NO_PSCAN,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL9, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {APL10, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5180_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F4_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
-        BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
-        BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ,
-        BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F1_5660_5700,
-           F6_5745_5825, -1, -1, -1, -1, -1, -1, -1),
-        BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-       {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240,
-           F2_5260_5320, F4_5500_5700, -1, -1),
-        BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
-        BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
-        BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
-        BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
-        BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1),
-        BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1,
-           -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320,
-           F4_5500_5700, -1, -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240,
-           F2_5260_5320, F4_5500_5700, -1, -1),
-        BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BM(F1_5170_5230, F7_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, -1, -1,
-           -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {MKK15, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
-        BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040,
-           F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240,
-           F2_5260_5320, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO},
-
-
-       {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F2_2312_2372, F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(G2_2312_2372, G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BMZERO},
-
-       {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC,
-        DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {MKKA, MKK, NO_DFS,
-        PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G |
-        PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
-           -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR,
-        ADHOC_PER_11D,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
-           W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR,
-        ADHOC_PER_11D,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472,
-           W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
-           -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825,
-           W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1,
-           -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
-        BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
-           W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1,
-           -1, -1, -1, -1, -1),
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432,
-           W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1,
-           -1, -1, -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
-        BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, -1, -1, -1, -1, -1,
-           -1, -1, -1, -1),
-        BMZERO,
-        BMZERO,
-        BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472,
-           W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
-        BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1,
-           -1, -1),
-        BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
-
-       {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO,
-        BMZERO}
-};
-
-static const struct cmode modes[] = {
-       {ATH9K_MODE_11A, CHANNEL_A},
-       {ATH9K_MODE_11B, CHANNEL_B},
-       {ATH9K_MODE_11G, CHANNEL_G},
-       {ATH9K_MODE_11NG_HT20, CHANNEL_G_HT20},
-       {ATH9K_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS},
-       {ATH9K_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS},
-       {ATH9K_MODE_11NA_HT20, CHANNEL_A_HT20},
-       {ATH9K_MODE_11NA_HT40PLUS, CHANNEL_A_HT40PLUS},
-       {ATH9K_MODE_11NA_HT40MINUS, CHANNEL_A_HT40MINUS},
-};
-
-static struct japan_bandcheck j_bandcheck[] = {
-       {F1_5170_5230, AR_EEPROM_EEREGCAP_EN_KK_U1_ODD},
-       {F4_5180_5240, AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN},
-       {F2_5260_5320, AR_EEPROM_EEREGCAP_EN_KK_U2},
-       {F4_5500_5700, AR_EEPROM_EEREGCAP_EN_KK_MIDBAND}
-};
-
-
 #endif
index c92f0c6e4adcd1ac64bf0975f5a1f32ed3bf0bfd..007ca91188d144349c2e26c39c15758f05d2a127 100644 (file)
@@ -55,1158 +55,1175 @@ static u32 bits_per_symbol[][2] = {
 
 #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
 
-/*
- * Insert a chain of ath_buf (descriptors) on a txq and
- * assume the descriptors are already chained together by caller.
- * NB: must be called with txq lock held
- */
-
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+                              struct ath_atx_tid *tid,
+                              struct list_head *bf_head);
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct list_head *bf_q,
+                               int txok, int sendbar);
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
-                            struct list_head *head)
+                            struct list_head *head);
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
+
+/*********************/
+/* Aggregation logic */
+/*********************/
+
+static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
 {
-       struct ath_hal *ah = sc->sc_ah;
-       struct ath_buf *bf;
+       struct ath_atx_tid *tid;
+       tid = ATH_AN_2_TID(an, tidno);
 
-       /*
-        * Insert the frame on the outbound list and
-        * pass it on to the hardware.
-        */
+       if (tid->state & AGGR_ADDBA_COMPLETE ||
+           tid->state & AGGR_ADDBA_PROGRESS)
+               return 1;
+       else
+               return 0;
+}
 
-       if (list_empty(head))
+static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+{
+       struct ath_atx_ac *ac = tid->ac;
+
+       if (tid->paused)
                return;
 
-       bf = list_first_entry(head, struct ath_buf, list);
+       if (tid->sched)
+               return;
 
-       list_splice_tail_init(head, &txq->axq_q);
-       txq->axq_depth++;
-       txq->axq_totalqueued++;
-       txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
+       tid->sched = true;
+       list_add_tail(&tid->list, &ac->tid_q);
 
-       DPRINTF(sc, ATH_DBG_QUEUE,
-               "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+       if (ac->sched)
+               return;
 
-       if (txq->axq_link == NULL) {
-               ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-               DPRINTF(sc, ATH_DBG_XMIT,
-                       "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, "link[%u] (%p)=%llx (%p)\n",
-                       txq->axq_qnum, txq->axq_link,
-                       ito64(bf->bf_daddr), bf->bf_desc);
-       }
-       txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
-       ath9k_hw_txstart(ah, txq->axq_qnum);
+       ac->sched = true;
+       list_add_tail(&ac->list, &txq->axq_acq);
 }
 
-static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-                           struct ath_xmit_status *tx_status)
+static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
-       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;
+       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 
-       DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+       spin_lock_bh(&txq->axq_lock);
+       tid->paused++;
+       spin_unlock_bh(&txq->axq_lock);
+}
 
-       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;
-       }
+static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 
-       if (tx_status->flags & ATH_TX_BAR) {
-               tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-               tx_status->flags &= ~ATH_TX_BAR;
-       }
+       ASSERT(tid->paused > 0);
+       spin_lock_bh(&txq->axq_lock);
 
-       if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
-               /* Frame was ACKed */
-               tx_info->flags |= IEEE80211_TX_STAT_ACK;
-       }
+       tid->paused--;
 
-       tx_info->status.rates[0].count = tx_status->retries + 1;
+       if (tid->paused > 0)
+               goto unlock;
 
-       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);
-       }
+       if (list_empty(&tid->buf_q))
+               goto unlock;
 
-       ieee80211_tx_status(hw, skb);
+       ath_tx_queue_tid(txq, tid);
+       ath_txq_schedule(sc, txq);
+unlock:
+       spin_unlock_bh(&txq->axq_lock);
 }
 
-/* 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 void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
-       struct ath_atx_tid *tid;
-       tid = ATH_AN_2_TID(an, tidno);
+       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       INIT_LIST_HEAD(&bf_head);
 
-       if (tid->state & AGGR_ADDBA_COMPLETE ||
-           tid->state & AGGR_ADDBA_PROGRESS)
-               return 1;
-       else
-               return 0;
-}
+       ASSERT(tid->paused > 0);
+       spin_lock_bh(&txq->axq_lock);
 
-static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
-                                struct ath_beacon_config *conf)
-{
-       struct ieee80211_hw *hw = sc->hw;
+       tid->paused--;
 
-       /* fill in beacon config data */
+       if (tid->paused > 0) {
+               spin_unlock_bh(&txq->axq_lock);
+               return;
+       }
 
-       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;
-}
+       while (!list_empty(&tid->buf_q)) {
+               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+               ASSERT(!bf_isretried(bf));
+               list_move_tail(&bf->list, &bf_head);
+               ath_tx_send_normal(sc, txq, tid, &bf_head);
+       }
 
-/* Calculate Atheros packet type from IEEE80211 packet header */
+       spin_unlock_bh(&txq->axq_lock);
+}
 
-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             int seqno)
 {
-       struct ieee80211_hdr *hdr;
-       enum ath9k_pkt_type htype;
-       __le16 fc;
+       int index, cindex;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
-       fc = hdr->frame_control;
+       index  = ATH_BA_INDEX(tid->seq_start, seqno);
+       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 
-       if (ieee80211_is_beacon(fc))
-               htype = ATH9K_PKT_TYPE_BEACON;
-       else if (ieee80211_is_probe_resp(fc))
-               htype = ATH9K_PKT_TYPE_PROBE_RESP;
-       else if (ieee80211_is_atim(fc))
-               htype = ATH9K_PKT_TYPE_ATIM;
-       else if (ieee80211_is_pspoll(fc))
-               htype = ATH9K_PKT_TYPE_PSPOLL;
-       else
-               htype = ATH9K_PKT_TYPE_NORMAL;
+       tid->tx_buf[cindex] = NULL;
 
-       return htype;
+       while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
+               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+               INCR(tid->baw_head, ATH_TID_MAX_BUFS);
+       }
 }
 
-static bool is_pae(struct sk_buff *skb)
+static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                            struct ath_buf *bf)
 {
-       struct ieee80211_hdr *hdr;
-       __le16 fc;
+       int index, cindex;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
-       fc = hdr->frame_control;
+       if (bf_isretried(bf))
+               return;
 
-       if (ieee80211_is_data(fc)) {
-               if (ieee80211_is_nullfunc(fc) ||
-                   /* Port Access Entity (IEEE 802.1X) */
-                   (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-                       return true;
-               }
-       }
+       index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
+       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 
-       return false;
+       ASSERT(tid->tx_buf[cindex] == NULL);
+       tid->tx_buf[cindex] = bf;
+
+       if (index >= ((tid->baw_tail - tid->baw_head) &
+               (ATH_TID_MAX_BUFS - 1))) {
+               tid->baw_tail = cindex;
+               INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
+       }
 }
 
-static int get_hw_crypto_keytype(struct sk_buff *skb)
+/*
+ * TODO: For frame(s) that are in the retry state, we will reuse the
+ * sequence number(s) without setting the retry bit. The
+ * alternative is to give up on these and BAR the receiver's window
+ * forward.
+ */
+static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
+                         struct ath_atx_tid *tid)
+
 {
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       INIT_LIST_HEAD(&bf_head);
 
-       if (tx_info->control.hw_key) {
-               if (tx_info->control.hw_key->alg == ALG_WEP)
-                       return ATH9K_KEY_TYPE_WEP;
-               else if (tx_info->control.hw_key->alg == ALG_TKIP)
-                       return ATH9K_KEY_TYPE_TKIP;
-               else if (tx_info->control.hw_key->alg == ALG_CCMP)
-                       return ATH9K_KEY_TYPE_AES;
+       for (;;) {
+               if (list_empty(&tid->buf_q))
+                       break;
+
+               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+               list_move_tail(&bf->list, &bf_head);
+
+               if (bf_isretried(bf))
+                       ath_tx_update_baw(sc, tid, bf->bf_seqno);
+
+               spin_unlock(&txq->axq_lock);
+               ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+               spin_lock(&txq->axq_lock);
        }
 
-       return ATH9K_KEY_TYPE_CLEAR;
+       tid->seq_next = tid->seq_start;
+       tid->baw_tail = tid->baw_head;
 }
 
-/* Called only when tx aggregation is enabled and HT is supported */
-
-static void assign_aggr_tid_seqno(struct sk_buff *skb,
-                                 struct ath_buf *bf)
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
 {
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
-       struct ath_node *an;
-       struct ath_atx_tid *tid;
-       __le16 fc;
-       u8 *qc;
 
-       if (!tx_info->control.sta)
-               return;
+       bf->bf_state.bf_type |= BUF_RETRY;
+       bf->bf_retries++;
 
-       an = (struct ath_node *)tx_info->control.sta->drv_priv;
+       skb = bf->bf_mpdu;
        hdr = (struct ieee80211_hdr *)skb->data;
-       fc = hdr->frame_control;
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+}
 
-       /* Get tidno */
+static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
+{
+       struct ath_buf *tbf;
 
-       if (ieee80211_is_data_qos(fc)) {
-               qc = ieee80211_get_qos_ctl(hdr);
-               bf->bf_tidno = qc[0] & 0xf;
-       }
+       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->tx.txbuflock);
 
-       /* Get seqno */
-       /* 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.
-        *
-        * 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.
-        */
-       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);
+       ATH_TXBUF_RESET(tbf);
+
+       tbf->bf_mpdu = bf->bf_mpdu;
+       tbf->bf_buf_addr = bf->bf_buf_addr;
+       *(tbf->bf_desc) = *(bf->bf_desc);
+       tbf->bf_state = bf->bf_state;
+       tbf->bf_dmacontext = bf->bf_dmacontext;
+
+       return tbf;
 }
 
-static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
-                         struct ath_txq *txq)
+static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                                struct ath_buf *bf, struct list_head *bf_q,
+                                int txok)
 {
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       int flags = 0;
+       struct ath_node *an = NULL;
+       struct sk_buff *skb;
+       struct ieee80211_sta *sta;
+       struct ieee80211_hdr *hdr;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+       struct ath_desc *ds = bf_last->bf_desc;
+       struct list_head bf_head, bf_pending;
+       u16 seq_st = 0;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
 
-       flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
-       flags |= ATH9K_TXDESC_INTREQ;
+       skb = (struct sk_buff *)bf->bf_mpdu;
+       hdr = (struct ieee80211_hdr *)skb->data;
 
-       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;
+       rcu_read_lock();
 
-       return flags;
-}
+       sta = ieee80211_find_sta(sc->hw, hdr->addr1);
+       if (!sta) {
+               rcu_read_unlock();
+               return;
+       }
 
-static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
-{
-       struct ath_buf *bf = NULL;
+       an = (struct ath_node *)sta->drv_priv;
+       tid = ATH_AN_2_TID(an, bf->bf_tidno);
 
-       spin_lock_bh(&sc->tx.txbuflock);
+       isaggr = bf_isaggr(bf);
+       memset(ba, 0, WME_BA_BMP_SIZE >> 3);
 
-       if (unlikely(list_empty(&sc->tx.txbuf))) {
-               spin_unlock_bh(&sc->tx.txbuflock);
-               return NULL;
+       if (isaggr && txok) {
+               if (ATH_DS_TX_BA(ds)) {
+                       seq_st = ATH_DS_BA_SEQ(ds);
+                       memcpy(ba, ATH_DS_BA_BITMAP(ds),
+                              WME_BA_BMP_SIZE >> 3);
+               } else {
+                       /*
+                        * AR5416 can become deaf/mute when BA
+                        * issue happens. Chip needs to be reset.
+                        * But AP code may have sychronization issues
+                        * when perform internal reset in this routine.
+                        * Only enable reset in STA mode for now.
+                        */
+                       if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION)
+                               needreset = 1;
+               }
        }
 
-       bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
-       list_del(&bf->list);
+       INIT_LIST_HEAD(&bf_pending);
+       INIT_LIST_HEAD(&bf_head);
 
-       spin_unlock_bh(&sc->tx.txbuflock);
+       while (bf) {
+               txfail = txpending = 0;
+               bf_next = bf->bf_next;
 
-       return bf;
-}
+               if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
+                       /* transmit completion, subframe is
+                        * acked by block ack */
+               } else if (!isaggr && txok) {
+                       /* transmit completion */
+               } else {
+                       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);
+                                       txpending = 1;
+                               } else {
+                                       bf->bf_state.bf_type |= BUF_XRETRY;
+                                       txfail = 1;
+                                       sendbar = 1;
+                               }
+                       } else {
+                               /*
+                                * cleanup in progress, just fail
+                                * the un-acked sub-frames
+                                */
+                               txfail = 1;
+                       }
+               }
 
-/* To complete a chain of buffers associated a frame */
+               if (bf_next == NULL) {
+                       INIT_LIST_HEAD(&bf_head);
+               } else {
+                       ASSERT(!list_empty(bf_q));
+                       list_move_tail(&bf->list, &bf_head);
+               }
 
-static void ath_tx_complete_buf(struct ath_softc *sc,
-                               struct ath_buf *bf,
-                               struct list_head *bf_q,
-                               int txok, int sendbar)
-{
-       struct sk_buff *skb = bf->bf_mpdu;
-       struct ath_xmit_status tx_status;
-       unsigned long flags;
+               if (!txpending) {
+                       /*
+                        * complete the acked-ones/xretried ones; update
+                        * block-ack window
+                        */
+                       spin_lock_bh(&txq->axq_lock);
+                       ath_tx_update_baw(sc, tid, bf->bf_seqno);
+                       spin_unlock_bh(&txq->axq_lock);
 
-       /*
-        * Set retry information.
-        * NB: Don't use the information in the descriptor, because the frame
-        * could be software retried.
-        */
-       tx_status.retries = bf->bf_retries;
-       tx_status.flags = 0;
+                       ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
+               } else {
+                       /* retry the un-acked ones */
+                       if (bf->bf_next == NULL &&
+                           bf_last->bf_status & ATH_BUFSTATUS_STALE) {
+                               struct ath_buf *tbf;
 
-       if (sendbar)
-               tx_status.flags = ATH_TX_BAR;
+                               tbf = ath_clone_txbuf(sc, bf_last);
+                               ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
+                               list_add_tail(&tbf->list, &bf_head);
+                       } else {
+                               /*
+                                * Clear descriptor status words for
+                                * software retry
+                                */
+                               ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc);
+                       }
 
-       if (!txok) {
-               tx_status.flags |= ATH_TX_ERROR;
+                       /*
+                        * Put this buffer to the temporary pending
+                        * queue to retain ordering
+                        */
+                       list_splice_tail_init(&bf_head, &bf_pending);
+               }
 
-               if (bf_isxretried(bf))
-                       tx_status.flags |= ATH_TX_XRETRY;
+               bf = bf_next;
        }
 
-       /* 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);
+       if (tid->state & AGGR_CLEANUP) {
+               if (tid->baw_head == tid->baw_tail) {
+                       tid->state &= ~AGGR_ADDBA_COMPLETE;
+                       tid->addba_exchangeattempts = 0;
+                       tid->state &= ~AGGR_CLEANUP;
 
-       /*
-        * Return the list of ath_buf of this mpdu to free queue
-        */
-       spin_lock_irqsave(&sc->tx.txbuflock, flags);
-       list_splice_tail_init(bf_q, &sc->tx.txbuf);
-       spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
-}
+                       /* send buffered frames as singles */
+                       ath_tx_flush_tid(sc, tid);
+               }
+               rcu_read_unlock();
+               return;
+       }
 
-/*
- * queue up a dest/ac pair for tx scheduling
- * NB: must be called with txq lock held
- */
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!list_empty(&bf_pending)) {
+               spin_lock_bh(&txq->axq_lock);
+               list_splice(&bf_pending, &tid->buf_q);
+               ath_tx_queue_tid(txq, tid);
+               spin_unlock_bh(&txq->axq_lock);
+       }
 
-static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+       rcu_read_unlock();
+
+       if (needreset)
+               ath_reset(sc, false);
+}
+
+static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
+                          struct ath_atx_tid *tid)
 {
-       struct ath_atx_ac *ac = tid->ac;
+       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, frmlen;
+       u16 aggr_limit, legacy = 0, maxampdu;
+       int i;
+
+       skb = (struct sk_buff *)bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+       tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
 
        /*
-        * if tid is paused, hold off
+        * Find the lowest frame length among the rate series that will have a
+        * 4ms transmit duration.
+        * TODO - TXOP limit needs to be considered.
         */
-       if (tid->paused)
-               return;
+       max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
+
+       for (i = 0; i < 4; i++) {
+               if (rates[i].count) {
+                       if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
+                               legacy = 1;
+                               break;
+                       }
+
+                       frmlen = rate_table->info[rates[i].idx].max_4ms_framelen;
+                       max_4ms_framelen = min(max_4ms_framelen, frmlen);
+               }
+       }
 
        /*
-        * add tid to ac atmost once
+        * limit aggregate size by the minimum rate if rate selected is
+        * not a probe rate, if rate selected is a probe rate then
+        * avoid aggregation of this packet.
         */
-       if (tid->sched)
-               return;
+       if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
+               return 0;
 
-       tid->sched = true;
-       list_add_tail(&tid->list, &ac->tid_q);
+       aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
 
        /*
-        * add node ac to txq atmost once
+        * h/w can accept aggregates upto 16 bit lengths (65535).
+        * The IE, however can hold upto 65536, which shows up here
+        * as zero. Ignore 65536 since we  are constrained by hw.
         */
-       if (ac->sched)
-               return;
+       maxampdu = tid->an->maxampdu;
+       if (maxampdu)
+               aggr_limit = min(aggr_limit, maxampdu);
 
-       ac->sched = true;
-       list_add_tail(&ac->list, &txq->axq_acq);
+       return aggr_limit;
 }
 
-/* pause a tid */
-
-static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+/*
+ * Returns the number of delimiters to be added to
+ * 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)
 {
-       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-       spin_lock_bh(&txq->axq_lock);
-
-       tid->paused++;
-
-       spin_unlock_bh(&txq->axq_lock);
-}
+       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;
+       int width, half_gi, ndelim, mindelim;
 
-/* resume a tid and schedule aggregate */
+       /* Select standard number of delimiters based on frame length alone */
+       ndelim = ATH_AGGR_GET_NDELIM(frmlen);
 
-void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-       ASSERT(tid->paused > 0);
-       spin_lock_bh(&txq->axq_lock);
-
-       tid->paused--;
-
-       if (tid->paused > 0)
-               goto unlock;
-
-       if (list_empty(&tid->buf_q))
-               goto unlock;
+       /*
+        * If encryption enabled, hardware requires some more padding between
+        * subframes.
+        * TODO - this could be improved to be dependent on the rate.
+        *      The hardware can keep up at lower rates, but not higher rates
+        */
+       if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
+               ndelim += ATH_AGGR_ENCRYPTDELIM;
 
        /*
-        * Add this TID to scheduler and try to send out aggregates
+        * Convert desired mpdu density from microeconds to bytes based
+        * on highest rate in rate series (i.e. first rate) to determine
+        * required minimum length for subframe. Take into account
+        * whether high rate is 20 or 40Mhz and half or full GI.
         */
-       ath_tx_queue_tid(txq, tid);
-       ath_txq_schedule(sc, txq);
-unlock:
-       spin_unlock_bh(&txq->axq_lock);
-}
+       mpdudensity = tid->an->mpdudensity;
 
-/* Compute the number of bad frames */
+       /*
+        * If there is no mpdu density restriction, no further calculation
+        * is needed.
+        */
+       if (mpdudensity == 0)
+               return ndelim;
 
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-                             int txok)
-{
-       struct ath_buf *bf_last = bf->bf_lastbf;
-       struct ath_desc *ds = bf_last->bf_desc;
-       u16 seq_st = 0;
-       u32 ba[WME_BA_BMP_SIZE >> 5];
-       int ba_index;
-       int nbad = 0;
-       int isaggr = 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 (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
-               return 0;
+       if (half_gi)
+               nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
+       else
+               nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
 
-       isaggr = bf_isaggr(bf);
-       if (isaggr) {
-               seq_st = ATH_DS_BA_SEQ(ds);
-               memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
-       }
+       if (nsymbols == 0)
+               nsymbols = 1;
 
-       while (bf) {
-               ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
-               if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
-                       nbad++;
+       nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
+       minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
 
-               bf = bf->bf_next;
+       if (frmlen < minlen) {
+               mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
+               ndelim = max(mindelim, ndelim);
        }
 
-       return nbad;
+       return ndelim;
 }
 
-static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
+static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
+                                            struct ath_atx_tid *tid,
+                                            struct list_head *bf_q)
 {
-       struct sk_buff *skb;
-       struct ieee80211_hdr *hdr;
-
-       bf->bf_state.bf_type |= BUF_RETRY;
-       bf->bf_retries++;
+#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
+       struct ath_buf *bf, *bf_first, *bf_prev = NULL;
+       int rl = 0, nframes = 0, ndelim, prev_al = 0;
+       u16 aggr_limit = 0, al = 0, bpad = 0,
+               al_delta, h_baw = tid->baw_size / 2;
+       enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
 
-       skb = bf->bf_mpdu;
-       hdr = (struct ieee80211_hdr *)skb->data;
-       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
-}
+       bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
 
-/* Update block ack window */
+       do {
+               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
 
-static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-                             int seqno)
-{
-       int index, cindex;
+               /* do not step over block-ack window */
+               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
+                       status = ATH_AGGR_BAW_CLOSED;
+                       break;
+               }
 
-       index  = ATH_BA_INDEX(tid->seq_start, seqno);
-       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+               if (!rl) {
+                       aggr_limit = ath_lookup_rate(sc, bf, tid);
+                       rl = 1;
+               }
 
-       tid->tx_buf[cindex] = NULL;
+               /* do not exceed aggregation limit */
+               al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
 
-       while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
-               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-               INCR(tid->baw_head, ATH_TID_MAX_BUFS);
-       }
-}
+               if (nframes &&
+                   (aggr_limit < (al + bpad + al_delta + prev_al))) {
+                       status = ATH_AGGR_LIMITED;
+                       break;
+               }
 
-/*
- * ath_pkt_dur - compute packet duration (NB: not NAV)
- *
- * rix - rate index
- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
- * 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)
-{
-       struct ath_rate_table *rate_table = sc->cur_rate_table;
-       u32 nbits, nsymbits, duration, nsymbols;
-       u8 rc;
-       int streams, pktlen;
+               /* do not exceed subframe limit */
+               if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
+                       status = ATH_AGGR_LIMITED;
+                       break;
+               }
+               nframes++;
 
-       pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
-       rc = rate_table->info[rix].ratecode;
+               /* add padding for previous frame to aggregation length */
+               al += bpad + al_delta;
 
-       /* for legacy rates, use old function to compute packet duration */
-       if (!IS_HT_RATE(rc))
-               return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
-                                             rix, shortPreamble);
+               /*
+                * Get the delimiters needed to meet the MPDU
+                * density for this node.
+                */
+               ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
+               bpad = PADBYTES(al_delta) + (ndelim << 2);
 
-       /* 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;
+               bf->bf_next = NULL;
+               bf->bf_desc->ds_link = 0;
 
-       if (!half_gi)
-               duration = SYMBOL_TIME(nsymbols);
-       else
-               duration = SYMBOL_TIME_HALFGI(nsymbols);
+               /* link buffers of this frame to the aggregate */
+               ath_tx_addto_baw(sc, tid, bf);
+               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+               list_move_tail(&bf->list, bf_q);
+               if (bf_prev) {
+                       bf_prev->bf_next = bf;
+                       bf_prev->bf_desc->ds_link = bf->bf_daddr;
+               }
+               bf_prev = bf;
+       } while (!list_empty(&tid->buf_q));
 
-       /* 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);
+       bf_first->bf_al = al;
+       bf_first->bf_nframes = nframes;
 
-       return duration;
+       return status;
+#undef PADBYTES
 }
 
-/* Rate module function to set rate related fields in tx descriptor */
-
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
+static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                             struct ath_atx_tid *tid)
 {
-       struct ath_hal *ah = sc->sc_ah;
-       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];
-       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;
-       __le16 fc;
+       struct ath_buf *bf;
+       enum ATH_AGGR_STATUS status;
+       struct list_head bf_q;
 
-       memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+       do {
+               if (list_empty(&tid->buf_q))
+                       return;
 
-       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;
+               INIT_LIST_HEAD(&bf_q);
 
-       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;
-       }
+               status = ath_tx_form_aggr(sc, tid, &bf_q);
 
-       /* 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;
+               /*
+                * no frames picked up to be aggregated;
+                * block-ack window is not open.
+                */
+               if (list_empty(&bf_q))
                        break;
-               }
-       }
 
-       flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA));
-       cix = rt->info[rix].ctrl_rate;
+               bf = list_first_entry(&bf_q, struct ath_buf, list);
+               bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
 
-       /*
-        * 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 && !(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;
+               /* if only one frame, send as non-aggregate */
+               if (bf->bf_nframes == 1) {
+                       bf->bf_state.bf_type &= ~BUF_AGGR;
+                       ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
+                       ath_buf_set_rate(sc, bf);
+                       ath_tx_txqaddbuf(sc, txq, &bf_q);
+                       continue;
+               }
 
-               cix = rt->info[sc->sc_protrix].ctrl_rate;
-               rtsctsena = 1;
-       }
+               /* setup first desc of aggregate */
+               bf->bf_state.bf_type |= BUF_AGGR;
+               ath_buf_set_rate(sc, bf);
+               ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
 
-       /* 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)) {
-               /* 802.11g protection not needed, use our default behavior */
-               if (!rtsctsena)
-                       flags = ATH9K_TXDESC_RTSENA;
-       }
+               /* anchor last desc of aggregate */
+               ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
 
-       /* 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].ctrl_rate;
-               rtsctsena = 1;
-       }
+               txq->axq_aggr_depth++;
+               ath_tx_txqaddbuf(sc, txq, &bf_q);
 
-       /* 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);
+       } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
+                status != ATH_AGGR_BAW_CLOSED);
+}
 
-       /*
-        * 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
-        */
-       ctsrate = rt->info[cix].ratecode |
-               (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0);
+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;
 
-       for (i = 0; i < 4; i++) {
-               if (!rates[i].count || (rates[i].idx < 0))
-                       continue;
+       an = (struct ath_node *)sta->drv_priv;
 
-               rix = rates[i].idx;
+       if (sc->sc_flags & SC_OP_TXAGGR) {
+               txtid = ATH_AN_2_TID(an, tid);
+               txtid->state |= AGGR_ADDBA_PROGRESS;
+               ath_tx_pause_tid(sc, txtid);
+       }
 
-               series[i].Rate = rt->info[rix].ratecode |
-                       (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0);
+       return 0;
+}
 
-               series[i].Tries = rates[i].count;
+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;
+       struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
+       struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       INIT_LIST_HEAD(&bf_head);
 
-               series[i].RateFlags = (
-                       (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ?
-                               ATH9K_RATESERIES_RTS_CTS : 0) |
-                       ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
-                               ATH9K_RATESERIES_2040 : 0) |
-                       ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ?
-                               ATH9K_RATESERIES_HALFGI : 0);
+       if (txtid->state & AGGR_CLEANUP)
+               return 0;
 
-               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 (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+               txtid->addba_exchangeattempts = 0;
+               return 0;
+       }
 
-               series[i].ChSel = sc->sc_tx_chainmask;
+       ath_tx_pause_tid(sc, txtid);
 
-               if (rtsctsena)
-                       series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+       /* drop all software retried frames and mark this TID */
+       spin_lock_bh(&txq->axq_lock);
+       while (!list_empty(&txtid->buf_q)) {
+               bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
+               if (!bf_isretried(bf)) {
+                       /*
+                        * NB: it's based on the assumption that
+                        * software retried frame will always stay
+                        * at the head of software queue.
+                        */
+                       break;
+               }
+               list_move_tail(&bf->list, &bf_head);
+               ath_tx_update_baw(sc, txtid, bf->bf_seqno);
+               ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
        }
+       spin_unlock_bh(&txq->axq_lock);
 
-       /* 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 (txtid->baw_head != txtid->baw_tail) {
+               txtid->state |= AGGR_CLEANUP;
+       } else {
+               txtid->state &= ~AGGR_ADDBA_COMPLETE;
+               txtid->addba_exchangeattempts = 0;
+               ath_tx_flush_tid(sc, txtid);
+       }
 
-       if (sc->sc_config.ath_aggr_prot && flags)
-               ath9k_hw_set11n_burstduration(ah, ds, 8192);
+       return 0;
 }
 
-/*
- * 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)
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 {
-       struct ath_buf *bf;
-
-       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 */
-
-       /* update starting sequence number for subsequent ADDBA request */
-       INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+       struct ath_atx_tid *txtid;
+       struct ath_node *an;
 
-       /* Queue to h/w without aggregation */
-       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);
+       an = (struct ath_node *)sta->drv_priv;
 
-       return 0;
+       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);
+       }
 }
 
-/* flush tid's software queue and send frames as non-ampdu's */
-
-static void ath_tx_flush_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)
 {
-       struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-       struct ath_buf *bf;
-       struct list_head bf_head;
-       INIT_LIST_HEAD(&bf_head);
-
-       ASSERT(tid->paused > 0);
-       spin_lock_bh(&txq->axq_lock);
+       struct ath_atx_tid *txtid;
 
-       tid->paused--;
+       if (!(sc->sc_flags & SC_OP_TXAGGR))
+               return false;
 
-       if (tid->paused > 0) {
-               spin_unlock_bh(&txq->axq_lock);
-               return;
-       }
+       txtid = ATH_AN_2_TID(an, tidno);
 
-       while (!list_empty(&tid->buf_q)) {
-               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-               ASSERT(!bf_isretried(bf));
-               list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
-               ath_tx_send_normal(sc, txq, tid, &bf_head);
+       if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+               if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
+                   (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
+                       txtid->addba_exchangeattempts++;
+                       return true;
+               }
        }
 
-       spin_unlock_bh(&txq->axq_lock);
+       return false;
 }
 
-/* Completion routine of an aggregate */
+/********************/
+/* Queue Management */
+/********************/
 
-static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
-                                     struct ath_txq *txq,
-                                     struct ath_buf *bf,
-                                     struct list_head *bf_q,
-                                     int txok)
+static u32 ath_txq_depth(struct ath_softc *sc, int qnum)
 {
-       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;
-       struct list_head bf_head, bf_pending;
-       u16 seq_st = 0;
-       u32 ba[WME_BA_BMP_SIZE >> 5];
-       int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
+       return sc->tx.txq[qnum].axq_depth;
+}
 
-       skb = (struct sk_buff *)bf->bf_mpdu;
-       tx_info = IEEE80211_SKB_CB(skb);
+static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
+                                struct ath_beacon_config *conf)
+{
+       struct ieee80211_hw *hw = sc->hw;
 
-       if (tx_info->control.sta) {
-               an = (struct ath_node *)tx_info->control.sta->drv_priv;
-               tid = ATH_AN_2_TID(an, bf->bf_tidno);
-       }
+       /* fill in beacon config data */
 
-       isaggr = bf_isaggr(bf);
-       if (isaggr) {
-               if (txok) {
-                       if (ATH_DS_TX_BA(ds)) {
-                               /*
-                                * extract starting sequence and
-                                * block-ack bitmap
-                                */
-                               seq_st = ATH_DS_BA_SEQ(ds);
-                               memcpy(ba,
-                                       ATH_DS_BA_BITMAP(ds),
-                                       WME_BA_BMP_SIZE >> 3);
-                       } else {
-                               memset(ba, 0, WME_BA_BMP_SIZE >> 3);
+       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;
+}
 
-                               /*
-                                * AR5416 can become deaf/mute when BA
-                                * issue happens. Chip needs to be reset.
-                                * But AP code may have sychronization issues
-                                * when perform internal reset in this routine.
-                                * Only enable reset in STA mode for now.
-                                */
-                               if (sc->sc_ah->ah_opmode ==
-                                           NL80211_IFTYPE_STATION)
-                                       needreset = 1;
-                       }
-               } else {
-                       memset(ba, 0, WME_BA_BMP_SIZE >> 3);
+static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
+                                         struct ath_txq *txq)
+{
+       struct ath_atx_ac *ac, *ac_tmp;
+       struct ath_atx_tid *tid, *tid_tmp;
+
+       list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+               list_del(&ac->list);
+               ac->sched = false;
+               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);
                }
        }
+}
 
-       INIT_LIST_HEAD(&bf_pending);
-       INIT_LIST_HEAD(&bf_head);
-
-       while (bf) {
-               txfail = txpending = 0;
-               bf_next = bf->bf_next;
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
+{
+       struct ath_hal *ah = sc->sc_ah;
+       struct ath9k_tx_queue_info qi;
+       int qnum;
 
-               if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
-                       /* transmit completion, subframe is
-                        * acked by block ack */
-               } else if (!isaggr && txok) {
-                       /* transmit completion */
-               } else {
+       memset(&qi, 0, sizeof(qi));
+       qi.tqi_subtype = subtype;
+       qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
+       qi.tqi_physCompBuf = 0;
 
-                       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);
-                                       txpending = 1;
-                               } else {
-                                       bf->bf_state.bf_type |= BUF_XRETRY;
-                                       txfail = 1;
-                                       sendbar = 1;
-                               }
-                       } else {
-                               /*
-                                * cleanup in progress, just fail
-                                * the un-acked sub-frames
-                                */
-                               txfail = 1;
-                       }
-               }
+       /*
+        * Enable interrupts only for EOL and DESC conditions.
+        * We mark tx descriptors to receive a DESC interrupt
+        * when a tx queue gets deep; otherwise waiting for the
+        * EOL to reap descriptors.  Note that this is done to
+        * reduce interrupt load and this only defers reaping
+        * descriptors, never transmitting frames.  Aside from
+        * reducing interrupts this also permits more concurrency.
+        * The only potential downside is if the tx queue backs
+        * up in which case the top half of the kernel may backup
+        * due to a lack of tx descriptors.
+        *
+        * The UAPSD queue is an exception, since we take a desc-
+        * based intr on the EOSP frames.
+        */
+       if (qtype == ATH9K_TX_QUEUE_UAPSD)
+               qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
+       else
+               qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
+                       TXQ_FLAG_TXDESCINT_ENABLE;
+       qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+       if (qnum == -1) {
                /*
-                * Remove ath_buf's of this sub-frame from aggregate queue.
+                * NB: don't print a message, this happens
+                * normally on parts with too few tx queues
                 */
-               if (bf_next == NULL) {  /* last subframe in the aggregate */
-                       ASSERT(bf->bf_lastfrm == bf_last);
-
-                       /*
-                        * The last descriptor of the last sub frame could be
-                        * a holding descriptor for h/w. If that's the case,
-                        * bf->bf_lastfrm won't be in the bf_q.
-                        * Make sure we handle bf_q properly here.
-                        */
-
-                       if (!list_empty(bf_q)) {
-                               bf_lastq = list_entry(bf_q->prev,
-                                       struct ath_buf, list);
-                               list_cut_position(&bf_head,
-                                       bf_q, &bf_lastq->list);
-                       } else {
-                               /*
-                                * XXX: if the last subframe only has one
-                                * descriptor which is also being used as
-                                * a holding descriptor. Then the ath_buf
-                                * is not in the bf_q at all.
-                                */
-                               INIT_LIST_HEAD(&bf_head);
-                       }
-               } else {
-                       ASSERT(!list_empty(bf_q));
-                       list_cut_position(&bf_head,
-                               bf_q, &bf->bf_lastfrm->list);
-               }
-
-               if (!txpending) {
-                       /*
-                        * complete the acked-ones/xretried ones; update
-                        * block-ack window
-                        */
-                       spin_lock_bh(&txq->axq_lock);
-                       ath_tx_update_baw(sc, tid, bf->bf_seqno);
-                       spin_unlock_bh(&txq->axq_lock);
+               return NULL;
+       }
+       if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
+               DPRINTF(sc, ATH_DBG_FATAL,
+                       "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->tx.txq[qnum];
 
-                       /* complete this sub-frame */
-                       ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
-               } else {
-                       /*
-                        * retry the un-acked ones
-                        */
-                       /*
-                        * XXX: if the last descriptor is holding descriptor,
-                        * in order to requeue the frame to software queue, we
-                        * need to allocate a new descriptor and
-                        * copy the content of holding descriptor to it.
-                        */
-                       if (bf->bf_next == NULL &&
-                           bf_last->bf_status & ATH_BUFSTATUS_STALE) {
-                               struct ath_buf *tbf;
+               txq->axq_qnum = qnum;
+               txq->axq_link = NULL;
+               INIT_LIST_HEAD(&txq->axq_q);
+               INIT_LIST_HEAD(&txq->axq_acq);
+               spin_lock_init(&txq->axq_lock);
+               txq->axq_depth = 0;
+               txq->axq_aggr_depth = 0;
+               txq->axq_totalqueued = 0;
+               txq->axq_linkbuf = NULL;
+               sc->tx.txqsetup |= 1<<qnum;
+       }
+       return &sc->tx.txq[qnum];
+}
 
-                               /* allocate new descriptor */
-                               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->tx.txbuflock);
+static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
+{
+       int qnum;
 
-                               ATH_TXBUF_RESET(tbf);
+       switch (qtype) {
+       case ATH9K_TX_QUEUE_DATA:
+               if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
+                       DPRINTF(sc, ATH_DBG_FATAL,
+                               "HAL AC %u out of range, max %zu!\n",
+                               haltype, ARRAY_SIZE(sc->tx.hwq_map));
+                       return -1;
+               }
+               qnum = sc->tx.hwq_map[haltype];
+               break;
+       case ATH9K_TX_QUEUE_BEACON:
+               qnum = sc->beacon.beaconq;
+               break;
+       case ATH9K_TX_QUEUE_CAB:
+               qnum = sc->beacon.cabq->axq_qnum;
+               break;
+       default:
+               qnum = -1;
+       }
+       return qnum;
+}
 
-                               /* copy descriptor content */
-                               tbf->bf_mpdu = bf_last->bf_mpdu;
-                               tbf->bf_buf_addr = bf_last->bf_buf_addr;
-                               *(tbf->bf_desc) = *(bf_last->bf_desc);
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
+{
+       struct ath_txq *txq = NULL;
+       int qnum;
 
-                               /* link it to the frame */
-                               if (bf_lastq) {
-                                       bf_lastq->bf_desc->ds_link =
-                                               tbf->bf_daddr;
-                                       bf->bf_lastfrm = tbf;
-                                       ath9k_hw_cleartxdesc(sc->sc_ah,
-                                               bf->bf_lastfrm->bf_desc);
-                               } else {
-                                       tbf->bf_state = bf_last->bf_state;
-                                       tbf->bf_lastfrm = tbf;
-                                       ath9k_hw_cleartxdesc(sc->sc_ah,
-                                               tbf->bf_lastfrm->bf_desc);
-
-                                       /* copy the DMA context */
-                                       tbf->bf_dmacontext =
-                                               bf_last->bf_dmacontext;
-                               }
-                               list_add_tail(&tbf->list, &bf_head);
-                       } else {
-                               /*
-                                * Clear descriptor status words for
-                                * software retry
-                                */
-                               ath9k_hw_cleartxdesc(sc->sc_ah,
-                                                    bf->bf_lastfrm->bf_desc);
-                       }
+       qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+       txq = &sc->tx.txq[qnum];
 
-                       /*
-                        * Put this buffer to the temporary pending
-                        * queue to retain ordering
-                        */
-                       list_splice_tail_init(&bf_head, &bf_pending);
-               }
+       spin_lock_bh(&txq->axq_lock);
 
-               bf = bf_next;
+       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;
        }
 
-       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->state &= ~AGGR_ADDBA_COMPLETE;
-                       tid->addba_exchangeattempts = 0;
-                       spin_unlock_bh(&txq->axq_lock);
+       spin_unlock_bh(&txq->axq_lock);
 
-                       tid->state &= ~AGGR_CLEANUP;
+       return txq;
+}
 
-                       /* send buffered frames as singles */
-                       ath_tx_flush_tid(sc, tid);
-               } else
-                       spin_unlock_bh(&txq->axq_lock);
+int ath_txq_update(struct ath_softc *sc, int qnum,
+                  struct ath9k_tx_queue_info *qinfo)
+{
+       struct ath_hal *ah = sc->sc_ah;
+       int error = 0;
+       struct ath9k_tx_queue_info qi;
 
-               return;
+       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->beacon.beacon_qi = *qinfo;
+               return 0;
        }
 
-       /*
-        * prepend un-acked frames to the beginning of the pending frame queue
-        */
-       if (!list_empty(&bf_pending)) {
-               spin_lock_bh(&txq->axq_lock);
-               /* Note: we _prepend_, we _do_not_ at to
-                * the end of the queue ! */
-               list_splice(&bf_pending, &tid->buf_q);
-               ath_tx_queue_tid(txq, tid);
-               spin_unlock_bh(&txq->axq_lock);
-       }
+       ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
 
-       if (needreset)
-               ath_reset(sc, false);
+       ath9k_hw_get_txq_props(ah, qnum, &qi);
+       qi.tqi_aifs = qinfo->tqi_aifs;
+       qi.tqi_cwmin = qinfo->tqi_cwmin;
+       qi.tqi_cwmax = qinfo->tqi_cwmax;
+       qi.tqi_burstTime = qinfo->tqi_burstTime;
+       qi.tqi_readyTime = qinfo->tqi_readyTime;
 
-       return;
+       if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
+               DPRINTF(sc, ATH_DBG_FATAL,
+                       "Unable to update hardware queue %u!\n", qnum);
+               error = -EIO;
+       } else {
+               ath9k_hw_resettxqueue(ah, qnum);
+       }
+
+       return error;
 }
 
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad)
+int ath_cabq_update(struct ath_softc *sc)
 {
-       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);
+       struct ath9k_tx_queue_info qi;
+       int qnum = sc->beacon.cabq->axq_qnum;
+       struct ath_beacon_config conf;
 
-       tx_info_priv->update_rc = false;
-       if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
-               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+       ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+       /*
+        * Ensure the readytime % is within the bounds.
+        */
+       if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
+               sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
+       else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
+               sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
 
-       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;
-               }
-       }
-}
+       ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf);
+       qi.tqi_readyTime =
+               (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100;
+       ath_txq_update(sc, qnum, &qi);
 
-/* Process completed xmit descriptors from the specified queue */
+       return 0;
+}
 
-static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
 {
-       struct ath_hal *ah = sc->sc_ah;
-       struct ath_buf *bf, *lastbf, *bf_held = NULL;
+       struct ath_buf *bf, *lastbf;
        struct list_head bf_head;
-       struct ath_desc *ds;
-       int txok, nbad = 0;
-       int status;
 
-       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);
+       INIT_LIST_HEAD(&bf_head);
 
        for (;;) {
                spin_lock_bh(&txq->axq_lock);
+
                if (list_empty(&txq->axq_q)) {
                        txq->axq_link = NULL;
                        txq->axq_linkbuf = NULL;
                        spin_unlock_bh(&txq->axq_lock);
                        break;
                }
+
                bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
 
-               /*
-                * There is a race condition that a BH gets scheduled
-                * after sw writes TxE 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.
-                */
-               bf_held = NULL;
                if (bf->bf_status & ATH_BUFSTATUS_STALE) {
-                       bf_held = bf;
-                       if (list_is_last(&bf_held->list, &txq->axq_q)) {
-                               /* FIXME:
-                                * The holding descriptor is the last
-                                * descriptor in queue. It's safe to remove
-                                * the last holding descriptor in BH context.
-                                */
-                               spin_unlock_bh(&txq->axq_lock);
-                               break;
-                       } else {
-                               /* Lets work with the next buffer now */
-                               bf = list_entry(bf_held->list.next,
-                                       struct ath_buf, list);
-                       }
+                       list_del(&bf->list);
+                       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);
+                       continue;
                }
 
                lastbf = bf->bf_lastbf;
-               ds = lastbf->bf_desc;    /* NB: last decriptor */
-
-               status = ath9k_hw_txprocdesc(ah, ds);
-               if (status == -EINPROGRESS) {
-                       spin_unlock_bh(&txq->axq_lock);
-                       break;
-               }
-               if (bf->bf_desc == txq->axq_lastdsWithCTS)
-                       txq->axq_lastdsWithCTS = NULL;
-               if (ds == txq->axq_gatingds)
-                       txq->axq_gatingds = NULL;
-
-               /*
-                * Remove ath_buf's of the same transmit unit from txq,
-                * however leave the last descriptor back as the holding
-                * descriptor for hw.
-                */
-               lastbf->bf_status |= ATH_BUFSTATUS_STALE;
-               INIT_LIST_HEAD(&bf_head);
-
-               if (!list_is_singular(&lastbf->list))
-                       list_cut_position(&bf_head,
-                               &txq->axq_q, lastbf->list.prev);
+               if (!retry_tx)
+                       lastbf->bf_desc->ds_txstat.ts_flags =
+                               ATH9K_TX_SW_ABORTED;
 
+               /* remove ath_buf's of the same mpdu from txq */
+               list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
                txq->axq_depth--;
 
-               if (bf_isaggr(bf))
-                       txq->axq_aggr_depth--;
-
-               txok = (ds->ds_txstat.ts_status == 0);
-
                spin_unlock_bh(&txq->axq_lock);
 
-               if (bf_held) {
-                       list_del(&bf_held->list);
-                       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)) {
-                       /*
-                        * This frame is sent out as a single frame.
-                        * Use hardware retry status for this frame.
-                        */
-                       bf->bf_retries = ds->ds_txstat.ts_longretry;
-                       if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
-                               bf->bf_state.bf_type |= BUF_XRETRY;
-                       nbad = 0;
-               } else {
-                       nbad = ath_tx_num_badfrms(sc, bf, txok);
-               }
-
-               ath_tx_rc_status(bf, ds, nbad);
-
-               /*
-                * Complete this transmit unit
-                */
                if (bf_isampdu(bf))
-                       ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok);
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
                else
-                       ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
-
-               /* Wake up mac80211 queue */
-
-               spin_lock_bh(&txq->axq_lock);
-               if (txq->stopped && ath_txq_depth(sc, txq->axq_qnum) <=
-                               (ATH_TXBUF - 20)) {
-                       int qnum;
-                       qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
-                       if (qnum != -1) {
-                               ieee80211_wake_queue(sc->hw, qnum);
-                               txq->stopped = 0;
-                       }
+                       ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+       }
 
+       /* flush any pending frames if aggregation is enabled */
+       if (sc->sc_flags & SC_OP_TXAGGR) {
+               if (!retry_tx) {
+                       spin_lock_bh(&txq->axq_lock);
+                       ath_txq_drain_pending_buffers(sc, txq);
+                       spin_unlock_bh(&txq->axq_lock);
                }
-
-               /*
-                * schedule any pending packets if aggregation is enabled
-                */
-               if (sc->sc_flags & SC_OP_TXAGGR)
-                       ath_txq_schedule(sc, txq);
-               spin_unlock_bh(&txq->axq_lock);
        }
 }
 
-static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
+void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hal *ah = sc->sc_ah;
+       struct ath_txq *txq;
+       int i, npend = 0;
 
-       (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum);
-       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);
-}
+       if (sc->sc_flags & SC_OP_INVALID)
+               return;
 
-/* Drain only the data queues */
+       /* Stop beacon queue */
+       ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 
-static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
-{
-       struct ath_hal *ah = sc->sc_ah;
-       int i, status, npend = 0;
-
-       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->tx.txq[i]);
-                               /* The TxDMA may not really be stopped.
-                                * Double check the hal tx pending count */
-                               npend += ath9k_hw_numtxpending(ah,
-                                                      sc->tx.txq[i].axq_qnum);
-                       }
+       /* Stop data queues */
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (ATH_TXQ_SETUP(sc, i)) {
+                       txq = &sc->tx.txq[i];
+                       ath9k_hw_stoptxdma(ah, txq->axq_qnum);
+                       npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
                }
        }
 
        if (npend) {
-               /* TxDMA not stopped, reset the hal */
+               int r;
+
                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->tx_chan_width,
-                                   sc->sc_tx_chainmask, sc->sc_rx_chainmask,
-                                   sc->sc_ht_extprotspacing, true, &status)) {
-
+               r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true);
+               if (r)
                        DPRINTF(sc, ATH_DBG_FATAL,
-                               "Unable to reset hardware; hal status %u\n",
-                               status);
-               }
+                               "Unable to reset hardware; reset status %u\n",
+                               r);
                spin_unlock_bh(&sc->sc_resetlock);
        }
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i))
-                       ath_tx_draintxq(sc, &sc->tx.txq[i], retry_tx);
+                       ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
        }
 }
 
-/* Add a sub-frame to block ack window */
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
+{
+       ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
+       sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
+}
 
-static void ath_tx_addto_baw(struct ath_softc *sc,
-                            struct ath_atx_tid *tid,
-                            struct ath_buf *bf)
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 {
-       int index, cindex;
+       struct ath_atx_ac *ac;
+       struct ath_atx_tid *tid;
 
-       if (bf_isretried(bf))
+       if (list_empty(&txq->axq_acq))
                return;
 
-       index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
-       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+       ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+       list_del(&ac->list);
+       ac->sched = false;
 
-       ASSERT(tid->tx_buf[cindex] == NULL);
-       tid->tx_buf[cindex] = bf;
+       do {
+               if (list_empty(&ac->tid_q))
+                       return;
 
-       if (index >= ((tid->baw_tail - tid->baw_head) &
-               (ATH_TID_MAX_BUFS - 1))) {
-               tid->baw_tail = cindex;
-               INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
+               tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
+               list_del(&tid->list);
+               tid->sched = false;
+
+               if (tid->paused)
+                       continue;
+
+               if ((txq->axq_depth % 2) == 0)
+                       ath_tx_sched_aggr(sc, txq, tid);
+
+               /*
+                * add tid to round-robin queue if more frames
+                * are pending for the tid
+                */
+               if (!list_empty(&tid->buf_q))
+                       ath_tx_queue_tid(txq, tid);
+
+               break;
+       } while (!list_empty(&ac->tid_q));
+
+       if (!list_empty(&ac->tid_q)) {
+               if (!ac->sched) {
+                       ac->sched = true;
+                       list_add_tail(&ac->list, &txq->axq_acq);
+               }
+       }
+}
+
+int ath_tx_setup(struct ath_softc *sc, int haltype)
+{
+       struct ath_txq *txq;
+
+       if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
+               DPRINTF(sc, ATH_DBG_FATAL,
+                       "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->tx.hwq_map[haltype] = txq->axq_qnum;
+               return 1;
+       } else
+               return 0;
 }
 
+/***********/
+/* TX, DMA */
+/***********/
+
 /*
- * Function to send an A-MPDU
- * NB: must be called with txq lock held
+ * Insert a chain of ath_buf (descriptors) on a txq and
+ * assume the descriptors are already chained together by caller.
  */
-static int ath_tx_send_ampdu(struct ath_softc *sc,
-                            struct ath_atx_tid *tid,
-                            struct list_head *bf_head,
-                            struct ath_tx_control *txctl)
+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;
 
-       BUG_ON(list_empty(bf_head));
+       /*
+        * Insert the frame on the outbound list and
+        * pass it on to the hardware.
+        */
+
+       if (list_empty(head))
+               return;
+
+       bf = list_first_entry(head, struct ath_buf, list);
+
+       list_splice_tail_init(head, &txq->axq_q);
+       txq->axq_depth++;
+       txq->axq_totalqueued++;
+       txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
+
+       DPRINTF(sc, ATH_DBG_QUEUE,
+               "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,
+                       "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, "link[%u] (%p)=%llx (%p)\n",
+                       txq->axq_qnum, txq->axq_link,
+                       ito64(bf->bf_daddr), bf->bf_desc);
+       }
+       txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
+       ath9k_hw_txstart(ah, txq->axq_qnum);
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+       struct ath_buf *bf = NULL;
+
+       spin_lock_bh(&sc->tx.txbuflock);
+
+       if (unlikely(list_empty(&sc->tx.txbuf))) {
+               spin_unlock_bh(&sc->tx.txbuflock);
+               return NULL;
+       }
+
+       bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       list_del(&bf->list);
+
+       spin_unlock_bh(&sc->tx.txbuflock);
+
+       return bf;
+}
+
+static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             struct list_head *bf_head,
+                             struct ath_tx_control *txctl)
+{
+       struct ath_buf *bf;
 
        bf = list_first_entry(bf_head, struct ath_buf, list);
        bf->bf_state.bf_type |= BUF_AMPDU;
@@ -1225,9 +1242,9 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
                 * Add this frame to software queue for scheduling later
                 * for aggregation.
                 */
-               list_splice_tail_init(bf_head, &tid->buf_q);
+               list_move_tail(&bf->list, &tid->buf_q);
                ath_tx_queue_tid(txctl->txq, tid);
-               return 0;
+               return;
        }
 
        /* Add sub-frame to BAW */
@@ -1235,421 +1252,317 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
 
        /* Queue to h/w without aggregation */
        bf->bf_nframes = 1;
-       bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */
+       bf->bf_lastbf = bf;
        ath_buf_set_rate(sc, bf);
        ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
-
-       return 0;
 }
 
-/*
- * 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_atx_tid *tid)
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+                              struct ath_atx_tid *tid,
+                              struct list_head *bf_head)
 {
-       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);
-       rates = tx_info->control.rates;
-       tx_info_priv =
-               (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
+       struct ath_buf *bf;
 
-       /*
-        * Find the lowest frame length among the rate series that will have a
-        * 4ms transmit duration.
-        * TODO - TXOP limit needs to be considered.
-        */
-       max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
+       bf = list_first_entry(bf_head, struct ath_buf, list);
+       bf->bf_state.bf_type &= ~BUF_AMPDU;
 
-       for (i = 0; i < 4; i++) {
-               if (rates[i].count) {
-                       if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
-                               legacy = 1;
-                               break;
-                       }
+       /* update starting sequence number for subsequent ADDBA request */
+       INCR(tid->seq_start, IEEE80211_SEQ_MAX);
 
-                       frame_length =
-                               rate_table->info[rates[i].idx].max_4ms_framelen;
-                       max_4ms_framelen = min(max_4ms_framelen, frame_length);
-               }
-       }
+       bf->bf_nframes = 1;
+       bf->bf_lastbf = bf;
+       ath_buf_set_rate(sc, bf);
+       ath_tx_txqaddbuf(sc, txq, bf_head);
+}
 
-       /*
-        * limit aggregate size by the minimum rate if rate selected is
-        * not a probe rate, if rate selected is a probe rate then
-        * avoid aggregation of this packet.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
-               return 0;
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr;
+       enum ath9k_pkt_type htype;
+       __le16 fc;
 
-       aggr_limit = min(max_4ms_framelen,
-               (u32)ATH_AMPDU_LIMIT_DEFAULT);
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
 
-       /*
-        * h/w can accept aggregates upto 16 bit lengths (65535).
-        * The IE, however can hold upto 65536, which shows up here
-        * as zero. Ignore 65536 since we  are constrained by hw.
-        */
-       maxampdu = tid->an->maxampdu;
-       if (maxampdu)
-               aggr_limit = min(aggr_limit, maxampdu);
+       if (ieee80211_is_beacon(fc))
+               htype = ATH9K_PKT_TYPE_BEACON;
+       else if (ieee80211_is_probe_resp(fc))
+               htype = ATH9K_PKT_TYPE_PROBE_RESP;
+       else if (ieee80211_is_atim(fc))
+               htype = ATH9K_PKT_TYPE_ATIM;
+       else if (ieee80211_is_pspoll(fc))
+               htype = ATH9K_PKT_TYPE_PSPOLL;
+       else
+               htype = ATH9K_PKT_TYPE_NORMAL;
 
-       return aggr_limit;
+       return htype;
 }
 
-/*
- * returns the number of delimiters to be added to
- * 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)
+static bool is_pae(struct sk_buff *skb)
 {
-       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;
-       int width, half_gi, ndelim, mindelim;
-
-       /* Select standard number of delimiters based on frame length alone */
-       ndelim = ATH_AGGR_GET_NDELIM(frmlen);
-
-       /*
-        * If encryption enabled, hardware requires some more padding between
-        * subframes.
-        * TODO - this could be improved to be dependent on the rate.
-        *      The hardware can keep up at lower rates, but not higher rates
-        */
-       if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
-               ndelim += ATH_AGGR_ENCRYPTDELIM;
-
-       /*
-        * Convert desired mpdu density from microeconds to bytes based
-        * on highest rate in rate series (i.e. first rate) to determine
-        * required minimum length for subframe. Take into account
-        * whether high rate is 20 or 40Mhz and half or full GI.
-        */
-       mpdudensity = tid->an->mpdudensity;
-
-       /*
-        * If there is no mpdu density restriction, no further calculation
-        * is needed.
-        */
-       if (mpdudensity == 0)
-               return ndelim;
-
-       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);
-       else
-               nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
-
-       if (nsymbols == 0)
-               nsymbols = 1;
+       struct ieee80211_hdr *hdr;
+       __le16 fc;
 
-       nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
-       minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
 
-       /* Is frame shorter than required minimum length? */
-       if (frmlen < minlen) {
-               /* Get the minimum number of delimiters required. */
-               mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
-               ndelim = max(mindelim, ndelim);
+       if (ieee80211_is_data(fc)) {
+               if (ieee80211_is_nullfunc(fc) ||
+                   /* Port Access Entity (IEEE 802.1X) */
+                   (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+                       return true;
+               }
        }
 
-       return ndelim;
+       return false;
 }
 
-/*
- * 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,
-                                       struct ath_buf **bf_last,
-                                       struct aggr_rifs_param *param,
-                                       int *prev_frames)
+static int get_hw_crypto_keytype(struct sk_buff *skb)
 {
-#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
-       struct ath_buf *bf, *tbf, *bf_first, *bf_prev = NULL;
-       struct list_head bf_head;
-       int rl = 0, nframes = 0, ndelim;
-       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;
-       INIT_LIST_HEAD(&bf_head);
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 
-       BUG_ON(list_empty(&tid->buf_q));
+       if (tx_info->control.hw_key) {
+               if (tx_info->control.hw_key->alg == ALG_WEP)
+                       return ATH9K_KEY_TYPE_WEP;
+               else if (tx_info->control.hw_key->alg == ALG_TKIP)
+                       return ATH9K_KEY_TYPE_TKIP;
+               else if (tx_info->control.hw_key->alg == ALG_CCMP)
+                       return ATH9K_KEY_TYPE_AES;
+       }
 
-       bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+       return ATH9K_KEY_TYPE_CLEAR;
+}
 
-       do {
-               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+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;
 
-               /*
-                * do not step over block-ack window
-                */
-               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
-                       status = ATH_AGGR_BAW_CLOSED;
-                       break;
-               }
+       if (!tx_info->control.sta)
+               return;
 
-               if (!rl) {
-                       aggr_limit = ath_lookup_rate(sc, bf, tid);
-                       rl = 1;
-               }
+       an = (struct ath_node *)tx_info->control.sta->drv_priv;
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
 
-               /*
-                * do not exceed aggregation limit
-                */
-               al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
+       if (ieee80211_is_data_qos(fc)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               bf->bf_tidno = qc[0] & 0xf;
+       }
 
-               if (nframes && (aggr_limit <
-                       (al + bpad + al_delta + prev_al))) {
-                       status = ATH_AGGR_LIMITED;
-                       break;
-               }
+       /*
+        * 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.
+        *
+        * 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.
+        */
+       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);
+}
 
-               /*
-                * do not exceed subframe limit
-                */
-               if ((nframes + *prev_frames) >=
-                   min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
-                       status = ATH_AGGR_LIMITED;
-                       break;
-               }
+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;
 
-               /*
-                * add padding for previous frame to aggregation length
-                */
-               al += bpad + al_delta;
+       flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+       flags |= ATH9K_TXDESC_INTREQ;
 
-               /*
-                * Get the delimiters needed to meet the MPDU
-                * density for this node.
-                */
-               ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
+       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;
 
-               bpad = PADBYTES(al_delta) + (ndelim << 2);
+       return flags;
+}
 
-               bf->bf_next = NULL;
-               bf->bf_lastfrm->bf_desc->ds_link = 0;
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * 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)
+{
+       struct ath_rate_table *rate_table = sc->cur_rate_table;
+       u32 nbits, nsymbits, duration, nsymbols;
+       u8 rc;
+       int streams, pktlen;
 
-               /*
-                * this packet is part of an aggregate
-                * - remove all descriptors belonging to this frame from
-                *   software queue
-                * - add it to block ack window
-                * - set up descriptors for aggregation
-                */
-               list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
-               ath_tx_addto_baw(sc, tid, bf);
+       pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
+       rc = rate_table->info[rix].ratecode;
 
-               list_for_each_entry(tbf, &bf_head, list) {
-                       ath9k_hw_set11n_aggr_middle(sc->sc_ah,
-                               tbf->bf_desc, ndelim);
-               }
+       /* for legacy rates, use old function to compute packet duration */
+       if (!IS_HT_RATE(rc))
+               return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
+                                             rix, shortPreamble);
 
-               /*
-                * link buffers of this frame to the aggregate
-                */
-               list_splice_tail_init(&bf_head, bf_q);
-               nframes++;
+       /* 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;
 
-               if (bf_prev) {
-                       bf_prev->bf_next = bf;
-                       bf_prev->bf_lastfrm->bf_desc->ds_link = bf->bf_daddr;
-               }
-               bf_prev = bf;
+       if (!half_gi)
+               duration = SYMBOL_TIME(nsymbols);
+       else
+               duration = SYMBOL_TIME_HALFGI(nsymbols);
 
-#ifdef AGGR_NOSHORT
-               /*
-                * terminate aggregation on a small packet boundary
-                */
-               if (bf->bf_frmlen < ATH_AGGR_MINPLEN) {
-                       status = ATH_AGGR_SHORTPKT;
-                       break;
-               }
-#endif
-       } while (!list_empty(&tid->buf_q));
+       /* 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);
 
-       bf_first->bf_al = al;
-       bf_first->bf_nframes = nframes;
-       *bf_last = bf_prev;
-       return status;
-#undef PADBYTES
+       return duration;
 }
 
-/*
- * 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)
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 {
-       struct ath_buf *bf, *tbf, *bf_last, *bf_lastaggr = NULL;
-       enum ATH_AGGR_STATUS status;
-       struct list_head bf_q;
-       struct aggr_rifs_param param = {0, 0, 0, 0, NULL};
-       int prev_frames = 0;
+       struct ath_hal *ah = sc->sc_ah;
+       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];
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_hw *hw = sc->hw;
+       int i, flags, rtsctsena = 0, enable_g_protection = 0;
+       u32 ctsduration = 0;
+       u8 rix = 0, cix, ctsrate = 0;
+       __le16 fc;
 
-       do {
-               if (list_empty(&tid->buf_q))
-                       return;
+       memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 
-               INIT_LIST_HEAD(&bf_q);
+       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;
 
-               status = ath_tx_form_aggr(sc, tid, &bf_q, &bf_lastaggr, &param,
-                                         &prev_frames);
+       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;
+       }
 
-               /*
-                * no frames picked up to be aggregated; block-ack
-                * window is not open
-                */
-               if (list_empty(&bf_q))
+       /* 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;
-
-               bf = list_first_entry(&bf_q, struct ath_buf, list);
-               bf_last = list_entry(bf_q.prev, struct ath_buf, list);
-               bf->bf_lastbf = bf_last;
-
-               /*
-                * if only one frame, send as non-aggregate
-                */
-               if (bf->bf_nframes == 1) {
-                       ASSERT(bf->bf_lastfrm == bf_last);
-
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
-                       /*
-                        * clear aggr bits for every descriptor
-                        * XXX TODO: is there a way to optimize it?
-                        */
-                       list_for_each_entry(tbf, &bf_q, list) {
-                               ath9k_hw_clr11n_aggr(sc->sc_ah, tbf->bf_desc);
-                       }
-
-                       ath_buf_set_rate(sc, bf);
-                       ath_tx_txqaddbuf(sc, txq, &bf_q);
-                       continue;
                }
+       }
 
-               /*
-                * setup first desc with rate and aggr info
-                */
-               bf->bf_state.bf_type |= BUF_AGGR;
-               ath_buf_set_rate(sc, bf);
-               ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
+       flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA));
+       cix = rt->info[rix].ctrl_rate;
 
-               /*
-                * anchor last frame of aggregate correctly
-                */
-               ASSERT(bf_lastaggr);
-               ASSERT(bf_lastaggr->bf_lastfrm == bf_last);
-               tbf = bf_lastaggr;
-               ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc);
-
-               /* XXX: We don't enter into this loop, consider removing this */
-               while (!list_empty(&bf_q) && !list_is_last(&tbf->list, &bf_q)) {
-                       tbf = list_entry(tbf->list.next, struct ath_buf, list);
-                       ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc);
-               }
+       /* All protection frames are transmited at 2Mb/s for 802.11g,
+        * otherwise we transmit them at 1Mb/s */
+       if (hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
+         !conf_is_ht(&hw->conf))
+               enable_g_protection = 1;
 
-               txq->axq_aggr_depth++;
-
-               /*
-                * Normal aggregate, queue to hardware
-                */
-               ath_tx_txqaddbuf(sc, txq, &bf_q);
+       /*
+        * 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 && !(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;
 
-       } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
-                status != ATH_AGGR_BAW_CLOSED);
-}
+               cix = rt->info[enable_g_protection].ctrl_rate;
+               rtsctsena = 1;
+       }
 
-/* Called with txq lock held */
+       /* 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)) {
+               /* 802.11g protection not needed, use our default behavior */
+               if (!rtsctsena)
+                       flags = ATH9K_TXDESC_RTSENA;
+       }
 
-static void ath_tid_drain(struct ath_softc *sc,
-                         struct ath_txq *txq,
-                         struct ath_atx_tid *tid)
+       /* 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[enable_g_protection].ctrl_rate;
+               rtsctsena = 1;
+       }
 
-{
-       struct ath_buf *bf;
-       struct list_head bf_head;
-       INIT_LIST_HEAD(&bf_head);
+       /* 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);
 
-       for (;;) {
-               if (list_empty(&tid->buf_q))
-                       break;
-               bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+       /*
+        * 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
+        */
+       ctsrate = rt->info[cix].ratecode |
+               (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0);
 
-               list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
+       for (i = 0; i < 4; i++) {
+               if (!rates[i].count || (rates[i].idx < 0))
+                       continue;
 
-               /* update baw for software retried frame */
-               if (bf_isretried(bf))
-                       ath_tx_update_baw(sc, tid, bf->bf_seqno);
+               rix = rates[i].idx;
 
-               /*
-                * do not indicate packets while holding txq spinlock.
-                * unlock is intentional here
-                */
-               spin_unlock(&txq->axq_lock);
+               series[i].Rate = rt->info[rix].ratecode |
+                       (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0);
 
-               /* complete this sub-frame */
-               ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+               series[i].Tries = rates[i].count;
 
-               spin_lock(&txq->axq_lock);
-       }
+               series[i].RateFlags = (
+                       (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ?
+                               ATH9K_RATESERIES_RTS_CTS : 0) |
+                       ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
+                               ATH9K_RATESERIES_2040 : 0) |
+                       ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ?
+                               ATH9K_RATESERIES_HALFGI : 0);
 
-       /*
-        * TODO: For frame(s) that are in the retry state, we will reuse the
-        * sequence number(s) without setting the retry bit. The
-        * alternative is to give up on these and BAR the receiver's window
-        * forward.
-        */
-       tid->seq_next = tid->seq_start;
-       tid->baw_tail = tid->baw_head;
-}
+               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));
 
-/*
- * 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)
-{
-       struct ath_atx_ac *ac, *ac_tmp;
-       struct ath_atx_tid *tid, *tid_tmp;
+               series[i].ChSel = sc->sc_tx_chainmask;
 
-       list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
-               list_del(&ac->list);
-               ac->sched = false;
-               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);
-               }
+               if (rtsctsena)
+                       series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
        }
+
+       /* 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);
 }
 
 static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
@@ -1671,33 +1584,23 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
 
        ATH_TXBUF_RESET(bf);
 
-       /* Frame type */
-
        bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
 
-       ieee80211_is_data(fc) ?
-               (bf->bf_state.bf_type |= BUF_DATA) :
-               (bf->bf_state.bf_type &= ~BUF_DATA);
-       ieee80211_is_back_req(fc) ?
-               (bf->bf_state.bf_type |= BUF_BAR) :
-               (bf->bf_state.bf_type &= ~BUF_BAR);
-       ieee80211_is_pspoll(fc) ?
-               (bf->bf_state.bf_type |= BUF_PSPOLL) :
-               (bf->bf_state.bf_type &= ~BUF_PSPOLL);
-       (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);
+       if (ieee80211_is_data(fc))
+               bf->bf_state.bf_type |= BUF_DATA;
+       if (ieee80211_is_back_req(fc))
+               bf->bf_state.bf_type |= BUF_BAR;
+       if (ieee80211_is_pspoll(fc))
+               bf->bf_state.bf_type |= BUF_PSPOLL;
+       if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+               bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE;
+       if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) &&
+            (tx_info->flags & IEEE80211_TX_CTL_AMPDU)))
+               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;
@@ -1705,20 +1608,17 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
                bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
        }
 
-       /* Assign seqno, tidno */
-
        if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
                assign_aggr_tid_seqno(skb, bf);
 
-       /* DMA setup */
        bf->bf_mpdu = skb;
 
-       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_dmacontext = dma_map_single(sc->dev, skb->data,
+                                          skb->len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
                bf->bf_mpdu = NULL;
                DPRINTF(sc, ATH_DBG_CONFIG,
-                       "pci_dma_mapping_error() on TX\n");
+                       "dma_mapping_error() on TX\n");
                return -ENOMEM;
        }
 
@@ -1744,14 +1644,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
        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;
 
-       /* Formulate first tx descriptor with tx controls */
-
        ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
                               bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
 
@@ -1761,8 +1657,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
                            true,       /* last segment */
                            ds);        /* first descriptor */
 
-       bf->bf_lastfrm = bf;
-
        spin_lock_bh(&txctl->txq->axq_lock);
 
        if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
@@ -1802,8 +1696,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
        struct ath_buf *bf;
        int r;
 
-       /* Check if a tx buffer is available */
-
        bf = ath_tx_get_buffer(sc);
        if (!bf) {
                DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
@@ -1840,580 +1732,395 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
        return 0;
 }
 
-/* Initialize TX queue and h/w */
-
-int ath_tx_init(struct ath_softc *sc, int nbufs)
+void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
 {
-       int error = 0;
+       int hdrlen, padsize;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ath_tx_control txctl;
 
-       do {
-               spin_lock_init(&sc->tx.txbuflock);
+       memset(&txctl, 0, sizeof(struct ath_tx_control));
 
-               /* Setup tx descriptors */
-               error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
-                       "tx", nbufs, 1);
-               if (error != 0) {
-                       DPRINTF(sc, ATH_DBG_FATAL,
-                               "Failed to allocate tx descriptors: %d\n",
-                               error);
-                       break;
-               }
+       /*
+        * As a temporary workaround, assign seq# here; this will likely need
+        * to be cleaned up to work better with Beacon transmission and virtual
+        * BSSes.
+        */
+       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->tx.seq_no += 0x10;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+       }
 
-               /* XXX allocate beacon state together with vap */
-               error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
-                                         "beacon", ATH_BCBUF, 1);
-               if (error != 0) {
-                       DPRINTF(sc, ATH_DBG_FATAL,
-                               "Failed to allocate beacon descriptors: %d\n",
-                               error);
-                       break;
+       /* Add the padding after the header if this is not already done */
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+       if (hdrlen & 3) {
+               padsize = hdrlen % 4;
+               if (skb_headroom(skb) < padsize) {
+                       DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
+                       dev_kfree_skb_any(skb);
+                       return;
                }
+               skb_push(skb, padsize);
+               memmove(skb->data, skb->data + padsize, hdrlen);
+       }
 
-       } while (0);
-
-       if (error != 0)
-               ath_tx_cleanup(sc);
-
-       return error;
-}
-
-/* Reclaim all tx queue resources */
-
-int ath_tx_cleanup(struct ath_softc *sc)
-{
-       /* cleanup beacon descriptors */
-       if (sc->beacon.bdma.dd_desc_len != 0)
-               ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
-
-       /* cleanup tx descriptors */
-       if (sc->tx.txdma.dd_desc_len != 0)
-               ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
-
-       return 0;
-}
-
-/* Setup a h/w transmit queue */
-
-struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
-{
-       struct ath_hal *ah = sc->sc_ah;
-       struct ath9k_tx_queue_info qi;
-       int qnum;
+       txctl.txq = sc->beacon.cabq;
 
-       memset(&qi, 0, sizeof(qi));
-       qi.tqi_subtype = subtype;
-       qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
-       qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
-       qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
-       qi.tqi_physCompBuf = 0;
+       DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
 
-       /*
-        * Enable interrupts only for EOL and DESC conditions.
-        * We mark tx descriptors to receive a DESC interrupt
-        * when a tx queue gets deep; otherwise waiting for the
-        * EOL to reap descriptors.  Note that this is done to
-        * reduce interrupt load and this only defers reaping
-        * descriptors, never transmitting frames.  Aside from
-        * reducing interrupts this also permits more concurrency.
-        * The only potential downside is if the tx queue backs
-        * up in which case the top half of the kernel may backup
-        * due to a lack of tx descriptors.
-        *
-        * The UAPSD queue is an exception, since we take a desc-
-        * based intr on the EOSP frames.
-        */
-       if (qtype == ATH9K_TX_QUEUE_UAPSD)
-               qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
-       else
-               qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
-                       TXQ_FLAG_TXDESCINT_ENABLE;
-       qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
-       if (qnum == -1) {
-               /*
-                * NB: don't print a message, this happens
-                * normally on parts with too few tx queues
-                */
-               return NULL;
-       }
-       if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
-               DPRINTF(sc, ATH_DBG_FATAL,
-                       "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_tx_start(sc, skb, &txctl) != 0) {
+               DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
+               goto exit;
        }
-       if (!ATH_TXQ_SETUP(sc, qnum)) {
-               struct ath_txq *txq = &sc->tx.txq[qnum];
 
-               txq->axq_qnum = qnum;
-               txq->axq_link = NULL;
-               INIT_LIST_HEAD(&txq->axq_q);
-               INIT_LIST_HEAD(&txq->axq_acq);
-               spin_lock_init(&txq->axq_lock);
-               txq->axq_depth = 0;
-               txq->axq_aggr_depth = 0;
-               txq->axq_totalqueued = 0;
-               txq->axq_linkbuf = NULL;
-               sc->tx.txqsetup |= 1<<qnum;
-       }
-       return &sc->tx.txq[qnum];
+       return;
+exit:
+       dev_kfree_skb_any(skb);
 }
 
-/* Reclaim resources for a setup queue */
+/*****************/
+/* TX Completion */
+/*****************/
 
-void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+                           struct ath_xmit_status *tx_status)
 {
-       ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
-       sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
-}
-
-/*
- * Setup a hardware data transmit queue for the specified
- * access control.  The hal may not support all requested
- * queues in which case it will return a reference to a
- * previously setup queue.  We record the mapping from ac's
- * to h/w queues for use by ath_tx_start and also track
- * the set of h/w queues being used to optimize work in the
- * transmit interrupt handler and related routines.
- */
+       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;
 
-int ath_tx_setup(struct ath_softc *sc, int haltype)
-{
-       struct ath_txq *txq;
+       DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
-       if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-               DPRINTF(sc, ATH_DBG_FATAL,
-                       "HAL AC %u out of range, max %zu!\n",
-                        haltype, ARRAY_SIZE(sc->tx.hwq_map));
-               return 0;
+       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;
        }
-       txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
-       if (txq != NULL) {
-               sc->tx.hwq_map[haltype] = txq->axq_qnum;
-               return 1;
-       } else
-               return 0;
-}
 
-int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
-{
-       int qnum;
+       if (tx_status->flags & ATH_TX_BAR) {
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+               tx_status->flags &= ~ATH_TX_BAR;
+       }
 
-       switch (qtype) {
-       case ATH9K_TX_QUEUE_DATA:
-               if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-                       DPRINTF(sc, ATH_DBG_FATAL,
-                               "HAL AC %u out of range, max %zu!\n",
-                               haltype, ARRAY_SIZE(sc->tx.hwq_map));
-                       return -1;
-               }
-               qnum = sc->tx.hwq_map[haltype];
-               break;
-       case ATH9K_TX_QUEUE_BEACON:
-               qnum = sc->beacon.beaconq;
-               break;
-       case ATH9K_TX_QUEUE_CAB:
-               qnum = sc->beacon.cabq->axq_qnum;
-               break;
-       default:
-               qnum = -1;
+       if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
        }
-       return qnum;
-}
 
-/* Get a transmit queue, if available */
+       tx_info->status.rates[0].count = tx_status->retries + 1;
 
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
+       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);
+       }
+
+       ieee80211_tx_status(hw, skb);
+}
+
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct list_head *bf_q,
+                               int txok, int sendbar)
 {
-       struct ath_txq *txq = NULL;
-       int qnum;
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ath_xmit_status tx_status;
+       unsigned long flags;
 
-       qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
-       txq = &sc->tx.txq[qnum];
+       /*
+        * Set retry information.
+        * NB: Don't use the information in the descriptor, because the frame
+        * could be software retried.
+        */
+       tx_status.retries = bf->bf_retries;
+       tx_status.flags = 0;
 
-       spin_lock_bh(&txq->axq_lock);
+       if (sendbar)
+               tx_status.flags = ATH_TX_BAR;
 
-       /* 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;
+       if (!txok) {
+               tx_status.flags |= ATH_TX_ERROR;
+
+               if (bf_isxretried(bf))
+                       tx_status.flags |= ATH_TX_XRETRY;
        }
 
-       spin_unlock_bh(&txq->axq_lock);
+       dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
+       ath_tx_complete(sc, skb, &tx_status);
 
-       return txq;
+       /*
+        * Return the list of ath_buf of this mpdu to free queue
+        */
+       spin_lock_irqsave(&sc->tx.txbuflock, flags);
+       list_splice_tail_init(bf_q, &sc->tx.txbuf);
+       spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
 }
 
-/* Update parameters for a transmit queue */
-
-int ath_txq_update(struct ath_softc *sc, int qnum,
-                  struct ath9k_tx_queue_info *qinfo)
+static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
+                             int txok)
 {
-       struct ath_hal *ah = sc->sc_ah;
-       int error = 0;
-       struct ath9k_tx_queue_info qi;
+       struct ath_buf *bf_last = bf->bf_lastbf;
+       struct ath_desc *ds = bf_last->bf_desc;
+       u16 seq_st = 0;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int ba_index;
+       int nbad = 0;
+       int isaggr = 0;
 
-       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->beacon.beacon_qi = *qinfo;
+       if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
                return 0;
-       }
 
-       ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
+       isaggr = bf_isaggr(bf);
+       if (isaggr) {
+               seq_st = ATH_DS_BA_SEQ(ds);
+               memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
+       }
 
-       ath9k_hw_get_txq_props(ah, qnum, &qi);
-       qi.tqi_aifs = qinfo->tqi_aifs;
-       qi.tqi_cwmin = qinfo->tqi_cwmin;
-       qi.tqi_cwmax = qinfo->tqi_cwmax;
-       qi.tqi_burstTime = qinfo->tqi_burstTime;
-       qi.tqi_readyTime = qinfo->tqi_readyTime;
+       while (bf) {
+               ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
+               if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+                       nbad++;
 
-       if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
-               DPRINTF(sc, ATH_DBG_FATAL,
-                       "Unable to update hardware queue %u!\n", qnum);
-               error = -EIO;
-       } else {
-               ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */
+               bf = bf->bf_next;
        }
 
-       return error;
+       return nbad;
 }
 
-int ath_cabq_update(struct ath_softc *sc)
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad)
 {
-       struct ath9k_tx_queue_info qi;
-       int qnum = sc->beacon.cabq->axq_qnum;
-       struct ath_beacon_config conf;
-
-       ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
-       /*
-        * Ensure the readytime % is within the bounds.
-        */
-       if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
-               sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
-       else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
-               sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
+       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);
 
-       ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf);
-       qi.tqi_readyTime =
-               (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100;
-       ath_txq_update(sc, qnum, &qi);
+       tx_info_priv->update_rc = false;
+       if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
+               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 
-       return 0;
+       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;
+               }
+       }
 }
 
-/* Deferred processing of transmit interrupt */
-
-void ath_tx_tasklet(struct ath_softc *sc)
+static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
 {
-       int i;
-       u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
-
-       ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
+       int qnum;
 
-       /*
-        * Process each active queue.
-        */
-       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-               if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
-                       ath_tx_processq(sc, &sc->tx.txq[i]);
+       spin_lock_bh(&txq->axq_lock);
+       if (txq->stopped &&
+           ath_txq_depth(sc, txq->axq_qnum) <= (ATH_TXBUF - 20)) {
+               qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
+               if (qnum != -1) {
+                       ieee80211_wake_queue(sc->hw, qnum);
+                       txq->stopped = 0;
+               }
        }
+       spin_unlock_bh(&txq->axq_lock);
 }
 
-void ath_tx_draintxq(struct ath_softc *sc,
-       struct ath_txq *txq, bool retry_tx)
+static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 {
-       struct ath_buf *bf, *lastbf;
+       struct ath_hal *ah = sc->sc_ah;
+       struct ath_buf *bf, *lastbf, *bf_held = NULL;
        struct list_head bf_head;
+       struct ath_desc *ds;
+       int txok, nbad = 0;
+       int status;
 
-       INIT_LIST_HEAD(&bf_head);
+       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);
 
-       /*
-        * NB: this assumes output has been stopped and
-        *     we do not need to block ath_tx_tasklet
-        */
        for (;;) {
                spin_lock_bh(&txq->axq_lock);
-
                if (list_empty(&txq->axq_q)) {
                        txq->axq_link = NULL;
                        txq->axq_linkbuf = NULL;
                        spin_unlock_bh(&txq->axq_lock);
                        break;
                }
-
                bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
 
+               /*
+                * There is a race condition that a BH gets scheduled
+                * after sw writes TxE 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.
+                */
+               bf_held = NULL;
                if (bf->bf_status & ATH_BUFSTATUS_STALE) {
-                       list_del(&bf->list);
-                       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);
-                       continue;
-               }
-
-               lastbf = bf->bf_lastbf;
-               if (!retry_tx)
-                       lastbf->bf_desc->ds_txstat.ts_flags =
-                               ATH9K_TX_SW_ABORTED;
-
-               /* remove ath_buf's of the same mpdu from txq */
-               list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
-               txq->axq_depth--;
-
-               spin_unlock_bh(&txq->axq_lock);
+                       bf_held = bf;
+                       if (list_is_last(&bf_held->list, &txq->axq_q)) {
+                               txq->axq_link = NULL;
+                               txq->axq_linkbuf = NULL;
+                               spin_unlock_bh(&txq->axq_lock);
 
-               if (bf_isampdu(bf))
-                       ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0);
-               else
-                       ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
-       }
+                               /*
+                                * The holding descriptor is the last
+                                * descriptor in queue. It's safe to remove
+                                * the last holding descriptor in BH context.
+                                */
+                               spin_lock_bh(&sc->tx.txbuflock);
+                               list_move_tail(&bf_held->list, &sc->tx.txbuf);
+                               spin_unlock_bh(&sc->tx.txbuflock);
 
-       /* flush any pending frames if aggregation is enabled */
-       if (sc->sc_flags & SC_OP_TXAGGR) {
-               if (!retry_tx) {
-                       spin_lock_bh(&txq->axq_lock);
-                       ath_txq_drain_pending_buffers(sc, txq);
-                       spin_unlock_bh(&txq->axq_lock);
+                               break;
+                       } else {
+                               bf = list_entry(bf_held->list.next,
+                                               struct ath_buf, list);
+                       }
                }
-       }
-}
-
-/* Drain the transmit queues and reclaim resources */
-
-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->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);
-}
-
-u32 ath_txq_depth(struct ath_softc *sc, int qnum)
-{
-       return sc->tx.txq[qnum].axq_depth;
-}
-
-u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum)
-{
-       return sc->tx.txq[qnum].axq_aggr_depth;
-}
-
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
-       struct ath_atx_tid *txtid;
-
-       if (!(sc->sc_flags & SC_OP_TXAGGR))
-               return false;
 
-       txtid = ATH_AN_2_TID(an, tidno);
+               lastbf = bf->bf_lastbf;
+               ds = lastbf->bf_desc;
 
-       if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
-               if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
-                   (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
-                       txtid->addba_exchangeattempts++;
-                       return true;
+               status = ath9k_hw_txprocdesc(ah, ds);
+               if (status == -EINPROGRESS) {
+                       spin_unlock_bh(&txq->axq_lock);
+                       break;
                }
-       }
+               if (bf->bf_desc == txq->axq_lastdsWithCTS)
+                       txq->axq_lastdsWithCTS = NULL;
+               if (ds == txq->axq_gatingds)
+                       txq->axq_gatingds = NULL;
 
-       return false;
-}
+               /*
+                * Remove ath_buf's of the same transmit unit from txq,
+                * however leave the last descriptor back as the holding
+                * descriptor for hw.
+                */
+               lastbf->bf_status |= ATH_BUFSTATUS_STALE;
+               INIT_LIST_HEAD(&bf_head);
+               if (!list_is_singular(&lastbf->list))
+                       list_cut_position(&bf_head,
+                               &txq->axq_q, lastbf->list.prev);
 
-/* Start TX aggregation */
+               txq->axq_depth--;
+               if (bf_isaggr(bf))
+                       txq->axq_aggr_depth--;
 
-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;
+               txok = (ds->ds_txstat.ts_status == 0);
+               spin_unlock_bh(&txq->axq_lock);
 
-       an = (struct ath_node *)sta->drv_priv;
+               if (bf_held) {
+                       spin_lock_bh(&sc->tx.txbuflock);
+                       list_move_tail(&bf_held->list, &sc->tx.txbuf);
+                       spin_unlock_bh(&sc->tx.txbuflock);
+               }
 
-       if (sc->sc_flags & SC_OP_TXAGGR) {
-               txtid = ATH_AN_2_TID(an, tid);
-               txtid->state |= AGGR_ADDBA_PROGRESS;
-               ath_tx_pause_tid(sc, txtid);
-       }
+               if (!bf_isampdu(bf)) {
+                       /*
+                        * This frame is sent out as a single frame.
+                        * Use hardware retry status for this frame.
+                        */
+                       bf->bf_retries = ds->ds_txstat.ts_longretry;
+                       if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
+                               bf->bf_state.bf_type |= BUF_XRETRY;
+                       nbad = 0;
+               } else {
+                       nbad = ath_tx_num_badfrms(sc, bf, txok);
+               }
 
-       return 0;
-}
+               ath_tx_rc_status(bf, ds, nbad);
 
-/* Stop tx aggregation */
+               if (bf_isampdu(bf))
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
+               else
+                       ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
 
-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_wake_mac80211_queue(sc, txq);
 
-       ath_tx_aggr_teardown(sc, an, tid);
-       return 0;
+               spin_lock_bh(&txq->axq_lock);
+               if (sc->sc_flags & SC_OP_TXAGGR)
+                       ath_txq_schedule(sc, txq);
+               spin_unlock_bh(&txq->axq_lock);
+       }
 }
 
-/* Resume tx aggregation */
 
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+void ath_tx_tasklet(struct ath_softc *sc)
 {
-       struct ath_atx_tid *txtid;
-       struct ath_node *an;
+       int i;
+       u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
 
-       an = (struct ath_node *)sta->drv_priv;
+       ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
 
-       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);
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
+                       ath_tx_processq(sc, &sc->tx.txq[i]);
        }
 }
 
-/*
- * Performs transmit side cleanup when TID changes from aggregated to
- * unaggregated.
- * - Pause the TID and mark cleanup in progress
- * - Discard all retry frames from the s/w queue.
- */
+/*****************/
+/* Init, Cleanup */
+/*****************/
 
-void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
+int ath_tx_init(struct ath_softc *sc, int nbufs)
 {
-       struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
-       struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
-       struct ath_buf *bf;
-       struct list_head bf_head;
-       INIT_LIST_HEAD(&bf_head);
-
-       if (txtid->state & AGGR_CLEANUP) /* cleanup is in progress */
-               return;
+       int error = 0;
 
-       if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
-               txtid->addba_exchangeattempts = 0;
-               return;
-       }
+       do {
+               spin_lock_init(&sc->tx.txbuflock);
 
-       /* TID must be paused first */
-       ath_tx_pause_tid(sc, txtid);
+               error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
+                       "tx", nbufs, 1);
+               if (error != 0) {
+                       DPRINTF(sc, ATH_DBG_FATAL,
+                               "Failed to allocate tx descriptors: %d\n",
+                               error);
+                       break;
+               }
 
-       /* drop all software retried frames and mark this TID */
-       spin_lock_bh(&txq->axq_lock);
-       while (!list_empty(&txtid->buf_q)) {
-               bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
-               if (!bf_isretried(bf)) {
-                       /*
-                        * NB: it's based on the assumption that
-                        * software retried frame will always stay
-                        * at the head of software queue.
-                        */
+               error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
+                                         "beacon", ATH_BCBUF, 1);
+               if (error != 0) {
+                       DPRINTF(sc, ATH_DBG_FATAL,
+                               "Failed to allocate beacon descriptors: %d\n",
+                               error);
                        break;
                }
-               list_cut_position(&bf_head,
-                       &txtid->buf_q, &bf->bf_lastfrm->list);
-               ath_tx_update_baw(sc, txtid, bf->bf_seqno);
 
-               /* complete this sub-frame */
-               ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
-       }
+       } while (0);
 
-       if (txtid->baw_head != txtid->baw_tail) {
-               spin_unlock_bh(&txq->axq_lock);
-               txtid->state |= AGGR_CLEANUP;
-       } else {
-               txtid->state &= ~AGGR_ADDBA_COMPLETE;
-               txtid->addba_exchangeattempts = 0;
-               spin_unlock_bh(&txq->axq_lock);
-               ath_tx_flush_tid(sc, txtid);
-       }
-}
+       if (error != 0)
+               ath_tx_cleanup(sc);
 
-/*
- * Tx scheduling logic
- * NB: must be called with txq lock held
- */
+       return error;
+}
 
-void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
+int ath_tx_cleanup(struct ath_softc *sc)
 {
-       struct ath_atx_ac *ac;
-       struct ath_atx_tid *tid;
-
-       /* nothing to schedule */
-       if (list_empty(&txq->axq_acq))
-               return;
-       /*
-        * get the first node/ac pair on the queue
-        */
-       ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
-       list_del(&ac->list);
-       ac->sched = false;
-
-       /*
-        * process a single tid per destination
-        */
-       do {
-               /* nothing to schedule */
-               if (list_empty(&ac->tid_q))
-                       return;
-
-               tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
-               list_del(&tid->list);
-               tid->sched = false;
-
-               if (tid->paused)    /* check next tid to keep h/w busy */
-                       continue;
-
-               if ((txq->axq_depth % 2) == 0)
-                       ath_tx_sched_aggr(sc, txq, tid);
-
-               /*
-                * add tid to round-robin queue if more frames
-                * are pending for the tid
-                */
-               if (!list_empty(&tid->buf_q))
-                       ath_tx_queue_tid(txq, tid);
+       if (sc->beacon.bdma.dd_desc_len != 0)
+               ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
 
-               /* only schedule one TID at a time */
-               break;
-       } while (!list_empty(&ac->tid_q));
+       if (sc->tx.txdma.dd_desc_len != 0)
+               ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
 
-       /*
-        * schedule AC if more TIDs need processing
-        */
-       if (!list_empty(&ac->tid_q)) {
-               /*
-                * add dest ac to txq if not already added
-                */
-               if (!ac->sched) {
-                       ac->sched = true;
-                       list_add_tail(&ac->list, &txq->axq_acq);
-               }
-       }
+       return 0;
 }
 
-/* Initialize per-node transmit state */
-
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 {
        struct ath_atx_tid *tid;
        struct ath_atx_ac *ac;
        int tidno, acno;
 
-       /*
-        * Init per tid tx state
-        */
        for (tidno = 0, tid = &an->tid[tidno];
             tidno < WME_NUM_TID;
             tidno++, tid++) {
@@ -2423,22 +2130,16 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
                tid->baw_size  = WME_MAX_BA;
                tid->baw_head  = tid->baw_tail = 0;
                tid->sched     = false;
-               tid->paused = 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->ac[acno];
             acno < WME_NUM_AC; acno++, ac++) {
                ac->sched    = false;
@@ -2465,14 +2166,13 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
        }
 }
 
-/* Cleanupthe pending buffers for the node. */
-
 void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 {
        int i;
        struct ath_atx_ac *ac, *ac_tmp;
        struct ath_atx_tid *tid, *tid_tmp;
        struct ath_txq *txq;
+
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i)) {
                        txq = &sc->tx.txq[i];
@@ -2503,51 +2203,3 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
                }
        }
 }
-
-void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
-{
-       int hdrlen, padsize;
-       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
-        * BSSes.
-        */
-       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->tx.seq_no += 0x10;
-               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-       }
-
-       /* Add the padding after the header if this is not already done */
-       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       if (hdrlen & 3) {
-               padsize = hdrlen % 4;
-               if (skb_headroom(skb) < padsize) {
-                       DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
-                       dev_kfree_skb_any(skb);
-                       return;
-               }
-               skb_push(skb, padsize);
-               memmove(skb->data, skb->data + padsize, hdrlen);
-       }
-
-       txctl.txq = sc->beacon.cabq;
-
-       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);
-}
index 4223672c4432a5784befad643e91b0f74e41cbb2..91930a2c3c6b61f0c5eddd0cc56b3320a7bf1f48 100644 (file)
@@ -2204,9 +2204,6 @@ static int atmel_get_frag(struct net_device *dev,
        return 0;
 }
 
-static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-                               2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-
 static int atmel_set_freq(struct net_device *dev,
                          struct iw_request_info *info,
                          struct iw_freq *fwrq,
@@ -2216,16 +2213,12 @@ static int atmel_set_freq(struct net_device *dev,
        int rc = -EINPROGRESS;          /* Call commit handler */
 
        /* If setting by frequency, convert to a channel */
-       if ((fwrq->e == 1) &&
-           (fwrq->m >= (int) 241200000) &&
-           (fwrq->m <= (int) 248700000)) {
+       if (fwrq->e == 1) {
                int f = fwrq->m / 100000;
-               int c = 0;
-               while ((c < 14) && (f != frequency_list[c]))
-                       c++;
+
                /* Hack to fall through... */
                fwrq->e = 0;
-               fwrq->m = c + 1;
+               fwrq->m = ieee80211_freq_to_dsss_chan(f);
        }
        /* Setting by channel number */
        if ((fwrq->m > 1000) || (fwrq->e > 0))
@@ -2384,8 +2377,11 @@ static int atmel_get_range(struct net_device *dev,
        if (range->num_channels != 0) {
                for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
                        range->freq[k].i = i; /* List index */
-                       range->freq[k].m = frequency_list[i - 1] * 100000;
-                       range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+
+                       /* Values in MHz -> * 10^5 * 10 */
+                       range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) *
+                                           100000);
+                       range->freq[k++].e = 1;
                }
                range->num_frequency = k;
        }
index 1f81d36f87c5e6cf8d254f87a8a161e987d2ef49..aab71a70ba788070b21a1452ba22478b0bbd5cd2 100644 (file)
@@ -110,10 +110,18 @@ config B43_DEBUG
        bool "Broadcom 43xx debugging"
        depends on B43
        ---help---
-         Broadcom 43xx debugging messages.
+         Broadcom 43xx debugging.
 
-         Say Y, if you want to find out why the driver does not
-         work for you.
+         This adds additional runtime sanity checks and statistics to the driver.
+         These checks and statistics might me expensive and hurt runtime performance
+         of your system.
+         This also adds the b43 debugfs interface.
+
+         Do not enable this, unless you are debugging the driver.
+
+         Say N, if you are a distributor or user building a release kernel
+         for production use.
+         Only say Y, if you are debugging a problem in the b43 driver sourcecode.
 
 config B43_FORCE_PIO
        bool "Force usage of PIO instead of DMA"
index a53c378e74844ebdca86dd83fb3b5c9104511b27..e9d60f0910be60a4bfdeb505dbf4bab5daf303b3 100644 (file)
@@ -655,10 +655,39 @@ struct b43_wl {
        struct work_struct txpower_adjust_work;
 };
 
+/* The type of the firmware file. */
+enum b43_firmware_file_type {
+       B43_FWTYPE_PROPRIETARY,
+       B43_FWTYPE_OPENSOURCE,
+       B43_NR_FWTYPES,
+};
+
+/* Context data for fetching firmware. */
+struct b43_request_fw_context {
+       /* The device we are requesting the fw for. */
+       struct b43_wldev *dev;
+       /* The type of firmware to request. */
+       enum b43_firmware_file_type req_type;
+       /* Error messages for each firmware type. */
+       char errors[B43_NR_FWTYPES][128];
+       /* Temporary buffer for storing the firmware name. */
+       char fwname[64];
+       /* A fatal error occured while requesting. Firmware reqest
+        * can not continue, as any other reqest will also fail. */
+       int fatal_failure;
+};
+
 /* In-memory representation of a cached microcode file. */
 struct b43_firmware_file {
        const char *filename;
        const struct firmware *data;
+       /* Type of the firmware file name. Note that this does only indicate
+        * the type by the firmware name. NOT the file contents.
+        * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource
+        * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware
+        * binary code, not just the filename.
+        */
+       enum b43_firmware_file_type type;
 };
 
 /* Pointers to the firmware data and meta information about it. */
@@ -677,7 +706,8 @@ struct b43_firmware {
        /* Firmware patchlevel */
        u16 patch;
 
-       /* Set to true, if we are using an opensource firmware. */
+       /* Set to true, if we are using an opensource firmware.
+        * Use this to check for proprietary vs opensource. */
        bool opensource;
        /* Set to true, if the core needs a PCM firmware, but
         * we failed to load one. This is always false for
@@ -848,12 +878,9 @@ void b43err(struct b43_wl *wl, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
 void b43warn(struct b43_wl *wl, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
-#if B43_DEBUG
 void b43dbg(struct b43_wl *wl, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
-#else /* DEBUG */
-# define b43dbg(wl, fmt...) do { /* nothing */ } while (0)
-#endif /* DEBUG */
+
 
 /* A WARN_ON variant that vanishes when b43 debugging is disabled.
  * This _also_ evaluates the arg with debugging disabled. */
index e04fc91f569ea573f3c9d3dfad8551b710d98c32..bc2767da46e8ba2c56d80c19f966f2d5dd753e97 100644 (file)
@@ -367,34 +367,6 @@ static int mmio32write__write_file(struct b43_wldev *dev,
        return 0;
 }
 
-/* wl->irq_lock is locked */
-static ssize_t tsf_read_file(struct b43_wldev *dev,
-                            char *buf, size_t bufsize)
-{
-       ssize_t count = 0;
-       u64 tsf;
-
-       b43_tsf_read(dev, &tsf);
-       fappend("0x%08x%08x\n",
-               (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
-               (unsigned int)(tsf & 0xFFFFFFFFULL));
-
-       return count;
-}
-
-/* wl->irq_lock is locked */
-static int tsf_write_file(struct b43_wldev *dev,
-                         const char *buf, size_t count)
-{
-       u64 tsf;
-
-       if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1)
-               return -EINVAL;
-       b43_tsf_write(dev, tsf);
-
-       return 0;
-}
-
 static ssize_t txstat_read_file(struct b43_wldev *dev,
                                char *buf, size_t bufsize)
 {
@@ -691,15 +663,23 @@ B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1);
 B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1);
 B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
 B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
-B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
 B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
 B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
 B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
 
 
-int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
+bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
 {
-       return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
+       bool enabled;
+
+       enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
+       if (unlikely(enabled)) {
+               /* Force full debugging messages, if the user enabled
+                * some dynamic debugging feature. */
+               b43_modparam_verbose = B43_VERBOSITY_MAX;
+       }
+
+       return enabled;
 }
 
 static void b43_remove_dynamic_debug(struct b43_wldev *dev)
@@ -805,7 +785,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
        ADD_FILE(mmio16write, 0200);
        ADD_FILE(mmio32read, 0600);
        ADD_FILE(mmio32write, 0200);
-       ADD_FILE(tsf, 0600);
        ADD_FILE(txstat, 0400);
        ADD_FILE(restart, 0200);
        ADD_FILE(loctls, 0400);
@@ -834,7 +813,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
        debugfs_remove(e->file_mmio16write.dentry);
        debugfs_remove(e->file_mmio32read.dentry);
        debugfs_remove(e->file_mmio32write.dentry);
-       debugfs_remove(e->file_tsf.dentry);
        debugfs_remove(e->file_txstat.dentry);
        debugfs_remove(e->file_restart.dentry);
        debugfs_remove(e->file_loctls.dentry);
index 7886cbe2d1d19276f22e3a974dd4d7e44a55347b..b9d4de4a979c7a9188858729ab41a58fcdae7eba 100644 (file)
@@ -46,7 +46,6 @@ struct b43_dfsentry {
        struct b43_dfs_file file_mmio16write;
        struct b43_dfs_file file_mmio32read;
        struct b43_dfs_file file_mmio32write;
-       struct b43_dfs_file file_tsf;
        struct b43_dfs_file file_txstat;
        struct b43_dfs_file file_txpower_g;
        struct b43_dfs_file file_restart;
@@ -72,7 +71,7 @@ struct b43_dfsentry {
        struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG];
 };
 
-int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature);
+bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature);
 
 void b43_debugfs_init(void);
 void b43_debugfs_exit(void);
@@ -83,7 +82,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
 
 #else /* CONFIG_B43_DEBUG */
 
-static inline int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
+static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
 {
        return 0;
 }
index c788bad10661b5fa2442d37ea636561e95258688..dbb8765506e8b99507f2b1aa04782954eab0913f 100644 (file)
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -88,6 +88,10 @@ static int modparam_btcoex = 1;
 module_param_named(btcoex, modparam_btcoex, int, 0444);
 MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)");
 
+int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
+module_param_named(verbose, b43_modparam_verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
+
 
 static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
@@ -97,6 +101,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
+       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15),
+       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
        SSB_DEVTABLE_END
 };
 
@@ -298,6 +304,8 @@ void b43info(struct b43_wl *wl, const char *fmt, ...)
 {
        va_list args;
 
+       if (b43_modparam_verbose < B43_VERBOSITY_INFO)
+               return;
        if (!b43_ratelimit(wl))
                return;
        va_start(args, fmt);
@@ -311,6 +319,8 @@ void b43err(struct b43_wl *wl, const char *fmt, ...)
 {
        va_list args;
 
+       if (b43_modparam_verbose < B43_VERBOSITY_ERROR)
+               return;
        if (!b43_ratelimit(wl))
                return;
        va_start(args, fmt);
@@ -324,6 +334,8 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...)
 {
        va_list args;
 
+       if (b43_modparam_verbose < B43_VERBOSITY_WARN)
+               return;
        if (!b43_ratelimit(wl))
                return;
        va_start(args, fmt);
@@ -333,18 +345,18 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...)
        va_end(args);
 }
 
-#if B43_DEBUG
 void b43dbg(struct b43_wl *wl, const char *fmt, ...)
 {
        va_list args;
 
+       if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
+               return;
        va_start(args, fmt);
        printk(KERN_DEBUG "b43-%s debug: ",
               (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
        vprintk(fmt, args);
        va_end(args);
 }
-#endif /* DEBUG */
 
 static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
 {
@@ -526,52 +538,20 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
 }
 
-void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
+void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
 {
-       /* We need to be careful. As we read the TSF from multiple
-        * registers, we should take care of register overflows.
-        * In theory, the whole tsf read process should be atomic.
-        * We try to be atomic here, by restaring the read process,
-        * if any of the high registers changed (overflew).
-        */
-       if (dev->dev->id.revision >= 3) {
-               u32 low, high, high2;
+       u32 low, high;
 
-               do {
-                       high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
-                       low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
-                       high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
-               } while (unlikely(high != high2));
+       B43_WARN_ON(dev->dev->id.revision < 3);
 
-               *tsf = high;
-               *tsf <<= 32;
-               *tsf |= low;
-       } else {
-               u64 tmp;
-               u16 v0, v1, v2, v3;
-               u16 test1, test2, test3;
-
-               do {
-                       v3 = b43_read16(dev, B43_MMIO_TSF_3);
-                       v2 = b43_read16(dev, B43_MMIO_TSF_2);
-                       v1 = b43_read16(dev, B43_MMIO_TSF_1);
-                       v0 = b43_read16(dev, B43_MMIO_TSF_0);
+       /* The hardware guarantees us an atomic read, if we
+        * read the low register first. */
+       low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
+       high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
 
-                       test3 = b43_read16(dev, B43_MMIO_TSF_3);
-                       test2 = b43_read16(dev, B43_MMIO_TSF_2);
-                       test1 = b43_read16(dev, B43_MMIO_TSF_1);
-               } while (v3 != test3 || v2 != test2 || v1 != test1);
-
-               *tsf = v3;
-               *tsf <<= 48;
-               tmp = v2;
-               tmp <<= 32;
-               *tsf |= tmp;
-               tmp = v1;
-               tmp <<= 16;
-               *tsf |= tmp;
-               *tsf |= v0;
-       }
+       *tsf = high;
+       *tsf <<= 32;
+       *tsf |= low;
 }
 
 static void b43_time_lock(struct b43_wldev *dev)
@@ -598,35 +578,18 @@ static void b43_time_unlock(struct b43_wldev *dev)
 
 static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
 {
-       /* Be careful with the in-progress timer.
-        * First zero out the low register, so we have a full
-        * register-overflow duration to complete the operation.
-        */
-       if (dev->dev->id.revision >= 3) {
-               u32 lo = (tsf & 0x00000000FFFFFFFFULL);
-               u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+       u32 low, high;
 
-               b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0);
-               mmiowb();
-               b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi);
-               mmiowb();
-               b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo);
-       } else {
-               u16 v0 = (tsf & 0x000000000000FFFFULL);
-               u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
-               u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
-               u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+       B43_WARN_ON(dev->dev->id.revision < 3);
 
-               b43_write16(dev, B43_MMIO_TSF_0, 0);
-               mmiowb();
-               b43_write16(dev, B43_MMIO_TSF_3, v3);
-               mmiowb();
-               b43_write16(dev, B43_MMIO_TSF_2, v2);
-               mmiowb();
-               b43_write16(dev, B43_MMIO_TSF_1, v1);
-               mmiowb();
-               b43_write16(dev, B43_MMIO_TSF_0, v0);
-       }
+       low = tsf;
+       high = (tsf >> 32);
+       /* The hardware guarantees us an atomic write, if we
+        * write the low register first. */
+       b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low);
+       mmiowb();
+       b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high);
+       mmiowb();
 }
 
 void b43_tsf_write(struct b43_wldev *dev, u64 tsf)
@@ -937,8 +900,7 @@ static int b43_key_write(struct b43_wldev *dev,
                B43_WARN_ON(dev->key[i].keyconf == keyconf);
        }
        if (index < 0) {
-               /* Either pairwise key or address is 00:00:00:00:00:00
-                * for transmit-only keys. Search the index. */
+               /* Pairwise key. Get an empty slot for the key. */
                if (b43_new_kidx_api(dev))
                        sta_keys_start = 4;
                else
@@ -951,7 +913,7 @@ static int b43_key_write(struct b43_wldev *dev,
                        }
                }
                if (index < 0) {
-                       b43err(dev->wl, "Out of hardware key memory\n");
+                       b43warn(dev->wl, "Out of hardware key memory\n");
                        return -ENOSPC;
                }
        } else
@@ -1982,7 +1944,7 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
        return ret;
 }
 
-static void do_release_fw(struct b43_firmware_file *fw)
+void b43_do_release_fw(struct b43_firmware_file *fw)
 {
        release_firmware(fw->data);
        fw->data = NULL;
@@ -1991,10 +1953,10 @@ static void do_release_fw(struct b43_firmware_file *fw)
 
 static void b43_release_firmware(struct b43_wldev *dev)
 {
-       do_release_fw(&dev->fw.ucode);
-       do_release_fw(&dev->fw.pcm);
-       do_release_fw(&dev->fw.initvals);
-       do_release_fw(&dev->fw.initvals_band);
+       b43_do_release_fw(&dev->fw.ucode);
+       b43_do_release_fw(&dev->fw.pcm);
+       b43_do_release_fw(&dev->fw.initvals);
+       b43_do_release_fw(&dev->fw.initvals_band);
 }
 
 static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
@@ -2002,20 +1964,19 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
        const char *text;
 
        text = "You must go to "
-              "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
-              "and download the latest firmware (version 4).\n";
+              "http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware "
+              "and download the correct firmware for this driver version. "
+              "Please carefully read all instructions on this website.\n";
        if (error)
                b43err(wl, text);
        else
                b43warn(wl, text);
 }
 
-static int do_request_fw(struct b43_wldev *dev,
-                        const char *name,
-                        struct b43_firmware_file *fw,
-                        bool silent)
+int b43_do_request_fw(struct b43_request_fw_context *ctx,
+                     const char *name,
+                     struct b43_firmware_file *fw)
 {
-       char path[sizeof(modparam_fwpostfix) + 32];
        const struct firmware *blob;
        struct b43_fw_header *hdr;
        u32 size;
@@ -2023,29 +1984,49 @@ static int do_request_fw(struct b43_wldev *dev,
 
        if (!name) {
                /* Don't fetch anything. Free possibly cached firmware. */
-               do_release_fw(fw);
+               /* FIXME: We should probably keep it anyway, to save some headache
+                * on suspend/resume with multiband devices. */
+               b43_do_release_fw(fw);
                return 0;
        }
        if (fw->filename) {
-               if (strcmp(fw->filename, name) == 0)
+               if ((fw->type == ctx->req_type) &&
+                   (strcmp(fw->filename, name) == 0))
                        return 0; /* Already have this fw. */
                /* Free the cached firmware first. */
-               do_release_fw(fw);
+               /* FIXME: We should probably do this later after we successfully
+                * got the new fw. This could reduce headache with multiband devices.
+                * We could also redesign this to cache the firmware for all possible
+                * bands all the time. */
+               b43_do_release_fw(fw);
+       }
+
+       switch (ctx->req_type) {
+       case B43_FWTYPE_PROPRIETARY:
+               snprintf(ctx->fwname, sizeof(ctx->fwname),
+                        "b43%s/%s.fw",
+                        modparam_fwpostfix, name);
+               break;
+       case B43_FWTYPE_OPENSOURCE:
+               snprintf(ctx->fwname, sizeof(ctx->fwname),
+                        "b43-open%s/%s.fw",
+                        modparam_fwpostfix, name);
+               break;
+       default:
+               B43_WARN_ON(1);
+               return -ENOSYS;
        }
-
-       snprintf(path, ARRAY_SIZE(path),
-                "b43%s/%s.fw",
-                modparam_fwpostfix, name);
-       err = request_firmware(&blob, path, dev->dev->dev);
+       err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
        if (err == -ENOENT) {
-               if (!silent) {
-                       b43err(dev->wl, "Firmware file \"%s\" not found\n",
-                              path);
-               }
+               snprintf(ctx->errors[ctx->req_type],
+                        sizeof(ctx->errors[ctx->req_type]),
+                        "Firmware file \"%s\" not found\n", ctx->fwname);
                return err;
        } else if (err) {
-               b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n",
-                      path, err);
+               snprintf(ctx->errors[ctx->req_type],
+                        sizeof(ctx->errors[ctx->req_type]),
+                        "Firmware file \"%s\" request failed (err=%d)\n",
+                        ctx->fwname, err);
                return err;
        }
        if (blob->size < sizeof(struct b43_fw_header))
@@ -2068,20 +2049,24 @@ static int do_request_fw(struct b43_wldev *dev,
 
        fw->data = blob;
        fw->filename = name;
+       fw->type = ctx->req_type;
 
        return 0;
 
 err_format:
-       b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);
+       snprintf(ctx->errors[ctx->req_type],
+                sizeof(ctx->errors[ctx->req_type]),
+                "Firmware file \"%s\" format error.\n", ctx->fwname);
        release_firmware(blob);
 
        return -EPROTO;
 }
 
-static int b43_request_firmware(struct b43_wldev *dev)
+static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 {
-       struct b43_firmware *fw = &dev->fw;
-       const u8 rev = dev->dev->id.revision;
+       struct b43_wldev *dev = ctx->dev;
+       struct b43_firmware *fw = &ctx->dev->fw;
+       const u8 rev = ctx->dev->dev->id.revision;
        const char *filename;
        u32 tmshigh;
        int err;
@@ -2096,7 +2081,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
                filename = "ucode13";
        else
                goto err_no_ucode;
-       err = do_request_fw(dev, filename, &fw->ucode, 0);
+       err = b43_do_request_fw(ctx, filename, &fw->ucode);
        if (err)
                goto err_load;
 
@@ -2108,7 +2093,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
        else
                goto err_no_pcm;
        fw->pcm_request_failed = 0;
-       err = do_request_fw(dev, filename, &fw->pcm, 1);
+       err = b43_do_request_fw(ctx, filename, &fw->pcm);
        if (err == -ENOENT) {
                /* We did not find a PCM file? Not fatal, but
                 * core rev <= 10 must do without hwcrypto then. */
@@ -2144,7 +2129,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
        default:
                goto err_no_initvals;
        }
-       err = do_request_fw(dev, filename, &fw->initvals, 0);
+       err = b43_do_request_fw(ctx, filename, &fw->initvals);
        if (err)
                goto err_load;
 
@@ -2178,30 +2163,34 @@ static int b43_request_firmware(struct b43_wldev *dev)
        default:
                goto err_no_initvals;
        }
-       err = do_request_fw(dev, filename, &fw->initvals_band, 0);
+       err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
        if (err)
                goto err_load;
 
        return 0;
 
-err_load:
-       b43_print_fw_helptext(dev->wl, 1);
-       goto error;
-
 err_no_ucode:
-       err = -ENODEV;
-       b43err(dev->wl, "No microcode available for core rev %u\n", rev);
+       err = ctx->fatal_failure = -EOPNOTSUPP;
+       b43err(dev->wl, "The driver does not know which firmware (ucode) "
+              "is required for your device (wl-core rev %u)\n", rev);
        goto error;
 
 err_no_pcm:
-       err = -ENODEV;
-       b43err(dev->wl, "No PCM available for core rev %u\n", rev);
+       err = ctx->fatal_failure = -EOPNOTSUPP;
+       b43err(dev->wl, "The driver does not know which firmware (PCM) "
+              "is required for your device (wl-core rev %u)\n", rev);
        goto error;
 
 err_no_initvals:
-       err = -ENODEV;
-       b43err(dev->wl, "No Initial Values firmware file for PHY %u, "
-              "core rev %u\n", dev->phy.type, rev);
+       err = ctx->fatal_failure = -EOPNOTSUPP;
+       b43err(dev->wl, "The driver does not know which firmware (initvals) "
+              "is required for your device (wl-core rev %u)\n", rev);
+       goto error;
+
+err_load:
+       /* We failed to load this firmware image. The error message
+        * already is in ctx->errors. Return and let our caller decide
+        * what to do. */
        goto error;
 
 error:
@@ -2209,6 +2198,48 @@ error:
        return err;
 }
 
+static int b43_request_firmware(struct b43_wldev *dev)
+{
+       struct b43_request_fw_context *ctx;
+       unsigned int i;
+       int err;
+       const char *errmsg;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->dev = dev;
+
+       ctx->req_type = B43_FWTYPE_PROPRIETARY;
+       err = b43_try_request_fw(ctx);
+       if (!err)
+               goto out; /* Successfully loaded it. */
+       err = ctx->fatal_failure;
+       if (err)
+               goto out;
+
+       ctx->req_type = B43_FWTYPE_OPENSOURCE;
+       err = b43_try_request_fw(ctx);
+       if (!err)
+               goto out; /* Successfully loaded it. */
+       err = ctx->fatal_failure;
+       if (err)
+               goto out;
+
+       /* Could not find a usable firmware. Print the errors. */
+       for (i = 0; i < B43_NR_FWTYPES; i++) {
+               errmsg = ctx->errors[i];
+               if (strlen(errmsg))
+                       b43err(dev->wl, errmsg);
+       }
+       b43_print_fw_helptext(dev->wl, 1);
+       err = -ENOENT;
+
+out:
+       kfree(ctx);
+       return err;
+}
+
 static int b43_upload_microcode(struct b43_wldev *dev)
 {
        const size_t hdr_len = sizeof(struct b43_fw_header);
@@ -2319,8 +2350,11 @@ static int b43_upload_microcode(struct b43_wldev *dev)
        }
 
        if (b43_is_old_txhdr_format(dev)) {
+               /* We're over the deadline, but we keep support for old fw
+                * until it turns out to be in major conflict with something new. */
                b43warn(dev->wl, "You are using an old firmware image. "
-                       "Support for old firmware will be removed in July 2008.\n");
+                       "Support for old firmware will be removed soon "
+                       "(official deadline was July 2008).\n");
                b43_print_fw_helptext(dev->wl, 0);
        }
 
@@ -3221,6 +3255,43 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
        return 0;
 }
 
+static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
+{
+       struct b43_wl *wl = hw_to_b43_wl(hw);
+       struct b43_wldev *dev;
+       u64 tsf;
+
+       mutex_lock(&wl->mutex);
+       spin_lock_irq(&wl->irq_lock);
+       dev = wl->current_dev;
+
+       if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
+               b43_tsf_read(dev, &tsf);
+       else
+               tsf = 0;
+
+       spin_unlock_irq(&wl->irq_lock);
+       mutex_unlock(&wl->mutex);
+
+       return tsf;
+}
+
+static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+       struct b43_wl *wl = hw_to_b43_wl(hw);
+       struct b43_wldev *dev;
+
+       mutex_lock(&wl->mutex);
+       spin_lock_irq(&wl->irq_lock);
+       dev = wl->current_dev;
+
+       if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
+               b43_tsf_write(dev, tsf);
+
+       spin_unlock_irq(&wl->irq_lock);
+       mutex_unlock(&wl->mutex);
+}
+
 static void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
        struct ssb_device *sdev = dev->dev;
@@ -3442,7 +3513,7 @@ out_unlock_mutex:
        return err;
 }
 
-static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates)
+static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates)
 {
        struct ieee80211_supported_band *sband =
                dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
@@ -3520,21 +3591,29 @@ out_unlock_mutex:
 }
 
 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)
+                         struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                         struct ieee80211_key_conf *key)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
-       unsigned long flags;
        u8 algorithm;
        u8 index;
        int err;
+       static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
        if (modparam_nohwcrypt)
                return -ENOSPC; /* User disabled HW-crypto */
 
        mutex_lock(&wl->mutex);
-       spin_lock_irqsave(&wl->irq_lock, flags);
+       spin_lock_irq(&wl->irq_lock);
+       write_lock(&wl->tx_lock);
+       /* Why do we need all this locking here?
+        * mutex     -> Every config operation must take it.
+        * irq_lock  -> We modify the dev->key array, which is accessed
+        *              in the IRQ handlers.
+        * tx_lock   -> We modify the dev->key array, which is accessed
+        *              in the TX handler.
+        */
 
        dev = wl->current_dev;
        err = -ENODEV;
@@ -3551,7 +3630,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        err = -EINVAL;
        switch (key->alg) {
        case ALG_WEP:
-               if (key->keylen == 5)
+               if (key->keylen == LEN_WEP40)
                        algorithm = B43_SEC_ALGO_WEP40;
                else
                        algorithm = B43_SEC_ALGO_WEP104;
@@ -3578,17 +3657,19 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                        goto out_unlock;
                }
 
-               if (is_broadcast_ether_addr(addr)) {
-                       /* addr is FF:FF:FF:FF:FF:FF for default keys */
+               if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+                       if (WARN_ON(!sta)) {
+                               err = -EOPNOTSUPP;
+                               goto out_unlock;
+                       }
+                       /* Pairwise key with an assigned MAC address. */
+                       err = b43_key_write(dev, -1, algorithm,
+                                           key->key, key->keylen,
+                                           sta->addr, key);
+               } else {
+                       /* Group key */
                        err = b43_key_write(dev, index, algorithm,
                                            key->key, key->keylen, NULL, key);
-               } else {
-                       /*
-                        * either pairwise key or address is 00:00:00:00:00:00
-                        * for transmit-only keys
-                        */
-                       err = b43_key_write(dev, -1, algorithm,
-                                           key->key, key->keylen, addr, key);
                }
                if (err)
                        goto out_unlock;
@@ -3617,10 +3698,11 @@ out_unlock:
                b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
                       "mac: %pM\n",
                       cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
-                      addr);
+                      sta ? sta->addr : bcast_addr);
                b43_dump_keymemory(dev);
        }
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
+       write_unlock(&wl->tx_lock);
+       spin_unlock_irq(&wl->irq_lock);
        mutex_unlock(&wl->mutex);
 
        return err;
@@ -3796,6 +3878,12 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                break;
 #ifdef CONFIG_B43_NPHY
        case B43_PHYTYPE_N:
+               if (phy_rev > 4)
+                       unsupported = 1;
+               break;
+#endif
+#ifdef CONFIG_B43_PHY_LP
+       case B43_PHYTYPE_LP:
                if (phy_rev > 1)
                        unsupported = 1;
                break;
@@ -3849,7 +3937,11 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                        unsupported = 1;
                break;
        case B43_PHYTYPE_N:
-               if (radio_ver != 0x2055)
+               if (radio_ver != 0x2055 && radio_ver != 0x2056)
+                       unsupported = 1;
+               break;
+       case B43_PHYTYPE_LP:
+               if (radio_ver != 0x2062)
                        unsupported = 1;
                break;
        default:
@@ -4317,6 +4409,8 @@ static const struct ieee80211_ops b43_hw_ops = {
        .set_key                = b43_op_set_key,
        .get_stats              = b43_op_get_stats,
        .get_tx_stats           = b43_op_get_tx_stats,
+       .get_tsf                = b43_op_get_tsf,
+       .set_tsf                = b43_op_set_tsf,
        .start                  = b43_op_start,
        .stop                   = b43_op_stop,
        .set_tim                = b43_op_beacon_set_tim,
@@ -4446,6 +4540,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
                        break;
                case B43_PHYTYPE_G:
                case B43_PHYTYPE_N:
+               case B43_PHYTYPE_LP:
                        have_2ghz_phy = 1;
                        break;
                default:
@@ -4657,9 +4752,10 @@ static int b43_wireless_init(struct ssb_device *dev)
        INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
 
        ssb_set_devtypedata(dev, wl);
-       b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+       b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+               dev->bus->chip_id, dev->id.revision);
        err = 0;
-      out:
+out:
        return err;
 }
 
index f871a252cb555f7c00ae767e73bde8d38f019f17..40abcf5d1b4307d27fb0c6d8d48cb29fda85ee15 100644 (file)
 
 
 extern int b43_modparam_qos;
+extern int b43_modparam_verbose;
+
+/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
+ * you add or remove levels. */
+enum b43_verbosity {
+       B43_VERBOSITY_ERROR,
+       B43_VERBOSITY_WARN,
+       B43_VERBOSITY_INFO,
+       B43_VERBOSITY_DEBUG,
+       __B43_VERBOSITY_AFTERLAST, /* keep last */
+
+       B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1,
+#if B43_DEBUG
+       B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG,
+#else
+       B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO,
+#endif
+};
 
 
 /* Lightweight function to convert a frequency (in Mhz) to a channel number. */
@@ -121,4 +139,11 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
 void b43_mac_suspend(struct b43_wldev *dev);
 void b43_mac_enable(struct b43_wldev *dev);
 
+
+struct b43_request_fw_context;
+int b43_do_request_fw(struct b43_request_fw_context *ctx,
+                     const char *name,
+                     struct b43_firmware_file *fw);
+void b43_do_release_fw(struct b43_firmware_file *fw);
+
 #endif /* B43_MAIN_H_ */
index caac4a45f0bf799bcf576c4ec0ede550008bc6ad..88bb303ae9d5907524f839b6d59afbbfd67fee0d 100644 (file)
@@ -3191,6 +3191,7 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
         * Baseband attennuation. Subtract it. */
        bbatt_delta -= 4 * rfatt_delta;
 
+#if B43_DEBUG
        if (b43_debug(dev, B43_DBG_XMITPOWER)) {
                int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust;
                b43dbg(dev->wl,
@@ -3199,6 +3200,8 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
                       (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm),
                       bbatt_delta, rfatt_delta);
        }
+#endif /* DEBUG */
+
        /* So do we finally need to adjust something in hardware? */
        if ((rfatt_delta == 0) && (bbatt_delta == 0))
                goto no_adjustment_needed;
index fb996c27a19b4b3340b7e682f319eae0a627631e..879edc786713710fdde14c61257a61e5c4798645 100644 (file)
@@ -2650,7 +2650,7 @@ out_unlock_mutex:
        return err;
 }
 
-static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates)
+static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates)
 {
        struct ieee80211_supported_band *sband =
                dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
index 47bee0ee0a7c3b1a040f477f450a2ecd4692e4ee..7b3bad1796c7f12250057eeb0a9de0a0b7cc1be0 100644 (file)
@@ -1,25 +1,26 @@
 config IWLWIFI
-       tristate
+       bool "Intel Wireless Wifi"
+       depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+       default y
 
 config IWLCORE
        tristate "Intel Wireless Wifi Core"
-       depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+       depends on IWLWIFI
        select LIB80211
-       select IWLWIFI
        select MAC80211_LEDS if IWLWIFI_LEDS
        select LEDS_CLASS if IWLWIFI_LEDS
        select RFKILL if IWLWIFI_RFKILL
 
 config IWLWIFI_LEDS
-       bool
-       default n
+       bool "Enable LED support in iwlagn driver"
+       depends on IWLCORE
 
 config IWLWIFI_RFKILL
-       boolean "Iwlwifi RF kill support"
+       bool "Enable RF kill support in iwlagn driver"
        depends on IWLCORE
 
 config IWLWIFI_DEBUG
-       bool "Enable full debugging output in iwlagn driver"
+       bool "Enable full debugging output in iwlagn and iwl3945 drivers"
        depends on IWLCORE
        ---help---
          This option will enable debug tracing output for the iwlwifi drivers
@@ -51,7 +52,7 @@ config IWLWIFI_DEBUGFS
 
 config IWLAGN
        tristate "Intel Wireless WiFi Next Gen AGN"
-       depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+       depends on IWLWIFI
        select FW_LOADER
        select IWLCORE
        ---help---
@@ -104,13 +105,12 @@ config IWL5000
 
 config IWL3945
        tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
-       depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+       depends on IWLWIFI
        select FW_LOADER
        select LIB80211
-       select IWLWIFI
        select MAC80211_LEDS if IWL3945_LEDS
        select LEDS_CLASS if IWL3945_LEDS
-       select RFKILL if IWL3945_RFKILL
+       select RFKILL if IWLWIFI_RFKILL
        ---help---
          Select to build the driver supporting the:
 
@@ -133,10 +133,6 @@ config IWL3945
          say M here and read <file:Documentation/kbuild/modules.txt>.  The
          module will be called iwl3945.ko.
 
-config IWL3945_RFKILL
-       bool "Enable RF kill support in iwl3945 drivers"
-       depends on IWL3945
-
 config IWL3945_SPECTRUM_MEASUREMENT
        bool "Enable Spectrum Measurement in iwl3945 drivers"
        depends on IWL3945
@@ -148,30 +144,3 @@ config IWL3945_LEDS
        depends on IWL3945
        ---help---
          This option enables LEDS for the iwl3945 driver.
-
-config IWL3945_DEBUG
-       bool "Enable full debugging output in iwl3945 driver"
-       depends on IWL3945
-       ---help---
-         This option will enable debug tracing output for the iwl3945
-         driver.
-
-         This will result in the kernel module being ~100k larger.  You can
-         control which debug output is sent to the kernel log by setting the
-         value in
-
-                 /sys/bus/pci/drivers/${DRIVER}/debug_level
-
-         This entry will only exist if this option is enabled.
-
-         To set a value, simply echo an 8-byte hex value to the same file:
-
-                 % echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level
-
-         You can find the list of debug mask values in:
-                 drivers/net/wireless/iwlwifi/iwl-3945-debug.h
-
-         If this is your first time using this driver, you should say Y here
-         as the debug information can assist others in helping you resolve
-         any problems you may encounter.
-
index 0be9e6b66aa0f0187b8072dbf1c5879b0b3f8b58..fec2fbf8dc02342fa840de8d0ca1b27a47a79d3c 100644 (file)
@@ -12,6 +12,8 @@ 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
+iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
+iwlagn-$(CONFIG_IWL5000) += iwl-100.o
 
 obj-$(CONFIG_IWL3945)  += iwl3945.o
 iwl3945-objs           := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-100.c
new file mode 100644 (file)
index 0000000..dbadaf4
--- /dev/null
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008-2009 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.
+ *
+ * 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/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-sta.h"
+#include "iwl-helpers.h"
+#include "iwl-5000-hw.h"
+
+/* Highest firmware API version supported */
+#define IWL100_UCODE_API_MAX 1
+
+/* Lowest firmware API version supported */
+#define IWL100_UCODE_API_MIN 1
+
+#define IWL100_FW_PRE "iwlwifi-100-"
+#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
+#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api)
+
+struct iwl_cfg iwl100_bgn_cfg = {
+       .name = "100 Series BGN",
+       .fw_name_pre = IWL100_FW_PRE,
+       .ucode_api_max = IWL100_UCODE_API_MAX,
+       .ucode_api_min = IWL100_UCODE_API_MIN,
+       .sku = 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,
+};
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
deleted file mode 100644 (file)
index c6f4eb5..0000000
+++ /dev/null
@@ -1,1702 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 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
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945-commands.h) only for uCode API definitions.
- * Please use iwl-3945-hw.h for hardware-related definitions.
- * Please use iwl-3945.h for driver implementation definitions.
- */
-
-#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,
-
-       /* RXON and QOS commands */
-       REPLY_RXON = 0x10,
-       REPLY_RXON_ASSOC = 0x11,
-       REPLY_QOS_PARAM = 0x13,
-       REPLY_RXON_TIMING = 0x14,
-
-       /* Multi-Station support */
-       REPLY_ADD_STA = 0x18,
-       REPLY_REMOVE_STA = 0x19,        /* not used */
-       REPLY_REMOVE_ALL_STA = 0x1a,    /* not used */
-
-       /* RX, TX, LEDs */
-       REPLY_3945_RX = 0x1b,           /* 3945 only */
-       REPLY_TX = 0x1c,
-       REPLY_RATE_SCALE = 0x47,        /* 3945 only */
-       REPLY_LEDS_CMD = 0x48,
-       REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */
-
-       /* 802.11h related */
-       RADAR_NOTIFICATION = 0x70,      /* not used */
-       REPLY_QUIET_CMD = 0x71,         /* not used */
-       REPLY_CHANNEL_SWITCH = 0x72,
-       CHANNEL_SWITCH_NOTIFICATION = 0x73,
-       REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
-       SPECTRUM_MEASURE_NOTIFICATION = 0x75,
-
-       /* Power Management */
-       POWER_TABLE_CMD = 0x77,
-       PM_SLEEP_NOTIFICATION = 0x7A,
-       PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
-
-       /* Scan commands and notifications */
-       REPLY_SCAN_CMD = 0x80,
-       REPLY_SCAN_ABORT_CMD = 0x81,
-       SCAN_START_NOTIFICATION = 0x82,
-       SCAN_RESULTS_NOTIFICATION = 0x83,
-       SCAN_COMPLETE_NOTIFICATION = 0x84,
-
-       /* IBSS/AP commands */
-       BEACON_NOTIFICATION = 0x90,
-       REPLY_TX_BEACON = 0x91,
-       WHO_IS_AWAKE_NOTIFICATION = 0x94,       /* not used */
-
-       /* Miscellaneous commands */
-       QUIET_NOTIFICATION = 0x96,              /* not used */
-       REPLY_TX_PWR_TABLE_CMD = 0x97,
-       MEASURE_ABORT_NOTIFICATION = 0x99,      /* not used */
-
-       /* Bluetooth device coexistence config command */
-       REPLY_BT_CONFIG = 0x9b,
-
-       /* Statistics */
-       REPLY_STATISTICS_CMD = 0x9c,
-       STATISTICS_NOTIFICATION = 0x9d,
-
-       /* RF-KILL commands and notifications */
-       REPLY_CARD_STATE_CMD = 0xa0,
-       CARD_STATE_NOTIFICATION = 0xa1,
-
-       /* Missed beacons notification */
-       MISSED_BEACONS_NOTIFICATION = 0xa2,
-
-       REPLY_MAX = 0xff
-};
-
-/******************************************************************************
- * (0)
- * Commonly used structures and definitions:
- * Command header, txpower
- *
- *****************************************************************************/
-
-/* iwl3945_cmd_header flags value */
-#define IWL_CMD_FAILED_MSK 0x40
-
-/**
- * struct iwl3945_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
-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 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
-        * don't get used by uCode, the driver may set up an arbitrary format.
-        *
-        * There is one exception:  uCode sets bit 15 when it originates
-        * the response/notification, i.e. when the response/notification
-        * is not a direct response to a command sent by the driver.  For
-        * example, uCode issues REPLY_3945_RX when it sends a received frame
-        * to the driver; it is not a direct response to any driver command.
-        *
-        * The Linux driver uses the following format:
-        *
-        *  0:7    index/position within Tx queue
-        *  8:13   Tx queue selection
-        * 14:14   driver sets this to indicate command is in the 'huge'
-        *         storage at the end of the command buffers, i.e. scan cmd
-        * 15:15   uCode sets this in uCode-originated response/notification
-        */
-       __le16 sequence;
-
-       /* command or response/notification data follows immediately */
-       u8 data[0];
-} __attribute__ ((packed));
-
-/**
- * struct iwl3945_tx_power
- *
- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
- *
- * Each entry contains two values:
- * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
- *     linear value that multiplies the output of the digital signal processor,
- *     before being sent to the analog radio.
- * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
- *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
- *
- * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
- */
-struct iwl3945_tx_power {
-       u8 tx_gain;             /* gain for analog radio */
-       u8 dsp_atten;           /* gain for DSP */
-} __attribute__ ((packed));
-
-/**
- * struct iwl3945_power_per_rate
- *
- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
- */
-struct iwl3945_power_per_rate {
-       u8 rate;                /* plcp */
-       struct iwl3945_tx_power tpc;
-       u8 reserved;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (0a)
- * Alive and Error Commands & Responses:
- *
- *****************************************************************************/
-
-#define UCODE_VALID_OK cpu_to_le32(0x1)
-#define INITIALIZE_SUBTYPE    (9)
-
-/*
- * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
- *
- * uCode issues this "initialize alive" notification once the initialization
- * uCode image has completed its work, and is ready to load the runtime image.
- * This is the *first* "alive" notification that the driver will receive after
- * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
- *
- * See comments documenting "BSM" (bootstrap state machine).
- */
-struct iwl3945_init_alive_resp {
-       u8 ucode_minor;
-       u8 ucode_major;
-       __le16 reserved1;
-       u8 sw_rev[8];
-       u8 ver_type;
-       u8 ver_subtype;                 /* "9" for initialize alive */
-       __le16 reserved2;
-       __le32 log_event_table_ptr;
-       __le32 error_event_table_ptr;
-       __le32 timestamp;
-       __le32 is_valid;
-} __attribute__ ((packed));
-
-
-/**
- * REPLY_ALIVE = 0x1 (response only, not a command)
- *
- * uCode issues this "alive" notification once the runtime image is ready
- * to receive commands from the driver.  This is the *second* "alive"
- * notification that the driver will receive after rebooting uCode;
- * this "alive" is indicated by subtype field != 9.
- *
- * See comments documenting "BSM" (bootstrap state machine).
- *
- * This response includes two pointers to structures within the device's
- * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
- *
- * 1)  log_event_table_ptr indicates base of the event log.  This traces
- *     a 256-entry history of uCode execution within a circular buffer.
- *
- * 2)  error_event_table_ptr indicates base of the error log.  This contains
- *     information about any uCode error that occurs.
- *
- * The Linux driver can print both logs to the system log when a uCode error
- * occurs.
- */
-struct iwl3945_alive_resp {
-       u8 ucode_minor;
-       u8 ucode_major;
-       __le16 reserved1;
-       u8 sw_rev[8];
-       u8 ver_type;
-       u8 ver_subtype;                 /* not "9" for runtime alive */
-       __le16 reserved2;
-       __le32 log_event_table_ptr;     /* SRAM address for event log */
-       __le32 error_event_table_ptr;   /* SRAM address for error log */
-       __le32 timestamp;
-       __le32 is_valid;
-} __attribute__ ((packed));
-
-union tsf {
-       u8 byte[8];
-       __le16 word[4];
-       __le32 dw[2];
-};
-
-/*
- * REPLY_ERROR = 0x2 (response only, not a command)
- */
-struct iwl3945_error_resp {
-       __le32 error_type;
-       u8 cmd_id;
-       u8 reserved1;
-       __le16 bad_cmd_seq_num;
-       __le16 reserved2;
-       __le32 error_info;
-       union tsf timestamp;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (1)
- * RXON Commands & Responses:
- *
- *****************************************************************************/
-
-/*
- * Rx config defines & structure
- */
-/* rx_config device types  */
-enum {
-       RXON_DEV_TYPE_AP = 1,
-       RXON_DEV_TYPE_ESS = 3,
-       RXON_DEV_TYPE_IBSS = 4,
-       RXON_DEV_TYPE_SNIFFER = 6,
-};
-
-/* rx_config flags */
-/* band & modulation selection */
-#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        cpu_to_le32(1 << 2)
-/* TGg protection when tx */
-#define RXON_FLG_TGG_PROTECT_MSK        cpu_to_le32(1 << 3)
-/* cck short slot & preamble */
-#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            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       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           cpu_to_le32(1 << 15)
-
-/* rx_config filter flags */
-/* accept all data frames */
-#define RXON_FILTER_PROMISC_MSK         cpu_to_le32(1 << 0)
-/* pass control & management to host */
-#define RXON_FILTER_CTL2HOST_MSK        cpu_to_le32(1 << 1)
-/* accept multi-cast */
-#define RXON_FILTER_ACCEPT_GRP_MSK      cpu_to_le32(1 << 2)
-/* don't decrypt uni-cast frames */
-#define RXON_FILTER_DIS_DECRYPT_MSK     cpu_to_le32(1 << 3)
-/* don't decrypt multi-cast frames */
-#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4)
-/* STA is associated */
-#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      cpu_to_le32(1 << 6)
-
-/**
- * REPLY_RXON = 0x10 (command, has simple generic response)
- *
- * RXON tunes the radio tuner to a service channel, and sets up a number
- * of parameters that are used primarily for Rx, but also for Tx operations.
- *
- * NOTE:  When tuning to a new channel, driver must set the
- *        RXON_FILTER_ASSOC_MSK to 0.  This will clear station-dependent
- *        info within the device, including the station tables, tx retry
- *        rate tables, and txpower tables.  Driver must build a new station
- *        table and txpower table before transmitting anything on the RXON
- *        channel.
- *
- * NOTE:  All RXONs wipe clean the internal txpower table.  Driver must
- *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
- *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
- */
-struct iwl3945_rxon_cmd {
-       u8 node_addr[6];
-       __le16 reserved1;
-       u8 bssid_addr[6];
-       __le16 reserved2;
-       u8 wlap_bssid_addr[6];
-       __le16 reserved3;
-       u8 dev_type;
-       u8 air_propagation;
-       __le16 reserved4;
-       u8 ofdm_basic_rates;
-       u8 cck_basic_rates;
-       __le16 assoc_id;
-       __le32 flags;
-       __le32 filter_flags;
-       __le16 channel;
-       __le16 reserved5;
-} __attribute__ ((packed));
-
-/*
- * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
- */
-struct iwl3945_rxon_assoc_cmd {
-       __le32 flags;
-       __le32 filter_flags;
-       u8 ofdm_basic_rates;
-       u8 cck_basic_rates;
-       __le16 reserved;
-} __attribute__ ((packed));
-
-/*
- * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
- */
-struct iwl3945_rxon_time_cmd {
-       union tsf timestamp;
-       __le16 beacon_interval;
-       __le16 atim_window;
-       __le32 beacon_init_val;
-       __le16 listen_interval;
-       __le16 reserved;
-} __attribute__ ((packed));
-
-/*
- * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
- */
-struct iwl3945_channel_switch_cmd {
-       u8 band;
-       u8 expect_beacon;
-       __le16 channel;
-       __le32 rxon_flags;
-       __le32 rxon_filter_flags;
-       __le32 switch_time;
-       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
-} __attribute__ ((packed));
-
-/*
- * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
- */
-struct iwl3945_csa_notification {
-       __le16 band;
-       __le16 channel;
-       __le32 status;          /* 0 - OK, 1 - fail */
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (2)
- * Quality-of-Service (QOS) Commands & Responses:
- *
- *****************************************************************************/
-
-/**
- * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
- * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
- *
- * @cw_min: Contention window, start value in numbers of slots.
- *          Should be a power-of-2, minus 1.  Device's default is 0x0f.
- * @cw_max: Contention window, max value in numbers of slots.
- *          Should be a power-of-2, minus 1.  Device's default is 0x3f.
- * @aifsn:  Number of slots in Arbitration Interframe Space (before
- *          performing random backoff timing prior to Tx).  Device default 1.
- * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.
- *
- * Device will automatically increase contention window by (2*CW) + 1 for each
- * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
- * value, to cap the CW value.
- */
-struct iwl3945_ac_qos {
-       __le16 cw_min;
-       __le16 cw_max;
-       u8 aifsn;
-       u8 reserved1;
-       __le16 edca_txop;
-} __attribute__ ((packed));
-
-/* QoS flags defines */
-#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
-
-/*
- * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
- *
- * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
- * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
- */
-struct iwl3945_qosparam_cmd {
-       __le32 qos_flags;
-       struct iwl3945_ac_qos ac[AC_NUM];
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (3)
- * Add/Modify Stations Commands & Responses:
- *
- *****************************************************************************/
-/*
- * Multi station support
- */
-
-/* Special, dedicated locations within device's station table */
-#define        IWL_AP_ID               0
-#define IWL_MULTICAST_ID       1
-#define        IWL_STA_ID              2
-#define        IWL3945_BROADCAST_ID    24
-#define IWL3945_STATION_COUNT  25
-
-#define        IWL_STATION_COUNT       32      /* MAX(3945,4965)*/
-#define        IWL_INVALID_STATION     255
-
-#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        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    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  cpu_to_le16(0x0008)
-
-/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
-#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
-#define        STA_MODIFY_TID_DISABLE_TX       0x02
-#define        STA_MODIFY_TX_RATE_MSK          0x04
-
-/*
- * Antenna masks:
- * bit14:15 01 B inactive, A active
- *          10 B active, A inactive
- *          11 Both active
- */
-#define RATE_MCS_ANT_A_POS     14
-#define RATE_MCS_ANT_B_POS     15
-#define RATE_MCS_ANT_A_MSK     0x4000
-#define RATE_MCS_ANT_B_MSK     0x8000
-#define RATE_MCS_ANT_AB_MSK    0xc000
-
-struct iwl3945_keyinfo {
-       __le16 key_flags;
-       u8 tkip_rx_tsc_byte2;   /* TSC[2] for key mix ph1 detection */
-       u8 reserved1;
-       __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
-       u8 key_offset;
-       u8 reserved2;
-       u8 key[16];             /* 16-byte unicast decryption key */
-} __attribute__ ((packed));
-
-/**
- * struct sta_id_modify
- * @addr[ETH_ALEN]: station's MAC address
- * @sta_id: index of station in uCode's station table
- * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
- *
- * Driver selects unused table index when adding new station,
- * or the index to a pre-existing station entry when modifying that station.
- * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
- *
- * modify_mask flags select which parameters to modify vs. leave alone.
- */
-struct sta_id_modify {
-       u8 addr[ETH_ALEN];
-       __le16 reserved1;
-       u8 sta_id;
-       u8 modify_mask;
-       __le16 reserved2;
-} __attribute__ ((packed));
-
-/*
- * REPLY_ADD_STA = 0x18 (command)
- *
- * The device contains an internal table of per-station information,
- * with info on security keys, aggregation parameters, and Tx rates for
- * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD,
- * 3945 uses REPLY_RATE_SCALE to set up rate tables).
- *
- * REPLY_ADD_STA sets up the table entry for one station, either creating
- * a new entry, or modifying a pre-existing one.
- *
- * NOTE:  RXON command (without "associated" bit set) wipes the station table
- *        clean.  Moving into RF_KILL state does this also.  Driver must set up
- *        new station table before transmitting anything on the RXON channel
- *        (except active scans or active measurements; those commands carry
- *        their own txpower/rate setup data).
- *
- *        When getting started on a new channel, driver must set up the
- *        IWL_BROADCAST_ID entry (last entry in the table).  For a client
- *        station in a BSS, once an AP is selected, driver sets up the AP STA
- *        in the IWL_AP_ID entry (1st entry in the table).  BROADCAST and AP
- *        are all that are needed for a BSS client station.  If the device is
- *        used as AP, or in an IBSS network, driver must set up station table
- *        entries for all STAs in network, starting with index IWL_STA_ID.
- */
-struct iwl3945_addsta_cmd {
-       u8 mode;                /* 1: modify existing, 0: add new station */
-       u8 reserved[3];
-       struct sta_id_modify sta;
-       struct iwl3945_keyinfo key;
-       __le32 station_flags;           /* STA_FLG_* */
-       __le32 station_flags_msk;       /* STA_FLG_* */
-
-       /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
-        * corresponding to bit (e.g. bit 5 controls TID 5).
-        * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
-       __le16 tid_disable_tx;
-
-       __le16 rate_n_flags;
-
-       /* TID for which to add block-ack support.
-        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
-       u8 add_immediate_ba_tid;
-
-       /* TID for which to remove block-ack support.
-        * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
-       u8 remove_immediate_ba_tid;
-
-       /* Starting Sequence Number for added block-ack support.
-        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
-       __le16 add_immediate_ba_ssn;
-} __attribute__ ((packed));
-
-#define ADD_STA_SUCCESS_MSK            0x1
-#define ADD_STA_NO_ROOM_IN_TABLE       0x2
-#define ADD_STA_NO_BLOCK_ACK_RESOURCE  0x4
-/*
- * REPLY_ADD_STA = 0x18 (response)
- */
-struct iwl3945_add_sta_resp {
-       u8 status;      /* ADD_STA_* */
-} __attribute__ ((packed));
-
-
-/******************************************************************************
- * (4)
- * Rx Responses:
- *
- *****************************************************************************/
-
-struct iwl3945_rx_frame_stats {
-       u8 phy_count;
-       u8 id;
-       u8 rssi;
-       u8 agc;
-       __le16 sig_avg;
-       __le16 noise_diff;
-       u8 payload[0];
-} __attribute__ ((packed));
-
-struct iwl3945_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   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   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)
-#define RX_RES_STATUS_SEC_TYPE_WEP     (0x1 << 8)
-#define RX_RES_STATUS_SEC_TYPE_CCMP    (0x2 << 8)
-#define RX_RES_STATUS_SEC_TYPE_TKIP    (0x3 << 8)
-
-#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
-#define RX_RES_STATUS_NOT_DECRYPT      (0x0 << 11)
-#define RX_RES_STATUS_DECRYPT_OK       (0x3 << 11)
-#define RX_RES_STATUS_BAD_ICV_MIC      (0x1 << 11)
-#define RX_RES_STATUS_BAD_KEY_TTAK     (0x2 << 11)
-
-struct iwl3945_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 iwl3945_rx_frame {
-       struct iwl3945_rx_frame_stats stats;
-       struct iwl3945_rx_frame_hdr hdr;
-       struct iwl3945_rx_frame_end end;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (5)
- * Tx Commands & Responses:
- *
- * Driver must place each REPLY_TX command into one of the prioritized Tx
- * queues in host DRAM, shared between driver and device.  When the device's
- * Tx scheduler and uCode are preparing to transmit, the device pulls the
- * Tx command over the PCI bus via one of the device's Tx DMA channels,
- * to fill an internal FIFO from which data will be transmitted.
- *
- * uCode handles all timing and protocol related to control frames
- * (RTS/CTS/ACK), based on flags in the Tx command.
- *
- * uCode handles retrying Tx when an ACK is expected but not received.
- * This includes trying lower data rates than the one requested in the Tx
- * command, as set up by the REPLY_RATE_SCALE (for 3945) or
- * REPLY_TX_LINK_QUALITY_CMD (4965).
- *
- * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
- * This command must be executed after every RXON command, before Tx can occur.
- *****************************************************************************/
-
-/* REPLY_TX Tx flags field */
-
-/* 1: Use Request-To-Send protocol before this frame.
- * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
-#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 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 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 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  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 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 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 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 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 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 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.
- * 0: No pad
- * 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 cpu_to_le32(1 << 20)
-
-/* HCCA-AP - disable duration overwriting. */
-#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
-
-/*
- * TX command security control
- */
-#define TX_CMD_SEC_WEP         0x01
-#define TX_CMD_SEC_CCM         0x02
-#define TX_CMD_SEC_TKIP                0x03
-#define TX_CMD_SEC_MSK         0x03
-#define TX_CMD_SEC_SHIFT       6
-#define TX_CMD_SEC_KEY128      0x08
-
-/*
- * REPLY_TX = 0x1c (command)
- */
-struct iwl3945_tx_cmd {
-       /*
-        * MPDU byte count:
-        * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
-        * + 8 byte IV for CCM or TKIP (not used for WEP)
-        * + Data payload
-        * + 8-byte MIC (not used for CCM/WEP)
-        * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
-        *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
-        * Range: 14-2342 bytes.
-        */
-       __le16 len;
-
-       /*
-        * MPDU or MSDU byte count for next frame.
-        * Used for fragmentation and bursting, but not 11n aggregation.
-        * Same as "len", but for next frame.  Set to 0 if not applicable.
-        */
-       __le16 next_frame_len;
-
-       __le32 tx_flags;        /* TX_CMD_FLG_* */
-
-       u8 rate;
-
-       /* Index of recipient station in uCode's station table */
-       u8 sta_id;
-       u8 tid_tspec;
-       u8 sec_ctl;
-       u8 key[16];
-       union {
-               u8 byte[8];
-               __le16 word[4];
-               __le32 dw[2];
-       } tkip_mic;
-       __le32 next_frame_info;
-       union {
-               __le32 life_time;
-               __le32 attempt;
-       } stop_time;
-       u8 supp_rates[2];
-       u8 rts_retry_limit;     /*byte 50 */
-       u8 data_retry_limit;    /*byte 51 */
-       union {
-               __le16 pm_frame_timeout;
-               __le16 attempt_duration;
-       } timeout;
-
-       /*
-        * Duration of EDCA burst Tx Opportunity, in 32-usec units.
-        * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
-        */
-       __le16 driver_txop;
-
-       /*
-        * MAC header goes here, followed by 2 bytes padding if MAC header
-        * length is 26 or 30 bytes, followed by payload data
-        */
-       u8 payload[0];
-       struct ieee80211_hdr hdr[0];
-} __attribute__ ((packed));
-
-/* TX command response is sent after *all* transmission attempts.
- *
- * NOTES:
- *
- * TX_STATUS_FAIL_NEXT_FRAG
- *
- * If the fragment flag in the MAC header for the frame being transmitted
- * is set and there is insufficient time to transmit the next frame, the
- * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
- *
- * TX_STATUS_FIFO_UNDERRUN
- *
- * Indicates the host did not provide bytes to the FIFO fast enough while
- * a TX was in progress.
- *
- * TX_STATUS_FAIL_MGMNT_ABORT
- *
- * This status is only possible if the ABORT ON MGMT RX parameter was
- * set to true with the TX command.
- *
- * If the MSB of the status parameter is set then an abort sequence is
- * required.  This sequence consists of the host activating the TX Abort
- * control line, and then waiting for the TX Abort command response.  This
- * indicates that a the device is no longer in a transmit state, and that the
- * command FIFO has been cleared.  The host must then deactivate the TX Abort
- * control line.  Receiving is still allowed in this case.
- */
-enum {
-       TX_STATUS_SUCCESS = 0x01,
-       TX_STATUS_DIRECT_DONE = 0x02,
-       TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
-       TX_STATUS_FAIL_LONG_LIMIT = 0x83,
-       TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
-       TX_STATUS_FAIL_MGMNT_ABORT = 0x85,
-       TX_STATUS_FAIL_NEXT_FRAG = 0x86,
-       TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
-       TX_STATUS_FAIL_DEST_PS = 0x88,
-       TX_STATUS_FAIL_ABORTED = 0x89,
-       TX_STATUS_FAIL_BT_RETRY = 0x8a,
-       TX_STATUS_FAIL_STA_INVALID = 0x8b,
-       TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
-       TX_STATUS_FAIL_TID_DISABLE = 0x8d,
-       TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
-       TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
-       TX_STATUS_FAIL_TX_LOCKED = 0x90,
-       TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
-};
-
-#define        TX_PACKET_MODE_REGULAR          0x0000
-#define        TX_PACKET_MODE_BURST_SEQ        0x0100
-#define        TX_PACKET_MODE_BURST_FIRST      0x0200
-
-enum {
-       TX_POWER_PA_NOT_ACTIVE = 0x0,
-};
-
-enum {
-       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_POWER_PA_DETECT_MSK = 0x7f800000,    /* bits 23:30 */
-       TX_ABORT_REQUIRED_MSK = 0x80000000,     /* bits 31:31 */
-};
-
-/*
- * REPLY_TX = 0x1c (response)
- */
-struct iwl3945_tx_resp {
-       u8 failure_rts;
-       u8 failure_frame;
-       u8 bt_kill_count;
-       u8 rate;
-       __le32 wireless_media_time;
-       __le32 status;          /* TX status */
-} __attribute__ ((packed));
-
-/*
- * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
- */
-struct iwl3945_txpowertable_cmd {
-       u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
-       u8 reserved;
-       __le16 channel;
-       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
-} __attribute__ ((packed));
-
-struct iwl3945_rate_scaling_info {
-       __le16 rate_n_flags;
-       u8 try_cnt;
-       u8 next_rate_index;
-} __attribute__ ((packed));
-
-/**
- * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
- *
- * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
- *
- * NOTE: The table of rates passed to the uCode via the
- * RATE_SCALE command sets up the corresponding order of
- * rates used for all related commands, including rate
- * masks, etc.
- *
- * For example, if you set 9MB (PLCP 0x0f) as the first
- * rate in the rate table, the bit mask for that rate
- * when passed through ofdm_basic_rates on the REPLY_RXON
- * command would be bit 0 (1 << 0)
- */
-struct iwl3945_rate_scaling_cmd {
-       u8 table_id;
-       u8 reserved[3];
-       struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
-} __attribute__ ((packed));
-
-/*
- * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
- *
- * 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 accommodate.
- */
-struct iwl3945_bt_cmd {
-       u8 flags;
-       u8 lead_time;
-       u8 max_kill;
-       u8 reserved;
-       __le32 kill_ack_mask;
-       __le32 kill_cts_mask;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (6)
- * Spectrum Management (802.11h) Commands, Responses, Notifications:
- *
- *****************************************************************************/
-
-/*
- * Spectrum Management
- */
-#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK         | \
-                                RXON_FILTER_CTL2HOST_MSK        | \
-                                RXON_FILTER_ACCEPT_GRP_MSK      | \
-                                RXON_FILTER_DIS_DECRYPT_MSK     | \
-                                RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
-                                RXON_FILTER_ASSOC_MSK           | \
-                                RXON_FILTER_BCON_AWARE_MSK)
-
-struct iwl3945_measure_channel {
-       __le32 duration;        /* measurement duration in extended beacon
-                                * format */
-       u8 channel;             /* channel to measure */
-       u8 type;                /* see enum iwl3945_measure_type */
-       __le16 reserved;
-} __attribute__ ((packed));
-
-/*
- * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
- */
-struct iwl3945_spectrum_cmd {
-       __le16 len;             /* number of bytes starting from token */
-       u8 token;               /* token id */
-       u8 id;                  /* measurement id -- 0 or 1 */
-       u8 origin;              /* 0 = TGh, 1 = other, 2 = TGk */
-       u8 periodic;            /* 1 = periodic */
-       __le16 path_loss_timeout;
-       __le32 start_time;      /* start time in extended beacon format */
-       __le32 reserved2;
-       __le32 flags;           /* rxon flags */
-       __le32 filter_flags;    /* rxon filter flags */
-       __le16 channel_count;   /* minimum 1, maximum 10 */
-       __le16 reserved3;
-       struct iwl3945_measure_channel channels[10];
-} __attribute__ ((packed));
-
-/*
- * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
- */
-struct iwl3945_spectrum_resp {
-       u8 token;
-       u8 id;                  /* id of the prior command replaced, or 0xff */
-       __le16 status;          /* 0 - command will be handled
-                                * 1 - cannot handle (conflicts with another
-                                *     measurement) */
-} __attribute__ ((packed));
-
-enum iwl3945_measurement_state {
-       IWL_MEASUREMENT_START = 0,
-       IWL_MEASUREMENT_STOP = 1,
-};
-
-enum iwl3945_measurement_status {
-       IWL_MEASUREMENT_OK = 0,
-       IWL_MEASUREMENT_CONCURRENT = 1,
-       IWL_MEASUREMENT_CSA_CONFLICT = 2,
-       IWL_MEASUREMENT_TGH_CONFLICT = 3,
-       /* 4-5 reserved */
-       IWL_MEASUREMENT_STOPPED = 6,
-       IWL_MEASUREMENT_TIMEOUT = 7,
-       IWL_MEASUREMENT_PERIODIC_FAILED = 8,
-};
-
-#define NUM_ELEMENTS_IN_HISTOGRAM 8
-
-struct iwl3945_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 iwl3945_measurement_cca_counters {
-       __le32 ofdm;
-       __le32 cck;
-} __attribute__ ((packed));
-
-enum iwl3945_measure_type {
-       IWL_MEASURE_BASIC = (1 << 0),
-       IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
-       IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
-       IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
-       IWL_MEASURE_FRAME = (1 << 4),
-       /* bits 5:6 are reserved */
-       IWL_MEASURE_IDLE = (1 << 7),
-};
-
-/*
- * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
- */
-struct iwl3945_spectrum_notification {
-       u8 id;                  /* measurement id -- 0 or 1 */
-       u8 token;
-       u8 channel_index;       /* index in measurement channel list */
-       u8 state;               /* 0 - start, 1 - stop */
-       __le32 start_time;      /* lower 32-bits of TSF */
-       u8 band;                /* 0 - 5.2GHz, 1 - 2.4GHz */
-       u8 channel;
-       u8 type;                /* see enum iwl3945_measurement_type */
-       u8 reserved1;
-       /* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
-        * valid if applicable for measurement type requested. */
-       __le32 cca_ofdm;        /* cca fraction time in 40Mhz clock periods */
-       __le32 cca_cck;         /* cca fraction time in 44Mhz clock periods */
-       __le32 cca_time;        /* channel load time in usecs */
-       u8 basic_type;          /* 0 - bss, 1 - ofdm preamble, 2 -
-                                * unidentified */
-       u8 reserved2[3];
-       struct iwl3945_measurement_histogram histogram;
-       __le32 stop_time;       /* lower 32-bits of TSF */
-       __le32 status;          /* see iwl3945_measurement_status */
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (7)
- * Power Management Commands, Responses, Notifications:
- *
- *****************************************************************************/
-
-/**
- * struct iwl3945_powertable_cmd - Power Table Command
- * @flags: See below:
- *
- * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
- *
- * PM allow:
- *   bit 0 - '0' Driver not allow power management
- *           '1' Driver allow PM (use rest of parameters)
- * uCode send sleep notifications:
- *   bit 1 - '0' Don't send sleep notification
- *           '1' send sleep notification (SEND_PM_NOTIFICATION)
- * Sleep over DTIM
- *   bit 2 - '0' PM have to walk up every DTIM
- *           '1' PM could sleep over DTIM till listen Interval.
- * PCI power managed
- *   bit 3 - '0' (PCI_LINK_CTRL & 0x1)
- *           '1' !(PCI_LINK_CTRL & 0x1)
- * Force sleep Modes
- *   bit 31/30- '00' use both mac/xtal sleeps
- *              '01' force Mac sleep
- *              '10' force xtal sleep
- *              '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
- * for every DTIM.
- */
-#define IWL_POWER_VEC_SIZE 5
-
-#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;
-       __le32 tx_data_timeout;
-       __le32 sleep_interval[IWL_POWER_VEC_SIZE];
-} __attribute__((packed));
-
-/*
- * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
- * 3945 and 4965 identical.
- */
-struct iwl3945_sleep_notification {
-       u8 pm_sleep_mode;
-       u8 pm_wakeup_src;
-       __le16 reserved;
-       __le32 sleep_time;
-       __le32 tsf_low;
-       __le32 bcon_timer;
-} __attribute__ ((packed));
-
-/* Sleep states.  3945 and 4965 identical. */
-enum {
-       IWL_PM_NO_SLEEP = 0,
-       IWL_PM_SLP_MAC = 1,
-       IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
-       IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
-       IWL_PM_SLP_PHY = 4,
-       IWL_PM_SLP_REPENT = 5,
-       IWL_PM_WAKEUP_BY_TIMER = 6,
-       IWL_PM_WAKEUP_BY_DRIVER = 7,
-       IWL_PM_WAKEUP_BY_RFKILL = 8,
-       /* 3 reserved */
-       IWL_PM_NUM_OF_MODES = 12,
-};
-
-/*
- * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response)
- */
-#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 iwl3945_card_state_cmd {
-       __le32 status;          /* CARD_STATE_CMD_* request new power state */
-} __attribute__ ((packed));
-
-/*
- * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
- */
-struct iwl3945_card_state_notif {
-       __le32 flags;
-} __attribute__ ((packed));
-
-#define HW_CARD_DISABLED   0x01
-#define SW_CARD_DISABLED   0x02
-#define RF_CARD_DISABLED   0x04
-#define RXON_CARD_DISABLED 0x10
-
-struct iwl3945_ct_kill_config {
-       __le32   reserved;
-       __le32   critical_temperature_M;
-       __le32   critical_temperature_R;
-}  __attribute__ ((packed));
-
-/******************************************************************************
- * (8)
- * Scan Commands, Responses, Notifications:
- *
- *****************************************************************************/
-
-/**
- * struct iwl3945_scan_channel - entry in REPLY_SCAN_CMD channel table
- *
- * One for each channel in the scan list.
- * Each channel can independently select:
- * 1)  SSID for directed active scans
- * 2)  Txpower setting (for rate specified within Tx command)
- * 3)  How long to stay on-channel (behavior may be modified by quiet_time,
- *     quiet_plcp_th, good_CRC_th)
- *
- * To avoid uCode errors, make sure the following are true (see comments
- * under struct iwl3945_scan_cmd about max_out_time and quiet_time):
- * 1)  If using passive_dwell (i.e. passive_dwell != 0):
- *     active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
- * 2)  quiet_time <= active_dwell
- * 3)  If restricting off-channel time (i.e. max_out_time !=0):
- *     passive_dwell < max_out_time
- *     active_dwell < max_out_time
- */
-struct iwl3945_scan_channel {
-       /*
-        * type is defined as:
-        * 0:0 1 = active, 0 = passive
-        * 1:4 SSID direct bit map; if a bit is set, then corresponding
-        *     SSID IE is transmitted in probe request.
-        * 5:7 reserved
-        */
-       u8 type;
-       u8 channel;     /* band is selected by iwl3945_scan_cmd "flags" field */
-       struct iwl3945_tx_power tpc;
-       __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
-       __le16 passive_dwell;   /* in 1024-uSec TU (time units), typ 20-500 */
-} __attribute__ ((packed));
-
-/**
- * struct iwl3945_ssid_ie - directed scan network information element
- *
- * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
- * in struct iwl3945_scan_channel; each channel may select different ssids from
- * among the 4 entries.  SSID IEs get transmitted in reverse order of entry.
- */
-struct iwl3945_ssid_ie {
-       u8 id;
-       u8 len;
-       u8 ssid[32];
-} __attribute__ ((packed));
-
-#define PROBE_OPTION_MAX        0x4
-#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
-
-/*
- * REPLY_SCAN_CMD = 0x80 (command)
- *
- * The hardware scan command is very powerful; the driver can set it up to
- * maintain (relatively) normal network traffic while doing a scan in the
- * background.  The max_out_time and suspend_time control the ratio of how
- * long the device stays on an associated network channel ("service channel")
- * vs. how long it's away from the service channel, tuned to other channels
- * for scanning.
- *
- * max_out_time is the max time off-channel (in usec), and suspend_time
- * is how long (in "extended beacon" format) that the scan is "suspended"
- * after returning to the service channel.  That is, suspend_time is the
- * time that we stay on the service channel, doing normal work, between
- * scan segments.  The driver may set these parameters differently to support
- * scanning when associated vs. not associated, and light vs. heavy traffic
- * loads when associated.
- *
- * After receiving this command, the device's scan engine does the following;
- *
- * 1)  Sends SCAN_START notification to driver
- * 2)  Checks to see if it has time to do scan for one channel
- * 3)  Sends NULL packet, with power-save (PS) bit set to 1,
- *     to tell AP that we're going off-channel
- * 4)  Tunes to first channel in scan list, does active or passive scan
- * 5)  Sends SCAN_RESULT notification to driver
- * 6)  Checks to see if it has time to do scan on *next* channel in list
- * 7)  Repeats 4-6 until it no longer has time to scan the next channel
- *     before max_out_time expires
- * 8)  Returns to service channel
- * 9)  Sends NULL packet with PS=0 to tell AP that we're back
- * 10) Stays on service channel until suspend_time expires
- * 11) Repeats entire process 2-10 until list is complete
- * 12) Sends SCAN_COMPLETE notification
- *
- * For fast, efficient scans, the scan command also has support for staying on
- * a channel for just a short time, if doing active scanning and getting no
- * responses to the transmitted probe request.  This time is controlled by
- * quiet_time, and the number of received packets below which a channel is
- * considered "quiet" is controlled by quiet_plcp_threshold.
- *
- * For active scanning on channels that have regulatory restrictions against
- * blindly transmitting, the scan can listen before transmitting, to make sure
- * that there is already legitimate activity on the channel.  If enough
- * packets are cleanly received on the channel (controlled by good_CRC_th,
- * typical value 1), the scan engine starts transmitting probe requests.
- *
- * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
- *
- * To avoid uCode errors, see timing restrictions described under
- * struct iwl3945_scan_channel.
- */
-struct iwl3945_scan_cmd {
-       __le16 len;
-       u8 reserved0;
-       u8 channel_count;       /* # channels in channel list */
-       __le16 quiet_time;      /* dwell only this # millisecs on quiet channel
-                                * (only for active scan) */
-       __le16 quiet_plcp_th;   /* quiet chnl is < this # pkts (typ. 1) */
-       __le16 good_CRC_th;     /* passive -> active promotion threshold */
-       __le16 reserved1;
-       __le32 max_out_time;    /* max usec to be away from associated (service)
-                                * channel */
-       __le32 suspend_time;    /* pause scan this long (in "extended beacon
-                                * format") when returning to service channel:
-                                * 3945; 31:24 # beacons, 19:0 additional usec,
-                                * 4965; 31:22 # beacons, 21:0 additional usec.
-                                */
-       __le32 flags;           /* RXON_FLG_* */
-       __le32 filter_flags;    /* RXON_FILTER_* */
-
-       /* For active scans (set to all-0s for passive scans).
-        * Does not include payload.  Must specify Tx rate; no rate scaling. */
-       struct iwl3945_tx_cmd tx_cmd;
-
-       /* For directed active scans (set to all-0s otherwise) */
-       struct iwl3945_ssid_ie direct_scan[PROBE_OPTION_MAX];
-
-       /*
-        * Probe request frame, followed by channel list.
-        *
-        * Size of probe request frame is specified by byte count in tx_cmd.
-        * Channel list follows immediately after probe request frame.
-        * Number of channels in list is specified by channel_count.
-        * Each channel in list is of type:
-        *
-        * struct iwl3945_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
-        * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
-        * before requesting another scan.
-        */
-       u8 data[0];
-} __attribute__ ((packed));
-
-/* Can abort will notify by complete notification with abort status. */
-#define CAN_ABORT_STATUS       cpu_to_le32(0x1)
-/* complete notification statuses */
-#define ABORT_STATUS            0x2
-
-/*
- * REPLY_SCAN_CMD = 0x80 (response)
- */
-struct iwl3945_scanreq_notification {
-       __le32 status;          /* 1: okay, 2: cannot fulfill request */
-} __attribute__ ((packed));
-
-/*
- * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
- */
-struct iwl3945_scanstart_notification {
-       __le32 tsf_low;
-       __le32 tsf_high;
-       __le32 beacon_timer;
-       u8 channel;
-       u8 band;
-       u8 reserved[2];
-       __le32 status;
-} __attribute__ ((packed));
-
-#define  SCAN_OWNER_STATUS 0x1;
-#define  MEASURE_OWNER_STATUS 0x2;
-
-#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */
-/*
- * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
- */
-struct iwl3945_scanresults_notification {
-       u8 channel;
-       u8 band;
-       u8 reserved[2];
-       __le32 tsf_low;
-       __le32 tsf_high;
-       __le32 statistics[NUMBER_OF_STATISTICS];
-} __attribute__ ((packed));
-
-/*
- * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
- */
-struct iwl3945_scancomplete_notification {
-       u8 scanned_channels;
-       u8 status;
-       u8 reserved;
-       u8 last_channel;
-       __le32 tsf_low;
-       __le32 tsf_high;
-} __attribute__ ((packed));
-
-
-/******************************************************************************
- * (9)
- * IBSS/AP Commands and Notifications:
- *
- *****************************************************************************/
-
-/*
- * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
- */
-struct iwl3945_beacon_notif {
-       struct iwl3945_tx_resp beacon_notify_hdr;
-       __le32 low_tsf;
-       __le32 high_tsf;
-       __le32 ibss_mgr_status;
-} __attribute__ ((packed));
-
-/*
- * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
- */
-struct iwl3945_tx_beacon_cmd {
-       struct iwl3945_tx_cmd tx;
-       __le16 tim_idx;
-       u8 tim_size;
-       u8 reserved1;
-       struct ieee80211_hdr frame[0];  /* beacon frame */
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (10)
- * Statistics Commands and Notifications:
- *
- *****************************************************************************/
-
-#define IWL_TEMP_CONVERT 260
-
-#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
-#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
-#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
-
-/* Used for passing to driver number of successes and failures per rate */
-struct rate_histogram {
-       union {
-               __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
-               __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
-               __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
-       } success;
-       union {
-               __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
-               __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
-               __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
-       } failed;
-} __attribute__ ((packed));
-
-/* statistics command response */
-
-struct statistics_rx_phy {
-       __le32 ina_cnt;
-       __le32 fina_cnt;
-       __le32 plcp_err;
-       __le32 crc32_err;
-       __le32 overrun_err;
-       __le32 early_overrun_err;
-       __le32 crc32_good;
-       __le32 false_alarm_cnt;
-       __le32 fina_sync_err_cnt;
-       __le32 sfd_timeout;
-       __le32 fina_timeout;
-       __le32 unresponded_rts;
-       __le32 rxe_frame_limit_overrun;
-       __le32 sent_ack_cnt;
-       __le32 sent_cts_cnt;
-} __attribute__ ((packed));
-
-struct statistics_rx_non_phy {
-       __le32 bogus_cts;       /* CTS received when not expecting CTS */
-       __le32 bogus_ack;       /* ACK received when not expecting ACK */
-       __le32 non_bssid_frames;        /* number of frames with BSSID that
-                                        * doesn't belong to the STA BSSID */
-       __le32 filtered_frames; /* count frames that were dumped in the
-                                * filtering process */
-       __le32 non_channel_beacons;     /* beacons with our bss id but not on
-                                        * our serving channel */
-} __attribute__ ((packed));
-
-struct statistics_rx {
-       struct statistics_rx_phy ofdm;
-       struct statistics_rx_phy cck;
-       struct statistics_rx_non_phy general;
-} __attribute__ ((packed));
-
-struct statistics_tx {
-       __le32 preamble_cnt;
-       __le32 rx_detected_cnt;
-       __le32 bt_prio_defer_cnt;
-       __le32 bt_prio_kill_cnt;
-       __le32 few_bytes_cnt;
-       __le32 cts_timeout;
-       __le32 ack_timeout;
-       __le32 expected_ack_cnt;
-       __le32 actual_ack_cnt;
-} __attribute__ ((packed));
-
-struct statistics_dbg {
-       __le32 burst_check;
-       __le32 burst_count;
-       __le32 reserved[4];
-} __attribute__ ((packed));
-
-struct statistics_div {
-       __le32 tx_on_a;
-       __le32 tx_on_b;
-       __le32 exec_time;
-       __le32 probe_time;
-} __attribute__ ((packed));
-
-struct statistics_general {
-       __le32 temperature;
-       struct statistics_dbg dbg;
-       __le32 sleep_time;
-       __le32 slots_out;
-       __le32 slots_idle;
-       __le32 ttl_timestamp;
-       struct statistics_div div;
-} __attribute__ ((packed));
-
-/*
- * REPLY_STATISTICS_CMD = 0x9c,
- * 3945 and 4965 identical.
- *
- * This command triggers an immediate response containing uCode statistics.
- * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
- *
- * If the CLEAR_STATS configuration flag is set, uCode will clear its
- * internal copy of the statistics (counters) after issuing the response.
- * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
- *
- * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
- * 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 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));
-
-/*
- * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
- *
- * By default, uCode issues this notification after receiving a beacon
- * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
- * REPLY_STATISTICS_CMD 0x9c, above.
- *
- * Statistics counters continue to increment beacon after beacon, but are
- * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
- * 0x9c with CLEAR_STATS bit set (see above).
- *
- * uCode also issues this notification during scans.  uCode clears statistics
- * appropriately so that each notification contains statistics for only the
- * one channel that has just been scanned.
- */
-#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;
-       struct statistics_tx tx;
-       struct statistics_general general;
-} __attribute__ ((packed));
-
-
-/*
- * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
- */
-/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row,
- * then this notification will be sent. */
-#define CONSECUTIVE_MISSED_BCONS_TH 20
-
-struct iwl3945_missed_beacon_notif {
-       __le32 consequtive_missed_beacons;
-       __le32 total_missed_becons;
-       __le32 num_expected_beacons;
-       __le32 num_recvd_beacons;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (11)
- * Rx Calibration Commands:
- *
- *****************************************************************************/
-
-#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
-#define HD_TABLE_SIZE  (11)
-
-struct iwl3945_sensitivity_cmd {
-       __le16 control;
-       __le16 table[HD_TABLE_SIZE];
-} __attribute__ ((packed));
-
-struct iwl3945_calibration_cmd {
-       u8 opCode;
-       u8 flags;
-       __le16 reserved;
-       s8 diff_gain_a;
-       s8 diff_gain_b;
-       s8 diff_gain_c;
-       u8 reserved1;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (12)
- * Miscellaneous Commands:
- *
- *****************************************************************************/
-
-/*
- * LEDs Command & Response
- * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
- *
- * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
- * this command turns it on or off, or sets up a periodic blinking cycle.
- */
-struct iwl3945_led_cmd {
-       __le32 interval;        /* "interval" in uSec */
-       u8 id;                  /* 1: Activity, 2: Link, 3: Tech */
-       u8 off;                 /* # intervals off while blinking;
-                                * "0", with >0 "on" value, turns LED on */
-       u8 on;                  /* # intervals on while blinking;
-                                * "0", regardless of "off", turns LED off */
-       u8 reserved;
-} __attribute__ ((packed));
-
-/******************************************************************************
- * (13)
- * Union of all expected notifications/responses:
- *
- *****************************************************************************/
-
-struct iwl3945_rx_packet {
-       __le32 len;
-       struct iwl3945_cmd_header hdr;
-       union {
-               struct iwl3945_alive_resp alive_frame;
-               struct iwl3945_rx_frame rx_frame;
-               struct iwl3945_tx_resp tx_resp;
-               struct iwl3945_spectrum_notification spectrum_notif;
-               struct iwl3945_csa_notification csa_notif;
-               struct iwl3945_error_resp err_resp;
-               struct iwl3945_card_state_notif card_state_notif;
-               struct iwl3945_beacon_notif beacon_status;
-               struct iwl3945_add_sta_resp add_sta;
-               struct iwl3945_sleep_notification sleep_notif;
-               struct iwl3945_spectrum_resp spectrum;
-               struct iwl3945_notif_statistics stats;
-               __le32 status;
-               u8 raw[0];
-       } u;
-} __attribute__ ((packed));
-
-#define IWL_RX_FRAME_SIZE        (4 + sizeof(struct iwl3945_rx_frame))
-
-#endif                         /* __iwl3945_3945_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
deleted file mode 100644 (file)
index 85eb778..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project.
- *
- * 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
- *
- *****************************************************************************/
-
-#ifndef __iwl3945_debug_h__
-#define __iwl3945_debug_h__
-
-#ifdef CONFIG_IWL3945_DEBUG
-extern u32 iwl3945_debug_level;
-#define IWL_DEBUG(level, fmt, args...) \
-do { if (iwl3945_debug_level & (level)) \
-  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-        in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
-
-#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
-  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-        in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
-
-static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
-{
-       if (!(iwl3945_debug_level & level))
-               return;
-
-       print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-                       p, len, 1);
-}
-#else
-static inline void IWL_DEBUG(int level, const char *fmt, ...)
-{
-}
-static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
-{
-}
-static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
-{
-}
-#endif /* CONFIG_IWL3945_DEBUG */
-
-
-
-/*
- * 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:
- *
- * #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)
- *
- * 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 iwl3945_debug_levels array.
- *
- * If you do not see debug_level in /proc/net/iwl then you do not have
- * CONFIG_IWL3945_DEBUG defined in your kernel configuration
- *
- */
-
-#define IWL_DL_INFO          (1 << 0)
-#define IWL_DL_MAC80211      (1 << 1)
-#define IWL_DL_HOST_COMMAND  (1 << 2)
-#define IWL_DL_STATE         (1 << 3)
-
-#define IWL_DL_RADIO         (1 << 7)
-#define IWL_DL_POWER         (1 << 8)
-#define IWL_DL_TEMP          (1 << 9)
-
-#define IWL_DL_NOTIF         (1 << 10)
-#define IWL_DL_SCAN          (1 << 11)
-#define IWL_DL_ASSOC         (1 << 12)
-#define IWL_DL_DROP          (1 << 13)
-
-#define IWL_DL_TXPOWER       (1 << 14)
-
-#define IWL_DL_AP            (1 << 15)
-
-#define IWL_DL_FW            (1 << 16)
-#define IWL_DL_RF_KILL       (1 << 17)
-#define IWL_DL_FW_ERRORS     (1 << 18)
-
-#define IWL_DL_LED           (1 << 19)
-
-#define IWL_DL_RATE          (1 << 20)
-
-#define IWL_DL_CALIB         (1 << 21)
-#define IWL_DL_WEP           (1 << 22)
-#define IWL_DL_TX            (1 << 23)
-#define IWL_DL_RX            (1 << 24)
-#define IWL_DL_ISR           (1 << 25)
-#define IWL_DL_HT            (1 << 26)
-#define IWL_DL_IO            (1 << 27)
-#define IWL_DL_11H           (1 << 28)
-
-#define IWL_DL_STATS         (1 << 29)
-#define IWL_DL_TX_REPLY      (1 << 30)
-#define IWL_DL_QOS           (1 << 31)
-
-#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
-#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
-#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
-
-#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
-#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
-#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
-#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
-#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
-#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
-#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
-#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
-#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
-#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
-#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
-#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
-#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
-#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
-#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
-#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
-       IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
-#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_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)
-#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, f, ## a)
-
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
new file mode 100644 (file)
index 0000000..08ce259
--- /dev/null
@@ -0,0 +1,188 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2009 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
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_3945_fh_h__
+#define __iwl_3945_fh_h__
+
+/************************************/
+/* iwl3945 Flow Handler Definitions */
+/************************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH39_MEM_LOWER_BOUND                   (0x0800)
+#define FH39_MEM_UPPER_BOUND                   (0x1000)
+
+#define FH39_CBCC_TABLE                (FH39_MEM_LOWER_BOUND + 0x140)
+#define FH39_TFDB_TABLE                (FH39_MEM_LOWER_BOUND + 0x180)
+#define FH39_RCSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x400)
+#define FH39_RSSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x4c0)
+#define FH39_TCSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x500)
+#define FH39_TSSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x680)
+
+/* TFDB (Transmit Frame Buffer Descriptor) */
+#define FH39_TFDB(_ch, buf)                    (FH39_TFDB_TABLE + \
+                                                ((_ch) * 2 + (buf)) * 0x28)
+#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)       (FH39_TFDB_TABLE + 0x50 * (_ch))
+
+/* CBCC channel is [0,2] */
+#define FH39_CBCC(_ch)         (FH39_CBCC_TABLE + (_ch) * 0x8)
+#define FH39_CBCC_CTRL(_ch)    (FH39_CBCC(_ch) + 0x00)
+#define FH39_CBCC_BASE(_ch)    (FH39_CBCC(_ch) + 0x04)
+
+/* RCSR channel is [0,2] */
+#define FH39_RCSR(_ch)                 (FH39_RCSR_TABLE + (_ch) * 0x40)
+#define FH39_RCSR_CONFIG(_ch)          (FH39_RCSR(_ch) + 0x00)
+#define FH39_RCSR_RBD_BASE(_ch)                (FH39_RCSR(_ch) + 0x04)
+#define FH39_RCSR_WPTR(_ch)            (FH39_RCSR(_ch) + 0x20)
+#define FH39_RCSR_RPTR_ADDR(_ch)       (FH39_RCSR(_ch) + 0x24)
+
+#define FH39_RSCSR_CHNL0_WPTR          (FH39_RCSR_WPTR(0))
+
+/* RSSR */
+#define FH39_RSSR_CTRL                 (FH39_RSSR_TABLE + 0x000)
+#define FH39_RSSR_STATUS               (FH39_RSSR_TABLE + 0x004)
+
+/* TCSR */
+#define FH39_TCSR(_ch)                 (FH39_TCSR_TABLE + (_ch) * 0x20)
+#define FH39_TCSR_CONFIG(_ch)          (FH39_TCSR(_ch) + 0x00)
+#define FH39_TCSR_CREDIT(_ch)          (FH39_TCSR(_ch) + 0x04)
+#define FH39_TCSR_BUFF_STTS(_ch)       (FH39_TCSR(_ch) + 0x08)
+
+/* TSSR */
+#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
+#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
+#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
+
+
+/* DBM */
+
+#define FH39_SRVC_CHNL                            (6)
+
+#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
+#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
+
+#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128          (0x01000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST          (0x00001000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH                        (0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF               (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER            (0x00000001)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL     (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL      (0x00000008)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD            (0x00200000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT             (0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE             (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE            (0x80000000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID           (0x00004000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR            (0x00000001)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON       (0xFF000000)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON       (0x00FF0000)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B     (0x00000400)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON                (0x00000100)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON                (0x00000080)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH      (0x00000020)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH            (0x00000005)
+
+#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)    (BIT(_ch) << 24)
+#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)   (BIT(_ch) << 16)
+
+#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
+       (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
+        FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
+
+#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE                    (0x01000000)
+
+struct iwl3945_tfd_tb {
+       __le32 addr;
+       __le32 len;
+} __attribute__ ((packed));
+
+struct iwl3945_tfd {
+       __le32 control_flags;
+       struct iwl3945_tfd_tb tbs[4];
+       u8 __pad[28];
+} __attribute__ ((packed));
+
+
+#endif /* __iwl_3945_fh_h__ */
+
index 94ea0e60c41076d9d5fa6a656595bc4bbda57cf8..1327b2ac1c53de9b57c024c421ae0748b2726c17 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef __iwl_3945_hw__
 #define __iwl_3945_hw__
 
+#include "iwl-eeprom.h"
+
 /*
  * uCode queue management definitions ...
  * Queue #4 is the command queue for 3945 and 4965.
  */
-#define IWL_CMD_QUEUE_NUM       4
-
-/* Tx rates */
-#define IWL_CCK_RATES 4
-#define IWL_OFDM_RATES 8
-#define IWL_HT_RATES 0
-#define IWL_MAX_RATES  (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
+#define IWL_CMD_QUEUE_NUM      4
 
 /* Time constants */
 #define SHORT_SLOT_TIME 9
 #define LONG_SLOT_TIME 20
 
 /* RSSI to dBm */
-#define IWL_RSSI_OFFSET        95
+#define IWL39_RSSI_OFFSET      95
 
 /*
  * EEPROM related constants, enums, and structures.
  */
-
-/*
- * 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 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 */
-
-/*
- * Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags.
- *
- * IBSS and/or AP operation is allowed *only* on those channels with
- * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
- * RADAR detection is not supported by the 3945 driver, but is a
- * requirement for establishing a new network for legal operation on channels
- * requiring RADAR detection or restricting ACTIVE scanning.
- *
- * NOTE:  "WIDE" flag indicates that 20 MHz channel is supported;
- *        3945 does not support FAT 40 MHz-wide channels.
- *
- * NOTE:  Using a channel inappropriately will result in a uCode error!
- */
-enum {
-       EEPROM_CHANNEL_VALID = (1 << 0),        /* usable for this SKU/geo */
-       EEPROM_CHANNEL_IBSS = (1 << 1),         /* usable as an IBSS channel */
-       /* Bit 2 Reserved */
-       EEPROM_CHANNEL_ACTIVE = (1 << 3),       /* active scanning allowed */
-       EEPROM_CHANNEL_RADAR = (1 << 4),        /* radar detection required */
-       EEPROM_CHANNEL_WIDE = (1 << 5),         /* 20 MHz channel okay */
-       /* Bit 6 Reserved (was Narrow Channel) */
-       EEPROM_CHANNEL_DFS = (1 << 7),  /* dynamic freq selection candidate */
-};
-
-/* SKU Capabilities */
-#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
-#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
 #define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
 
-/* *regulatory* channel data from eeprom, one for each channel */
-struct iwl3945_eeprom_channel {
-       u8 flags;               /* flags copied from EEPROM */
-       s8 max_power_avg;       /* max power (dBm) on this chnl, limit 31 */
-} __attribute__ ((packed));
-
 /*
  * Mapping of a Tx power level, at factory calibration temperature,
  *   to a radio/DSP gain table index.
@@ -233,7 +182,7 @@ struct iwl3945_eeprom {
  * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  */
        u16 band_1_count;       /* abs.ofs: 196 */
-       struct iwl3945_eeprom_channel band_1_channels[14];  /* abs.ofs: 196 */
+       struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
 
 /*
  * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
@@ -241,28 +190,28 @@ struct iwl3945_eeprom {
  * (4915-5080MHz) (none of these is ever supported)
  */
        u16 band_2_count;       /* abs.ofs: 226 */
-       struct iwl3945_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
+       struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
 
 /*
  * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
  * (5170-5320MHz)
  */
        u16 band_3_count;       /* abs.ofs: 254 */
-       struct iwl3945_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
+       struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
 
 /*
  * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
  * (5500-5700MHz)
  */
        u16 band_4_count;       /* abs.ofs: 280 */
-       struct iwl3945_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
+       struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
 
 /*
  * 5.7 GHz channels 145, 149, 153, 157, 161, 165
  * (5725-5825MHz)
  */
        u16 band_5_count;       /* abs.ofs: 304 */
-       struct iwl3945_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
+       struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
 
        u8 reserved9[194];
 
@@ -276,125 +225,21 @@ struct iwl3945_eeprom {
        u8 reserved16[172];     /* fill out to full 1024 byte block */
 } __attribute__ ((packed));
 
-#define IWL_EEPROM_IMAGE_SIZE 1024
+#define IWL3945_EEPROM_IMG_SIZE 1024
 
 /* End of EEPROM */
 
 
-#include "iwl-3945-commands.h"
-
 #define PCI_LINK_CTRL      0x0F0
 #define PCI_POWER_SOURCE   0x0C8
 #define PCI_REG_WUM8       0x0E8
 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
 
-/*=== FH (data Flow Handler) ===*/
-#define FH_BASE     (0x800)
-
-#define FH_CBCC_TABLE           (FH_BASE+0x140)
-#define FH_TFDB_TABLE           (FH_BASE+0x180)
-#define FH_RCSR_TABLE           (FH_BASE+0x400)
-#define FH_RSSR_TABLE           (FH_BASE+0x4c0)
-#define FH_TCSR_TABLE           (FH_BASE+0x500)
-#define FH_TSSR_TABLE           (FH_BASE+0x680)
-
-/* TFDB (Transmit Frame Buffer Descriptor) */
-#define FH_TFDB(_channel, buf) \
-       (FH_TFDB_TABLE+((_channel)*2+(buf))*0x28)
-#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \
-       (FH_TFDB_TABLE + 0x50 * _channel)
-/* CBCC _channel is [0,2] */
-#define FH_CBCC(_channel)           (FH_CBCC_TABLE+(_channel)*0x8)
-#define FH_CBCC_CTRL(_channel)      (FH_CBCC(_channel)+0x00)
-#define FH_CBCC_BASE(_channel)      (FH_CBCC(_channel)+0x04)
-
-/* RCSR _channel is [0,2] */
-#define FH_RCSR(_channel)           (FH_RCSR_TABLE+(_channel)*0x40)
-#define FH_RCSR_CONFIG(_channel)    (FH_RCSR(_channel)+0x00)
-#define FH_RCSR_RBD_BASE(_channel)  (FH_RCSR(_channel)+0x04)
-#define FH_RCSR_WPTR(_channel)      (FH_RCSR(_channel)+0x20)
-#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24)
-
-#define FH_RSCSR_CHNL0_WPTR        (FH_RCSR_WPTR(0))
-
-/* 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)
-#define FH_TCSR_CREDIT(_channel)    (FH_TCSR(_channel)+0x04)
-#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08)
-/* TSSR */
-#define FH_TSSR_CBB_BASE        (FH_TSSR_TABLE+0x000)
-#define FH_TSSR_MSG_CONFIG      (FH_TSSR_TABLE+0x008)
-#define FH_TSSR_TX_STATUS       (FH_TSSR_TABLE+0x010)
-
-
-/* DBM */
-
-#define ALM_FH_SRVC_CHNL                            (6)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
-#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128         (0x01000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST         (0x00001000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH               (0x00000000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF              (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER           (0x00000001)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL    (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL     (0x00000008)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD           (0x00200000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT            (0x00000000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE            (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE           (0x80000000)
-
-#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID          (0x00004000)
-
-#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR           (0x00000001)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON      (0xFF000000)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON      (0x00FF0000)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B    (0x00000400)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON       (0x00000100)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON       (0x00000080)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH     (0x00000020)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH           (0x00000005)
-
-#define ALM_TB_MAX_BYTES_COUNT      (0xFFF0)
-
-#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \
-       ((1LU << _channel) << 24)
-#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \
-       ((1LU << _channel) << 16)
-
-#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \
-       (ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \
-        ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel))
 #define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)     /* bit 6    */
 #define PCI_CFG_REV_ID_BIT_RTP                      (0x80)     /* bit 7    */
 
 #define TFD_QUEUE_MIN           0
 #define TFD_QUEUE_MAX           6
-#define TFD_QUEUE_SIZE_MAX      (256)
 
 #define IWL_NUM_SCAN_RATES         (2)
 
@@ -416,12 +261,6 @@ struct iwl3945_eeprom {
 #define TFD_CTL_PAD_SET(n)         (n << 28)
 #define TFD_CTL_PAD_GET(ctl)       (ctl >> 28)
 
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \
-                             sizeof(struct iwl3945_cmd_meta))
-
 /*
  * RX related structures and functions
  */
@@ -430,45 +269,35 @@ struct iwl3945_eeprom {
 
 /* Sizes and addresses for instruction and data memory (SRAM) in
  * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define RTC_INST_LOWER_BOUND                   (0x000000)
-#define ALM_RTC_INST_UPPER_BOUND               (0x014000)
+#define IWL39_RTC_INST_LOWER_BOUND             (0x000000)
+#define IWL39_RTC_INST_UPPER_BOUND             (0x014000)
 
-#define RTC_DATA_LOWER_BOUND                   (0x800000)
-#define ALM_RTC_DATA_UPPER_BOUND               (0x808000)
+#define IWL39_RTC_DATA_LOWER_BOUND             (0x800000)
+#define IWL39_RTC_DATA_UPPER_BOUND             (0x808000)
 
-#define ALM_RTC_INST_SIZE (ALM_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
-#define ALM_RTC_DATA_SIZE (ALM_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
+#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
+                               IWL39_RTC_INST_LOWER_BOUND)
+#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
+                               IWL39_RTC_DATA_LOWER_BOUND)
 
-#define IWL_MAX_INST_SIZE ALM_RTC_INST_SIZE
-#define IWL_MAX_DATA_SIZE ALM_RTC_DATA_SIZE
+#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
+#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
 
 /* Size of uCode instruction memory in bootstrap state machine */
-#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
+#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
 
 #define IWL39_MAX_NUM_QUEUES   8
 
 static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
 {
-       return (addr >= RTC_DATA_LOWER_BOUND) &&
-              (addr < ALM_RTC_DATA_UPPER_BOUND);
+       return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
+              (addr < IWL39_RTC_DATA_UPPER_BOUND);
 }
 
 /* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
  * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
 struct iwl3945_shared {
        __le32 tx_base_ptr[8];
-       __le32 rx_read_ptr[3];
-} __attribute__ ((packed));
-
-struct iwl3945_tfd_frame_data {
-       __le32 addr;
-       __le32 len;
-} __attribute__ ((packed));
-
-struct iwl3945_tfd_frame {
-       __le32 control_flags;
-       struct iwl3945_tfd_frame_data pa[4];
-       u8 reserved[28];
 } __attribute__ ((packed));
 
 static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
deleted file mode 100644 (file)
index 2440fd6..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project.
- *
- * 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
- *
- *****************************************************************************/
-
-#ifndef __iwl3945_io_h__
-#define __iwl3945_io_h__
-
-#include <linux/io.h>
-
-#include "iwl-3945-debug.h"
-
-/*
- * IO, register, and NIC memory access functions
- *
- * NOTE on naming convention and macro usage for these
- *
- * A single _ prefix before a an access function means that no state
- * check or debug information is printed when that function is called.
- *
- * A double __ prefix before an access function means that state is checked
- * and the current line number is printed in addition to any other debug output.
- *
- * The non-prefixed name is the #define that maps the caller into a
- * #define that provides the caller's __LINE__ to the double prefix version.
- *
- * If you wish to call the function without any debug or state checking,
- * you should use the single _ prefix version (as is used by dependent IO
- * routines, for example _iwl3945_read_direct32 calls the non-check version of
- * _iwl3945_read32.)
- *
- * These declarations are *extremely* useful in quickly isolating code deltas
- * 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.
- *
- */
-
-#define _iwl3945_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs))
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
-                                u32 ofs, u32 val)
-{
-       IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
-       _iwl3945_write32(priv, ofs, val);
-}
-#define iwl3945_write32(priv, ofs, val) \
-       __iwl3945_write32(__FILE__, __LINE__, priv, ofs, val)
-#else
-#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
-#endif
-
-#define _iwl3945_read32(priv, ofs) ioread32((priv)->hw_base + (ofs))
-#ifdef CONFIG_IWL3945_DEBUG
-static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
-{
-       IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-       return _iwl3945_read32(priv, ofs);
-}
-#define iwl3945_read32(priv, ofs)__iwl3945_read32(__FILE__, __LINE__, priv, ofs)
-#else
-#define iwl3945_read32(p, o) _iwl3945_read32(p, o)
-#endif
-
-static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr,
-                               u32 bits, u32 mask, int timeout)
-{
-       int i = 0;
-
-       do {
-               if ((_iwl3945_read32(priv, addr) & mask) == (bits & mask))
-                       return i;
-               udelay(10);
-               i += 10;
-       } while (i < timeout);
-
-       return -ETIMEDOUT;
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static inline int __iwl3945_poll_bit(const char *f, u32 l,
-                                struct iwl3945_priv *priv, u32 addr,
-                                u32 bits, u32 mask, int timeout)
-{
-       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);
-       return ret;
-}
-#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
-       __iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
-#else
-#define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
-#endif
-
-static inline void _iwl3945_set_bit(struct iwl3945_priv *priv, u32 reg, u32 mask)
-{
-       _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) | mask);
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_set_bit(const char *f, u32 l,
-                                struct iwl3945_priv *priv, u32 reg, u32 mask)
-{
-       u32 val = _iwl3945_read32(priv, reg) | mask;
-       IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-       _iwl3945_write32(priv, reg, val);
-}
-#define iwl3945_set_bit(p, r, m) __iwl3945_set_bit(__FILE__, __LINE__, p, r, m)
-#else
-#define iwl3945_set_bit(p, r, m) _iwl3945_set_bit(p, r, m)
-#endif
-
-static inline void _iwl3945_clear_bit(struct iwl3945_priv *priv, u32 reg, u32 mask)
-{
-       _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) & ~mask);
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_clear_bit(const char *f, u32 l,
-                                  struct iwl3945_priv *priv, u32 reg, u32 mask)
-{
-       u32 val = _iwl3945_read32(priv, reg) & ~mask;
-       IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-       _iwl3945_write32(priv, reg, val);
-}
-#define iwl3945_clear_bit(p, r, m) __iwl3945_clear_bit(__FILE__, __LINE__, p, r, m)
-#else
-#define iwl3945_clear_bit(p, r, m) _iwl3945_clear_bit(p, r, m)
-#endif
-
-static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv)
-{
-       int ret;
-#ifdef CONFIG_IWL3945_DEBUG
-       if (atomic_read(&priv->restrict_refcnt))
-               return 0;
-#endif
-       /* this bit wakes up the NIC */
-       _iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-       ret = _iwl3945_poll_bit(priv, CSR_GP_CNTRL,
-                          CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-                          (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-                           CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
-       if (ret < 0) {
-               IWL_ERROR("MAC is in deep sleep!\n");
-               return -EIO;
-       }
-
-#ifdef CONFIG_IWL3945_DEBUG
-       atomic_inc(&priv->restrict_refcnt);
-#endif
-       return 0;
-}
-
-#ifdef CONFIG_IWL3945_DEBUG
-static inline int __iwl3945_grab_nic_access(const char *f, u32 l,
-                                              struct iwl3945_priv *priv)
-{
-       if (atomic_read(&priv->restrict_refcnt))
-               IWL_DEBUG_INFO("Grabbing access while already held at "
-                              "line %d.\n", l);
-
-       IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
-       return _iwl3945_grab_nic_access(priv);
-}
-#define iwl3945_grab_nic_access(priv) \
-       __iwl3945_grab_nic_access(__FILE__, __LINE__, priv)
-#else
-#define iwl3945_grab_nic_access(priv) \
-       _iwl3945_grab_nic_access(priv)
-#endif
-
-static inline void _iwl3945_release_nic_access(struct iwl3945_priv *priv)
-{
-#ifdef CONFIG_IWL3945_DEBUG
-       if (atomic_dec_and_test(&priv->restrict_refcnt))
-#endif
-               _iwl3945_clear_bit(priv, CSR_GP_CNTRL,
-                              CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_release_nic_access(const char *f, u32 l,
-                                           struct iwl3945_priv *priv)
-{
-       if (atomic_read(&priv->restrict_refcnt) <= 0)
-               IWL_ERROR("Release unheld nic access at line %d.\n", l);
-
-       IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
-       _iwl3945_release_nic_access(priv);
-}
-#define iwl3945_release_nic_access(priv) \
-       __iwl3945_release_nic_access(__FILE__, __LINE__, priv)
-#else
-#define iwl3945_release_nic_access(priv) \
-       _iwl3945_release_nic_access(priv)
-#endif
-
-static inline u32 _iwl3945_read_direct32(struct iwl3945_priv *priv, u32 reg)
-{
-       return _iwl3945_read32(priv, reg);
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static inline u32 __iwl3945_read_direct32(const char *f, u32 l,
-                                       struct iwl3945_priv *priv, u32 reg)
-{
-       u32 value = _iwl3945_read_direct32(priv, reg);
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s %d\n", f, l);
-       IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
-                    f, l);
-       return value;
-}
-#define iwl3945_read_direct32(priv, reg) \
-       __iwl3945_read_direct32(__FILE__, __LINE__, priv, reg)
-#else
-#define iwl3945_read_direct32 _iwl3945_read_direct32
-#endif
-
-static inline void _iwl3945_write_direct32(struct iwl3945_priv *priv,
-                                        u32 reg, u32 value)
-{
-       _iwl3945_write32(priv, reg, value);
-}
-#ifdef CONFIG_IWL3945_DEBUG
-static void __iwl3945_write_direct32(u32 line,
-                                  struct iwl3945_priv *priv, u32 reg, u32 value)
-{
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from line %d\n", line);
-       _iwl3945_write_direct32(priv, reg, value);
-}
-#define iwl3945_write_direct32(priv, reg, value) \
-       __iwl3945_write_direct32(__LINE__, priv, reg, value)
-#else
-#define iwl3945_write_direct32 _iwl3945_write_direct32
-#endif
-
-static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv,
-                                              u32 reg, u32 len, u32 *values)
-{
-       u32 count = sizeof(u32);
-
-       if ((priv != NULL) && (values != NULL)) {
-               for (; 0 < len; len -= count, reg += count, values++)
-                       _iwl3945_write_direct32(priv, reg, *values);
-       }
-}
-
-static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv,
-                                          u32 addr, u32 mask, int timeout)
-{
-       return _iwl3945_poll_bit(priv, addr, mask, mask, timeout);
-}
-
-#ifdef CONFIG_IWL3945_DEBUG
-static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
-                                           struct iwl3945_priv *priv,
-                                           u32 addr, u32 mask, int timeout)
-{
-       int ret  = _iwl3945_poll_direct_bit(priv, addr, mask, timeout);
-
-       if (unlikely(ret == -ETIMEDOUT))
-               IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
-                            "timedout - %s %d\n", addr, mask, f, l);
-       else
-               IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
-                            "- %s %d\n", addr, mask, ret, f, l);
-       return ret;
-}
-#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \
-       __iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
-#else
-#define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
-#endif
-
-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
-static inline u32 __iwl3945_read_prph(u32 line, struct iwl3945_priv *priv, u32 reg)
-{
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from line %d\n", line);
-       return _iwl3945_read_prph(priv, reg);
-}
-
-#define iwl3945_read_prph(priv, reg) \
-       __iwl3945_read_prph(__LINE__, priv, reg)
-#else
-#define iwl3945_read_prph _iwl3945_read_prph
-#endif
-
-static inline void _iwl3945_write_prph(struct iwl3945_priv *priv,
-                                            u32 addr, u32 val)
-{
-       _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
-static inline void __iwl3945_write_prph(u32 line, struct iwl3945_priv *priv,
-                                             u32 addr, u32 val)
-{
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access from line %d\n", line);
-       _iwl3945_write_prph(priv, addr, val);
-}
-
-#define iwl3945_write_prph(priv, addr, val) \
-       __iwl3945_write_prph(__LINE__, priv, addr, val);
-#else
-#define iwl3945_write_prph _iwl3945_write_prph
-#endif
-
-#define _iwl3945_set_bits_prph(priv, reg, mask) \
-       _iwl3945_write_prph(priv, reg, (_iwl3945_read_prph(priv, reg) | mask))
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_set_bits_prph(u32 line, struct iwl3945_priv *priv,
-                                       u32 reg, u32 mask)
-{
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from line %d\n", line);
-
-       _iwl3945_set_bits_prph(priv, reg, mask);
-}
-#define iwl3945_set_bits_prph(priv, reg, mask) \
-       __iwl3945_set_bits_prph(__LINE__, priv, reg, mask)
-#else
-#define iwl3945_set_bits_prph _iwl3945_set_bits_prph
-#endif
-
-#define _iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \
-       _iwl3945_write_prph(priv, reg, ((_iwl3945_read_prph(priv, reg) & mask) | bits))
-
-#ifdef CONFIG_IWL3945_DEBUG
-static inline void __iwl3945_set_bits_mask_prph(u32 line,
-               struct iwl3945_priv *priv, u32 reg, u32 bits, u32 mask)
-{
-       if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from line %d\n", line);
-       _iwl3945_set_bits_mask_prph(priv, reg, bits, mask);
-}
-#define iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \
-       __iwl3945_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
-#else
-#define iwl3945_set_bits_mask_prph _iwl3945_set_bits_mask_prph
-#endif
-
-static inline void iwl3945_clear_bits_prph(struct iwl3945_priv
-                                                *priv, u32 reg, u32 mask)
-{
-       u32 val = _iwl3945_read_prph(priv, reg);
-       _iwl3945_write_prph(priv, reg, (val & ~mask));
-}
-
-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);
-}
-
-static inline void iwl3945_write_targ_mem_buf(struct iwl3945_priv *priv, u32 addr,
-                                         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);
-}
-#endif
index 4c638909a7db325bd6314c3f2f065824f8d66f0a..fab137365000af01210d2ab71e3a9d005b19a8da 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
 #include <linux/etherdevice.h>
 #include <asm/unaligned.h>
 
+#include "iwl-commands.h"
 #include "iwl-3945.h"
-#include "iwl-helpers.h"
+#include "iwl-core.h"
+#include "iwl-dev.h"
 
 
 static const struct {
@@ -67,8 +69,8 @@ static const struct {
 #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
 #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
 
-static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
-                                   struct iwl3945_cmd *cmd,
+static int iwl3945_led_cmd_callback(struct iwl_priv *priv,
+                                   struct iwl_cmd *cmd,
                                    struct sk_buff *skb)
 {
        return 1;
@@ -80,27 +82,27 @@ static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
 }
 
 /* Send led command */
-static int iwl_send_led_cmd(struct iwl3945_priv *priv,
-                           struct iwl3945_led_cmd *led_cmd)
+static int iwl_send_led_cmd(struct iwl_priv *priv,
+                           struct iwl_led_cmd *led_cmd)
 {
-       struct iwl3945_host_cmd cmd = {
+       struct iwl_host_cmd cmd = {
                .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl3945_led_cmd),
+               .len = sizeof(struct iwl_led_cmd),
                .data = led_cmd,
                .meta.flags = CMD_ASYNC,
                .meta.u.callback = iwl3945_led_cmd_callback,
        };
 
-       return iwl3945_send_cmd(priv, &cmd);
+       return iwl_send_cmd(priv, &cmd);
 }
 
 
 
 /* Set led on command */
-static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
+static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id,
                               unsigned int idx)
 {
-       struct iwl3945_led_cmd led_cmd = {
+       struct iwl_led_cmd led_cmd = {
                .id = led_id,
                .interval = IWL_DEF_LED_INTRVL
        };
@@ -114,11 +116,10 @@ static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
 }
 
 
-#if 1
 /* Set led on command */
-static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
+static int iwl3945_led_on(struct iwl_priv *priv, int led_id)
 {
-       struct iwl3945_led_cmd led_cmd = {
+       struct iwl_led_cmd led_cmd = {
                .id = led_id,
                .on = IWL_LED_SOLID,
                .off = 0,
@@ -128,9 +129,9 @@ static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
 }
 
 /* Set led off command */
-static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
+static int iwl3945_led_off(struct iwl_priv *priv, int led_id)
 {
-       struct iwl3945_led_cmd led_cmd = {
+       struct iwl_led_cmd led_cmd = {
                .id = led_id,
                .on = 0,
                .off = 0,
@@ -139,13 +140,11 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
        IWL_DEBUG_LED("led off %d\n", led_id);
        return iwl_send_led_cmd(priv, &led_cmd);
 }
-#endif
-
 
 /*
  * brightness call back function for Tx/Rx LED
  */
-static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id)
+static int iwl3945_led_associated(struct iwl_priv *priv, int led_id)
 {
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
            !test_bit(STATUS_READY, &priv->status))
@@ -166,7 +165,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
 {
        struct iwl3945_led *led = container_of(led_cdev,
                                               struct iwl3945_led, led_dev);
-       struct iwl3945_priv *priv = led->priv;
+       struct iwl_priv *priv = led->priv;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -202,7 +201,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
 /*
  * Register led class with the system
  */
-static int iwl3945_led_register_led(struct iwl3945_priv *priv,
+static int iwl3945_led_register_led(struct iwl_priv *priv,
                                   struct iwl3945_led *led,
                                   enum led_type type, u8 set_led,
                                   char *trigger)
@@ -219,7 +218,7 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv,
 
        ret = led_classdev_register(device, &led->led_dev);
        if (ret) {
-               IWL_ERROR("Error: failed to register led handler.\n");
+               IWL_ERR(priv, "Error: failed to register led handler.\n");
                return ret;
        }
 
@@ -234,7 +233,7 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv,
 /*
  * calculate blink rate according to last 2 sec Tx/Rx activities
  */
-static inline u8 get_blink_rate(struct iwl3945_priv *priv)
+static inline u8 get_blink_rate(struct iwl_priv *priv)
 {
        int index;
        u64 current_tpt = priv->rxtxpackets;
@@ -253,7 +252,7 @@ static inline u8 get_blink_rate(struct iwl3945_priv *priv)
        return index;
 }
 
-static inline int is_rf_kill(struct iwl3945_priv *priv)
+static inline int is_rf_kill(struct iwl_priv *priv)
 {
        return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
                test_bit(STATUS_RF_KILL_SW, &priv->status);
@@ -264,7 +263,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv)
  * happen very frequent we postpone led command to be called from
  * REPLY handler so we know ucode is up
  */
-void iwl3945_led_background(struct iwl3945_priv *priv)
+void iwl3945_led_background(struct iwl_priv *priv)
 {
        u8 blink_idx;
 
@@ -304,7 +303,7 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
 
 
 /* Register all led handler */
-int iwl3945_led_register(struct iwl3945_priv *priv)
+int iwl3945_led_register(struct iwl_priv *priv)
 {
        char *trigger;
        int ret;
@@ -316,66 +315,66 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
        priv->allow_blinking = 0;
 
        trigger = ieee80211_get_radio_led_name(priv->hw);
-       snprintf(priv->led[IWL_LED_TRG_RADIO].name,
-                sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio",
+       snprintf(priv->led39[IWL_LED_TRG_RADIO].name,
+                sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s:radio",
                 wiphy_name(priv->hw->wiphy));
 
-       priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
-       priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off;
-       priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
+       priv->led39[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
+       priv->led39[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off;
+       priv->led39[IWL_LED_TRG_RADIO].led_pattern = NULL;
 
        ret = iwl3945_led_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_RADIO],
+                                  &priv->led39[IWL_LED_TRG_RADIO],
                                   IWL_LED_TRG_RADIO, 1, trigger);
 
        if (ret)
                goto exit_fail;
 
        trigger = ieee80211_get_assoc_led_name(priv->hw);
-       snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
-                sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc",
+       snprintf(priv->led39[IWL_LED_TRG_ASSOC].name,
+                sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc",
                 wiphy_name(priv->hw->wiphy));
 
        ret = iwl3945_led_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_ASSOC],
+                                  &priv->led39[IWL_LED_TRG_ASSOC],
                                   IWL_LED_TRG_ASSOC, 0, trigger);
 
        /* for assoc always turn led on */
-       priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
-       priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
-       priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
+       priv->led39[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
+       priv->led39[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
+       priv->led39[IWL_LED_TRG_ASSOC].led_pattern = NULL;
 
        if (ret)
                goto exit_fail;
 
        trigger = ieee80211_get_rx_led_name(priv->hw);
-       snprintf(priv->led[IWL_LED_TRG_RX].name,
-                sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX",
+       snprintf(priv->led39[IWL_LED_TRG_RX].name,
+                sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s:RX",
                 wiphy_name(priv->hw->wiphy));
 
        ret = iwl3945_led_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_RX],
+                                  &priv->led39[IWL_LED_TRG_RX],
                                   IWL_LED_TRG_RX, 0, trigger);
 
-       priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
-       priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
-       priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
+       priv->led39[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
+       priv->led39[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
+       priv->led39[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
 
        if (ret)
                goto exit_fail;
 
        trigger = ieee80211_get_tx_led_name(priv->hw);
-       snprintf(priv->led[IWL_LED_TRG_TX].name,
-                sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX",
+       snprintf(priv->led39[IWL_LED_TRG_TX].name,
+                sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s:TX",
                 wiphy_name(priv->hw->wiphy));
 
        ret = iwl3945_led_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_TX],
+                                  &priv->led39[IWL_LED_TRG_TX],
                                   IWL_LED_TRG_TX, 0, trigger);
 
-       priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
-       priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
-       priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
+       priv->led39[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
+       priv->led39[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
+       priv->led39[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
 
        if (ret)
                goto exit_fail;
@@ -402,11 +401,11 @@ static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led)
 }
 
 /* Unregister all led handlers */
-void iwl3945_led_unregister(struct iwl3945_priv *priv)
+void iwl3945_led_unregister(struct iwl_priv *priv)
 {
-       iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
-       iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
-       iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
-       iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
+       iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_ASSOC], 0);
+       iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RX], 0);
+       iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_TX], 0);
+       iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RADIO], 1);
 }
 
index 749ac035fd6aa3a20d4a7c85b8778f2084dc11e1..88185a6ccd6aca02677b468ba42e3c1834ed2e8b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
 #ifndef IWL3945_LEDS_H
 #define IWL3945_LEDS_H
 
-struct iwl3945_priv;
+struct iwl_priv;
 
 #ifdef CONFIG_IWL3945_LEDS
-#define IWL_LED_SOLID 11
-#define IWL_LED_NAME_LEN 31
-#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
 
-#define IWL_LED_ACTIVITY       (0<<1)
-#define IWL_LED_LINK           (1<<1)
-
-enum led_type {
-       IWL_LED_TRG_TX,
-       IWL_LED_TRG_RX,
-       IWL_LED_TRG_ASSOC,
-       IWL_LED_TRG_RADIO,
-       IWL_LED_TRG_MAX,
-};
-
-#include <linux/leds.h>
+#include "iwl-led.h"
 
 struct iwl3945_led {
-       struct iwl3945_priv *priv;
+       struct iwl_priv *priv;
        struct led_classdev led_dev;
        char name[32];
 
-       int (*led_on) (struct iwl3945_priv *priv, int led_id);
-       int (*led_off) (struct iwl3945_priv *priv, int led_id);
-       int (*led_pattern) (struct iwl3945_priv *priv, int led_id,
+       int (*led_on) (struct iwl_priv *priv, int led_id);
+       int (*led_off) (struct iwl_priv *priv, int led_id);
+       int (*led_pattern) (struct iwl_priv *priv, int led_id,
                            unsigned int idx);
 
        enum led_type type;
        unsigned int registered;
 };
 
-extern int iwl3945_led_register(struct iwl3945_priv *priv);
-extern void iwl3945_led_unregister(struct iwl3945_priv *priv);
-extern void iwl3945_led_background(struct iwl3945_priv *priv);
+extern int iwl3945_led_register(struct iwl_priv *priv);
+extern void iwl3945_led_unregister(struct iwl_priv *priv);
+extern void iwl3945_led_background(struct iwl_priv *priv);
 
 #else
-static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; }
-static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {}
-static inline void iwl3945_led_background(struct iwl3945_priv *priv) {}
+static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; }
+static inline void iwl3945_led_unregister(struct iwl_priv *priv) {}
+static inline void iwl3945_led_background(struct iwl_priv *priv) {}
 #endif /* CONFIG_IWL3945_LEDS */
 
 #endif /* IWL3945_LEDS_H */
index 21c841847d886022072f44fea41792ae64227d0c..044abf734eb610ea60c084574095403dab45d080 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -36,6 +36,7 @@
 
 #include <linux/workqueue.h>
 
+#include "iwl-commands.h"
 #include "iwl-3945.h"
 
 #define RS_NAME "iwl-3945-rs"
@@ -51,6 +52,7 @@ struct iwl3945_rate_scale_data {
 
 struct iwl3945_rs_sta {
        spinlock_t lock;
+       struct iwl_priv *priv;
        s32 *expected_tpt;
        unsigned long last_partial_flush;
        unsigned long last_flush;
@@ -62,7 +64,7 @@ struct iwl3945_rs_sta {
        u8 start_rate;
        u8 ibss_sta_added;
        struct timer_list rate_scale_flush;
-       struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
+       struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct dentry *rs_sta_dbgfs_stats_table_file;
 #endif
@@ -71,19 +73,19 @@ struct iwl3945_rs_sta {
        int last_txrate_idx;
 };
 
-static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
        7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
 };
 
-static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
        7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
 };
 
-static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
        0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
 };
 
-static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
        7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
@@ -119,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
 #define IWL_RATE_MAX_WINDOW          62
 #define IWL_RATE_FLUSH          (3*HZ)
 #define IWL_RATE_WIN_FLUSH       (HZ/2)
-#define IWL_RATE_HIGH_TH          11520
+#define IWL39_RATE_HIGH_TH          11520
 #define IWL_SUCCESS_UP_TH         8960
 #define IWL_SUCCESS_DOWN_TH      10880
 #define IWL_RATE_MIN_FAILURE_TH       8
@@ -165,7 +167,7 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
        window->success_counter = 0;
        window->success_ratio = -1;
        window->counter = 0;
-       window->average_tpt = IWL_INV_TPT;
+       window->average_tpt = IWL_INVALID_VALUE;
        window->stamp = 0;
 }
 
@@ -181,13 +183,14 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
        int unflushed = 0;
        int i;
        unsigned long flags;
+       struct iwl_priv *priv = rs_sta->priv;
 
        /*
         * For each rate, if we have collected data on that rate
         * and it has been more than IWL_RATE_WIN_FLUSH
         * since we flushed, clear out the gathered statistics
         */
-       for (i = 0; i < IWL_RATE_COUNT; i++) {
+       for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
                if (!rs_sta->win[i].counter)
                        continue;
 
@@ -213,6 +216,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
 static void iwl3945_bg_rate_scale_flush(unsigned long data)
 {
        struct iwl3945_rs_sta *rs_sta = (void *)data;
+       struct iwl_priv *priv = rs_sta->priv;
        int unflushed = 0;
        unsigned long flags;
        u32 packet_count, duration, pps;
@@ -286,6 +290,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
 {
        unsigned long flags;
        s32 fail_count;
+       struct iwl_priv *priv = rs_sta->priv;
 
        if (!retries) {
                IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n");
@@ -329,7 +334,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
                window->average_tpt = ((window->success_ratio *
                                rs_sta->expected_tpt[index] + 64) / 128);
        else
-               window->average_tpt = IWL_INV_TPT;
+               window->average_tpt = IWL_INVALID_VALUE;
 
        spin_unlock_irqrestore(&rs_sta->lock, flags);
 
@@ -339,7 +344,7 @@ 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;
+       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
        int i;
 
        IWL_DEBUG_RATE("enter\n");
@@ -379,10 +384,11 @@ static void rs_free(void *priv)
        return;
 }
 
-static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
+static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
 {
        struct iwl3945_rs_sta *rs_sta;
        struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
+       struct iwl_priv *priv = iwl_priv;
        int i;
 
        /*
@@ -402,6 +408,8 @@ static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 
        spin_lock_init(&rs_sta->lock);
 
+       rs_sta->priv = priv;
+
        rs_sta->start_rate = IWL_RATE_INVALID;
 
        /* default to just 802.11b */
@@ -417,7 +425,7 @@ static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
        rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
        rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush;
 
-       for (i = 0; i < IWL_RATE_COUNT; i++)
+       for (i = 0; i < IWL_RATE_COUNT_3945; i++)
                iwl3945_clear_window(&rs_sta->win[i]);
 
        IWL_DEBUG_RATE("leave\n");
@@ -425,11 +433,12 @@ static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
        return rs_sta;
 }
 
-static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
+static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
                        void *priv_sta)
 {
        struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
        struct iwl3945_rs_sta *rs_sta = priv_sta;
+       struct iwl_priv *priv = rs_sta->priv;
 
        psta->rs_sta = NULL;
 
@@ -443,7 +452,7 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
 /**
  * rs_tx_status - Update rate control values based on Tx results
  *
- * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
+ * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
  * the hardware for each rate.
  */
 static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
@@ -453,7 +462,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
        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;
+       struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
        struct iwl3945_rs_sta *rs_sta = priv_sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
@@ -462,7 +471,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
        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)) {
+       if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
                IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
                return;
        }
@@ -547,6 +556,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
 {
        u8 high = IWL_RATE_INVALID;
        u8 low = IWL_RATE_INVALID;
+       struct iwl_priv *priv = rs_sta->priv;
 
        /* 802.11A walks to the next literal adjacent rate in
         * the rate table */
@@ -565,7 +575,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
 
                /* Find the next rate that is in the rate mask */
                i = index + 1;
-               for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {
+               for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
+                    i++, mask <<= 1) {
                        if (rate_mask & mask) {
                                high = i;
                                break;
@@ -631,16 +642,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
        int index;
        struct iwl3945_rs_sta *rs_sta = priv_sta;
        struct iwl3945_rate_scale_data *window = NULL;
-       int current_tpt = IWL_INV_TPT;
-       int low_tpt = IWL_INV_TPT;
-       int high_tpt = IWL_INV_TPT;
+       int current_tpt = IWL_INVALID_VALUE;
+       int low_tpt = IWL_INVALID_VALUE;
+       int high_tpt = IWL_INVALID_VALUE;
        u32 fail_count;
        s8 scale_action = 0;
        unsigned long flags;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        u16 fc;
        u16 rate_mask = 0;
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
+       s8 max_rate_idx = -1;
+       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        IWL_DEBUG_RATE("enter\n");
@@ -664,7 +676,14 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                return;
        }
 
-       index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
+       /* get user max rate if set */
+       max_rate_idx = txrc->max_rate_idx;
+       if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
+               max_rate_idx += IWL_FIRST_OFDM_RATE;
+       if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
+               max_rate_idx = -1;
+
+       index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
 
        if (sband->band == IEEE80211_BAND_5GHZ)
                rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
@@ -695,6 +714,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                rs_sta->start_rate = IWL_RATE_INVALID;
        }
 
+       /* force user max rate if set by user */
+       if ((max_rate_idx != -1) && (max_rate_idx < index)) {
+               if (rate_mask & (1 << max_rate_idx))
+                       index = max_rate_idx;
+       }
+
        window = &(rs_sta->win[index]);
 
        fail_count = window->counter - window->success_counter;
@@ -721,6 +746,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
+       /* If user set max rate, dont allow higher than user constrain */
+       if ((max_rate_idx != -1) && (max_rate_idx < high))
+               high = IWL_RATE_INVALID;
+
        if (low != IWL_RATE_INVALID)
                low_tpt = rs_sta->win[low].average_tpt;
 
@@ -734,16 +763,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
        if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
                IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
                scale_action = -1;
-       } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
+       } else if ((low_tpt == IWL_INVALID_VALUE) &&
+                  (high_tpt == IWL_INVALID_VALUE))
                scale_action = 1;
-       else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
+       else if ((low_tpt != IWL_INVALID_VALUE) &&
+                (high_tpt != IWL_INVALID_VALUE) &&
                 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
                IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
                               "current_tpt [%d]\n",
                               low_tpt, high_tpt, current_tpt);
                scale_action = 0;
        } else {
-               if (high_tpt != IWL_INV_TPT) {
+               if (high_tpt != IWL_INVALID_VALUE) {
                        if (high_tpt > current_tpt)
                                scale_action = 1;
                        else {
@@ -751,7 +782,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                                    ("decrease rate because of high tpt\n");
                                scale_action = -1;
                        }
-               } else if (low_tpt != IWL_INV_TPT) {
+               } else if (low_tpt != IWL_INVALID_VALUE) {
                        if (low_tpt > current_tpt) {
                                IWL_DEBUG_RATE
                                    ("decrease rate because of low tpt\n");
@@ -825,7 +856,7 @@ static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
                        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++) {
+       for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
                desc += sprintf(buff+desc,
                                "counter=%d success=%d %%=%d\n",
                                lq_sta->win[j].counter,
@@ -877,7 +908,7 @@ static struct rate_control_ops rs_ops = {
 
 void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        s32 rssi = 0;
        unsigned long flags;
        struct iwl3945_rs_sta *rs_sta;
@@ -888,7 +919,7 @@ 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);
+       sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr);
        if (!sta) {
                rcu_read_unlock();
                return;
@@ -903,7 +934,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
        switch (priv->band) {
        case IEEE80211_BAND_2GHZ:
                /* TODO: this always does G, not a regression */
-               if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
+               if (priv->active39_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
                        rs_sta->tgg = 1;
                        rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
                } else
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
deleted file mode 100644 (file)
index b5a6613..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_3945_rs_h__
-#define __iwl_3945_rs_h__
-
-struct iwl3945_rate_info {
-       u8 plcp;                /* uCode API:  IWL_RATE_6M_PLCP, etc. */
-       u8 ieee;                /* MAC header:  IWL_RATE_6M_IEEE, etc. */
-       u8 prev_ieee;           /* previous rate in IEEE speeds */
-       u8 next_ieee;           /* next rate in IEEE speeds */
-       u8 prev_rs;             /* previous rate used in rs algo */
-       u8 next_rs;             /* next rate used in rs algo */
-       u8 prev_rs_tgg;         /* previous rate used in TGG rs algo */
-       u8 next_rs_tgg;         /* next rate used in TGG rs algo */
-       u8 table_rs_index;      /* index in rate scale table cmd */
-       u8 prev_table_rs;       /* prev in rate table cmd */
-};
-
-/*
- * These serve as indexes into
- * struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT];
- */
-enum {
-       IWL_RATE_1M_INDEX = 0,
-       IWL_RATE_2M_INDEX,
-       IWL_RATE_5M_INDEX,
-       IWL_RATE_11M_INDEX,
-       IWL_RATE_6M_INDEX,
-       IWL_RATE_9M_INDEX,
-       IWL_RATE_12M_INDEX,
-       IWL_RATE_18M_INDEX,
-       IWL_RATE_24M_INDEX,
-       IWL_RATE_36M_INDEX,
-       IWL_RATE_48M_INDEX,
-       IWL_RATE_54M_INDEX,
-       IWL_RATE_COUNT,
-       IWL_RATE_INVM_INDEX,
-       IWL_RATE_INVALID = IWL_RATE_INVM_INDEX
-};
-
-enum {
-       IWL_RATE_6M_INDEX_TABLE = 0,
-       IWL_RATE_9M_INDEX_TABLE,
-       IWL_RATE_12M_INDEX_TABLE,
-       IWL_RATE_18M_INDEX_TABLE,
-       IWL_RATE_24M_INDEX_TABLE,
-       IWL_RATE_36M_INDEX_TABLE,
-       IWL_RATE_48M_INDEX_TABLE,
-       IWL_RATE_54M_INDEX_TABLE,
-       IWL_RATE_1M_INDEX_TABLE,
-       IWL_RATE_2M_INDEX_TABLE,
-       IWL_RATE_5M_INDEX_TABLE,
-       IWL_RATE_11M_INDEX_TABLE,
-       IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX,
-};
-
-enum {
-       IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
-       IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
-       IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
-       IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
-};
-
-/* #define vs. enum to keep from defaulting to 'large integer' */
-#define        IWL_RATE_6M_MASK   (1 << IWL_RATE_6M_INDEX)
-#define        IWL_RATE_9M_MASK   (1 << IWL_RATE_9M_INDEX)
-#define        IWL_RATE_12M_MASK  (1 << IWL_RATE_12M_INDEX)
-#define        IWL_RATE_18M_MASK  (1 << IWL_RATE_18M_INDEX)
-#define        IWL_RATE_24M_MASK  (1 << IWL_RATE_24M_INDEX)
-#define        IWL_RATE_36M_MASK  (1 << IWL_RATE_36M_INDEX)
-#define        IWL_RATE_48M_MASK  (1 << IWL_RATE_48M_INDEX)
-#define        IWL_RATE_54M_MASK  (1 << IWL_RATE_54M_INDEX)
-#define        IWL_RATE_1M_MASK   (1 << IWL_RATE_1M_INDEX)
-#define        IWL_RATE_2M_MASK   (1 << IWL_RATE_2M_INDEX)
-#define        IWL_RATE_5M_MASK   (1 << IWL_RATE_5M_INDEX)
-#define        IWL_RATE_11M_MASK  (1 << IWL_RATE_11M_INDEX)
-
-/* 3945 uCode API values for (legacy) bit rates, both OFDM and CCK */
-enum {
-       IWL_RATE_6M_PLCP = 13,
-       IWL_RATE_9M_PLCP = 15,
-       IWL_RATE_12M_PLCP = 5,
-       IWL_RATE_18M_PLCP = 7,
-       IWL_RATE_24M_PLCP = 9,
-       IWL_RATE_36M_PLCP = 11,
-       IWL_RATE_48M_PLCP = 1,
-       IWL_RATE_54M_PLCP = 3,
-       IWL_RATE_1M_PLCP = 10,
-       IWL_RATE_2M_PLCP = 20,
-       IWL_RATE_5M_PLCP = 55,
-       IWL_RATE_11M_PLCP = 110,
-};
-
-/* MAC header values for bit rates */
-enum {
-       IWL_RATE_6M_IEEE = 12,
-       IWL_RATE_9M_IEEE = 18,
-       IWL_RATE_12M_IEEE = 24,
-       IWL_RATE_18M_IEEE = 36,
-       IWL_RATE_24M_IEEE = 48,
-       IWL_RATE_36M_IEEE = 72,
-       IWL_RATE_48M_IEEE = 96,
-       IWL_RATE_54M_IEEE = 108,
-       IWL_RATE_1M_IEEE = 2,
-       IWL_RATE_2M_IEEE = 4,
-       IWL_RATE_5M_IEEE = 11,
-       IWL_RATE_11M_IEEE = 22,
-};
-
-#define IWL_CCK_BASIC_RATES_MASK    \
-       (IWL_RATE_1M_MASK          | \
-       IWL_RATE_2M_MASK)
-
-#define IWL_CCK_RATES_MASK          \
-       (IWL_BASIC_RATES_MASK      | \
-       IWL_RATE_5M_MASK          | \
-       IWL_RATE_11M_MASK)
-
-#define IWL_OFDM_BASIC_RATES_MASK   \
-       (IWL_RATE_6M_MASK         | \
-       IWL_RATE_12M_MASK         | \
-       IWL_RATE_24M_MASK)
-
-#define IWL_OFDM_RATES_MASK         \
-       (IWL_OFDM_BASIC_RATES_MASK | \
-       IWL_RATE_9M_MASK          | \
-       IWL_RATE_18M_MASK         | \
-       IWL_RATE_36M_MASK         | \
-       IWL_RATE_48M_MASK         | \
-       IWL_RATE_54M_MASK)
-
-#define IWL_BASIC_RATES_MASK         \
-       (IWL_OFDM_BASIC_RATES_MASK | \
-        IWL_CCK_BASIC_RATES_MASK)
-
-#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
-
-#define IWL_INV_TPT    -1
-
-#define IWL_MIN_RSSI_VAL                 -100
-#define IWL_MAX_RSSI_VAL                    0
-
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT];
-
-static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
-{
-       u8 rate = iwl3945_rates[rate_index].prev_ieee;
-
-       if (rate == IWL_RATE_INVALID)
-               rate = rate_index;
-       return rate;
-}
-
-/**
- * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
- *
- * The specific throughput table used is based on the type of network
- * the associated with, including A, B, G, and G w/ TGG protection
- */
-extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
-
-/**
- * iwl3945_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
- * iwl3945_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
- *
- */
-extern int iwl3945_rate_control_register(void);
-
-/**
- * iwl3945_rate_control_unregister - Unregister the rate control callbacks
- *
- * This should be called after calling ieee80211_unregister_hw, but before
- * the driver is unloaded.
- */
-extern void iwl3945_rate_control_unregister(void);
-
-#endif
index 45cfa1cf194a2d3218efe4cb2a9ba8e03adc9df3..12f93b6207d6b90b49c491591793d4daf7889c42 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
 #include <asm/unaligned.h>
 #include <net/mac80211.h>
 
-#include "iwl-3945-core.h"
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
 #include "iwl-3945.h"
+#include "iwl-eeprom.h"
 #include "iwl-helpers.h"
-#include "iwl-3945-rs.h"
+#include "iwl-core.h"
+#include "iwl-agn-rs.h"
 
 #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
        [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
@@ -63,7 +68,7 @@
  * maps to IWL_RATE_INVALID
  *
  */
-const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT] = {
+const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
        IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
        IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
        IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
@@ -91,7 +96,7 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT] = {
  * Use for only special debugging.  This function is just a placeholder as-is,
  *   you'll need to provide the special bits! ...
  *   ... and set IWL_EVT_DISABLE to 1. */
-void iwl3945_disable_events(struct iwl3945_priv *priv)
+void iwl3945_disable_events(struct iwl_priv *priv)
 {
        int ret;
        int i;
@@ -150,30 +155,30 @@ void iwl3945_disable_events(struct iwl3945_priv *priv)
 
        base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
        if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+               IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
                return;
        }
 
-       ret = iwl3945_grab_nic_access(priv);
+       ret = iwl_grab_nic_access(priv);
        if (ret) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
+               IWL_WARN(priv, "Can not read from adapter at this time.\n");
                return;
        }
 
-       disable_ptr = iwl3945_read_targ_mem(priv, base + (4 * sizeof(u32)));
-       array_size = iwl3945_read_targ_mem(priv, base + (5 * sizeof(u32)));
-       iwl3945_release_nic_access(priv);
+       disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32)));
+       array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32)));
+       iwl_release_nic_access(priv);
 
        if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
                IWL_DEBUG_INFO("Disabling selected uCode log events at 0x%x\n",
                               disable_ptr);
-               ret = iwl3945_grab_nic_access(priv);
+               ret = iwl_grab_nic_access(priv);
                for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
-                       iwl3945_write_targ_mem(priv,
+                       iwl_write_targ_mem(priv,
                                           disable_ptr + (i * sizeof(u32)),
                                           evt_disable[i]);
 
-               iwl3945_release_nic_access(priv);
+               iwl_release_nic_access(priv);
        } else {
                IWL_DEBUG_INFO("Selected uCode log events may be disabled\n");
                IWL_DEBUG_INFO("  by writing \"1\"s into disable bitmap\n");
@@ -193,40 +198,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
        return -1;
 }
 
-/**
- * iwl3945_get_antenna_flags - Get antenna flags for RXON command
- * @priv: eeprom and antenna fields are used to determine antenna flags
- *
- * priv->eeprom  is used to determine if antenna AUX/MAIN are reversed
- * priv->antenna specifies the antenna diversity mode:
- *
- * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
- * IWL_ANTENNA_MAIN      - Force MAIN antenna
- * IWL_ANTENNA_AUX       - Force AUX antenna
- */
-__le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
-{
-       switch (priv->antenna) {
-       case IWL_ANTENNA_DIVERSITY:
-               return 0;
-
-       case IWL_ANTENNA_MAIN:
-               if (priv->eeprom.antenna_switch_type)
-                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-
-       case IWL_ANTENNA_AUX:
-               if (priv->eeprom.antenna_switch_type)
-                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-       }
-
-       /* bad antenna selector value */
-       IWL_ERROR("Bad antenna selector value (0x%x)\n", priv->antenna);
-       return 0;               /* "diversity" is default if error */
-}
-
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
 #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
 
 static const char *iwl3945_get_tx_fail_reason(u32 status)
@@ -266,7 +238,7 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status)
  * for A and B mode we need to overright prev
  * value
  */
-int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate)
+int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
 {
        int next_rate = iwl3945_get_prev_ieee_rate(rate);
 
@@ -300,12 +272,12 @@ int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate)
  * 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 iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
+static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
                                     int txq_id, int index)
 {
-       struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl3945_queue *q = &txq->q;
-       struct iwl3945_tx_info *tx_info;
+       struct iwl_tx_queue *txq = &priv->txq[txq_id];
+       struct iwl_queue *q = &txq->q;
+       struct iwl_tx_info *tx_info;
 
        BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
 
@@ -315,10 +287,10 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
                tx_info = &txq->txb[txq->q.read_ptr];
                ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
                tx_info->skb[0] = NULL;
-               iwl3945_hw_txq_free_tfd(priv, txq);
+               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
        }
 
-       if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+       if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
                        (txq_id != IWL_CMD_QUEUE_NUM) &&
                        priv->mac80211_registered)
                ieee80211_wake_queue(priv->hw, txq_id);
@@ -327,22 +299,22 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
 /**
  * iwl3945_rx_reply_tx - Handle Tx response
  */
-static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
-                           struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
+                           struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
        int txq_id = SEQ_TO_QUEUE(sequence);
        int index = SEQ_TO_INDEX(sequence);
-       struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+       struct iwl_tx_queue *txq = &priv->txq[txq_id];
        struct ieee80211_tx_info *info;
        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 "
+       if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
+               IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
                          "is out of range [0-%d] %d %d\n", txq_id,
                          index, txq->q.n_bd, txq->q.write_ptr,
                          txq->q.read_ptr);
@@ -374,7 +346,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
        iwl3945_tx_queue_reclaim(priv, txq_id, index);
 
        if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-               IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
+               IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
 
 
@@ -387,14 +359,14 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
  *
  *****************************************************************************/
 
-void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
+void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
                     (int)sizeof(struct iwl3945_notif_statistics),
                     le32_to_cpu(pkt->len));
 
-       memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
+       memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
 
        iwl3945_led_background(priv);
 
@@ -406,7 +378,7 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b
  * Misc. internal state and helper functions
  *
  ******************************************************************************/
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
 
 /**
  * iwl3945_report_frame - dump frame to syslog during debug sessions
@@ -415,8 +387,8 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b
  * including selective frame dumps.
  * group100 parameter selects whether to show 1 out of 100 good frames.
  */
-static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
-                     struct iwl3945_rx_packet *pkt,
+static void _iwl3945_dbg_report_frame(struct iwl_priv *priv,
+                     struct iwl_rx_packet *pkt,
                      struct ieee80211_hdr *header, int group100)
 {
        u32 to_us;
@@ -540,18 +512,27 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
                }
        }
        if (print_dump)
-               iwl3945_print_hex_dump(IWL_DL_RX, data, length);
+               iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
+}
+
+static void iwl3945_dbg_report_frame(struct iwl_priv *priv,
+                     struct iwl_rx_packet *pkt,
+                     struct ieee80211_hdr *header, int group100)
+{
+       if (priv->debug_level & IWL_DL_RX)
+               _iwl3945_dbg_report_frame(priv, pkt, header, group100);
 }
+
 #else
-static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
-                     struct iwl3945_rx_packet *pkt,
+static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv,
+                     struct iwl_rx_packet *pkt,
                      struct ieee80211_hdr *header, int group100)
 {
 }
 #endif
 
 /* This is necessary only for a number of statistics, see the caller. */
-static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
+static int iwl3945_is_network_packet(struct iwl_priv *priv,
                struct ieee80211_hdr *header)
 {
        /* Filter incoming packets to determine if they are targeted toward
@@ -568,11 +549,11 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
        }
 }
 
-static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
-                                  struct iwl3945_rx_mem_buffer *rxb,
+static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
+                                  struct iwl_rx_mem_buffer *rxb,
                                   struct ieee80211_rx_status *stats)
 {
-       struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 #ifdef CONFIG_IWL3945_LEDS
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
 #endif
@@ -581,7 +562,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
        short len = le16_to_cpu(rx_hdr->len);
 
        /* We received data from the HW, so stop the watchdog */
-       if (unlikely((len + IWL_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
+       if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
                IWL_DEBUG_DROP("Corruption detected!\n");
                return;
        }
@@ -597,7 +578,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
        /* Set the size of the skb to the size of the frame */
        skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
 
-       if (iwl3945_param_hwcrypto)
+       if (!iwl3945_mod_params.sw_crypto)
                iwl3945_set_decrypted_flag(priv, rxb->skb,
                                       le32_to_cpu(rx_end->status), stats);
 
@@ -611,12 +592,12 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
 
 #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
 
-static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
-                               struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+                               struct iwl_rx_mem_buffer *rxb)
 {
        struct ieee80211_hdr *header;
        struct ieee80211_rx_status rx_status;
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
@@ -659,7 +640,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
 
 
        /* Convert 3945's rssi indicator to dBm */
-       rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET;
+       rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
 
        /* Set default noise value to -127 */
        if (priv->last_rx_noise == 0)
@@ -705,11 +686,8 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
                              rx_status.signal, rx_status.signal,
                              rx_status.noise, rx_status.rate_idx);
 
-#ifdef CONFIG_IWL3945_DEBUG
-       if (iwl3945_debug_level & (IWL_DL_RX))
-               /* Set "1" to report good data frames in groups of 100 */
-               iwl3945_dbg_report_frame(priv, pkt, header, 1);
-#endif
+       /* Set "1" to report good data frames in groups of 100 */
+       iwl3945_dbg_report_frame(priv, pkt, header, 1);
 
        if (network_packet) {
                priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
@@ -721,24 +699,31 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
        iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
 }
 
-int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr,
-                                dma_addr_t addr, u16 len)
+int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+                                    struct iwl_tx_queue *txq,
+                                    dma_addr_t addr, u16 len, u8 reset, u8 pad)
 {
        int count;
-       u32 pad;
-       struct iwl3945_tfd_frame *tfd = (struct iwl3945_tfd_frame *)ptr;
+       struct iwl_queue *q;
+       struct iwl3945_tfd *tfd, *tfd_tmp;
+
+       q = &txq->q;
+       tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
 
        count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-       pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags));
 
        if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
-               IWL_ERROR("Error can not send more than %d chunks\n",
+               IWL_ERR(priv, "Error can not send more than %d chunks\n",
                          NUM_TFD_CHUNKS);
                return -EINVAL;
        }
 
-       tfd->pa[count].addr = cpu_to_le32(addr);
-       tfd->pa[count].len = cpu_to_le32(len);
+       tfd->tbs[count].addr = cpu_to_le32(addr);
+       tfd->tbs[count].len = cpu_to_le32(len);
 
        count++;
 
@@ -753,10 +738,10 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr,
  *
  * Does NOT advance any indexes
  */
-int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
+void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 {
-       struct iwl3945_tfd_frame *bd_tmp = (struct iwl3945_tfd_frame *)&txq->bd[0];
-       struct iwl3945_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+       struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+       struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr];
        struct pci_dev *dev = priv->pci_dev;
        int i;
        int counter;
@@ -764,21 +749,21 @@ int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *
        /* classify bd */
        if (txq->q.id == IWL_CMD_QUEUE_NUM)
                /* nothing to cleanup after for host commands */
-               return 0;
+               return;
 
        /* sanity check */
-       counter = TFD_CTL_COUNT_GET(le32_to_cpu(bd->control_flags));
+       counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
        if (counter > NUM_TFD_CHUNKS) {
-               IWL_ERROR("Too many chunks: %i\n", counter);
+               IWL_ERR(priv, "Too many chunks: %i\n", counter);
                /* @todo issue fatal error, it is quite serious situation */
-               return 0;
+               return;
        }
 
        /* unmap chunks if any */
 
        for (i = 1; i < counter; i++) {
-               pci_unmap_single(dev, le32_to_cpu(bd->pa[i].addr),
-                                le32_to_cpu(bd->pa[i].len), PCI_DMA_TODEVICE);
+               pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
+                        le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
                if (txq->txb[txq->q.read_ptr].skb[0]) {
                        struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0];
                        if (txq->txb[txq->q.read_ptr].skb[0]) {
@@ -788,10 +773,10 @@ int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *
                        }
                }
        }
-       return 0;
+       return ;
 }
 
-u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
+u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr)
 {
        int i, start = IWL_AP_ID;
        int ret = IWL_INVALID_STATION;
@@ -802,13 +787,13 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
                start = IWL_STA_ID;
 
        if (is_broadcast_ether_addr(addr))
-               return priv->hw_setting.bcast_sta_id;
+               return priv->hw_params.bcast_sta_id;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
-       for (i = start; i < priv->hw_setting.max_stations; i++)
-               if ((priv->stations[i].used) &&
+       for (i = start; i < priv->hw_params.max_stations; i++)
+               if ((priv->stations_39[i].used) &&
                    (!compare_ether_addr
-                    (priv->stations[i].sta.sta.addr, addr))) {
+                    (priv->stations_39[i].sta.sta.addr, addr))) {
                        ret = i;
                        goto out;
                }
@@ -824,12 +809,10 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
  * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
  *
 */
-void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
-                             struct iwl3945_cmd *cmd,
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
                              struct ieee80211_tx_info *info,
                              struct ieee80211_hdr *hdr, int sta_id, int tx_id)
 {
-       unsigned long flags;
        u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
        u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
        u16 rate_mask;
@@ -838,25 +821,15 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
        u8 data_retry_limit;
        __le32 tx_flags;
        __le16 fc = hdr->frame_control;
+       struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
 
        rate = iwl3945_rates[rate_index].plcp;
-       tx_flags = cmd->cmd.tx.tx_flags;
+       tx_flags = tx->tx_flags;
 
        /* We need to figure out how to get the sta->supp_rates while
         * in this running context */
        rate_mask = IWL_RATES_MASK;
 
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->stations[sta_id].current_rate.rate_n_flags = rate;
-
-       if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
-           (sta_id != priv->hw_setting.bcast_sta_id) &&
-               (sta_id != IWL_MULTICAST_ID))
-               priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
        if (tx_id >= IWL_CMD_QUEUE_NUM)
                rts_retry_limit = 3;
        else
@@ -888,25 +861,25 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
                }
        }
 
-       cmd->cmd.tx.rts_retry_limit = rts_retry_limit;
-       cmd->cmd.tx.data_retry_limit = data_retry_limit;
-       cmd->cmd.tx.rate = rate;
-       cmd->cmd.tx.tx_flags = tx_flags;
+       tx->rts_retry_limit = rts_retry_limit;
+       tx->data_retry_limit = data_retry_limit;
+       tx->rate = rate;
+       tx->tx_flags = tx_flags;
 
        /* OFDM */
-       cmd->cmd.tx.supp_rates[0] =
+       tx->supp_rates[0] =
           ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
 
        /* CCK */
-       cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF);
+       tx->supp_rates[1] = (rate_mask & 0xF);
 
        IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
                       "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
-                      cmd->cmd.tx.rate, le32_to_cpu(cmd->cmd.tx.tx_flags),
-                      cmd->cmd.tx.supp_rates[1], cmd->cmd.tx.supp_rates[0]);
+                      tx->rate, le32_to_cpu(tx->tx_flags),
+                      tx->supp_rates[1], tx->supp_rates[0]);
 }
 
-u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags)
+u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
 {
        unsigned long flags_spin;
        struct iwl3945_station_entry *station;
@@ -915,56 +888,56 @@ u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags
                return IWL_INVALID_STATION;
 
        spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       station = &priv->stations[sta_id];
+       station = &priv->stations_39[sta_id];
 
        station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
        station->sta.rate_n_flags = cpu_to_le16(tx_rate);
-       station->current_rate.rate_n_flags = tx_rate;
        station->sta.mode = STA_CONTROL_MODIFY_MSK;
 
        spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
-       iwl3945_send_add_station(priv, &station->sta, flags);
+       iwl_send_add_sta(priv,
+                        (struct iwl_addsta_cmd *)&station->sta, flags);
        IWL_DEBUG_RATE("SCALE sync station %d to rate %d\n",
                        sta_id, tx_rate);
        return sta_id;
 }
 
-static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max)
+static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
 {
        int rc;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
 
-       if (!pwr_max) {
+       if (src == IWL_PWR_SRC_VAUX) {
                u32 val;
 
                rc = pci_read_config_dword(priv->pci_dev,
                                PCI_POWER_SOURCE, &val);
                if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
-                       iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+                       iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
                                        APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
                                        ~APMG_PS_CTRL_MSK_PWR_SRC);
-                       iwl3945_release_nic_access(priv);
+                       iwl_release_nic_access(priv);
 
-                       iwl3945_poll_bit(priv, CSR_GPIO_IN,
+                       iwl_poll_bit(priv, CSR_GPIO_IN,
                                     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
                                     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
                } else
-                       iwl3945_release_nic_access(priv);
+                       iwl_release_nic_access(priv);
        } else {
-               iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+               iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
                                APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
                                ~APMG_PS_CTRL_MSK_PWR_SRC);
 
-               iwl3945_release_nic_access(priv);
-               iwl3945_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+               iwl_release_nic_access(priv);
+               iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
                             CSR_GPIO_IN_BIT_AUX_POWER, 5000);  /* uS */
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -972,81 +945,79 @@ static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max)
        return rc;
 }
 
-static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
+static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 {
        int rc;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
 
-       iwl3945_write_direct32(priv, FH_RCSR_RBD_BASE(0), rxq->dma_addr);
-       iwl3945_write_direct32(priv, FH_RCSR_RPTR_ADDR(0),
-                            priv->hw_setting.shared_phys +
-                            offsetof(struct iwl3945_shared, rx_read_ptr[0]));
-       iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), 0);
-       iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0),
-               ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
-               ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
-               ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
-               ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
-               (RX_QUEUE_SIZE_LOG << ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
-               ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
-               (1 << ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
-               ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
+       iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr);
+       iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
+       iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
+       iwl_write_direct32(priv, FH39_RCSR_CONFIG(0),
+               FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
+               FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
+               FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
+               FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
+               (RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
+               FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
+               (1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
+               FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
 
        /* fake read to flush all prev I/O */
-       iwl3945_read_direct32(priv, FH_RSSR_CTRL);
+       iwl_read_direct32(priv, FH39_RSSR_CTRL);
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
 }
 
-static int iwl3945_tx_reset(struct iwl3945_priv *priv)
+static int iwl3945_tx_reset(struct iwl_priv *priv)
 {
        int rc;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
 
        /* bypass mode */
-       iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
+       iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
 
        /* RA 0 is active */
-       iwl3945_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
+       iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
 
        /* all 6 fifo are active */
-       iwl3945_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
-
-       iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
-       iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
-       iwl3945_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
-       iwl3945_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
-
-       iwl3945_write_direct32(priv, FH_TSSR_CBB_BASE,
-                            priv->hw_setting.shared_phys);
-
-       iwl3945_write_direct32(priv, FH_TSSR_MSG_CONFIG,
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
-               ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
-
-       iwl3945_release_nic_access(priv);
+       iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
+
+       iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
+       iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
+       iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
+       iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
+
+       iwl_write_direct32(priv, FH39_TSSR_CBB_BASE,
+                            priv->shared_phys);
+
+       iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
+               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
+
+       iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
@@ -1057,7 +1028,7 @@ static int iwl3945_tx_reset(struct iwl3945_priv *priv)
  *
  * Destroys all DMA structures and initialize them again
  */
-static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv)
+static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
 {
        int rc;
        int txq_id, slots_num;
@@ -1073,10 +1044,10 @@ static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv)
        for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) {
                slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
                                TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-                               txq_id);
+               rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+                                      txq_id);
                if (rc) {
-                       IWL_ERROR("Tx %d queue init failed\n", txq_id);
+                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
                        goto error;
                }
        }
@@ -1088,111 +1059,140 @@ static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv)
        return rc;
 }
 
-int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+static int iwl3945_apm_init(struct iwl_priv *priv)
 {
-       u8 rev_id;
-       int rc;
-       unsigned long flags;
-       struct iwl3945_rx_queue *rxq = &priv->rxq;
+       int ret = 0;
 
        iwl3945_power_init_handle(priv);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_set_bit(priv, CSR_ANA_PLL_CFG, CSR39_ANA_PLL_CFG_VAL);
-       iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-                   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_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_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+                         CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+       /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
+       iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+                         CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
+       /* set "initialization complete" bit to move adapter
+       * D0U* --> D0A* state */
+       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+       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 rc;
+               goto out;
        }
 
-       rc = iwl3945_grab_nic_access(priv);
-       if (rc) {
-               spin_unlock_irqrestore(&priv->lock, flags);
-               return rc;
-       }
-       iwl3945_write_prph(priv, APMG_CLK_EN_REG,
-                                APMG_CLK_VAL_DMA_CLK_RQT |
-                                APMG_CLK_VAL_BSM_CLK_RQT);
+       ret = iwl_grab_nic_access(priv);
+       if (ret)
+               goto out;
+
+       /* enable DMA */
+       iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
+                                               APMG_CLK_VAL_BSM_CLK_RQT);
+
        udelay(20);
-       iwl3945_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
-                                   APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-       iwl3945_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* Determine HW type */
-       rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-       if (rc)
-               return rc;
-       IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id);
+       /* disable L1-Active */
+       iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+       iwl_release_nic_access(priv);
+out:
+       return ret;
+}
+
+static void iwl3945_nic_config(struct iwl_priv *priv)
+{
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+       unsigned long flags;
+       u8 rev_id = 0;
 
-       iwl3945_nic_set_pwr_src(priv, 1);
        spin_lock_irqsave(&priv->lock, flags);
 
        if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
                IWL_DEBUG_INFO("RTP type \n");
        else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
                IWL_DEBUG_INFO("3945 RADIO-MB type\n");
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
        } else {
                IWL_DEBUG_INFO("3945 RADIO-MM type\n");
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
        }
 
-       if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) {
+       if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
                IWL_DEBUG_INFO("SKU OP mode is mrc\n");
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
        } else
                IWL_DEBUG_INFO("SKU OP mode is basic\n");
 
-       if ((priv->eeprom.board_revision & 0xF0) == 0xD0) {
+       if ((eeprom->board_revision & 0xF0) == 0xD0) {
                IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
-                              priv->eeprom.board_revision);
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+                              eeprom->board_revision);
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
        } else {
                IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
-                              priv->eeprom.board_revision);
-               iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+                              eeprom->board_revision);
+               iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
                              CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
        }
 
-       if (priv->eeprom.almgor_m_version <= 1) {
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+       if (eeprom->almgor_m_version <= 1) {
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
                IWL_DEBUG_INFO("Card M type A version is 0x%X\n",
-                              priv->eeprom.almgor_m_version);
+                              eeprom->almgor_m_version);
        } else {
                IWL_DEBUG_INFO("Card M type B version is 0x%X\n",
-                              priv->eeprom.almgor_m_version);
-               iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+                              eeprom->almgor_m_version);
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                            CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
+       if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
                IWL_DEBUG_RF_KILL("SW RF KILL supported in EEPROM.\n");
 
-       if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
+       if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
                IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n");
+}
+
+int iwl3945_hw_nic_init(struct iwl_priv *priv)
+{
+       u8 rev_id;
+       int rc;
+       unsigned long flags;
+       struct iwl_rx_queue *rxq = &priv->rxq;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->cfg->ops->lib->apm_ops.init(priv);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* Determine HW type */
+       rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
+       if (rc)
+               return rc;
+       IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id);
+
+       rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
+       if(rc)
+               return rc;
+
+       priv->cfg->ops->lib->apm_ops.config(priv);
 
        /* Allocate the RX queue, or reset if it is already allocated */
        if (!rxq->bd) {
-               rc = iwl3945_rx_queue_alloc(priv);
+               rc = iwl_rx_queue_alloc(priv);
                if (rc) {
-                       IWL_ERROR("Unable to initialize Rx queue\n");
+                       IWL_ERR(priv, "Unable to initialize Rx queue\n");
                        return -ENOMEM;
                }
        } else
-               iwl3945_rx_queue_reset(priv, rxq);
+               iwl_rx_queue_reset(priv, rxq);
 
        iwl3945_rx_replenish(priv);
 
@@ -1202,16 +1202,16 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
 
        /* Look at using this instead:
        rxq->need_update = 1;
-       iwl3945_rx_queue_update_write_ptr(priv, rxq);
+       iwl_rx_queue_update_write_ptr(priv, rxq);
        */
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
-       iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), rxq->write & ~7);
-       iwl3945_release_nic_access(priv);
+       iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
+       iwl_release_nic_access(priv);
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -1229,116 +1229,121 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
  *
  * Destroy all TX DMA queues and structures
  */
-void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv)
+void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
 {
        int txq_id;
 
        /* Tx queues */
        for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++)
-               iwl3945_tx_queue_free(priv, &priv->txq[txq_id]);
+               iwl_tx_queue_free(priv, txq_id);
 }
 
-void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv)
+void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
 {
-       int queue;
+       int txq_id;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
-       if (iwl3945_grab_nic_access(priv)) {
+       if (iwl_grab_nic_access(priv)) {
                spin_unlock_irqrestore(&priv->lock, flags);
                iwl3945_hw_txq_ctx_free(priv);
                return;
        }
 
        /* stop SCD */
-       iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0);
+       iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
 
        /* reset TFD queues */
-       for (queue = TFD_QUEUE_MIN; queue < TFD_QUEUE_MAX; queue++) {
-               iwl3945_write_direct32(priv, FH_TCSR_CONFIG(queue), 0x0);
-               iwl3945_poll_direct_bit(priv, FH_TSSR_TX_STATUS,
-                               ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(queue),
+       for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) {
+               iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
+               iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
+                               FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
                                1000);
        }
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        iwl3945_hw_txq_ctx_free(priv);
 }
 
-int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv)
+static int iwl3945_apm_stop_master(struct iwl_priv *priv)
 {
-       int rc = 0;
-       u32 reg_val;
+       int ret = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
 
        /* set stop master bit */
-       iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
 
-       reg_val = iwl3945_read32(priv, CSR_GP_CNTRL);
+       iwl_poll_direct_bit(priv, CSR_RESET,
+                           CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
 
-       if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
-           (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
-               IWL_DEBUG_INFO("Card in power save, master is already "
-                              "stopped\n");
-       else {
-               rc = iwl3945_poll_direct_bit(priv, CSR_RESET,
-                                 CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
-               if (rc < 0) {
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       return rc;
-               }
-       }
+       if (ret < 0)
+               goto out;
 
+out:
        spin_unlock_irqrestore(&priv->lock, flags);
        IWL_DEBUG_INFO("stop master\n");
 
-       return rc;
+       return ret;
+}
+
+static void iwl3945_apm_stop(struct iwl_priv *priv)
+{
+       unsigned long flags;
+
+       iwl3945_apm_stop_master(priv);
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+       udelay(10);
+       /* clear "init complete"  move adapter D0A* --> D0U state */
+       iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-int iwl3945_hw_nic_reset(struct iwl3945_priv *priv)
+static int iwl3945_apm_reset(struct iwl_priv *priv)
 {
        int rc;
        unsigned long flags;
 
-       iwl3945_hw_nic_stop_master(priv);
+       iwl3945_apm_stop_master(priv);
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       udelay(10);
 
-       iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+       iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
                         CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (!rc) {
-               iwl3945_write_prph(priv, APMG_CLK_CTRL_REG,
+               iwl_write_prph(priv, APMG_CLK_CTRL_REG,
                                         APMG_CLK_VAL_BSM_CLK_RQT);
 
-               udelay(10);
-
-               iwl3945_set_bit(priv, CSR_GP_CNTRL,
-                           CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
-               iwl3945_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
-               iwl3945_write_prph(priv, APMG_RTC_INT_STT_REG,
+               iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
+               iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
                                        0xFFFFFFFF);
 
                /* enable DMA */
-               iwl3945_write_prph(priv, APMG_CLK_EN_REG,
+               iwl_write_prph(priv, APMG_CLK_EN_REG,
                                         APMG_CLK_VAL_DMA_CLK_RQT |
                                         APMG_CLK_VAL_BSM_CLK_RQT);
                udelay(10);
 
-               iwl3945_set_bits_prph(priv, APMG_PS_CTRL_REG,
+               iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
                                APMG_PS_CTRL_VAL_RESET_REQ);
                udelay(5);
-               iwl3945_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+               iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
                                APMG_PS_CTRL_VAL_RESET_REQ);
-               iwl3945_release_nic_access(priv);
+               iwl_release_nic_access(priv);
        }
 
        /* Clear the 'host command active' bit... */
@@ -1367,17 +1372,18 @@ static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
        return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
 }
 
-int iwl3945_hw_get_temperature(struct iwl3945_priv *priv)
+int iwl3945_hw_get_temperature(struct iwl_priv *priv)
 {
-       return iwl3945_read32(priv, CSR_UCODE_DRV_GP2);
+       return iwl_read32(priv, CSR_UCODE_DRV_GP2);
 }
 
 /**
  * iwl3945_hw_reg_txpower_get_temperature
  * get the current temperature by reading from NIC
 */
-static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv)
+static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
 {
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
        int temperature;
 
        temperature = iwl3945_hw_get_temperature(priv);
@@ -1388,12 +1394,12 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv)
 
        /* handle insane temp reading */
        if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
-               IWL_ERROR("Error bad temperature value  %d\n", temperature);
+               IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
 
                /* if really really hot(?),
                 *   substitute the 3rd band/group's temp measured at factory */
                if (priv->last_temperature > 100)
-                       temperature = priv->eeprom.groups[2].temperature;
+                       temperature = eeprom->groups[2].temperature;
                else /* else use most recent "sane" value from driver */
                        temperature = priv->last_temperature;
        }
@@ -1412,7 +1418,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv)
  * records new temperature in tx_mgr->temperature.
  * replaces tx_mgr->last_temperature *only* if calib needed
  *    (assumes caller will actually do the calibration!). */
-static int is_temp_calib_needed(struct iwl3945_priv *priv)
+static int is_temp_calib_needed(struct iwl_priv *priv)
 {
        int temp_diff;
 
@@ -1627,9 +1633,9 @@ static inline u8 iwl3945_hw_reg_fix_power_index(int index)
  * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
  * or 6 Mbit (OFDM) rates.
  */
-static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tbl_index,
+static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
                               s32 rate_index, const s8 *clip_pwrs,
-                              struct iwl3945_channel_info *ch_info,
+                              struct iwl_channel_info *ch_info,
                               int band_index)
 {
        struct iwl3945_scan_power_info *scan_power_info;
@@ -1646,7 +1652,7 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tb
        /* further limit to user's max power preference.
         * FIXME:  Other spectrum management power limitations do not
         *   seem to apply?? */
-       power = min(power, priv->user_txpower_limit);
+       power = min(power, priv->tx_power_user_lmt);
        scan_power_info->requested_power = power;
 
        /* find difference between new scan *power* and current "normal"
@@ -1678,27 +1684,27 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tb
 }
 
 /**
- * iwl3945_hw_reg_send_txpower - fill in Tx Power command with gain settings
+ * iwl3945_send_tx_power - fill in Tx Power command with gain settings
  *
  * Configures power settings for all rates for the current channel,
  * using values from channel info struct, and send to NIC
  */
-int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
+int iwl3945_send_tx_power(struct iwl_priv *priv)
 {
        int rate_idx, i;
-       const struct iwl3945_channel_info *ch_info = NULL;
+       const struct iwl_channel_info *ch_info = NULL;
        struct iwl3945_txpowertable_cmd txpower = {
-               .channel = priv->active_rxon.channel,
+               .channel = priv->active39_rxon.channel,
        };
 
        txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
-       ch_info = iwl3945_get_channel_info(priv,
+       ch_info = iwl_get_channel_info(priv,
                                       priv->band,
-                                      le16_to_cpu(priv->active_rxon.channel));
+                                      le16_to_cpu(priv->active39_rxon.channel));
        if (!ch_info) {
-               IWL_ERROR
-                   ("Failed to get channel info for channel %d [%d]\n",
-                    le16_to_cpu(priv->active_rxon.channel), priv->band);
+               IWL_ERR(priv,
+                       "Failed to get channel info for channel %d [%d]\n",
+                       le16_to_cpu(priv->active39_rxon.channel), priv->band);
                return -EINVAL;
        }
 
@@ -1711,7 +1717,7 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
        /* fill cmd with power settings for all rates for current channel */
        /* Fill OFDM rate */
        for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
-            rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {
+            rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
 
                txpower.power[i].tpc = ch_info->power_info[i].tpc;
                txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
@@ -1737,8 +1743,9 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
                                txpower.power[i].rate);
        }
 
-       return iwl3945_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
-                       sizeof(struct iwl3945_txpowertable_cmd), &txpower);
+       return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
+                               sizeof(struct iwl3945_txpowertable_cmd),
+                               &txpower);
 
 }
 
@@ -1758,8 +1765,8 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
  *      properly fill out the scan powers, and actual h/w gain settings,
  *      and send changes to NIC
  */
-static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv,
-                            struct iwl3945_channel_info *ch_info)
+static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
+                            struct iwl_channel_info *ch_info)
 {
        struct iwl3945_channel_power_info *power_info;
        int power_changed = 0;
@@ -1768,7 +1775,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv,
        int power;
 
        /* Get this chnlgrp's rate-to-max/clip-powers table */
-       clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;
+       clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
 
        /* Get this channel's rate-to-current-power settings table */
        power_info = ch_info->power_info;
@@ -1821,7 +1828,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv,
  *      based strictly on regulatory (eeprom and spectrum mgt) limitations
  *      (no consideration for h/w clipping limitations).
  */
-static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl3945_channel_info *ch_info)
+static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
 {
        s8 max_power;
 
@@ -1849,9 +1856,10 @@ static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl3945_channel_info *ch_i
  *
  * If RxOn is "associated", this sends the new Txpower to NIC!
  */
-static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
+static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
 {
-       struct iwl3945_channel_info *ch_info = NULL;
+       struct iwl_channel_info *ch_info = NULL;
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
        int delta_index;
        const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
        u8 a_band;
@@ -1867,7 +1875,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
                a_band = is_channel_a_band(ch_info);
 
                /* Get this chnlgrp's factory calibration temperature */
-               ref_temp = (s16)priv->eeprom.groups[ch_info->group_index].
+               ref_temp = (s16)eeprom->groups[ch_info->group_index].
                    temperature;
 
                /* get power index adjustment based on current and factory
@@ -1893,7 +1901,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
                }
 
                /* Get this chnlgrp's rate-to-max/clip-powers table */
-               clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;
+               clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
 
                /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
                for (scan_tbl_index = 0;
@@ -1907,24 +1915,24 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
        }
 
        /* send Txpower command for current channel to ucode */
-       return iwl3945_hw_reg_send_txpower(priv);
+       return priv->cfg->ops->lib->send_tx_power(priv);
 }
 
-int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power)
+int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
 {
-       struct iwl3945_channel_info *ch_info;
+       struct iwl_channel_info *ch_info;
        s8 max_power;
        u8 a_band;
        u8 i;
 
-       if (priv->user_txpower_limit == power) {
+       if (priv->tx_power_user_lmt == power) {
                IWL_DEBUG_POWER("Requested Tx power same as current "
                                "limit: %ddBm.\n", power);
                return 0;
        }
 
        IWL_DEBUG_POWER("Setting upper limit clamp to %ddBm.\n", power);
-       priv->user_txpower_limit = power;
+       priv->tx_power_user_lmt = power;
 
        /* set up new Tx powers for each and every channel, 2.4 and 5.x */
 
@@ -1953,7 +1961,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power)
 }
 
 /* will add 3945 channel switch cmd handling later */
-int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel)
+int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 {
        return 0;
 }
@@ -1968,7 +1976,7 @@ int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel)
  *     -- send new set of gain settings to NIC
  * NOTE:  This should continue working, even when we're not associated,
  *   so we can keep our internal table of scan powers current. */
-void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv)
+void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
 {
        /* This will kick in the "brute force"
         * iwl3945_hw_reg_comp_txpower_temp() below */
@@ -1987,7 +1995,7 @@ void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv)
 
 static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
 {
-       struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv,
+       struct iwl_priv *priv = container_of(work, struct iwl_priv,
                                             thermal_periodic.work);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -2009,10 +2017,11 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
  *      on A-band, EEPROM's "group frequency" entries represent the top
  *      channel in each group 1-4.  Group 5 All B/G channels are in group 0.
  */
-static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv,
-                                      const struct iwl3945_channel_info *ch_info)
+static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
+                                      const struct iwl_channel_info *ch_info)
 {
-       struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0];
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+       struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
        u8 group;
        u16 group_index = 0;    /* based on factory calib frequencies */
        u8 grp_channel;
@@ -2043,11 +2052,12 @@ static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv,
  * Interpolate to get nominal (i.e. at factory calibration temperature) index
  *   into radio/DSP gain settings table for requested power.
  */
-static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv,
+static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
                                       s8 requested_power,
                                       s32 setting_index, s32 *new_index)
 {
        const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
        s32 index0, index1;
        s32 power = 2 * requested_power;
        s32 i;
@@ -2056,7 +2066,7 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv,
        s32 res;
        s32 denominator;
 
-       chnl_grp = &priv->eeprom.groups[setting_index];
+       chnl_grp = &eeprom->groups[setting_index];
        samples = chnl_grp->samples;
        for (i = 0; i < 5; i++) {
                if (power == samples[i].power) {
@@ -2091,10 +2101,11 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv,
        return 0;
 }
 
-static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv)
+static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
 {
        u32 i;
        s32 rate_index;
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
        const struct iwl3945_eeprom_txpower_group *group;
 
        IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n");
@@ -2102,11 +2113,11 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv)
        for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
                s8 *clip_pwrs;  /* table of power levels for each rate */
                s8 satur_pwr;   /* saturation power for each chnl group */
-               group = &priv->eeprom.groups[i];
+               group = &eeprom->groups[i];
 
                /* sanity check on factory saturation power value */
                if (group->saturation_power < 40) {
-                       IWL_WARNING("Error: saturation power is %d, "
+                       IWL_WARN(priv, "Error: saturation power is %d, "
                                    "less than minimum expected 40\n",
                                    group->saturation_power);
                        return;
@@ -2121,7 +2132,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv)
                 *   power peaks, without too much distortion (clipping).
                 */
                /* we'll fill in this array with h/w max power levels */
-               clip_pwrs = (s8 *) priv->clip_groups[i].clip_powers;
+               clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers;
 
                /* divide factory saturation power by 2 to find -3dB level */
                satur_pwr = (s8) (group->saturation_power >> 1);
@@ -2171,10 +2182,11 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv)
  *
  * This does *not* write values to NIC, just sets up our internal table.
  */
-int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
+int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
 {
-       struct iwl3945_channel_info *ch_info = NULL;
+       struct iwl_channel_info *ch_info = NULL;
        struct iwl3945_channel_power_info *pwr_info;
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
        int delta_index;
        u8 rate_index;
        u8 scan_tbl_index;
@@ -2204,12 +2216,12 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
                        iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
 
                /* Get this chnlgrp's rate->max/clip-powers table */
-               clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;
+               clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
 
                /* calculate power index *adjustment* value according to
                 *  diff between current temperature and factory temperature */
                delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-                               priv->eeprom.groups[ch_info->group_index].
+                               eeprom->groups[ch_info->group_index].
                                temperature);
 
                IWL_DEBUG_POWER("Delta index for channel %d: %d [%d]\n",
@@ -2235,7 +2247,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
                                                         ch_info->group_index,
                                                         &power_idx);
                        if (rc) {
-                               IWL_ERROR("Invalid power index\n");
+                               IWL_ERR(priv, "Invalid power index\n");
                                return rc;
                        }
                        pwr_info->base_power_index = (u8) power_idx;
@@ -2295,75 +2307,88 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
        return 0;
 }
 
-int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv)
+int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
 {
        int rc;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
 
-       iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), 0);
-       rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS,
-                       FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+       iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
+       rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
+                       FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
        if (rc < 0)
-               IWL_ERROR("Can't stop Rx DMA.\n");
+               IWL_ERR(priv, "Can't stop Rx DMA.\n");
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
 }
 
-int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
+int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 {
        int rc;
        unsigned long flags;
        int txq_id = txq->q.id;
 
-       struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt;
+       struct iwl3945_shared *shared_data = priv->shared_virt;
 
        shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
-       iwl3945_write_direct32(priv, FH_CBCC_CTRL(txq_id), 0);
-       iwl3945_write_direct32(priv, FH_CBCC_BASE(txq_id), 0);
+       iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
+       iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
 
-       iwl3945_write_direct32(priv, FH_TCSR_CONFIG(txq_id),
-               ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
-               ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
-               ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
-               ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
-               ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
-       iwl3945_release_nic_access(priv);
+       iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
+               FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
+               FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
+               FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
+               FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
+               FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
+       iwl_release_nic_access(priv);
 
        /* fake read to flush all prev. writes */
-       iwl3945_read32(priv, FH_TSSR_CBB_BASE);
+       iwl_read32(priv, FH39_TSSR_CBB_BASE);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
 }
 
-int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv)
+/*
+ * HCMD utils
+ */
+static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
 {
-       struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt;
+       switch (cmd_id) {
+       case REPLY_RXON:
+               return (u16) sizeof(struct iwl3945_rxon_cmd);
+       default:
+               return len;
+       }
+}
 
-       return le32_to_cpu(shared_data->rx_read_ptr[0]);
+static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+       u16 size = (u16)sizeof(struct iwl3945_addsta_cmd);
+       memcpy(data, cmd, size);
+       return size;
 }
 
 /**
  * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
  */
-int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
 {
        int rc, i, index, prev_index;
        struct iwl3945_rate_scaling_cmd rate_cmd = {
@@ -2428,47 +2453,48 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
 
        /* Update the rate scaling for control frame Tx */
        rate_cmd.table_id = 0;
-       rc = iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+       rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
                              &rate_cmd);
        if (rc)
                return rc;
 
        /* Update the rate scaling for data frame Tx */
        rate_cmd.table_id = 1;
-       return iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+       return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
                                &rate_cmd);
 }
 
 /* Called when initializing driver */
-int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
 {
-       memset((void *)&priv->hw_setting, 0,
-              sizeof(struct iwl3945_driver_hw_info));
+       memset((void *)&priv->hw_params, 0,
+              sizeof(struct iwl_hw_params));
 
-       priv->hw_setting.shared_virt =
+       priv->shared_virt =
            pci_alloc_consistent(priv->pci_dev,
                                 sizeof(struct iwl3945_shared),
-                                &priv->hw_setting.shared_phys);
+                                &priv->shared_phys);
 
-       if (!priv->hw_setting.shared_virt) {
-               IWL_ERROR("failed to allocate pci memory\n");
+       if (!priv->shared_virt) {
+               IWL_ERR(priv, "failed to allocate pci memory\n");
                mutex_unlock(&priv->mutex);
                return -ENOMEM;
        }
 
-       priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
-       priv->hw_setting.max_pkt_size = 2342;
-       priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
-       priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
-       priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
-       priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
-       priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
+       priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
+       priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;
+       priv->hw_params.max_pkt_size = 2342;
+       priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+       priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+       priv->hw_params.max_stations = IWL3945_STATION_COUNT;
+       priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID;
+
+       priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
 
-       priv->hw_setting.tx_ant_num = 2;
        return 0;
 }
 
-unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
                          struct iwl3945_frame *frame, u8 rate)
 {
        struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
@@ -2477,7 +2503,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
        tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
        memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
 
-       tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id;
+       tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
        tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 
        frame_size = iwl3945_fill_beacon_frame(priv,
@@ -2501,37 +2527,261 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
        return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
 }
 
-void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
+void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
 {
        priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
        priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
 }
 
-void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv)
+void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
 {
        INIT_DELAYED_WORK(&priv->thermal_periodic,
                          iwl3945_bg_reg_txpower_periodic);
 }
 
-void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
+void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
 {
        cancel_delayed_work(&priv->thermal_periodic);
 }
 
-static struct iwl_3945_cfg iwl3945_bg_cfg = {
+/* check contents of special bootstrap uCode SRAM */
+static int iwl3945_verify_bsm(struct iwl_priv *priv)
+ {
+       __le32 *image = priv->ucode_boot.v_addr;
+       u32 len = priv->ucode_boot.len;
+       u32 reg;
+       u32 val;
+
+       IWL_DEBUG_INFO("Begin verify bsm\n");
+
+       /* verify BSM SRAM contents */
+       val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
+       for (reg = BSM_SRAM_LOWER_BOUND;
+            reg < BSM_SRAM_LOWER_BOUND + len;
+            reg += sizeof(u32), image++) {
+               val = iwl_read_prph(priv, reg);
+               if (val != le32_to_cpu(*image)) {
+                       IWL_ERR(priv, "BSM uCode verification failed at "
+                                 "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+                                 BSM_SRAM_LOWER_BOUND,
+                                 reg - BSM_SRAM_LOWER_BOUND, len,
+                                 val, le32_to_cpu(*image));
+                       return -EIO;
+               }
+       }
+
+       IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
+
+       return 0;
+}
+
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+ ******************************************************************************/
+
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+       _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+       return 0;
+}
+
+
+static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+       return;
+}
+
+ /**
+  * iwl3945_load_bsm - Load bootstrap instructions
+  *
+  * BSM operation:
+  *
+  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+  * in special SRAM that does not power down during RFKILL.  When powering back
+  * up after power-saving sleeps (or during initial uCode load), the BSM loads
+  * the bootstrap program into the on-board processor, and starts it.
+  *
+  * The bootstrap program loads (via DMA) instructions and data for a new
+  * program from host DRAM locations indicated by the host driver in the
+  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+  * automatically.
+  *
+  * When initializing the NIC, the host driver points the BSM to the
+  * "initialize" uCode image.  This uCode sets up some internal data, then
+  * notifies host via "initialize alive" that it is complete.
+  *
+  * The host then replaces the BSM_DRAM_* pointer values to point to the
+  * normal runtime uCode instructions and a backup uCode data cache buffer
+  * (filled initially with starting data values for the on-board processor),
+  * then triggers the "initialize" uCode to load and launch the runtime uCode,
+  * which begins normal operation.
+  *
+  * When doing a power-save shutdown, runtime uCode saves data SRAM into
+  * the backup data cache in DRAM before SRAM is powered down.
+  *
+  * When powering back up, the BSM loads the bootstrap program.  This reloads
+  * the runtime uCode instructions and the backup data cache into SRAM,
+  * and re-launches the runtime uCode from where it left off.
+  */
+static int iwl3945_load_bsm(struct iwl_priv *priv)
+{
+       __le32 *image = priv->ucode_boot.v_addr;
+       u32 len = priv->ucode_boot.len;
+       dma_addr_t pinst;
+       dma_addr_t pdata;
+       u32 inst_len;
+       u32 data_len;
+       int rc;
+       int i;
+       u32 done;
+       u32 reg_offset;
+
+       IWL_DEBUG_INFO("Begin load bsm\n");
+
+       /* make sure bootstrap program is no larger than BSM's SRAM size */
+       if (len > IWL39_MAX_BSM_SIZE)
+               return -EINVAL;
+
+       /* Tell bootstrap uCode where to find the "Initialize" uCode
+       *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
+       * NOTE:  iwl3945_initialize_alive_start() will replace these values,
+       *        after the "initialize" uCode has run, to point to
+       *        runtime/protocol instructions and backup data cache. */
+       pinst = priv->ucode_init.p_addr;
+       pdata = priv->ucode_init_data.p_addr;
+       inst_len = priv->ucode_init.len;
+       data_len = priv->ucode_init_data.len;
+
+       rc = iwl_grab_nic_access(priv);
+       if (rc)
+               return rc;
+
+       iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+       iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+       iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+       iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+       /* Fill BSM memory with bootstrap instructions */
+       for (reg_offset = BSM_SRAM_LOWER_BOUND;
+            reg_offset < BSM_SRAM_LOWER_BOUND + len;
+            reg_offset += sizeof(u32), image++)
+               _iwl_write_prph(priv, reg_offset,
+                                         le32_to_cpu(*image));
+
+       rc = iwl3945_verify_bsm(priv);
+       if (rc) {
+               iwl_release_nic_access(priv);
+               return rc;
+       }
+
+       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+       iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+       iwl_write_prph(priv, BSM_WR_MEM_DST_REG,
+                                IWL39_RTC_INST_LOWER_BOUND);
+       iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+       /* Load bootstrap code into instruction SRAM now,
+        *   to prepare to load "initialize" uCode */
+       iwl_write_prph(priv, BSM_WR_CTRL_REG,
+               BSM_WR_CTRL_REG_BIT_START);
+
+       /* Wait for load of bootstrap uCode to finish */
+       for (i = 0; i < 100; i++) {
+               done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
+               if (!(done & BSM_WR_CTRL_REG_BIT_START))
+                       break;
+               udelay(10);
+       }
+       if (i < 100)
+               IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
+       else {
+               IWL_ERR(priv, "BSM write did not complete!\n");
+               return -EIO;
+       }
+
+       /* Enable future boot loads whenever power management unit triggers it
+        *   (e.g. when powering back up after power-save shutdown) */
+       iwl_write_prph(priv, BSM_WR_CTRL_REG,
+               BSM_WR_CTRL_REG_BIT_START_EN);
+
+       iwl_release_nic_access(priv);
+
+       return 0;
+}
+
+static struct iwl_lib_ops iwl3945_lib = {
+       .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = iwl3945_hw_txq_free_tfd,
+       .txq_init = iwl3945_hw_tx_queue_init,
+       .load_ucode = iwl3945_load_bsm,
+       .apm_ops = {
+               .init = iwl3945_apm_init,
+               .reset = iwl3945_apm_reset,
+               .stop = iwl3945_apm_stop,
+               .config = iwl3945_nic_config,
+               .set_pwr_src = iwl3945_set_pwr_src,
+       },
+       .eeprom_ops = {
+               .regulatory_bands = {
+                       EEPROM_REGULATORY_BAND_1_CHANNELS,
+                       EEPROM_REGULATORY_BAND_2_CHANNELS,
+                       EEPROM_REGULATORY_BAND_3_CHANNELS,
+                       EEPROM_REGULATORY_BAND_4_CHANNELS,
+                       EEPROM_REGULATORY_BAND_5_CHANNELS,
+                       IWL3945_EEPROM_IMG_SIZE,
+                       IWL3945_EEPROM_IMG_SIZE,
+               },
+               .verify_signature  = iwlcore_eeprom_verify_signature,
+               .acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
+               .release_semaphore = iwl3945_eeprom_release_semaphore,
+               .query_addr = iwlcore_eeprom_query_addr,
+       },
+       .send_tx_power  = iwl3945_send_tx_power,
+};
+
+static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
+       .get_hcmd_size = iwl3945_get_hcmd_size,
+       .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
+};
+
+static struct iwl_ops iwl3945_ops = {
+       .lib = &iwl3945_lib,
+       .utils = &iwl3945_hcmd_utils,
+};
+
+static struct iwl_cfg iwl3945_bg_cfg = {
        .name = "3945BG",
        .fw_name_pre = IWL3945_FW_PRE,
        .ucode_api_max = IWL3945_UCODE_API_MAX,
        .ucode_api_min = IWL3945_UCODE_API_MIN,
        .sku = IWL_SKU_G,
+       .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
+       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+       .ops = &iwl3945_ops,
+       .mod_params = &iwl3945_mod_params
 };
 
-static struct iwl_3945_cfg iwl3945_abg_cfg = {
+static struct iwl_cfg iwl3945_abg_cfg = {
        .name = "3945ABG",
        .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,
+       .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
+       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+       .ops = &iwl3945_ops,
+       .mod_params = &iwl3945_mod_params
 };
 
 struct pci_device_id iwl3945_hw_card_ids[] = {
index 2c0ddc5110c6b1611e631239a8ef84a16c8e0539..fef54e9cf8a8ccd3a921d56243bb5788e62809ba 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 extern struct pci_device_id iwl3945_hw_card_ids[];
 
-#define DRV_NAME       "iwl3945"
 #include "iwl-csr.h"
 #include "iwl-prph.h"
+#include "iwl-fh.h"
 #include "iwl-3945-hw.h"
-#include "iwl-3945-debug.h"
+#include "iwl-debug.h"
+#include "iwl-power.h"
+#include "iwl-dev.h"
 #include "iwl-3945-led.h"
 
 /* Highest firmware API version supported */
@@ -74,8 +76,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
 #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
 
 /* Module parameters accessible from iwl-*.c */
-extern int iwl3945_param_hwcrypto;
-extern int iwl3945_param_queues_num;
+extern struct iwl_mod_params iwl3945_mod_params;
 
 struct iwl3945_sta_priv {
        struct iwl3945_rs_sta *rs_sta;
@@ -95,7 +96,6 @@ enum iwl3945_antenna {
  * else RTS for data/management frames where MPDU is larger
  *   than RTS value.
  */
-#define IWL_RX_BUF_SIZE           3000U
 #define DEFAULT_RTS_THRESHOLD     2347U
 #define MIN_RTS_THRESHOLD         0U
 #define MAX_RTS_THRESHOLD         2347U
@@ -105,136 +105,7 @@ enum iwl3945_antenna {
 #define        DEFAULT_SHORT_RETRY_LIMIT 7U
 #define        DEFAULT_LONG_RETRY_LIMIT  4U
 
-struct iwl3945_rx_mem_buffer {
-       dma_addr_t dma_addr;
-       struct sk_buff *skb;
-       struct list_head list;
-};
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues
- */
-struct iwl3945_queue {
-       int n_bd;              /* number of BDs in this queue */
-       int write_ptr;       /* 1-st empty entry (index) host_w*/
-       int read_ptr;         /* last used entry (index) host_r*/
-       dma_addr_t dma_addr;   /* physical addr for BD's */
-       int n_window;          /* safe queue window */
-       u32 id;
-       int low_mark;          /* low watermark, resume queue if free
-                               * space more than this */
-       int high_mark;         /* high watermark, stop queue if free
-                               * space less than this */
-} __attribute__ ((packed));
-
-int iwl3945_queue_space(const struct iwl3945_queue *q);
-int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i);
-
-#define MAX_NUM_OF_TBS          (20)
-
-/* One for each TFD */
-struct iwl3945_tx_info {
-       struct sk_buff *skb[MAX_NUM_OF_TBS];
-};
-
-/**
- * struct iwl3945_tx_queue - Tx Queue for DMA
- * @q: generic Rx/Tx queue descriptor
- * @bd: base of circular buffer of TFDs
- * @cmd: array of command/Tx buffers
- * @dma_addr_cmd: physical address of cmd/tx buffer array
- * @txb: array of per-TFD driver data
- * @need_update: indicates need to update read/write index
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- */
-struct iwl3945_tx_queue {
-       struct iwl3945_queue q;
-       struct iwl3945_tfd_frame *bd;
-       struct iwl3945_cmd *cmd;
-       dma_addr_t dma_addr_cmd;
-       struct iwl3945_tx_info *txb;
-       int need_update;
-       int active;
-};
-
-#define IWL_NUM_SCAN_RATES         (2)
-
-struct iwl3945_channel_tgd_info {
-       u8 type;
-       s8 max_power;
-};
-
-struct iwl3945_channel_tgh_info {
-       s64 last_radar_time;
-};
-
-/* current Tx power values to use, one for each rate for each channel.
- * requested power is limited by:
- * -- regulatory EEPROM limits for this channel
- * -- hardware capabilities (clip-powers)
- * -- spectrum management
- * -- user preference (e.g. iwconfig)
- * when requested power is set, base power index must also be set. */
-struct iwl3945_channel_power_info {
-       struct iwl3945_tx_power tpc;    /* actual radio and DSP gain settings */
-       s8 power_table_index;   /* actual (compenst'd) index into gain table */
-       s8 base_power_index;    /* gain index for power at factory temp. */
-       s8 requested_power;     /* power (dBm) requested for this chnl/rate */
-};
-
-/* current scan Tx power values to use, one for each scan rate for each
- * channel. */
-struct iwl3945_scan_power_info {
-       struct iwl3945_tx_power tpc;    /* actual radio and DSP gain settings */
-       s8 power_table_index;   /* actual (compenst'd) index into gain table */
-       s8 requested_power;     /* scan pwr (dBm) requested for chnl/rate */
-};
-
-/*
- * One for each channel, holds all channel setup data
- * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
- *     with one another!
- */
-#define IWL4965_MAX_RATE (33)
-
-struct iwl3945_channel_info {
-       struct iwl3945_channel_tgd_info tgd;
-       struct iwl3945_channel_tgh_info tgh;
-       struct iwl3945_eeprom_channel eeprom;   /* EEPROM regulatory limit */
-       struct iwl3945_eeprom_channel fat_eeprom;       /* EEPROM regulatory limit for
-                                                * FAT channel */
-
-       u8 channel;       /* channel number */
-       u8 flags;         /* flags copied from EEPROM */
-       s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
-       s8 curr_txpow;    /* (dBm) regulatory/spectrum/user (not h/w) */
-       s8 min_power;     /* always 0 */
-       s8 scan_power;    /* (dBm) regul. eeprom, direct scans, any rate */
-
-       u8 group_index;   /* 0-4, maps channel to group1/2/3/4/5 */
-       u8 band_index;    /* 0-4, maps channel to band1/2/3/4/5 */
-       enum ieee80211_band band;
-
-       /* Radio/DSP gain settings for each "normal" data Tx rate.
-        * These include, in addition to RF and DSP gain, a few fields for
-        *   remembering/modifying gain settings (indexes). */
-       struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
-
-       /* Radio/DSP gain settings for each scan rate, for directed scans. */
-       struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
-};
-
-struct iwl3945_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];
-};
-
-#include "iwl-3945-rs.h"
+#include "iwl-agn-rs.h"
 
 #define IWL_TX_FIFO_AC0        0
 #define IWL_TX_FIFO_AC1        1
@@ -247,33 +118,6 @@ struct iwl3945_clip_group {
 /* Minimum number of queues. MAX_NUM is defined in hw specific files */
 #define IWL_MIN_NUM_QUEUES     4
 
-/* Power management (not Tx power) structures */
-
-struct iwl3945_power_vec_entry {
-       struct iwl3945_powertable_cmd cmd;
-       u8 no_dtim;
-};
-#define IWL_POWER_RANGE_0  (0)
-#define IWL_POWER_RANGE_1  (1)
-
-#define IWL_POWER_MODE_CAM     0x00    /* Continuously Aware Mode, always on */
-#define IWL_POWER_INDEX_3      0x03
-#define IWL_POWER_INDEX_5      0x05
-#define IWL_POWER_AC           0x06
-#define IWL_POWER_BATTERY      0x07
-#define IWL_POWER_LIMIT                0x07
-#define IWL_POWER_MASK         0x0F
-#define IWL_POWER_ENABLED      0x10
-#define IWL_POWER_LEVEL(x)     ((x) & IWL_POWER_MASK)
-
-struct iwl3945_power_mgr {
-       spinlock_t lock;
-       struct iwl3945_power_vec_entry pwr_range_0[IWL_POWER_AC];
-       struct iwl3945_power_vec_entry pwr_range_1[IWL_POWER_AC];
-       u8 active_index;
-       u32 dtim_val;
-};
-
 #define IEEE80211_DATA_LEN              2304
 #define IEEE80211_4ADDR_LEN             30
 #define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
@@ -289,81 +133,10 @@ struct iwl3945_frame {
        struct list_head list;
 };
 
-#define SEQ_TO_QUEUE(x)  ((x >> 8) & 0xbf)
-#define QUEUE_TO_SEQ(x)  ((x & 0xbf) << 8)
-#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
-#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
-#define SEQ_HUGE_FRAME  (0x4000)
-#define SEQ_RX_FRAME    __constant_cpu_to_le16(0x8000)
 #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
 #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
 #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
 
-enum {
-       /* CMD_SIZE_NORMAL = 0, */
-       CMD_SIZE_HUGE = (1 << 0),
-       /* CMD_SYNC = 0, */
-       CMD_ASYNC = (1 << 1),
-       /* CMD_NO_SKB = 0, */
-       CMD_WANT_SKB = (1 << 2),
-};
-
-struct iwl3945_cmd;
-struct iwl3945_priv;
-
-struct iwl3945_cmd_meta {
-       struct iwl3945_cmd_meta *source;
-       union {
-               struct sk_buff *skb;
-               int (*callback)(struct iwl3945_priv *priv,
-                               struct iwl3945_cmd *cmd, struct sk_buff *skb);
-       } __attribute__ ((packed)) u;
-
-       /* The CMD_SIZE_HUGE flag bit indicates that the command
-        * structure is stored at the end of the shared queue memory. */
-       u32 flags;
-
-} __attribute__ ((packed));
-
-/**
- * struct iwl3945_cmd
- *
- * For allocation of the command and tx queues, this establishes the overall
- * size of the largest command we send to uCode, except for a scan command
- * (which is relatively huge; space is allocated separately).
- */
-struct iwl3945_cmd {
-       struct iwl3945_cmd_meta meta;
-       struct iwl3945_cmd_header hdr;
-       union {
-               struct iwl3945_addsta_cmd addsta;
-               struct iwl3945_led_cmd led;
-               u32 flags;
-               u8 val8;
-               u16 val16;
-               u32 val32;
-               struct iwl3945_bt_cmd bt;
-               struct iwl3945_rxon_time_cmd rxon_time;
-               struct iwl3945_powertable_cmd powertable;
-               struct iwl3945_qosparam_cmd qosparam;
-               struct iwl3945_tx_cmd tx;
-               struct iwl3945_tx_beacon_cmd tx_beacon;
-               struct iwl3945_rxon_assoc_cmd rxon_assoc;
-               u8 *indirect;
-               u8 payload[360];
-       } __attribute__ ((packed)) cmd;
-} __attribute__ ((packed));
-
-struct iwl3945_host_cmd {
-       u8 id;
-       u16 len;
-       struct iwl3945_cmd_meta meta;
-       const void *data;
-};
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \
-                             sizeof(struct iwl3945_cmd_meta))
-
 /*
  * RX related structures and functions
  */
@@ -374,33 +147,6 @@ struct iwl3945_host_cmd {
 #define SUP_RATE_11B_MAX_NUM_CHANNELS  4
 #define SUP_RATE_11G_MAX_NUM_CHANNELS  12
 
-/**
- * struct iwl3945_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
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
- * @need_update: flag to indicate we need to update read/write index
- *
- * NOTE:  rx_free and rx_used are used as a FIFO for iwl3945_rx_mem_buffers
- */
-struct iwl3945_rx_queue {
-       __le32 *bd;
-       dma_addr_t dma_addr;
-       struct iwl3945_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
-       struct iwl3945_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;
-       spinlock_t lock;
-};
-
 #define IWL_SUPPORTED_RATES_IE_LEN         8
 
 #define SCAN_INTERVAL 100
@@ -430,87 +176,9 @@ struct iwl3945_rx_queue {
 #define IWL_INVALID_RATE     0xFF
 #define IWL_INVALID_VALUE    -1
 
-struct iwl3945_tid_data {
-       u16 seq_number;
-};
-
-struct iwl3945_hw_key {
-       enum ieee80211_key_alg alg;
-       int keylen;
-       u8 key[32];
-};
-
-union iwl3945_ht_rate_supp {
-       u16 rates;
-       struct {
-               u8 siso_rate;
-               u8 mimo_rate;
-       };
-};
-
-union iwl3945_qos_capabity {
-       struct {
-               u8 edca_count:4;        /* bit 0-3 */
-               u8 q_ack:1;             /* bit 4 */
-               u8 queue_request:1;     /* bit 5 */
-               u8 txop_request:1;      /* bit 6 */
-               u8 reserved:1;          /* bit 7 */
-       } q_AP;
-       struct {
-               u8 acvo_APSD:1;         /* bit 0 */
-               u8 acvi_APSD:1;         /* bit 1 */
-               u8 ac_bk_APSD:1;        /* bit 2 */
-               u8 ac_be_APSD:1;        /* bit 3 */
-               u8 q_ack:1;             /* bit 4 */
-               u8 max_len:2;           /* bit 5-6 */
-               u8 more_data_ack:1;     /* bit 7 */
-       } q_STA;
-       u8 val;
-};
-
-/* QoS structures */
-struct iwl3945_qos_info {
-       int qos_active;
-       union iwl3945_qos_capabity qos_cap;
-       struct iwl3945_qosparam_cmd def_qos_parm;
-};
-
 #define STA_PS_STATUS_WAKE             0
 #define STA_PS_STATUS_SLEEP            1
 
-struct iwl3945_station_entry {
-       struct iwl3945_addsta_cmd sta;
-       struct iwl3945_tid_data tid[MAX_TID_COUNT];
-       union {
-               struct {
-                       u8 rate;
-                       u8 flags;
-               } s;
-               u16 rate_n_flags;
-       } current_rate;
-       u8 used;
-       u8 ps_status;
-       struct iwl3945_hw_key keyinfo;
-};
-
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_desc {
-       void *v_addr;           /* access by driver */
-       dma_addr_t p_addr;      /* access by card's busmaster DMA */
-       u32 len;                /* bytes */
-};
-
-/* uCode file layout */
-struct iwl3945_ucode {
-       __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 */
-       __le32 init_data_size;  /* bytes of initialization data */
-       __le32 boot_size;       /* bytes of bootstrap instructions */
-       u8 data[0];             /* data in same order as "size" elements */
-};
-
 struct iwl3945_ibss_seq {
        u8 mac[ETH_ALEN];
        u16 seq_num;
@@ -519,34 +187,6 @@ struct iwl3945_ibss_seq {
        struct list_head list;
 };
 
-/**
- * struct iwl3945_driver_hw_info
- * @max_txq_num: Max # Tx queues supported
- * @tx_cmd_len: Size of Tx command (but not including frame itself)
- * @tx_ant_num: Number of TX antennas
- * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
- * @rx_buf_size:
- * @max_pkt_size:
- * @max_rxq_log: Log-base-2 of max_rxq_size
- * @max_stations:
- * @bcast_sta_id:
- * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
- * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
- */
-struct iwl3945_driver_hw_info {
-       u16 max_txq_num;
-       u16 tx_cmd_len;
-       u16 tx_ant_num;
-       u16 max_rxq_size;
-       u32 rx_buf_size;
-       u32 max_pkt_size;
-       u16 max_rxq_log;
-       u8  max_stations;
-       u8  bcast_sta_id;
-       void *shared_virt;
-       dma_addr_t shared_phys;
-};
-
 #define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
                       x->u.rx_frame.stats.payload + \
                       x->u.rx_frame.stats.phy_count))
@@ -564,40 +204,33 @@ struct iwl3945_driver_hw_info {
  *
  *****************************************************************************/
 struct iwl3945_addsta_cmd;
-extern int iwl3945_send_add_station(struct iwl3945_priv *priv,
+extern int iwl3945_send_add_station(struct iwl_priv *priv,
                                struct iwl3945_addsta_cmd *sta, u8 flags);
-extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid,
+extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid,
                          int is_ap, u8 flags);
-extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
-extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
-extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv);
-extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv,
-                              struct iwl3945_rx_queue *rxq);
+extern int iwl3945_power_init_handle(struct iwl_priv *priv);
+extern int iwl3945_eeprom_init(struct iwl_priv *priv);
 extern int iwl3945_calc_db_from_ratio(int sig_ratio);
 extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm);
-extern int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
-                            struct iwl3945_tx_queue *txq, int count, u32 id);
+extern int iwl3945_tx_queue_init(struct iwl_priv *priv,
+                            struct iwl_tx_queue *txq, int count, u32 id);
 extern void iwl3945_rx_replenish(void *data);
-extern void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq);
-extern int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len,
+extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len,
                            const void *data);
-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,
+extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv,
+                                        struct iwl_host_cmd *cmd);
+extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
                                        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);
-extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
+extern void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
                                   u32 decrypt_res,
                                   struct ieee80211_rx_status *stats);
-extern const u8 iwl3945_broadcast_addr[ETH_ALEN];
 
 /*
  * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
  * call this... todo... fix that.
 */
-extern u8 iwl3945_sync_station(struct iwl3945_priv *priv, int sta_id,
+extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id,
                           u16 tx_rate, u8 flags);
 
 /******************************************************************************
@@ -616,36 +249,37 @@ extern u8 iwl3945_sync_station(struct iwl3945_priv *priv, int sta_id,
  * iwl3945_mac_     <-- mac80211 callback
  *
  ****************************************************************************/
-extern void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv);
-extern void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv);
-extern void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv);
-extern int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv);
-extern int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv);
-extern int iwl3945_hw_nic_init(struct iwl3945_priv *priv);
-extern int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv);
-extern void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv);
-extern void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv);
-extern int iwl3945_hw_nic_reset(struct iwl3945_priv *priv);
-extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *tfd,
-                                       dma_addr_t addr, u16 len);
-extern int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq);
-extern int iwl3945_hw_get_temperature(struct iwl3945_priv *priv);
-extern int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv,
-                               struct iwl3945_tx_queue *txq);
-extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
+extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
+extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
+extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
+extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+                                           struct iwl_tx_queue *txq,
+                                           dma_addr_t addr, u16 len,
+                                           u8 reset, u8 pad);
+extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
+                                   struct iwl_tx_queue *txq);
+extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
+extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
+                               struct iwl_tx_queue *txq);
+extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
                                 struct iwl3945_frame *frame, u8 rate);
-extern int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv);
-extern void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
-                                    struct iwl3945_cmd *cmd,
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
                                     struct ieee80211_tx_info *info,
                                     struct ieee80211_hdr *hdr,
                                     int sta_id, int tx_id);
-extern int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv);
-extern int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power);
-extern void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv,
-                                struct iwl3945_rx_mem_buffer *rxb);
-extern void iwl3945_disable_events(struct iwl3945_priv *priv);
-extern int iwl4965_get_temperature(const struct iwl3945_priv *priv);
+extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
+extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
+extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+                                struct iwl_rx_mem_buffer *rxb);
+extern void iwl3945_disable_events(struct iwl_priv *priv);
+extern int iwl4965_get_temperature(const struct iwl_priv *priv);
 
 /**
  * iwl3945_hw_find_station - Find station id for a given BSSID
@@ -655,302 +289,31 @@ extern int iwl4965_get_temperature(const struct iwl3945_priv *priv);
  * not yet been merged into a single common layer for managing the
  * station tables.
  */
-extern u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *bssid);
+extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
 
-extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel);
+extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel);
 
 /*
  * Forward declare iwl-3945.c functions for iwl-base.c
  */
-extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv);
-extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv);
-extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv);
-extern int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv);
-extern u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id,
+extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
+extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
+extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
+extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
+extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
                 u16 tx_rate, u8 flags);
 
-
-#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
-
-enum {
-       MEASUREMENT_READY = (1 << 0),
-       MEASUREMENT_ACTIVE = (1 << 1),
-};
-
-#endif
-
-#ifdef CONFIG_IWL3945_RFKILL
-struct iwl3945_priv;
-
-void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv);
-void iwl3945_rfkill_unregister(struct iwl3945_priv *priv);
-int iwl3945_rfkill_init(struct iwl3945_priv *priv);
-#else
-static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {}
-static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {}
-static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; }
-#endif
-
-#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
-
-struct iwl3945_priv {
-
-       /* ieee device used by generic ieee processing code */
-       struct ieee80211_hw *hw;
-       struct ieee80211_channel *ieee_channels;
-       struct ieee80211_rate *ieee_rates;
-       struct iwl_3945_cfg *cfg; /* device configuration */
-
-       /* temporary frame storage list */
-       struct list_head free_frames;
-       int frames_count;
-
-       enum ieee80211_band band;
-       int alloc_rxb_skb;
-
-       void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
-                                      struct iwl3945_rx_mem_buffer *rxb);
-
-       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-
-#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
-       /* spectrum measurement report caching */
-       struct iwl3945_spectrum_notification measure_report;
-       u8 measurement_status;
-#endif
-       /* ucode beacon time */
-       u32 ucode_beacon_time;
-
-       /* we allocate array of iwl3945_channel_info for NIC's valid channels.
-        *    Access via channel # using indirect index array */
-       struct iwl3945_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 iwl3945_clip_group clip_groups[5];
-
-       /* thermal calibration */
-       s32 temperature;        /* degrees Kelvin */
-       s32 last_temperature;
-
-       /* Scan related variables */
-       unsigned long last_scan_jiffies;
-       unsigned long next_scan_jiffies;
-       unsigned long scan_start;
-       unsigned long scan_pass_start;
-       unsigned long scan_start_tsf;
-       int scan_bands;
-       int one_direct_scan;
-       u8 direct_ssid_len;
-       u8 direct_ssid[IW_ESSID_MAX_SIZE];
-       struct iwl3945_scan_cmd *scan;
-
-       /* spinlock */
-       spinlock_t lock;        /* protect general shared data */
-       spinlock_t hcmd_lock;   /* protect hcmd */
-       struct mutex mutex;
-
-       /* basic pci-network driver stuff */
-       struct pci_dev *pci_dev;
-
-       /* pci hardware address support */
-       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 */
-       struct fw_desc ucode_init;      /* initialization inst */
-       struct fw_desc ucode_init_data; /* initialization data */
-       struct fw_desc ucode_boot;      /* bootstrap inst */
-
-
-       struct iwl3945_rxon_time_cmd rxon_timing;
-
-       /* We declare this const so it can only be
-        * changed via explicit cast within the
-        * routines that actually update the physical
-        * hardware */
-       const struct iwl3945_rxon_cmd active_rxon;
-       struct iwl3945_rxon_cmd staging_rxon;
-
-       int error_recovering;
-       struct iwl3945_rxon_cmd recovery_rxon;
-
-       /* 1st responses from initialize and runtime uCode images.
-        * 4965's initialize alive response contains some calibration data. */
-       struct iwl3945_init_alive_resp card_alive_init;
-       struct iwl3945_alive_resp card_alive;
-
-#ifdef CONFIG_IWL3945_RFKILL
-       struct rfkill *rfkill;
-#endif
-
-#ifdef CONFIG_IWL3945_LEDS
-       struct iwl3945_led led[IWL_LED_TRG_MAX];
-       unsigned long last_blink_time;
-       u8 last_blink_rate;
-       u8 allow_blinking;
-       unsigned int rxtxpackets;
-       u64 led_tpt;
-#endif
-
-
-       u16 active_rate;
-       u16 active_rate_basic;
-
-       u32 sta_supp_rates;
-
-       u8 call_post_assoc_from_beacon;
-       /* Rate scaling data */
-       s8 data_retry_limit;
-       u8 retry_rate;
-
-       wait_queue_head_t wait_command_queue;
-
-       int activity_timer_active;
-
-       /* Rx and Tx DMA processing queues */
-       struct iwl3945_rx_queue rxq;
-       struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES];
-
-       unsigned long status;
-
-       int last_rx_rssi;       /* From Rx packet statisitics */
-       int last_rx_noise;      /* From beacon statistics */
-
-       struct iwl3945_power_mgr power_data;
-
-       struct iwl3945_notif_statistics statistics;
-       unsigned long last_statistics_time;
-
-       /* context information */
-       u16 rates_mask;
-
-       u32 power_mode;
-       u32 antenna;
-       u8 bssid[ETH_ALEN];
-       u16 rts_threshold;
-       u8 mac_addr[ETH_ALEN];
-
-       /*station table variables */
-       spinlock_t sta_lock;
-       int num_stations;
-       struct iwl3945_station_entry stations[IWL_STATION_COUNT];
-
-       /* Indication if ieee80211_ops->open has been called */
-       u8 is_open;
-
-       u8 mac80211_registered;
-
-       /* Rx'd packet timing information */
-       u32 last_beacon_time;
-       u64 last_tsf;
-
-       /* eeprom */
-       struct iwl3945_eeprom eeprom;
-
-       enum nl80211_iftype iw_mode;
-
-       struct sk_buff *ibss_beacon;
-
-       /* Last Rx'd beacon timestamp */
-       u32 timestamp0;
-       u32 timestamp1;
-       u16 beacon_int;
-       struct iwl3945_driver_hw_info hw_setting;
-       struct ieee80211_vif *vif;
-
-       /* Current association information needed to configure the
-        * hardware */
-       u16 assoc_id;
-       u16 assoc_capability;
-       u8 ps_mode;
-
-       struct iwl3945_qos_info qos_data;
-
-       struct workqueue_struct *workqueue;
-
-       struct work_struct up;
-       struct work_struct restart;
-       struct work_struct calibrated_work;
-       struct work_struct scan_completed;
-       struct work_struct rx_replenish;
-       struct work_struct rf_kill;
-       struct work_struct abort_scan;
-       struct work_struct update_link_led;
-       struct work_struct auth_work;
-       struct work_struct report_work;
-       struct work_struct request_scan;
-       struct work_struct beacon_update;
-
-       struct tasklet_struct irq_tasklet;
-
-       struct delayed_work init_alive_start;
-       struct delayed_work alive_start;
-       struct delayed_work activity_timer;
-       struct delayed_work thermal_periodic;
-       struct delayed_work gather_stats;
-       struct delayed_work scan_check;
-
-#define IWL_DEFAULT_TX_POWER 0x0F
-       s8 user_txpower_limit;
-       s8 max_channel_txpower_limit;
-
-
-#ifdef CONFIG_IWL3945_DEBUG
-       /* debugging info */
-       u32 framecnt_to_us;
-       atomic_t restrict_refcnt;
-#endif
-};                             /*iwl3945_priv */
-
-static inline int iwl3945_is_associated(struct iwl3945_priv *priv)
-{
-       return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
-}
-
-static inline int is_channel_valid(const struct iwl3945_channel_info *ch_info)
-{
-       if (ch_info == NULL)
-               return 0;
-       return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
-}
-
-static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info)
-{
-       return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
-}
-
-static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
-{
-       return ch_info->band == IEEE80211_BAND_5GHZ;
-}
-
-static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
-{
-       return ch_info->band == IEEE80211_BAND_2GHZ;
-}
-
-static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
-{
-       return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
-}
-
-static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
+static inline int iwl3945_is_associated(struct iwl_priv *priv)
 {
-       return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+       return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
 }
 
-extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
-       const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
+extern const struct iwl_channel_info *iwl3945_get_channel_info(
+       const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
 
-extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate);
+extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
 
-/* Requires full declaration of iwl3945_priv before including */
-#include "iwl-3945-io.h"
+/* Requires full declaration of iwl_priv before including */
+#include "iwl-io.h"
 
 #endif
index 6649f7b55650012ef01310bab088fc2f56455526..af4c1bb0de14f79530dd55621bb798d4a611697f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@
 #define LONG_SLOT_TIME 20
 
 /* RSSI to dBm */
-#define IWL_RSSI_OFFSET        44
+#define IWL49_RSSI_OFFSET      44
 
 
 
 
 #define IWL_DEFAULT_TX_RETRY  15
 
-#define RX_QUEUE_SIZE                         256
-#define RX_QUEUE_MASK                         255
-#define RX_QUEUE_SIZE_LOG                     8
-
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-/*
- * RX related structures and functions
- */
-#define RX_FREE_BUFFERS 64
-#define RX_LOW_WATERMARK 8
-
-/* Size of one Rx buffer in host DRAM */
-#define IWL_RX_BUF_SIZE_4K (4 * 1024)
-#define IWL_RX_BUF_SIZE_8K (8 * 1024)
 
 /* Sizes and addresses for instruction and data memory (SRAM) in
  * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define RTC_INST_LOWER_BOUND                   (0x000000)
+#define IWL49_RTC_INST_LOWER_BOUND             (0x000000)
 #define IWL49_RTC_INST_UPPER_BOUND             (0x018000)
 
-#define RTC_DATA_LOWER_BOUND                   (0x800000)
+#define IWL49_RTC_DATA_LOWER_BOUND             (0x800000)
 #define IWL49_RTC_DATA_UPPER_BOUND             (0x80A000)
 
-#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
-#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
+#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
+                               IWL49_RTC_INST_LOWER_BOUND)
+#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
+                               IWL49_RTC_DATA_LOWER_BOUND)
 
-#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE
-#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
+#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
+#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
 
 /* Size of uCode instruction memory in bootstrap state machine */
-#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
+#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
 
 static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
 {
-       return (addr >= RTC_DATA_LOWER_BOUND) &&
+       return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
               (addr < IWL49_RTC_DATA_UPPER_BOUND);
 }
 
index 5a72bc0377ded292dcfd7048b9fbfc86373eab4e..d7d956db19d1dc6db1fd151ad75292ce3a88d2c2 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
@@ -85,7 +85,7 @@ static int iwl4965_verify_bsm(struct iwl_priv *priv)
             reg += sizeof(u32), image++) {
                val = iwl_read_prph(priv, reg);
                if (val != le32_to_cpu(*image)) {
-                       IWL_ERROR("BSM uCode verification failed at "
+                       IWL_ERR(priv, "BSM uCode verification failed at "
                                  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
                                  BSM_SRAM_LOWER_BOUND,
                                  reg - BSM_SRAM_LOWER_BOUND, len,
@@ -149,7 +149,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
        priv->ucode_type = UCODE_RT;
 
        /* make sure bootstrap program is no larger than BSM's SRAM size */
-       if (len > IWL_MAX_BSM_SIZE)
+       if (len > IWL49_MAX_BSM_SIZE)
                return -EINVAL;
 
        /* Tell bootstrap uCode where to find the "Initialize" uCode
@@ -186,7 +186,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
 
        /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
        iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-       iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
+       iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
        iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
 
        /* Load bootstrap code into instruction SRAM now,
@@ -203,7 +203,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
        if (i < 100)
                IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
        else {
-               IWL_ERROR("BSM write did not complete!\n");
+               IWL_ERR(priv, "BSM write did not complete!\n");
                return -EIO;
        }
 
@@ -523,7 +523,8 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
                cmd.diff_gain_c = 0;
                if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
                                 sizeof(cmd), &cmd))
-                       IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
+                       IWL_ERR(priv,
+                               "Could not send REPLY_PHY_CALIBRATION_CMD\n");
                data->state = IWL_CHAIN_NOISE_ACCUMULATE;
                IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
        }
@@ -804,8 +805,9 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
 
        if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) ||
            (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
-               IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-                         IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES);
+               IWL_ERR(priv,
+                       "invalid queues_num, should be between %d and %d\n",
+                       IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES);
                return -EINVAL;
        }
 
@@ -813,6 +815,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
        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.tfd_size = sizeof(struct iwl_tfd);
        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;
@@ -820,6 +823,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
        priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
        priv->hw_params.fat_channel = BIT(IEEE80211_BAND_5GHZ);
 
+       priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
        priv->hw_params.tx_chains_num = 2;
        priv->hw_params.rx_chains_num = 2;
        priv->hw_params.valid_tx_ant = ANT_A | ANT_B;
@@ -902,7 +907,6 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
            channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
                return CALIB_CH_GROUP_4;
 
-       IWL_ERROR("Can't find txatten group for channel %d.\n", channel);
        return -1;
 }
 
@@ -956,7 +960,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
 
        s = iwl4965_get_sub_band(priv, channel);
        if (s >= EEPROM_TX_POWER_BANDS) {
-               IWL_ERROR("Tx Power can not find channel %d\n", channel);
+               IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
                return -1;
        }
 
@@ -1303,7 +1307,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
        s32 factory_actual_pwr[2];
        s32 power_index;
 
-       /* user_txpower_limit is in dBm, convert to half-dBm (half-dB units
+       /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
         *   are used for indexing into txpower table) */
        user_target_power = 2 * priv->tx_power_user_lmt;
 
@@ -1319,8 +1323,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
        /* get txatten group, used to select 1) thermal txpower adjustment
         *   and 2) mimo txpower balance between Tx chains. */
        txatten_grp = iwl4965_get_tx_atten_grp(channel);
-       if (txatten_grp < 0)
+       if (txatten_grp < 0) {
+               IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
+                         channel);
                return -EINVAL;
+       }
 
        IWL_DEBUG_TXPOWER("channel %d belongs to txatten group %d\n",
                          channel, txatten_grp);
@@ -1483,12 +1490,12 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 
                        /* stay within the table! */
                        if (power_index > 107) {
-                               IWL_WARNING("txpower index %d > 107\n",
+                               IWL_WARN(priv, "txpower index %d > 107\n",
                                            power_index);
                                power_index = 107;
                        }
                        if (power_index < 0) {
-                               IWL_WARNING("txpower index %d < 0\n",
+                               IWL_WARN(priv, "txpower index %d < 0\n",
                                            power_index);
                                power_index = 0;
                        }
@@ -1531,7 +1538,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
                /* If this gets hit a lot, switch it to a BUG() and catch
                 * the stack trace to find out who is calling this during
                 * a scan. */
-               IWL_WARNING("TX Power requested while scanning!\n");
+               IWL_WARN(priv, "TX Power requested while scanning!\n");
                return -EAGAIN;
        }
 
@@ -1725,7 +1732,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv)
        IWL_DEBUG_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 
        if (R3 == R1) {
-               IWL_ERROR("Calibration conflict R1 == R3\n");
+               IWL_ERR(priv, "Calibration conflict R1 == R3\n");
                return -1;
        }
 
@@ -1837,7 +1844,8 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 
        if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
-               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+               IWL_WARN(priv,
+                       "queue number out of range: %d, must be %d to %d\n",
                        txq_id, IWL49_FIRST_AMPDU_QUEUE,
                        IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
@@ -1908,7 +1916,8 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 
        if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
-               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+               IWL_WARN(priv,
+                       "queue number out of range: %d, must be %d to %d\n",
                        txq_id, IWL49_FIRST_AMPDU_QUEUE,
                        IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
@@ -2067,10 +2076,10 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
 
                        sc = le16_to_cpu(hdr->seq_ctrl);
                        if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-                               IWL_ERROR("BUG_ON idx doesn't match seq control"
-                                         " idx=%d, seq_idx=%d, seq=%d\n",
-                                         idx, SEQ_TO_SN(sc),
-                                         hdr->seq_ctrl);
+                               IWL_ERR(priv,
+                                       "BUG_ON idx doesn't match seq control"
+                                       " idx=%d, seq_idx=%d, seq=%d\n",
+                                       idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
                                return -1;
                        }
 
@@ -2129,7 +2138,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
        u8 *qc = NULL;
 
        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 "
+               IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
                          "is out of range [0-%d] %d %d\n", txq_id,
                          index, txq->q.n_bd, txq->q.write_ptr,
                          txq->q.read_ptr);
@@ -2147,7 +2156,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
 
        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");
+               IWL_ERR(priv, "Station not known\n");
                return;
        }
 
@@ -2210,7 +2219,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                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");
+               IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
 
 static int iwl4965_calc_rssi(struct iwl_priv *priv,
@@ -2244,7 +2253,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv,
 
        /* dBm = max_rssi dB - agc dB - constant.
         * Higher AGC (higher radio gain) means lower signal. */
-       return max_rssi - agc - IWL_RSSI_OFFSET;
+       return max_rssi - agc - IWL49_RSSI_OFFSET;
 }
 
 
@@ -2287,6 +2296,9 @@ static struct iwl_lib_ops iwl4965_lib = {
        .txq_set_sched = iwl4965_txq_set_sched,
        .txq_agg_enable = iwl4965_txq_agg_enable,
        .txq_agg_disable = iwl4965_txq_agg_disable,
+       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = iwl_hw_txq_free_tfd,
+       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwl4965_rx_handler_setup,
        .setup_deferred_work = iwl4965_setup_deferred_work,
        .cancel_deferred_work = iwl4965_cancel_deferred_work,
index 82c3859ce0f8bf8fb95ac751ef53810984986458..15cac70e36e2d202d17419e36bc86414f8ace6e0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef __iwl_5000_hw_h__
 #define __iwl_5000_hw_h__
 
+#define IWL50_RTC_INST_LOWER_BOUND             (0x000000)
 #define IWL50_RTC_INST_UPPER_BOUND             (0x020000)
+
+#define IWL50_RTC_DATA_LOWER_BOUND             (0x800000)
 #define IWL50_RTC_DATA_UPPER_BOUND             (0x80C000)
-#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)
+
+#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \
+                               IWL50_RTC_INST_LOWER_BOUND)
+#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \
+                               IWL50_RTC_DATA_LOWER_BOUND)
 
 /* EEPROM */
 #define IWL_5000_EEPROM_IMG_SIZE                       2048
index 66d053d28a7470dbb395dd57202edb224cd36b15..89d92a8ca15728b8552a38e2f15cc3533c5f7d23 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007-2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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
@@ -289,7 +289,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
                offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
                break;
        default:
-               IWL_ERROR("illegal indirect type: 0x%X\n",
+               IWL_ERR(priv, "illegal indirect type: 0x%X\n",
                address & INDIRECT_TYPE_MSK);
                break;
        }
@@ -384,7 +384,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
                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");
+                       IWL_ERR(priv,
+                               "Could not send REPLY_PHY_CALIBRATION_CMD\n");
                data->state = IWL_CHAIN_NOISE_ACCUMULATE;
                IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
        }
@@ -507,7 +508,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
                index = IWL_CALIB_BASE_BAND;
                break;
        default:
-               IWL_ERROR("Unknown calibration notification %d\n",
+               IWL_ERR(priv, "Unknown calibration notification %d\n",
                          hdr->op_code);
                return;
        }
@@ -580,7 +581,8 @@ 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,
+                                  IWL50_RTC_INST_LOWER_BOUND);
        if (ret)
                return ret;
 
@@ -588,19 +590,19 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
                                        priv->ucode_write_complete, 5 * HZ);
        if (ret == -ERESTARTSYS) {
-               IWL_ERROR("Could not load the INST uCode section due "
+               IWL_ERR(priv, "Could not load the INST uCode section due "
                        "to interrupt\n");
                return ret;
        }
        if (!ret) {
-               IWL_ERROR("Could not load the INST uCode section\n");
+               IWL_ERR(priv, "Could not load the INST uCode section\n");
                return -ETIMEDOUT;
        }
 
        priv->ucode_write_complete = 0;
 
        ret = iwl5000_load_section(
-               priv, data_image, RTC_DATA_LOWER_BOUND);
+               priv, data_image, IWL50_RTC_DATA_LOWER_BOUND);
        if (ret)
                return ret;
 
@@ -609,11 +611,11 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
                                priv->ucode_write_complete, 5 * HZ);
        if (ret == -ERESTARTSYS) {
-               IWL_ERROR("Could not load the INST uCode section due "
+               IWL_ERR(priv, "Could not load the INST uCode section due "
                        "to interrupt\n");
                return ret;
        } else if (!ret) {
-               IWL_ERROR("Could not load the DATA uCode section\n");
+               IWL_ERR(priv, "Could not load the DATA uCode section\n");
                return -ETIMEDOUT;
        } else
                ret = 0;
@@ -675,7 +677,8 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
        iwl_clear_stations_table(priv);
        ret = priv->cfg->ops->lib->alive_notify(priv);
        if (ret) {
-               IWL_WARNING("Could not complete ALIVE transition: %d\n", ret);
+               IWL_WARN(priv,
+                       "Could not complete ALIVE transition: %d\n", ret);
                goto restart;
        }
 
@@ -824,8 +827,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 {
        if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
            (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
-               IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-                         IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES);
+               IWL_ERR(priv,
+                       "invalid queues_num, should be between %d and %d\n",
+                       IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES);
                return -EINVAL;
        }
 
@@ -833,6 +837,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
        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.tfd_size = sizeof(struct iwl_tfd);
        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;
@@ -840,6 +845,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
        priv->hw_params.max_bsm_size = 0;
        priv->hw_params.fat_channel =  BIT(IEEE80211_BAND_2GHZ) |
                                        BIT(IEEE80211_BAND_5GHZ);
+       priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
        priv->hw_params.sens = &iwl5000_sensitivity;
 
        switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
@@ -1011,7 +1018,8 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 
        if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
-               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+               IWL_WARN(priv,
+                       "queue number out of range: %d, must be %d to %d\n",
                        txq_id, IWL50_FIRST_AMPDU_QUEUE,
                        IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
@@ -1076,7 +1084,8 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 
        if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
-               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+               IWL_WARN(priv,
+                       "queue number out of range: %d, must be %d to %d\n",
                        txq_id, IWL50_FIRST_AMPDU_QUEUE,
                        IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
@@ -1197,8 +1206,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
 
                        sc = le16_to_cpu(hdr->seq_ctrl);
                        if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-                               IWL_ERROR("BUG_ON idx doesn't match seq control"
-                                         " idx=%d, seq_idx=%d, seq=%d\n",
+                               IWL_ERR(priv,
+                                       "BUG_ON idx doesn't match seq control"
+                                       " idx=%d, seq_idx=%d, seq=%d\n",
                                          idx, SEQ_TO_SN(sc),
                                          hdr->seq_ctrl);
                                return -1;
@@ -1254,7 +1264,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
        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 "
+               IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
                          "is out of range [0-%d] %d %d\n", txq_id,
                          index, txq->q.n_bd, txq->q.write_ptr,
                          txq->q.read_ptr);
@@ -1328,7 +1338,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
                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");
+               IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
 
 /* Currently 5000 is the superset of everything */
@@ -1356,7 +1366,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
 
 static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
 {
-       return (addr >= RTC_DATA_LOWER_BOUND) &&
+       return (addr >= IWL50_RTC_DATA_LOWER_BOUND) &&
                (addr < IWL50_RTC_DATA_UPPER_BOUND);
 }
 
@@ -1460,7 +1470,7 @@ static int iwl5000_calc_rssi(struct iwl_priv *priv,
 
        /* dBm = max_rssi dB - agc dB - constant.
         * Higher AGC (higher radio gain) means lower signal. */
-       return max_rssi - agc - IWL_RSSI_OFFSET;
+       return max_rssi - agc - IWL49_RSSI_OFFSET;
 }
 
 static struct iwl_hcmd_ops iwl5000_hcmd = {
@@ -1483,6 +1493,9 @@ static struct iwl_lib_ops iwl5000_lib = {
        .txq_set_sched = iwl5000_txq_set_sched,
        .txq_agg_enable = iwl5000_txq_agg_enable,
        .txq_agg_disable = iwl5000_txq_agg_disable,
+       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = iwl_hw_txq_free_tfd,
+       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwl5000_rx_handler_setup,
        .setup_deferred_work = iwl5000_setup_deferred_work,
        .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
@@ -1517,13 +1530,13 @@ static struct iwl_lib_ops iwl5000_lib = {
        },
 };
 
-static struct iwl_ops iwl5000_ops = {
+struct iwl_ops iwl5000_ops = {
        .lib = &iwl5000_lib,
        .hcmd = &iwl5000_hcmd,
        .utils = &iwl5000_hcmd_utils,
 };
 
-static struct iwl_mod_params iwl50_mod_params = {
+struct iwl_mod_params iwl50_mod_params = {
        .num_of_queues = IWL50_NUM_QUEUES,
        .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
        .amsdu_size_8K = 1,
similarity index 64%
rename from drivers/net/wireless/iwlwifi/iwl-3945-core.h
rename to drivers/net/wireless/iwlwifi/iwl-6000-hw.h
index 6f463555402c7bb1b751d1ec9846730efca355bc..90185777d98bcb05745edb0fa2317a0ea9c131c8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
  *****************************************************************************/
+/*
+ * Please use this file (iwl-6000-hw.h) only for hardware-related definitions.
+ * Use iwl-5000-commands.h for uCode API definitions.
+ */
 
-#ifndef __iwl_3945_dev_h__
-#define __iwl_3945_dev_h__
-
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-       .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
-       .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-       .driver_data = (kernel_ulong_t)&(cfg)
+#ifndef __iwl_6000_hw_h__
+#define __iwl_6000_hw_h__
 
-#define IWL_SKU_G       0x1
-#define IWL_SKU_A       0x2
+#define IWL60_RTC_INST_LOWER_BOUND             (0x000000)
+#define IWL60_RTC_INST_UPPER_BOUND             (0x040000)
+#define IWL60_RTC_DATA_LOWER_BOUND             (0x800000)
+#define IWL60_RTC_DATA_UPPER_BOUND             (0x814000)
+#define IWL60_RTC_INST_SIZE \
+       (IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND)
+#define IWL60_RTC_DATA_SIZE \
+       (IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND)
 
-/**
- * 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_pre;
-       const unsigned int ucode_api_max;
-       const unsigned int ucode_api_min;
-       unsigned int sku;
-};
+#endif /* __iwl_6000_hw_h__ */
 
-#endif /* __iwl_dev_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
new file mode 100644 (file)
index 0000000..4515a60
--- /dev/null
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008-2009 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.
+ *
+ * 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/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-sta.h"
+#include "iwl-helpers.h"
+#include "iwl-5000-hw.h"
+
+/* Highest firmware API version supported */
+#define IWL6000_UCODE_API_MAX 1
+#define IWL6050_UCODE_API_MAX 1
+
+/* Lowest firmware API version supported */
+#define IWL6000_UCODE_API_MIN 1
+#define IWL6050_UCODE_API_MIN 1
+
+#define IWL6000_FW_PRE "iwlwifi-6000-"
+#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
+#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api)
+
+#define IWL6050_FW_PRE "iwlwifi-6050-"
+#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
+#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
+
+struct iwl_cfg iwl6000_2ag_cfg = {
+       .name = "6000 Series 2x2 AG",
+       .fw_name_pre = IWL6000_FW_PRE,
+       .ucode_api_max = IWL6000_UCODE_API_MAX,
+       .ucode_api_min = IWL6000_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 iwl6000_2agn_cfg = {
+       .name = "6000 Series 2x2 AGN",
+       .fw_name_pre = IWL6000_FW_PRE,
+       .ucode_api_max = IWL6000_UCODE_API_MAX,
+       .ucode_api_min = IWL6000_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 iwl6050_2agn_cfg = {
+       .name = "6050 Series 2x2 AGN",
+       .fw_name_pre = IWL6050_FW_PRE,
+       .ucode_api_max = IWL6050_UCODE_API_MAX,
+       .ucode_api_min = IWL6050_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 iwl6000_3agn_cfg = {
+       .name = "6000 Series 3x3 AGN",
+       .fw_name_pre = IWL6000_FW_PRE,
+       .ucode_api_max = IWL6000_UCODE_API_MAX,
+       .ucode_api_min = IWL6000_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 iwl6050_3agn_cfg = {
+       .name = "6050 Series 3x3 AGN",
+       .fw_name_pre = IWL6050_FW_PRE,
+       .ucode_api_max = IWL6050_UCODE_API_MAX,
+       .ucode_api_min = IWL6050_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,
+};
+
+MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
index b8137eeae1db87eae6a6dd19fda2e65c8e19712f..1217a1da88f53515f47d76c7d4eb53bee5def855 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
  * 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 iwl_agn_check_rxon_cmd(struct iwl_priv *priv)
 {
        int error = 0;
        int counter = 1;
+       struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 
        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",
+                       IWL_WARN(priv, "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",
+                       IWL_WARN(priv, "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",
+                       IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
                            counter++, error);
 
        if (error)
-               IWL_WARNING("Tuning to channel %d\n",
+               IWL_WARN(priv, "Tuning to channel %d\n",
                            le16_to_cpu(rxon->channel));
 
        if (error) {
-               IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
+               IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n");
                return -1;
        }
        return 0;
index 27f50471aed8fd0f4e0349975705b6b06c9e9066..13039a024473eb25da5081e7754ad0cbd5d5e748 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -49,6 +49,8 @@
 #define IWL_RATE_MIN_FAILURE_TH                6       /* min failures to calc tpt */
 #define IWL_RATE_MIN_SUCCESS_TH                8       /* min successes to calc tpt */
 
+/* max allowed rate miss before sync LQ cmd */
+#define IWL_MISSED_RATE_MAX            15
 /* max time to accum history 2 seconds */
 #define IWL_RATE_SCALE_FLUSH_INTVL   (2*HZ)
 
@@ -148,6 +150,8 @@ struct iwl_lq_sta {
        u16 active_mimo2_rate;
        u16 active_mimo3_rate;
        u16 active_rate_basic;
+       s8 max_rate_idx;     /* Max rate set by user */
+       u8 missed_rate_counter;
 
        struct iwl_link_quality_cmd lq;
        struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
@@ -463,8 +467,9 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
  * Fill uCode API rate_n_flags field, based on "search" or "active" table.
  */
 /* FIXME:RS:remove this function and put the flags statically in the table */
-static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
-                                      int index, u8 use_green)
+static u32 rate_n_flags_from_tbl(struct iwl_priv *priv,
+                                struct iwl_scale_tbl_info *tbl,
+                                int index, u8 use_green)
 {
        u32 rate_n_flags = 0;
 
@@ -475,7 +480,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
 
        } else if (is_Ht(tbl->lq_type)) {
                if (index > IWL_LAST_OFDM_RATE) {
-                       IWL_ERROR("invalid HT rate index %d\n", index);
+                       IWL_ERR(priv, "Invalid HT rate index %d\n", index);
                        index = IWL_LAST_OFDM_RATE;
                }
                rate_n_flags = RATE_MCS_HT_MSK;
@@ -487,7 +492,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
                else
                        rate_n_flags |= iwl_rates[index].plcp_mimo3;
        } else {
-               IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type);
+               IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type);
        }
 
        rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
@@ -507,7 +512,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
                        rate_n_flags |= RATE_MCS_GF_MSK;
                        if (is_siso(tbl->lq_type) && tbl->is_SGI) {
                                rate_n_flags &= ~RATE_MCS_SGI_MSK;
-                               IWL_ERROR("GF was set with SGI:SISO\n");
+                               IWL_ERR(priv, "GF was set with SGI:SISO\n");
                        }
                }
        }
@@ -758,7 +763,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
                low = scale_index;
 
 out:
-       return rate_n_flags_from_tbl(tbl, low, is_green);
+       return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
 }
 
 /*
@@ -839,10 +844,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
                /* 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);
+               lq_sta->missed_rate_counter++;
+               if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
+                       lq_sta->missed_rate_counter = 0;
+                       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+               }
                goto out;
        }
 
+       lq_sta->missed_rate_counter = 0;
        /* Update frame history window with "failure" for each Tx retry. */
        while (retries) {
                /* Look up the rate and other info used for each tx attempt.
@@ -1129,7 +1139,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
        s32 rate;
        s8 is_green = lq_sta->is_green;
 
-       if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
+       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
                return -1;
 
        if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
@@ -1176,7 +1186,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
                                                rate, rate_mask);
                return -1;
        }
-       tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green);
+       tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
 
        IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n",
                     tbl->current_rate, is_green);
@@ -1196,7 +1206,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
        u8 is_green = lq_sta->is_green;
        s32 rate;
 
-       if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
+       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
                return -1;
 
        IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@@ -1236,7 +1246,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
                             rate, rate_mask);
                return -1;
        }
-       tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green);
+       tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
        IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n",
                     tbl->current_rate, is_green);
        return 0;
@@ -1430,7 +1440,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
                                if (!tbl->is_SGI)
                                        break;
                                else
-                                       IWL_ERROR("SGI was set in GF+SISO\n");
+                                       IWL_ERR(priv,
+                                               "SGI was set in GF+SISO\n");
                        }
                        search_tbl->is_SGI = !tbl->is_SGI;
                        rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1439,8 +1450,9 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
                                if (tpt >= search_tbl->expected_tpt[index])
                                        break;
                        }
-                       search_tbl->current_rate = rate_n_flags_from_tbl(
-                                               search_tbl, index, is_green);
+                       search_tbl->current_rate =
+                               rate_n_flags_from_tbl(priv, search_tbl,
+                                                     index, is_green);
                        goto out;
                }
                tbl->action++;
@@ -1551,8 +1563,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
                                if (tpt >= search_tbl->expected_tpt[index])
                                        break;
                        }
-                       search_tbl->current_rate = rate_n_flags_from_tbl(
-                                               search_tbl, index, is_green);
+                       search_tbl->current_rate =
+                               rate_n_flags_from_tbl(priv, search_tbl,
+                                                     index, is_green);
                        goto out;
 
                }
@@ -1745,16 +1758,25 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                rate_scale_index_msk = rate_mask;
 
        if (!((1 << index) & rate_scale_index_msk)) {
-               IWL_ERROR("Current Rate is not valid\n");
+               IWL_ERR(priv, "Current Rate is not valid\n");
                return;
        }
 
        /* Get expected throughput table and history window for current rate */
        if (!tbl->expected_tpt) {
-               IWL_ERROR("tbl->expected_tpt is NULL\n");
+               IWL_ERR(priv, "tbl->expected_tpt is NULL\n");
                return;
        }
 
+       /* force user max rate if set by user */
+       if ((lq_sta->max_rate_idx != -1) &&
+           (lq_sta->max_rate_idx < index)) {
+               index = lq_sta->max_rate_idx;
+               update_lq = 1;
+               window = &(tbl->win[index]);
+               goto lq_update;
+       }
+
        window = &(tbl->win[index]);
 
        /*
@@ -1846,6 +1868,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
+       /* If user set max rate, dont allow higher than user constrain */
+       if ((lq_sta->max_rate_idx != -1) &&
+           (lq_sta->max_rate_idx < high))
+               high = IWL_RATE_INVALID;
+
        sr = window->success_ratio;
 
        /* Collect measured throughputs for current and adjacent rates */
@@ -1944,7 +1971,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 lq_update:
        /* Replace uCode's rate table for the destination station. */
        if (update_lq) {
-               rate = rate_n_flags_from_tbl(tbl, index, is_green);
+               rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
                rs_fill_link_cmd(priv, lq_sta, rate);
                iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
        }
@@ -1993,7 +2020,7 @@ 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->ht.enabled &&
+               if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
                    lq_sta->action_counter >= 1) {
                        lq_sta->action_counter = 0;
                        IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
@@ -2028,7 +2055,7 @@ lq_update:
        }
 
 out:
-       tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green);
+       tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
        i = index;
        lq_sta->last_txrate_idx = i;
 
@@ -2081,7 +2108,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
        if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
            rs_toggle_antenna(valid_tx_ant, &rate, tbl);
 
-       rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green);
+       rate = rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green);
        tbl->current_rate = rate;
        rs_set_expected_tpt_table(lq_sta, tbl);
        rs_fill_link_cmd(NULL, lq_sta, rate);
@@ -2106,6 +2133,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 
        IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
 
+       /* Get max rate if user set max rate */
+       if (lq_sta) {
+               lq_sta->max_rate_idx = txrc->max_rate_idx;
+               if ((sband->band == IEEE80211_BAND_5GHZ) &&
+                   (lq_sta->max_rate_idx != -1))
+                       lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
+               if ((lq_sta->max_rate_idx < 0) ||
+                   (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
+                       lq_sta->max_rate_idx = -1;
+       }
+
        if (sta)
                mask_bit = sta->supp_rates[sband->band];
 
@@ -2182,6 +2220,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
        struct ieee80211_conf *conf = &priv->hw->conf;
        struct iwl_lq_sta *lq_sta = priv_sta;
        u16 mask_bit = 0;
+       int count;
+       int start_rate = 0;
 
        lq_sta->flush_timer = 0;
        lq_sta->supp_rates = sta->supp_rates[sband->band];
@@ -2216,6 +2256,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
        }
 
        lq_sta->is_dup = 0;
+       lq_sta->max_rate_idx = -1;
+       lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
        lq_sta->is_green = rs_use_green(priv, conf);
        lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
        lq_sta->active_rate_basic = priv->active_rate_basic;
@@ -2254,16 +2296,20 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
        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++)
+       mask_bit = sta->supp_rates[sband->band];
+       count = sband->n_bitrates;
+       if (sband->band == IEEE80211_BAND_5GHZ) {
+               count += IWL_FIRST_OFDM_RATE;
+               start_rate = IWL_FIRST_OFDM_RATE;
+               mask_bit <<= IWL_FIRST_OFDM_RATE;
+       }
+
+       mask_bit = mask_bit & lq_sta->active_legacy_rate;
+       lq_sta->last_txrate_idx = 4;
+       for (i = start_rate; i < count; 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);
 }
 
index 78ee83adf742d632c440710d4bdd7ec056ffb6f6..345806dd8870b74d1ff792b72be3f797d4af4c07 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
@@ -27,8 +27,6 @@
 #ifndef __iwl_agn_rs_h__
 #define __iwl_agn_rs_h__
 
-#include "iwl-dev.h"
-
 struct iwl_rate_info {
        u8 plcp;        /* uCode API:  IWL_RATE_6M_PLCP, etc. */
        u8 plcp_siso;   /* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */
@@ -43,6 +41,19 @@ struct iwl_rate_info {
        u8 next_rs_tgg;  /* next rate used in TGG rs algo */
 };
 
+struct iwl3945_rate_info {
+       u8 plcp;                /* uCode API:  IWL_RATE_6M_PLCP, etc. */
+       u8 ieee;                /* MAC header:  IWL_RATE_6M_IEEE, etc. */
+       u8 prev_ieee;           /* previous rate in IEEE speeds */
+       u8 next_ieee;           /* next rate in IEEE speeds */
+       u8 prev_rs;             /* previous rate used in rs algo */
+       u8 next_rs;             /* next rate used in rs algo */
+       u8 prev_rs_tgg;         /* previous rate used in TGG rs algo */
+       u8 next_rs_tgg;         /* next rate used in TGG rs algo */
+       u8 table_rs_index;      /* index in rate scale table cmd */
+       u8 prev_table_rs;       /* prev in rate table cmd */
+};
+
 /*
  * These serve as indexes into
  * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
@@ -62,12 +73,30 @@ enum {
        IWL_RATE_54M_INDEX,
        IWL_RATE_60M_INDEX,
        IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/
+       IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1,
        IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
        IWL_RATE_INVALID = IWL_RATE_COUNT,
 };
 
+enum {
+       IWL_RATE_6M_INDEX_TABLE = 0,
+       IWL_RATE_9M_INDEX_TABLE,
+       IWL_RATE_12M_INDEX_TABLE,
+       IWL_RATE_18M_INDEX_TABLE,
+       IWL_RATE_24M_INDEX_TABLE,
+       IWL_RATE_36M_INDEX_TABLE,
+       IWL_RATE_48M_INDEX_TABLE,
+       IWL_RATE_54M_INDEX_TABLE,
+       IWL_RATE_1M_INDEX_TABLE,
+       IWL_RATE_2M_INDEX_TABLE,
+       IWL_RATE_5M_INDEX_TABLE,
+       IWL_RATE_11M_INDEX_TABLE,
+       IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1,
+};
+
 enum {
        IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
+       IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
        IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
        IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
        IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
@@ -248,6 +277,7 @@ enum {
 #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
 
 extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
+extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
 
 enum iwl_table_type {
        LQ_NONE,
@@ -303,6 +333,23 @@ static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
        return rate;
 }
 
+static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
+{
+       u8 rate = iwl3945_rates[rate_index].prev_ieee;
+
+       if (rate == IWL_RATE_INVALID)
+               rate = rate_index;
+       return rate;
+}
+
+/**
+ * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
+ *
+ * The specific throughput table used is based on the type of network
+ * the associated with, including A, B, G, and G w/ TGG protection
+ */
+extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+
 /**
  * iwl_rate_control_register - Register the rate control algorithm callbacks
  *
@@ -314,6 +361,7 @@ static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
  *
  */
 extern int iwlagn_rate_control_register(void);
+extern int iwl3945_rate_control_register(void);
 
 /**
  * iwl_rate_control_unregister - Unregister the rate control callbacks
@@ -322,5 +370,6 @@ extern int iwlagn_rate_control_register(void);
  * the driver is unloaded.
  */
 extern void iwlagn_rate_control_unregister(void);
+extern void iwl3945_rate_control_unregister(void);
 
 #endif /* __iwl_agn__rs__ */
index b35c8813bef43fe9173d8a5b88bf8d69241a29d1..6b7120a41ab2515bd714d8f678934e640d1f2844 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -44,6 +44,8 @@
 
 #include <asm/div64.h>
 
+#define DRV_NAME        "iwlagn"
+
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -61,9 +63,7 @@
 
 /*
  * module name, copyright, version, etc.
- * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
  */
-
 #define DRV_DESCRIPTION        "Intel(R) Wireless WiFi Link AGN driver for Linux"
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -179,9 +179,9 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
         * 5000, but will not damage 4965 */
        priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
 
-       ret = iwl_agn_check_rxon_cmd(&priv->staging_rxon);
+       ret = iwl_agn_check_rxon_cmd(priv);
        if (ret) {
-               IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
+               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
                return -EINVAL;
        }
 
@@ -191,7 +191,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
        if (!iwl_full_rxon_required(priv)) {
                ret = iwl_send_rxon_assoc(priv);
                if (ret) {
-                       IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
+                       IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
                        return ret;
                }
 
@@ -218,7 +218,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
                 * active_rxon back to what it was previously */
                if (ret) {
                        active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret);
+                       IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
                        return ret;
                }
        }
@@ -242,7 +242,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
                ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
                              sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
                if (ret) {
-                       IWL_ERROR("Error setting new RXON (%d)\n", ret);
+                       IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
                        return ret;
                }
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
@@ -256,7 +256,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
        /* Add the broadcast address so we can send broadcast frames */
        if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
                                                IWL_INVALID_STATION) {
-               IWL_ERROR("Error adding BROADCAST address for transmit.\n");
+               IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
                return -EIO;
        }
 
@@ -267,13 +267,15 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
                        ret = iwl_rxon_add_station(priv,
                                           priv->active_rxon.bssid_addr, 1);
                        if (ret == IWL_INVALID_STATION) {
-                               IWL_ERROR("Error adding AP address for TX.\n");
+                               IWL_ERR(priv,
+                                       "Error adding AP address for TX.\n");
                                return -EIO;
                        }
                        priv->assoc_station_added = 1;
                        if (priv->default_wep_key &&
                            iwl_send_static_wepkey_cmd(priv, 0))
-                               IWL_ERROR("Could not send WEP static key.\n");
+                               IWL_ERR(priv,
+                                       "Could not send WEP static key.\n");
                }
 
                /* Apply the new configuration
@@ -282,7 +284,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
                ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
                              sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
                if (ret) {
-                       IWL_ERROR("Error setting new RXON (%d)\n", ret);
+                       IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
                        return ret;
                }
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
@@ -294,7 +296,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
         * send a new TXPOWER command or we won't be able to Tx any frames */
        ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
        if (ret) {
-               IWL_ERROR("Error sending TX power (%d)\n", ret);
+               IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
                return ret;
        }
 
@@ -308,20 +310,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
        iwl_commit_rxon(priv);
 }
 
-static int iwl_send_bt_config(struct iwl_priv *priv)
-{
-       struct iwl_bt_cmd bt_cmd = {
-               .flags = 3,
-               .lead_time = 0xAA,
-               .max_kill = 1,
-               .kill_ack_mask = 0,
-               .kill_cts_mask = 0,
-       };
-
-       return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-                               sizeof(struct iwl_bt_cmd), &bt_cmd);
-}
-
 static void iwl_clear_free_frames(struct iwl_priv *priv)
 {
        struct list_head *element;
@@ -337,7 +325,7 @@ static void iwl_clear_free_frames(struct iwl_priv *priv)
        }
 
        if (priv->frames_count) {
-               IWL_WARNING("%d frames still in use.  Did we lose one?\n",
+               IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
                            priv->frames_count);
                priv->frames_count = 0;
        }
@@ -350,7 +338,7 @@ static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
        if (list_empty(&priv->free_frames)) {
                frame = kzalloc(sizeof(*frame), GFP_KERNEL);
                if (!frame) {
-                       IWL_ERROR("Could not allocate frame!\n");
+                       IWL_ERR(priv, "Could not allocate frame!\n");
                        return NULL;
                }
 
@@ -452,7 +440,7 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
        frame = iwl_get_free_frame(priv);
 
        if (!frame) {
-               IWL_ERROR("Could not obtain free frame buffer for beacon "
+               IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
                          "command.\n");
                return -ENOMEM;
        }
@@ -469,6 +457,159 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
        return rc;
 }
 
+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)
+ */
+void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+       struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
+       struct iwl_tfd *tfd;
+       struct pci_dev *dev = priv->pci_dev;
+       int index = txq->q.read_ptr;
+       int i;
+       int num_tbs;
+
+       tfd = &tfd_tmp[index];
+
+       /* Sanity check on number of chunks */
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+               /* @todo issue fatal error, it is quite serious situation */
+               return;
+       }
+
+       /* 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);
+
+       /* 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);
+
+               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;
+               }
+       }
+}
+
+int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+                                struct iwl_tx_queue *txq,
+                                dma_addr_t addr, u16 len,
+                                u8 reset, u8 pad)
+{
+       struct iwl_queue *q;
+       struct iwl_tfd *tfd, *tfd_tmp;
+       u32 num_tbs;
+
+       q = &txq->q;
+       tfd_tmp = (struct iwl_tfd *)txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
+
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       /* Each TFD can point to a maximum 20 Tx buffers */
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(priv, "Error can not send more than %d chunks\n",
+                         IWL_NUM_OF_TBS);
+               return -EINVAL;
+       }
+
+       BUG_ON(addr & ~DMA_BIT_MASK(36));
+       if (unlikely(addr & ~IWL_TX_DMA_MASK))
+               IWL_ERR(priv, "Unaligned address = %llx\n",
+                         (unsigned long long)addr);
+
+       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+
+       return 0;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+int iwl_hw_tx_queue_init(struct iwl_priv *priv,
+                        struct iwl_tx_queue *txq)
+{
+       int ret;
+       unsigned long flags;
+       int txq_id = txq->q.id;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       ret = iwl_grab_nic_access(priv);
+       if (ret) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               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);
+
+       iwl_release_nic_access(priv);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+
 /******************************************************************************
  *
  * Misc. internal state and helper functions
@@ -520,9 +661,9 @@ static void iwl_ht_conf(struct iwl_priv *priv,
         */
 
        iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-       if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS)
+       if (conf_is_ht40_minus(&priv->hw->conf))
                iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-       else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS)
+       else if (conf_is_ht40_plus(&priv->hw->conf))
                iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
 
        /* If no above or below channel supplied disable FAT channel */
@@ -686,7 +827,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
                    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
                break;
        default:
-               IWL_ERROR("Unsupported interface type %d\n", mode);
+               IWL_ERR(priv, "Unsupported interface type %d\n", mode);
                break;
        }
 
@@ -745,7 +886,7 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode)
 
        cancel_delayed_work(&priv->scan_check);
        if (iwl_scan_cancel_timeout(priv, 100)) {
-               IWL_WARNING("Aborted scan still in progress after 100ms\n");
+               IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
                IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
                return -EAGAIN;
        }
@@ -763,7 +904,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
 
        hw = iwl_get_hw_mode(priv, priv->band);
        if (!hw) {
-               IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+               IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
                return;
        }
 
@@ -841,7 +982,7 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
                queue_delayed_work(priv->workqueue, pwork,
                                   msecs_to_jiffies(5));
        else
-               IWL_WARNING("uCode did not respond OK.\n");
+               IWL_WARN(priv, "uCode did not respond OK.\n");
 }
 
 static void iwl_rx_reply_error(struct iwl_priv *priv,
@@ -849,7 +990,7 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
 {
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
-       IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
+       IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
                "seq 0x%04X ser 0x%08X\n",
                le32_to_cpu(pkt->u.err_resp.error_type),
                get_cmd_string(pkt->u.err_resp.cmd_id),
@@ -902,7 +1043,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
        beacon = ieee80211_beacon_get(priv->hw, priv->vif);
 
        if (!beacon) {
-               IWL_ERROR("update beacon failed\n");
+               IWL_ERR(priv, "update beacon failed\n");
                return;
        }
 
@@ -1193,7 +1334,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
                        if (rxb && rxb->skb)
                                iwl_tx_cmd_complete(priv, rxb);
                        else
-                               IWL_WARNING("Claim null rxb?\n");
+                               IWL_WARN(priv, "Claim null rxb?\n");
                }
 
                /* For now we just don't re-use anything.  We can tweak this
@@ -1357,7 +1498,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 
        /* Now service all interrupt bits discovered above. */
        if (inta & CSR_INT_BIT_HW_ERR) {
-               IWL_ERROR("Microcode HW error detected.  Restarting.\n");
+               IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
 
                /* Tell the device to stop sending interrupts */
                iwl_disable_interrupts(priv);
@@ -1397,13 +1538,16 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
                                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
+                * the driver allows loading the ucode even if the radio
+                * is killed. Hence update the killswitch state here. The
+                * rfkill handler will care about restarting if needed.
                 */
-               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);
+               if (!test_bit(STATUS_ALIVE, &priv->status)) {
+                       if (hw_rf_kill)
+                               set_bit(STATUS_RF_KILL_HW, &priv->status);
+                       else
+                               clear_bit(STATUS_RF_KILL_HW, &priv->status);
+                       queue_work(priv->workqueue, &priv->rf_kill);
                }
 
                handled |= CSR_INT_BIT_RF_KILL;
@@ -1411,14 +1555,14 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 
        /* Chip got too hot and stopped itself */
        if (inta & CSR_INT_BIT_CT_KILL) {
-               IWL_ERROR("Microcode CT kill error detected.\n");
+               IWL_ERR(priv, "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",
-                         inta);
+               IWL_ERR(priv, "Microcode SW error detected. "
+                       " Restarting 0x%X.\n", inta);
                iwl_irq_handle_error(priv);
                handled |= CSR_INT_BIT_SW_ERR;
        }
@@ -1454,12 +1598,12 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
        }
 
        if (inta & ~handled)
-               IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
 
        if (inta & ~CSR_INI_SET_MASK) {
-               IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
+               IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
                         inta & ~CSR_INI_SET_MASK);
-               IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
+               IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
        }
 
        /* Re-enable all interrupts */
@@ -1511,7 +1655,7 @@ static irqreturn_t iwl_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%08x\n", inta);
+               IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
                goto unplugged;
        }
 
@@ -1584,7 +1728,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
                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",
+                       IWL_ERR(priv, "%s firmware file req failed: %d\n",
                                  buf, ret);
                        if (ret == -ENOENT)
                                continue;
@@ -1592,8 +1736,11 @@ static int iwl_read_ucode(struct iwl_priv *priv)
                                goto error;
                } else {
                        if (index < api_max)
-                               IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+                               IWL_ERR(priv, "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;
@@ -1605,7 +1752,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
 
        /* Make sure that we got at least our header! */
        if (ucode_raw->size < sizeof(*ucode)) {
-               IWL_ERROR("File size way too small!\n");
+               IWL_ERR(priv, "File size way too small!\n");
                ret = -EINVAL;
                goto err_release;
        }
@@ -1626,7 +1773,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
         * 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. "
+               IWL_ERR(priv, "Driver unable to support your firmware API. "
                          "Driver supports v%u, firmware is v%u.\n",
                          api_max, api_ver);
                priv->ucode_ver = 0;
@@ -1634,16 +1781,16 @@ static int iwl_read_ucode(struct iwl_priv *priv)
                goto err_release;
        }
        if (api_ver != api_max)
-               IWL_ERROR("Firmware has old API version. Expected v%u, "
+               IWL_ERR(priv, "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_INFO(priv, "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);
@@ -1791,7 +1938,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
        return 0;
 
  err_pci_alloc:
-       IWL_ERROR("failed to allocate pci memory\n");
+       IWL_ERR(priv, "failed to allocate pci memory\n");
        ret = -ENOMEM;
        iwl_dealloc_ucode_pci(priv);
 
@@ -1837,8 +1984,8 @@ static void iwl_alive_start(struct iwl_priv *priv)
        iwl_clear_stations_table(priv);
        ret = priv->cfg->ops->lib->alive_notify(priv);
        if (ret) {
-               IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
-                           ret);
+               IWL_WARN(priv,
+                       "Could not complete ALIVE transition [ntf]: %d\n", ret);
                goto restart;
        }
 
@@ -2024,12 +2171,12 @@ static int __iwl_up(struct iwl_priv *priv)
        int ret;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_WARNING("Exit pending; will not bring the NIC up\n");
+               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
                return -EIO;
        }
 
        if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERROR("ucode not available for device bringup\n");
+               IWL_ERR(priv, "ucode not available for device bringup\n");
                return -EIO;
        }
 
@@ -2041,7 +2188,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
        if (iwl_is_rfkill(priv)) {
                iwl_enable_interrupts(priv);
-               IWL_WARNING("Radio disabled by %s RF Kill switch\n",
+               IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
                    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
                return 0;
        }
@@ -2050,7 +2197,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
        ret = iwl_hw_nic_init(priv);
        if (ret) {
-               IWL_ERROR("Unable to init nic\n");
+               IWL_ERR(priv, "Unable to init nic\n");
                return ret;
        }
 
@@ -2083,7 +2230,8 @@ static int __iwl_up(struct iwl_priv *priv)
                ret = priv->cfg->ops->lib->load_ucode(priv);
 
                if (ret) {
-                       IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
+                       IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
+                               ret);
                        continue;
                }
 
@@ -2104,7 +2252,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
        /* tried to restart and config the device for as long as our
         * patience could withstand */
-       IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
+       IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
        return -EIO;
 }
 
@@ -2141,40 +2289,6 @@ static void iwl_bg_alive_start(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
-static void iwl_bg_rf_kill(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
-       wake_up_interruptible(&priv->wait_command_queue);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
-
-       if (!iwl_is_rfkill(priv)) {
-               IWL_DEBUG(IWL_DL_RF_KILL,
-                         "HW and/or SW RF Kill no longer active, restarting "
-                         "device\n");
-               if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       queue_work(priv->workqueue, &priv->restart);
-       } else {
-               /* make sure mac80211 stop sending Tx frame */
-               if (priv->mac80211_registered)
-                       ieee80211_stop_queues(priv->hw);
-
-               if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-                       IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-                                         "disabled by SW switch\n");
-               else
-                       IWL_WARNING("Radio Frequency Kill Switch is On:\n"
-                                   "Kill switch must be turned off for "
-                                   "wireless networking to work.\n");
-       }
-       mutex_unlock(&priv->mutex);
-       iwl_rfkill_set_hw_state(priv);
-}
-
 static void iwl_bg_run_time_calib_work(struct work_struct *work)
 {
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -2244,7 +2358,7 @@ static void iwl_post_associate(struct iwl_priv *priv)
        unsigned long flags;
 
        if (priv->iw_mode == NL80211_IFTYPE_AP) {
-               IWL_ERROR("%s Should not be called in AP mode\n", __func__);
+               IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
                return;
        }
 
@@ -2271,7 +2385,7 @@ static void iwl_post_associate(struct iwl_priv *priv)
        ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                              sizeof(priv->rxon_timing), &priv->rxon_timing);
        if (ret)
-               IWL_WARNING("REPLY_RXON_TIMING failed - "
+               IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                            "Attempting to continue.\n");
 
        priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
@@ -2317,7 +2431,7 @@ static void iwl_post_associate(struct iwl_priv *priv)
                break;
 
        default:
-               IWL_ERROR("%s Should not be called in %d mode\n",
+               IWL_ERR(priv, "%s Should not be called in %d mode\n",
                          __func__, priv->iw_mode);
                break;
        }
@@ -2353,31 +2467,9 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
 {
        struct iwl_priv *priv = hw->priv;
        int ret;
-       u16 pci_cmd;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (pci_enable_device(priv->pci_dev)) {
-               IWL_ERROR("Fail to pci_enable_device\n");
-               return -ENODEV;
-       }
-       pci_restore_state(priv->pci_dev);
-       pci_enable_msi(priv->pci_dev);
-
-       /* enable interrupts if needed: hw bug w/a */
-       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-       }
-
-       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);
-               goto out_disable_msi;
-       }
-
        /* we should be verifying the device is ready to be opened */
        mutex_lock(&priv->mutex);
 
@@ -2388,9 +2480,9 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
        if (!priv->ucode_code.len) {
                ret = iwl_read_ucode(priv);
                if (ret) {
-                       IWL_ERROR("Could not read microcode: %d\n", ret);
+                       IWL_ERR(priv, "Could not read microcode: %d\n", ret);
                        mutex_unlock(&priv->mutex);
-                       goto out_release_irq;
+                       return ret;
                }
        }
 
@@ -2401,7 +2493,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
        iwl_rfkill_set_hw_state(priv);
 
        if (ret)
-               goto out_release_irq;
+               return ret;
 
        if (iwl_is_rfkill(priv))
                goto out;
@@ -2418,10 +2510,9 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
                        UCODE_READY_TIMEOUT);
        if (!ret) {
                if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERROR("START_ALIVE timeout after %dms.\n",
+                       IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
                                jiffies_to_msecs(UCODE_READY_TIMEOUT));
-                       ret = -ETIMEDOUT;
-                       goto out_release_irq;
+                       return -ETIMEDOUT;
                }
        }
 
@@ -2429,15 +2520,6 @@ out:
        priv->is_open = 1;
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
-
-out_release_irq:
-       free_irq(priv->pci_dev->irq, priv);
-out_disable_msi:
-       pci_disable_msi(priv->pci_dev);
-       pci_disable_device(priv->pci_dev);
-       priv->is_open = 0;
-       IWL_DEBUG_MAC80211("leave - failed\n");
-       return ret;
 }
 
 static void iwl_mac_stop(struct ieee80211_hw *hw)
@@ -2465,10 +2547,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
        iwl_down(priv);
 
        flush_workqueue(priv->workqueue);
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_save_state(priv->pci_dev);
-       pci_disable_device(priv->pci_dev);
+
+       /* enable interrupts again in order to receive rfkill changes */
+       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+       iwl_enable_interrupts(priv);
 
        IWL_DEBUG_MAC80211("leave\n");
 }
@@ -2544,7 +2626,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
        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;
+       priv->current_ht_config.is_ht = conf_is_ht(conf);
 
        if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
                IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
@@ -2577,7 +2659,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 
        if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
            !is_channel_ibss(ch_info)) {
-               IWL_ERROR("channel %d in band %d not IBSS channel\n",
+               IWL_ERR(priv, "channel %d in band %d not IBSS channel\n",
                        conf->channel->hw_value, conf->channel->band);
                ret = -EINVAL;
                goto out;
@@ -2639,6 +2721,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 
        iwl_set_rate(priv);
 
+       /* call to ensure that 4965 rx_chain is set properly in monitor mode */
+       iwl_set_rxon_chain(priv);
+
        if (memcmp(&priv->active_rxon,
                   &priv->staging_rxon, sizeof(priv->staging_rxon)))
                iwl_commit_rxon(priv);
@@ -2672,7 +2757,7 @@ static void iwl_config_ap(struct iwl_priv *priv)
                ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                                sizeof(priv->rxon_timing), &priv->rxon_timing);
                if (ret)
-                       IWL_WARNING("REPLY_RXON_TIMING failed - "
+                       IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                                        "Attempting to continue.\n");
 
                iwl_set_rxon_chain(priv);
@@ -2778,7 +2863,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw,
                /* If there is currently a HW scan going on in the background
                 * then we need to cancel it else the RXON below will fail. */
                if (iwl_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARNING("Aborted scan still in progress "
+                       IWL_WARN(priv, "Aborted scan still in progress "
                                    "after 100ms\n");
                        IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
                        mutex_unlock(&priv->mutex);
@@ -3019,13 +3104,15 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
 }
 
 static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                          const u8 *local_addr, const u8 *addr,
+                          struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
                           struct ieee80211_key_conf *key)
 {
        struct iwl_priv *priv = hw->priv;
-       int ret = 0;
-       u8 sta_id = IWL_INVALID_STATION;
-       u8 is_default_wep_key = 0;
+       const u8 *addr;
+       int ret;
+       u8 sta_id;
+       bool is_default_wep_key = false;
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -3033,11 +3120,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
                return -EOPNOTSUPP;
        }
-
-       if (is_zero_ether_addr(addr))
-               /* only support pairwise keys */
-               return -EOPNOTSUPP;
-
+       addr = sta ? sta->addr : iwl_bcast_addr;
        sta_id = iwl_find_station(priv, addr);
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
@@ -3359,8 +3442,7 @@ static ssize_t store_debug_level(struct device *d,
 
        ret = strict_strtoul(buf, 0, &val);
        if (ret)
-               printk(KERN_INFO DRV_NAME
-                      ": %s is not in hex or decimal form.\n", buf);
+               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
        else
                priv->debug_level = val;
 
@@ -3439,8 +3521,7 @@ static ssize_t store_tx_power(struct device *d,
 
        ret = strict_strtoul(buf, 10, &val);
        if (ret)
-               printk(KERN_INFO DRV_NAME
-                      ": %s is not in decimal form.\n", buf);
+               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
        else
                iwl_set_tx_power(priv, val, false);
 
@@ -3473,7 +3554,7 @@ static ssize_t store_flags(struct device *d,
        if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
                /* Cancel any currently running scans... */
                if (iwl_scan_cancel_timeout(priv, 100))
-                       IWL_WARNING("Could not cancel scan.\n");
+                       IWL_WARN(priv, "Could not cancel scan.\n");
                else {
                        IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags);
                        priv->staging_rxon.flags = cpu_to_le32(flags);
@@ -3512,7 +3593,7 @@ static ssize_t store_filter_flags(struct device *d,
        if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
                /* Cancel any currently running scans... */
                if (iwl_scan_cancel_timeout(priv, 100))
-                       IWL_WARNING("Could not cancel scan.\n");
+                       IWL_WARN(priv, "Could not cancel scan.\n");
                else {
                        IWL_DEBUG_INFO("Committing rxon.filter_flags = "
                                       "0x%04X\n", filter_flags);
@@ -3529,31 +3610,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);
 
-static ssize_t store_retry_rate(struct device *d,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       long val;
-       int ret  = strict_strtol(buf, 10, &val);
-       if (!ret)
-               return ret;
-
-       priv->retry_rate = (val > 0) ? val : 1;
-
-       return count;
-}
-
-static ssize_t show_retry_rate(struct device *d,
-                              struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "%d", priv->retry_rate);
-}
-
-static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
-                  store_retry_rate);
-
 static ssize_t store_power_level(struct device *d,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
@@ -3656,16 +3712,6 @@ static ssize_t show_statistics(struct device *d,
 
 static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
 
-static ssize_t show_status(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-       return sprintf(buf, "0x%08x\n", (int)priv->status);
-}
-
-static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 
 /*****************************************************************************
  *
@@ -3719,9 +3765,7 @@ static struct attribute *iwl_sysfs_entries[] = {
        &dev_attr_flags.attr,
        &dev_attr_filter_flags.attr,
        &dev_attr_power_level.attr,
-       &dev_attr_retry_rate.attr,
        &dev_attr_statistics.attr,
-       &dev_attr_status.attr,
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -3764,6 +3808,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ieee80211_hw *hw;
        struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
        unsigned long flags;
+       u16 pci_cmd;
 
        /************************
         * 1. Allocating HW data
@@ -3816,8 +3861,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                /* both attempts failed: */
                if (err) {
-                       printk(KERN_WARNING "%s: No suitable DMA available.\n",
-                               DRV_NAME);
+                       IWL_WARN(priv, "No suitable DMA available.\n");
                        goto out_pci_disable_device;
                }
        }
@@ -3843,8 +3887,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
 
        iwl_hw_detect(priv);
-       printk(KERN_INFO DRV_NAME
-               ": Detected Intel Wireless WiFi Link %s REV=0x%X\n",
+       IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
                priv->cfg->name, priv->hw_rev);
 
        /* We disable the RETRY_TIMEOUT register (0x41) to keep
@@ -3863,7 +3906,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Read the EEPROM */
        err = iwl_eeprom_init(priv);
        if (err) {
-               IWL_ERROR("Unable to init EEPROM\n");
+               IWL_ERR(priv, "Unable to init EEPROM\n");
                goto out_iounmap;
        }
        err = iwl_eeprom_check_version(priv);
@@ -3879,7 +3922,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * 5. Setup HW constants
         ************************/
        if (iwl_set_hw_params(priv)) {
-               IWL_ERROR("failed to set hw parameters\n");
+               IWL_ERR(priv, "failed to set hw parameters\n");
                goto out_free_eeprom;
        }
 
@@ -3909,43 +3952,65 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        iwl_disable_interrupts(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       pci_enable_msi(priv->pci_dev);
+
+       err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
+                         DRV_NAME, priv);
+       if (err) {
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+               goto out_disable_msi;
+       }
        err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
        if (err) {
-               IWL_ERROR("failed to create sysfs device attributes\n");
+               IWL_ERR(priv, "failed to create sysfs device attributes\n");
                goto out_uninit_drv;
        }
 
-
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
 
-       /********************
-        * 9. Conclude
-        ********************/
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-
        /**********************************
-        * 10. Setup and register mac80211
+        * 9. Setup and register mac80211
         **********************************/
 
+       /* enable interrupts if needed: hw bug w/a */
+       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
+       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
+       }
+
+       iwl_enable_interrupts(priv);
+
        err = iwl_setup_mac(priv);
        if (err)
                goto out_remove_sysfs;
 
        err = iwl_dbgfs_register(priv, DRV_NAME);
        if (err)
-               IWL_ERROR("failed to create debugfs files\n");
+               IWL_ERR(priv, "failed to create debugfs files\n");
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(STATUS_RF_KILL_HW, &priv->status);
+       else
+               set_bit(STATUS_RF_KILL_HW, &priv->status);
 
        err = iwl_rfkill_init(priv);
        if (err)
-               IWL_ERROR("Unable to initialize RFKILL system. "
+               IWL_ERR(priv, "Unable to initialize RFKILL system. "
                                  "Ignoring error: %d\n", err);
+       else
+               iwl_rfkill_set_hw_state(priv);
+
        iwl_power_initialize(priv);
        return 0;
 
  out_remove_sysfs:
        sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ out_disable_msi:
+       pci_disable_msi(priv->pci_dev);
+       pci_disable_device(priv->pci_dev);
  out_uninit_drv:
        iwl_uninit_drv(priv);
  out_free_eeprom:
@@ -4017,6 +4082,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
 
+       free_irq(priv->pci_dev->irq, priv);
+       pci_disable_msi(priv->pci_dev);
        pci_iounmap(pdev, priv->hw_base);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
@@ -4042,6 +4109,8 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                priv->is_open = 1;
        }
 
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
@@ -4052,6 +4121,9 @@ static int iwl_pci_resume(struct pci_dev *pdev)
        struct iwl_priv *priv = pci_get_drvdata(pdev);
 
        pci_set_power_state(pdev, PCI_D0);
+       pci_enable_device(pdev);
+       pci_restore_state(pdev);
+       iwl_enable_interrupts(priv);
 
        if (priv->is_open)
                iwl_mac_start(priv->hw);
@@ -4092,6 +4164,21 @@ static struct pci_device_id iwl_hw_card_ids[] = {
 /* 5150 Wifi/WiMax */
        {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
        {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
+/* 6000/6050 Series */
+       {IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
+       {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)},
+/* 100 Series WiFi */
+       {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl100_bgn_cfg)},
 #endif /* CONFIG_IWL5000 */
 
        {0}
@@ -4118,13 +4205,14 @@ static int __init iwl_init(void)
 
        ret = iwlagn_rate_control_register();
        if (ret) {
-               IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
+               printk(KERN_ERR DRV_NAME
+                      "Unable to register rate control algorithm: %d\n", ret);
                return ret;
        }
 
        ret = pci_register_driver(&iwl_driver);
        if (ret) {
-               IWL_ERROR("Unable to initialize PCI module\n");
+               printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
                goto error_register;
        }
 
index f836ecc55758a4d4ab12bf0a796fbd17b9ef2556..8e5e6663be3569346f22e3e6c2be7d618fbe454f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 
        return 0;
 err:
-       IWL_ERROR("Error %d iteration %d\n", ret, i);
+       IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
        return ret;
 }
 EXPORT_SYMBOL(iwl_send_calib_results);
@@ -483,7 +483,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
 
        ret = iwl_send_cmd(priv, &cmd_out);
        if (ret)
-               IWL_ERROR("SENSITIVITY_CMD failed\n");
+               IWL_ERR(priv, "SENSITIVITY_CMD failed\n");
 
        return ret;
 }
index 1abe84bb74ad0bd022e3a7318160f3c2e31c8c21..b6cef989a7965beb98a150d8702819d8381c4fbf 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index ba997204c8d4482a219128428629b8eebca4974f..e49415c7fb2abbe33fc260f014b3152e0639ddae 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef __iwl_commands_h__
 #define __iwl_commands_h__
 
+struct iwl_priv;
+
 /* 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)
 
+
+/* Tx rates */
+#define IWL_CCK_RATES  4
+#define IWL_OFDM_RATES 8
+#define IWL_MAX_RATES  (IWL_CCK_RATES + IWL_OFDM_RATES)
+
 enum {
        REPLY_ALIVE = 0x1,
        REPLY_ERROR = 0x2,
@@ -219,6 +227,37 @@ struct iwl_cmd_header {
        u8 data[0];
 } __attribute__ ((packed));
 
+
+/**
+ * struct iwl3945_tx_power
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
+ */
+struct iwl3945_tx_power {
+       u8 tx_gain;             /* gain for analog radio */
+       u8 dsp_atten;           /* gain for DSP */
+} __attribute__ ((packed));
+
+/**
+ * struct iwl3945_power_per_rate
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl3945_power_per_rate {
+       u8 rate;                /* plcp */
+       struct iwl3945_tx_power tpc;
+       u8 reserved;
+} __attribute__ ((packed));
+
 /**
  * iwlagn rate_n_flags bit fields
  *
@@ -300,11 +339,12 @@ struct iwl_cmd_header {
  * 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_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_AB_MSK    (RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK)
+#define RATE_MCS_ANT_ABC_MSK   (RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK)
 #define RATE_ANT_NUM 3
 
 #define POWER_TABLE_NUM_ENTRIES                        33
@@ -492,8 +532,6 @@ struct iwl_alive_resp {
        __le32 is_valid;
 } __attribute__ ((packed));
 
-
-
 /*
  * REPLY_ERROR = 0x2 (response only, not a command)
  */
@@ -525,6 +563,7 @@ enum {
 
 
 #define RXON_RX_CHAIN_DRIVER_FORCE_MSK         cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_DRIVER_FORCE_POS         (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            cpu_to_le16(0x7 << 4)
@@ -611,6 +650,26 @@ enum {
  *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
  *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
  */
+
+struct iwl3945_rxon_cmd {
+       u8 node_addr[6];
+       __le16 reserved1;
+       u8 bssid_addr[6];
+       __le16 reserved2;
+       u8 wlap_bssid_addr[6];
+       __le16 reserved3;
+       u8 dev_type;
+       u8 air_propagation;
+       __le16 reserved4;
+       u8 ofdm_basic_rates;
+       u8 cck_basic_rates;
+       __le16 assoc_id;
+       __le32 flags;
+       __le32 filter_flags;
+       __le16 channel;
+       __le16 reserved5;
+} __attribute__ ((packed));
+
 struct iwl4965_rxon_cmd {
        u8 node_addr[6];
        __le16 reserved1;
@@ -656,33 +715,41 @@ struct iwl_rxon_cmd {
        __le16 reserved6;
 } __attribute__ ((packed));
 
-struct iwl5000_rxon_assoc_cmd {
+/*
+ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
+ */
+struct iwl3945_rxon_assoc_cmd {
+       __le32 flags;
+       __le32 filter_flags;
+       u8 ofdm_basic_rates;
+       u8 cck_basic_rates;
+       __le16 reserved;
+} __attribute__ ((packed));
+
+struct iwl4965_rxon_assoc_cmd {
        __le32 flags;
        __le32 filter_flags;
        u8 ofdm_basic_rates;
        u8 cck_basic_rates;
-       __le16 reserved1;
        u8 ofdm_ht_single_stream_basic_rates;
        u8 ofdm_ht_dual_stream_basic_rates;
-       u8 ofdm_ht_triple_stream_basic_rates;
-       u8 reserved2;
        __le16 rx_chain_select_flags;
-       __le16 acquisition_data;
-       __le32 reserved3;
+       __le16 reserved;
 } __attribute__ ((packed));
 
-/*
- * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
- */
-struct iwl4965_rxon_assoc_cmd {
+struct iwl5000_rxon_assoc_cmd {
        __le32 flags;
        __le32 filter_flags;
        u8 ofdm_basic_rates;
        u8 cck_basic_rates;
+       __le16 reserved1;
        u8 ofdm_ht_single_stream_basic_rates;
        u8 ofdm_ht_dual_stream_basic_rates;
+       u8 ofdm_ht_triple_stream_basic_rates;
+       u8 reserved2;
        __le16 rx_chain_select_flags;
-       __le16 reserved;
+       __le16 acquisition_data;
+       __le32 reserved3;
 } __attribute__ ((packed));
 
 #define IWL_CONN_MAX_LISTEN_INTERVAL   10
@@ -702,6 +769,16 @@ struct iwl_rxon_time_cmd {
 /*
  * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
  */
+struct iwl3945_channel_switch_cmd {
+       u8 band;
+       u8 expect_beacon;
+       __le16 channel;
+       __le32 rxon_flags;
+       __le32 rxon_filter_flags;
+       __le32 switch_time;
+       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __attribute__ ((packed));
+
 struct iwl_channel_switch_cmd {
        u8 band;
        u8 expect_beacon;
@@ -783,6 +860,8 @@ struct iwl_qosparam_cmd {
 #define        IWL_AP_ID               0
 #define IWL_MULTICAST_ID       1
 #define        IWL_STA_ID              2
+#define        IWL3945_BROADCAST_ID    24
+#define IWL3945_STATION_COUNT  25
 #define IWL4965_BROADCAST_ID   31
 #define        IWL4965_STATION_COUNT   32
 #define IWL5000_BROADCAST_ID   15
@@ -791,6 +870,8 @@ struct iwl_qosparam_cmd {
 #define        IWL_STATION_COUNT       32      /* MAX(3945,4965)*/
 #define        IWL_INVALID_STATION     255
 
+#define STA_FLG_TX_RATE_MSK            cpu_to_le32(1 << 2);
+#define STA_FLG_PWR_SAVE_MSK           cpu_to_le32(1 << 8);
 #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)
@@ -901,6 +982,35 @@ struct sta_id_modify {
  *        used as AP, or in an IBSS network, driver must set up station table
  *        entries for all STAs in network, starting with index IWL_STA_ID.
  */
+
+struct iwl3945_addsta_cmd {
+       u8 mode;                /* 1: modify existing, 0: add new station */
+       u8 reserved[3];
+       struct sta_id_modify sta;
+       struct iwl4965_keyinfo key;
+       __le32 station_flags;           /* STA_FLG_* */
+       __le32 station_flags_msk;       /* STA_FLG_* */
+
+       /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+        * corresponding to bit (e.g. bit 5 controls TID 5).
+        * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+       __le16 tid_disable_tx;
+
+       __le16 rate_n_flags;
+
+       /* TID for which to add block-ack support.
+        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+       u8 add_immediate_ba_tid;
+
+       /* TID for which to remove block-ack support.
+        * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+       u8 remove_immediate_ba_tid;
+
+       /* Starting Sequence Number for added block-ack support.
+        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+       __le16 add_immediate_ba_ssn;
+} __attribute__ ((packed));
+
 struct iwl4965_addsta_cmd {
        u8 mode;                /* 1: modify existing, 0: add new station */
        u8 reserved[3];
@@ -1054,6 +1164,48 @@ struct iwl_wep_cmd {
 #define RX_MPDU_RES_STATUS_TTAK_OK     (1 << 7)
 #define RX_MPDU_RES_STATUS_DEC_DONE_MSK        (0x800)
 
+
+struct iwl3945_rx_frame_stats {
+       u8 phy_count;
+       u8 id;
+       u8 rssi;
+       u8 agc;
+       __le16 sig_avg;
+       __le16 noise_diff;
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct iwl3945_rx_frame_hdr {
+       __le16 channel;
+       __le16 phy_flags;
+       u8 reserved1;
+       u8 rate;
+       __le16 len;
+       u8 payload[0];
+} __attribute__ ((packed));
+
+struct iwl3945_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 iwl3945_rx_frame {
+       struct iwl3945_rx_frame_stats stats;
+       struct iwl3945_rx_frame_hdr hdr;
+       struct iwl3945_rx_frame_end end;
+} __attribute__ ((packed));
+
+#define IWL39_RX_FRAME_SIZE    (4 + sizeof(struct iwl3945_rx_frame))
+
 /* Fixed (non-configurable) rx data from phy */
 
 #define IWL49_RX_RES_PHY_CNT 14
@@ -1233,6 +1385,84 @@ struct iwl4965_rx_mpdu_res_start {
 #define CCMP_MIC_LEN 8
 #define TKIP_ICV_LEN 4
 
+/*
+ * REPLY_TX = 0x1c (command)
+ */
+
+struct iwl3945_tx_cmd {
+       /*
+        * MPDU byte count:
+        * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+        * + 8 byte IV for CCM or TKIP (not used for WEP)
+        * + Data payload
+        * + 8-byte MIC (not used for CCM/WEP)
+        * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+        *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+        * Range: 14-2342 bytes.
+        */
+       __le16 len;
+
+       /*
+        * MPDU or MSDU byte count for next frame.
+        * Used for fragmentation and bursting, but not 11n aggregation.
+        * Same as "len", but for next frame.  Set to 0 if not applicable.
+        */
+       __le16 next_frame_len;
+
+       __le32 tx_flags;        /* TX_CMD_FLG_* */
+
+       u8 rate;
+
+       /* Index of recipient station in uCode's station table */
+       u8 sta_id;
+       u8 tid_tspec;
+       u8 sec_ctl;
+       u8 key[16];
+       union {
+               u8 byte[8];
+               __le16 word[4];
+               __le32 dw[2];
+       } tkip_mic;
+       __le32 next_frame_info;
+       union {
+               __le32 life_time;
+               __le32 attempt;
+       } stop_time;
+       u8 supp_rates[2];
+       u8 rts_retry_limit;     /*byte 50 */
+       u8 data_retry_limit;    /*byte 51 */
+       union {
+               __le16 pm_frame_timeout;
+               __le16 attempt_duration;
+       } timeout;
+
+       /*
+        * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+        * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+        */
+       __le16 driver_txop;
+
+       /*
+        * MAC header goes here, followed by 2 bytes padding if MAC header
+        * length is 26 or 30 bytes, followed by payload data
+        */
+       u8 payload[0];
+       struct ieee80211_hdr hdr[0];
+} __attribute__ ((packed));
+
+/*
+ * REPLY_TX = 0x1c (response)
+ */
+struct iwl3945_tx_resp {
+       u8 failure_rts;
+       u8 failure_frame;
+       u8 bt_kill_count;
+       u8 rate;
+       __le32 wireless_media_time;
+       __le32 status;          /* TX status */
+} __attribute__ ((packed));
+
+
 /*
  * 4965 uCode updates these Tx attempt count values in host DRAM.
  * Used for managing Tx retries when expecting block-acks.
@@ -1244,9 +1474,6 @@ struct iwl_dram_scratch {
        __le16 reserved;
 } __attribute__ ((packed));
 
-/*
- * REPLY_TX = 0x1c (command)
- */
 struct iwl_tx_cmd {
        /*
         * MPDU byte count:
@@ -1584,6 +1811,14 @@ struct iwl_compressed_ba_resp {
  *
  * See details under "TXPOWER" in iwl-4965-hw.h.
  */
+
+struct iwl3945_txpowertable_cmd {
+       u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
+       u8 reserved;
+       __le16 channel;
+       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __attribute__ ((packed));
+
 struct iwl4965_txpowertable_cmd {
        u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
        u8 reserved;
@@ -1591,6 +1826,35 @@ struct iwl4965_txpowertable_cmd {
        struct iwl4965_tx_power_db tx_power;
 } __attribute__ ((packed));
 
+
+/**
+ * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
+ *
+ * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
+ *
+ * NOTE: The table of rates passed to the uCode via the
+ * RATE_SCALE command sets up the corresponding order of
+ * rates used for all related commands, including rate
+ * masks, etc.
+ *
+ * For example, if you set 9MB (PLCP 0x0f) as the first
+ * rate in the rate table, the bit mask for that rate
+ * when passed through ofdm_basic_rates on the REPLY_RXON
+ * command would be bit 0 (1 << 0)
+ */
+struct iwl3945_rate_scaling_info {
+       __le16 rate_n_flags;
+       u8 try_cnt;
+       u8 next_rate_index;
+} __attribute__ ((packed));
+
+struct iwl3945_rate_scaling_cmd {
+       u8 table_id;
+       u8 reserved[3];
+       struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
+} __attribute__ ((packed));
+
+
 /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
 #define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK   (1 << 0)
 
@@ -2044,15 +2308,23 @@ struct iwl_spectrum_notification {
  */
 #define IWL_POWER_VEC_SIZE 5
 
-#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)
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK       cpu_to_le16(BIT(0))
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK          cpu_to_le16(BIT(2))
+#define IWL_POWER_PCI_PM_MSK                   cpu_to_le16(BIT(3))
+#define IWL_POWER_FAST_PD                      cpu_to_le16(BIT(4))
+
+struct iwl3945_powertable_cmd {
+       __le16 flags;
+       u8 reserved[2];
+       __le32 rx_data_timeout;
+       __le32 tx_data_timeout;
+       __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+} __attribute__ ((packed));
 
 struct iwl_powertable_cmd {
        __le16 flags;
-       u8 keep_alive_seconds;
-       u8 debug_flags;
+       u8 keep_alive_seconds;          /* 3945 reserved */
+       u8 debug_flags;                 /* 3945 reserved */
        __le32 rx_data_timeout;
        __le32 tx_data_timeout;
        __le32 sleep_interval[IWL_POWER_VEC_SIZE];
@@ -2143,6 +2415,26 @@ struct iwl_ct_kill_config {
  *     passive_dwell < max_out_time
  *     active_dwell < max_out_time
  */
+
+/* FIXME: rename to AP1, remove tpc */
+struct iwl3945_scan_channel {
+       /*
+        * type is defined as:
+        * 0:0 1 = active, 0 = passive
+        * 1:4 SSID direct bit map; if a bit is set, then corresponding
+        *     SSID IE is transmitted in probe request.
+        * 5:7 reserved
+        */
+       u8 type;
+       u8 channel;     /* band is selected by iwl3945_scan_cmd "flags" field */
+       struct iwl3945_tx_power tpc;
+       __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
+       __le16 passive_dwell;   /* in 1024-uSec TU (time units), typ 20-500 */
+} __attribute__ ((packed));
+
+/* set number of direct probes u8 type */
+#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1))))
+
 struct iwl_scan_channel {
        /*
         * type is defined as:
@@ -2159,6 +2451,9 @@ struct iwl_scan_channel {
        __le16 passive_dwell;   /* in 1024-uSec TU (time units), typ 20-500 */
 } __attribute__ ((packed));
 
+/* set number of direct probes __le32 type */
+#define IWL_SCAN_PROBE_MASK(n)         cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+
 /**
  * struct iwl_ssid_ie - directed scan network information element
  *
@@ -2172,6 +2467,7 @@ struct iwl_ssid_ie {
        u8 ssid[32];
 } __attribute__ ((packed));
 
+#define PROBE_OPTION_MAX_API1          0x4
 #define PROBE_OPTION_MAX               0x14
 #define TX_CMD_LIFE_TIME_INFINITE      cpu_to_le32(0xFFFFFFFF)
 #define IWL_GOOD_CRC_TH                        cpu_to_le16(1)
@@ -2229,6 +2525,51 @@ struct iwl_ssid_ie {
  * To avoid uCode errors, see timing restrictions described under
  * struct iwl_scan_channel.
  */
+
+struct iwl3945_scan_cmd {
+       __le16 len;
+       u8 reserved0;
+       u8 channel_count;       /* # channels in channel list */
+       __le16 quiet_time;      /* dwell only this # millisecs on quiet channel
+                                * (only for active scan) */
+       __le16 quiet_plcp_th;   /* quiet chnl is < this # pkts (typ. 1) */
+       __le16 good_CRC_th;     /* passive -> active promotion threshold */
+       __le16 reserved1;
+       __le32 max_out_time;    /* max usec to be away from associated (service)
+                                * channel */
+       __le32 suspend_time;    /* pause scan this long (in "extended beacon
+                                * format") when returning to service channel:
+                                * 3945; 31:24 # beacons, 19:0 additional usec,
+                                * 4965; 31:22 # beacons, 21:0 additional usec.
+                                */
+       __le32 flags;           /* RXON_FLG_* */
+       __le32 filter_flags;    /* RXON_FILTER_* */
+
+       /* For active scans (set to all-0s for passive scans).
+        * Does not include payload.  Must specify Tx rate; no rate scaling. */
+       struct iwl3945_tx_cmd tx_cmd;
+
+       /* For directed active scans (set to all-0s otherwise) */
+       struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1];
+
+       /*
+        * Probe request frame, followed by channel list.
+        *
+        * Size of probe request frame is specified by byte count in tx_cmd.
+        * Channel list follows immediately after probe request frame.
+        * Number of channels in list is specified by channel_count.
+        * Each channel in list is of type:
+        *
+        * struct iwl3945_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
+        * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+        * before requesting another scan.
+        */
+       u8 data[0];
+} __attribute__ ((packed));
+
 struct iwl_scan_cmd {
        __le16 len;
        u8 reserved0;
@@ -2336,6 +2677,14 @@ struct iwl_scancomplete_notification {
 /*
  * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
  */
+
+struct iwl3945_beacon_notif {
+       struct iwl3945_tx_resp beacon_notify_hdr;
+       __le32 low_tsf;
+       __le32 high_tsf;
+       __le32 ibss_mgr_status;
+} __attribute__ ((packed));
+
 struct iwl4965_beacon_notif {
        struct iwl4965_tx_resp beacon_notify_hdr;
        __le32 low_tsf;
@@ -2346,6 +2695,15 @@ struct iwl4965_beacon_notif {
 /*
  * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
  */
+
+struct iwl3945_tx_beacon_cmd {
+       struct iwl3945_tx_cmd tx;
+       __le16 tim_idx;
+       u8 tim_size;
+       u8 reserved1;
+       struct ieee80211_hdr frame[0];  /* beacon frame */
+} __attribute__ ((packed));
+
 struct iwl_tx_beacon_cmd {
        struct iwl_tx_cmd tx;
        __le16 tim_idx;
@@ -2382,6 +2740,76 @@ struct rate_histogram {
 
 /* statistics command response */
 
+struct iwl39_statistics_rx_phy {
+       __le32 ina_cnt;
+       __le32 fina_cnt;
+       __le32 plcp_err;
+       __le32 crc32_err;
+       __le32 overrun_err;
+       __le32 early_overrun_err;
+       __le32 crc32_good;
+       __le32 false_alarm_cnt;
+       __le32 fina_sync_err_cnt;
+       __le32 sfd_timeout;
+       __le32 fina_timeout;
+       __le32 unresponded_rts;
+       __le32 rxe_frame_limit_overrun;
+       __le32 sent_ack_cnt;
+       __le32 sent_cts_cnt;
+} __attribute__ ((packed));
+
+struct iwl39_statistics_rx_non_phy {
+       __le32 bogus_cts;       /* CTS received when not expecting CTS */
+       __le32 bogus_ack;       /* ACK received when not expecting ACK */
+       __le32 non_bssid_frames;        /* number of frames with BSSID that
+                                        * doesn't belong to the STA BSSID */
+       __le32 filtered_frames; /* count frames that were dumped in the
+                                * filtering process */
+       __le32 non_channel_beacons;     /* beacons with our bss id but not on
+                                        * our serving channel */
+} __attribute__ ((packed));
+
+struct iwl39_statistics_rx {
+       struct iwl39_statistics_rx_phy ofdm;
+       struct iwl39_statistics_rx_phy cck;
+       struct iwl39_statistics_rx_non_phy general;
+} __attribute__ ((packed));
+
+struct iwl39_statistics_tx {
+       __le32 preamble_cnt;
+       __le32 rx_detected_cnt;
+       __le32 bt_prio_defer_cnt;
+       __le32 bt_prio_kill_cnt;
+       __le32 few_bytes_cnt;
+       __le32 cts_timeout;
+       __le32 ack_timeout;
+       __le32 expected_ack_cnt;
+       __le32 actual_ack_cnt;
+} __attribute__ ((packed));
+
+struct statistics_dbg {
+       __le32 burst_check;
+       __le32 burst_count;
+       __le32 reserved[4];
+} __attribute__ ((packed));
+
+struct iwl39_statistics_div {
+       __le32 tx_on_a;
+       __le32 tx_on_b;
+       __le32 exec_time;
+       __le32 probe_time;
+} __attribute__ ((packed));
+
+struct iwl39_statistics_general {
+       __le32 temperature;
+       struct statistics_dbg dbg;
+       __le32 sleep_time;
+       __le32 slots_out;
+       __le32 slots_idle;
+       __le32 ttl_timestamp;
+       struct iwl39_statistics_div div;
+} __attribute__ ((packed));
+
 struct statistics_rx_phy {
        __le32 ina_cnt;
        __le32 fina_cnt;
@@ -2493,11 +2921,6 @@ struct statistics_tx {
        struct statistics_tx_non_phy_agg agg;
 } __attribute__ ((packed));
 
-struct statistics_dbg {
-       __le32 burst_check;
-       __le32 burst_count;
-       __le32 reserved[4];
-} __attribute__ ((packed));
 
 struct statistics_div {
        __le32 tx_on_a;
@@ -2561,6 +2984,14 @@ struct iwl_statistics_cmd {
  */
 #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 iwl39_statistics_rx rx;
+       struct iwl39_statistics_tx tx;
+       struct iwl39_statistics_general general;
+} __attribute__ ((packed));
+
 struct iwl_notif_statistics {
        __le32 flag;
        struct statistics_rx rx;
@@ -3012,6 +3443,10 @@ struct iwl_rx_packet {
        __le32 len;
        struct iwl_cmd_header hdr;
        union {
+               struct iwl3945_rx_frame rx_frame;
+               struct iwl3945_tx_resp tx_resp;
+               struct iwl3945_beacon_notif beacon_status;
+
                struct iwl_alive_resp alive_frame;
                struct iwl_spectrum_notification spectrum_notif;
                struct iwl_csa_notification csa_notif;
@@ -3029,6 +3464,6 @@ struct iwl_rx_packet {
        } u;
 } __attribute__ ((packed));
 
-int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon);
+int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
 
 #endif                         /* __iwl_commands_h__ */
index 73d7973707eb023243dccc545a9bc0f29570e291..21f386568c9c1957e38e3afb6c8410a96d122b52 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -170,7 +170,8 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
        struct ieee80211_hw *hw =
                ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
        if (hw == NULL) {
-               IWL_ERROR("Can not allocate network device\n");
+               printk(KERN_ERR "%s: Can not allocate network device\n",
+                      cfg->name);
                goto out;
        }
 
@@ -210,7 +211,7 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
        if (!rxq->bd) {
                ret = iwl_rx_queue_alloc(priv);
                if (ret) {
-                       IWL_ERROR("Unable to initialize Rx queue\n");
+                       IWL_ERR(priv, "Unable to initialize Rx queue\n");
                        return -ENOMEM;
                }
        } else
@@ -405,7 +406,7 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv,
 /**
  * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
  */
-static int iwlcore_init_geos(struct iwl_priv *priv)
+int iwlcore_init_geos(struct iwl_priv *priv)
 {
        struct iwl_channel_info *ch;
        struct ieee80211_supported_band *sband;
@@ -457,8 +458,6 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
        priv->ieee_channels = channels;
        priv->ieee_rates = rates;
 
-       iwlcore_init_hw_rates(priv, rates);
-
        for (i = 0;  i < priv->channel_count; i++) {
                ch = &priv->channel_info[i];
 
@@ -510,33 +509,33 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
 
        if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
             priv->cfg->sku & IWL_SKU_A) {
-               printk(KERN_INFO DRV_NAME
-                      ": Incorrectly detected BG card as ABG.  Please send "
-                      "your PCI ID 0x%04X:0x%04X to maintainer.\n",
-                      priv->pci_dev->device, priv->pci_dev->subsystem_device);
+               IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
+                       "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
+                          priv->pci_dev->device,
+                          priv->pci_dev->subsystem_device);
                priv->cfg->sku &= ~IWL_SKU_A;
        }
 
-       printk(KERN_INFO DRV_NAME
-              ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-              priv->bands[IEEE80211_BAND_2GHZ].n_channels,
-              priv->bands[IEEE80211_BAND_5GHZ].n_channels);
-
+       IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+                  priv->bands[IEEE80211_BAND_2GHZ].n_channels,
+                  priv->bands[IEEE80211_BAND_5GHZ].n_channels);
 
        set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 
        return 0;
 }
+EXPORT_SYMBOL(iwlcore_init_geos);
 
 /*
  * iwlcore_free_geos - undo allocations in iwlcore_init_geos
  */
-static void iwlcore_free_geos(struct iwl_priv *priv)
+void iwlcore_free_geos(struct iwl_priv *priv)
 {
        kfree(priv->ieee_channels);
        kfree(priv->ieee_rates);
        clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
+EXPORT_SYMBOL(iwlcore_free_geos);
 
 static bool is_single_rx_stream(struct iwl_priv *priv)
 {
@@ -679,7 +678,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("invalid mimo ps mode %d\n",
+               IWL_ERR(priv, "invalid mimo ps mode %d\n",
                           priv->current_ht_config.sm_ps);
                WARN_ON(1);
                idle_cnt = -1;
@@ -699,6 +698,18 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
        return res;
 }
 
+/**
+ * iwl_is_monitor_mode - Determine if interface in monitor mode
+ *
+ * priv->iw_mode is set in add_interface, but add_interface is
+ * never called for monitor mode. The only way mac80211 informs us about
+ * monitor mode is through configuring filters (call to configure_filter).
+ */
+static bool iwl_is_monitor_mode(struct iwl_priv *priv)
+{
+       return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK);
+}
+
 /**
  * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
  *
@@ -742,6 +753,19 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
        rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
        rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
 
+       /* copied from 'iwl_bg_request_scan()' */
+       /* Force use of chains B and C (0x6) for Rx for 4965
+        * Avoid A (0x1) because of its off-channel reception on A-band.
+        * MIMO is not used here, but value is required */
+       if (iwl_is_monitor_mode(priv) &&
+           !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) &&
+           ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) {
+               rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS;
+               rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS;
+               rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+               rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+       }
+
        priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
 
        if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
@@ -806,12 +830,13 @@ int iwl_setup_mac(struct iwl_priv *priv)
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
                    IEEE80211_HW_NOISE_DBM |
-                   IEEE80211_HW_AMPDU_AGGREGATION;
+                   IEEE80211_HW_AMPDU_AGGREGATION |
+                   IEEE80211_HW_SUPPORTS_PS;
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->fw_handles_regulatory = true;
+       hw->wiphy->custom_regulatory = true;
 
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
@@ -831,7 +856,7 @@ int iwl_setup_mac(struct iwl_priv *priv)
 
        ret = ieee80211_register_hw(priv->hw);
        if (ret) {
-               IWL_ERROR("Failed to register hw (error %d)\n", ret);
+               IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
                return ret;
        }
        priv->mac80211_registered = 1;
@@ -863,7 +888,6 @@ int iwl_init_drv(struct iwl_priv *priv)
 {
        int ret;
 
-       priv->retry_rate = 1;
        priv->ibss_beacon = NULL;
 
        spin_lock_init(&priv->lock);
@@ -903,15 +927,16 @@ int iwl_init_drv(struct iwl_priv *priv)
 
        ret = iwl_init_channel_map(priv);
        if (ret) {
-               IWL_ERROR("initializing regulatory failed: %d\n", ret);
+               IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
                goto err;
        }
 
        ret = iwlcore_init_geos(priv);
        if (ret) {
-               IWL_ERROR("initializing geos failed: %d\n", ret);
+               IWL_ERR(priv, "initializing geos failed: %d\n", ret);
                goto err_free_channel_map;
        }
+       iwlcore_init_hw_rates(priv, priv->ieee_rates);
 
        return 0;
 
@@ -926,13 +951,13 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
        int ret = 0;
        if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
-               IWL_WARNING("Requested user TXPOWER %d below limit.\n",
+               IWL_WARN(priv, "Requested user TXPOWER %d below limit.\n",
                            priv->tx_power_user_lmt);
                return -EINVAL;
        }
 
        if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) {
-               IWL_WARNING("Requested user TXPOWER %d above limit.\n",
+               IWL_WARN(priv, "Requested user TXPOWER %d above limit.\n",
                            priv->tx_power_user_lmt);
                return -EINVAL;
        }
@@ -982,6 +1007,21 @@ void iwl_enable_interrupts(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_enable_interrupts);
 
+int iwl_send_bt_config(struct iwl_priv *priv)
+{
+       struct iwl_bt_cmd bt_cmd = {
+               .flags = 3,
+               .lead_time = 0xAA,
+               .max_kill = 1,
+               .kill_ack_mask = 0,
+               .kill_cts_mask = 0,
+       };
+
+       return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+                               sizeof(struct iwl_bt_cmd), &bt_cmd);
+}
+EXPORT_SYMBOL(iwl_send_bt_config);
+
 int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
 {
        u32 stat_flags = 0;
@@ -1018,7 +1058,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
                /* NOTE: Use the debugless read so we don't flood kernel log
                 * if IWL_DL_IO is set */
                iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                       i + RTC_INST_LOWER_BOUND);
+                       i + IWL49_RTC_INST_LOWER_BOUND);
                val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
                if (val != le32_to_cpu(*image)) {
                        ret = -EIO;
@@ -1051,7 +1091,8 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
        if (ret)
                return ret;
 
-       iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+       iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+                          IWL49_RTC_INST_LOWER_BOUND);
 
        errcnt = 0;
        for (; len > 0; len -= sizeof(u32), image++) {
@@ -1060,7 +1101,7 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
                 * if IWL_DL_IO is set */
                val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
                if (val != le32_to_cpu(*image)) {
-                       IWL_ERROR("uCode INST section is invalid at "
+                       IWL_ERR(priv, "uCode INST section is invalid at "
                                  "offset 0x%x, is 0x%x, s/b 0x%x\n",
                                  save_len - len, val, le32_to_cpu(*image));
                        ret = -EIO;
@@ -1116,7 +1157,7 @@ int iwl_verify_ucode(struct iwl_priv *priv)
                return 0;
        }
 
-       IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+       IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
 
        /* Since nothing seems to match, show first several data entries in
         * instruction SRAM, so maybe visual inspection will give a clue.
@@ -1188,21 +1229,22 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
                base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 
        if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
+               IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
                return;
        }
 
        ret = iwl_grab_nic_access(priv);
        if (ret) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
+               IWL_WARN(priv, "Can not read from adapter at this time.\n");
                return;
        }
 
        count = iwl_read_targ_mem(priv, base);
 
        if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-               IWL_ERROR("Start IWL Error Log Dump:\n");
-               IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+               IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+               IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+                       priv->status, count);
        }
 
        desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
@@ -1215,12 +1257,12 @@ 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_ERR(priv, "Desc                               Time       "
                "data1      data2      line\n");
-       IWL_ERROR("%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+       IWL_ERR(priv, "%-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,
+       IWL_ERR(priv, "blink1  blink2  ilink1  ilink2\n");
+       IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
                ilink1, ilink2);
 
        iwl_release_nic_access(priv);
@@ -1266,11 +1308,11 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
                ptr += sizeof(u32);
                if (mode == 0) {
                        /* data, ev */
-                       IWL_ERROR("EVT_LOG:0x%08x:%04u\n", time, ev);
+                       IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
                } else {
                        data = iwl_read_targ_mem(priv, ptr);
                        ptr += sizeof(u32);
-                       IWL_ERROR("EVT_LOGT:%010u:0x%08x:%04u\n",
+                       IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
                                        time, data, ev);
                }
        }
@@ -1292,13 +1334,13 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
                base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
 
        if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+               IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
                return;
        }
 
        ret = iwl_grab_nic_access(priv);
        if (ret) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
+               IWL_WARN(priv, "Can not read from adapter at this time.\n");
                return;
        }
 
@@ -1312,12 +1354,12 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
 
        /* bail out if nothing in log */
        if (size == 0) {
-               IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
+               IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
                iwl_release_nic_access(priv);
                return;
        }
 
-       IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
+       IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
                        size, num_wraps);
 
        /* if uCode has wrapped back to top of log, start at the oldest entry,
@@ -1349,7 +1391,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
        ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
                               sizeof(cmd), &cmd);
        if (ret)
-               IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n");
+               IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
        else
                IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded, "
                        "critical temperature is %d\n",
@@ -1368,7 +1410,7 @@ EXPORT_SYMBOL(iwl_rf_kill_ct_config);
  * When in the 'halt' state, the card is shut down and must be fully
  * restarted to come back on.
  */
-static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
 {
        struct iwl_host_cmd cmd = {
                .id = REPLY_CARD_STATE_CMD,
@@ -1379,6 +1421,7 @@ static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
 
        return iwl_send_cmd(priv, &cmd);
 }
+EXPORT_SYMBOL(iwl_send_card_state);
 
 void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
 {
@@ -1463,3 +1506,39 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
        return 1;
 }
 EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
+
+void iwl_bg_rf_kill(struct work_struct *work)
+{
+       struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+
+       wake_up_interruptible(&priv->wait_command_queue);
+
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+               return;
+
+       mutex_lock(&priv->mutex);
+
+       if (!iwl_is_rfkill(priv)) {
+               IWL_DEBUG(IWL_DL_RF_KILL,
+                         "HW and/or SW RF Kill no longer active, restarting "
+                         "device\n");
+               if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
+                   test_bit(STATUS_ALIVE, &priv->status))
+                       queue_work(priv->workqueue, &priv->restart);
+       } else {
+               /* make sure mac80211 stop sending Tx frame */
+               if (priv->mac80211_registered)
+                       ieee80211_stop_queues(priv->hw);
+
+               if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
+                       IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+                                         "disabled by SW switch\n");
+               else
+                       IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
+                                   "Kill switch must be turned off for "
+                                   "wireless networking to work.\n");
+       }
+       mutex_unlock(&priv->mutex);
+       iwl_rfkill_set_hw_state(priv);
+}
+EXPORT_SYMBOL(iwl_bg_rf_kill);
index 7c3a20a986bbd3567a6ed7c9102206e0d81e9aa1..3c6a4b0c2c3b8aad3e72423db594d234497723d5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@ struct iwl_cmd;
 
 
 #define IWLWIFI_VERSION "1.3.27k"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2008 Intel Corporation"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2009 Intel Corporation"
 #define DRV_AUTHOR     "<ilw@linux.intel.com>"
 
 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
@@ -110,6 +110,14 @@ struct iwl_lib_ops {
        void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv,
                                       struct iwl_tx_queue *txq);
        void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
+       int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
+                                    struct iwl_tx_queue *txq,
+                                    dma_addr_t addr,
+                                    u16 len, u8 reset, u8 pad);
+       void (*txq_free_tfd)(struct iwl_priv *priv,
+                            struct iwl_tx_queue *txq);
+       int (*txq_init)(struct iwl_priv *priv,
+                       struct iwl_tx_queue *txq);
        /* aggregations */
        int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo,
                              int sta_id, int tid, u16 ssn_idx);
@@ -252,9 +260,18 @@ void iwl_rx_statistics(struct iwl_priv *priv,
 * TX
 ******************************************************/
 int iwl_txq_ctx_reset(struct iwl_priv *priv);
+void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+                                struct iwl_tx_queue *txq,
+                                dma_addr_t addr, u16 len, u8 reset, u8 pad);
 int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
 void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
+int iwl_hw_tx_queue_init(struct iwl_priv *priv,
+                        struct iwl_tx_queue *txq);
 int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+                     int slots_num, u32 txq_id);
+void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
 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);
@@ -267,7 +284,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
  * RF -Kill - here and not in iwl-rfkill.h to be available when
  * RF-kill subsystem is not compiled.
  ****************************************************/
-void iwl_rf_kill(struct iwl_priv *priv);
+void iwl_bg_rf_kill(struct work_struct *work);
 void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
 int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
 
@@ -306,8 +323,29 @@ void iwl_init_scan_params(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
 int iwl_scan_initiate(struct iwl_priv *priv);
+u16 iwl_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band,
+                      struct ieee80211_mgmt *frame, int left);
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
+u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
+                             enum ieee80211_band band,
+                             u8 n_probes);
+u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
+                              enum ieee80211_band band);
+void iwl_bg_scan_check(struct work_struct *data);
+void iwl_bg_abort_scan(struct work_struct *work);
+void iwl_bg_scan_completed(struct work_struct *work);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
+int iwl_send_scan_abort(struct iwl_priv *priv);
+
+/* For faster active scanning, scan will move to the next channel if fewer than
+ * PLCP_QUIET_THRESH packets are heard on this channel within
+ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
+ * time if it's a quiet channel (nothing responded to our probe, and there's
+ * no other traffic).
+ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
+#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(10)  /* msec */
+#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)  /* packets */
+
 
 /*******************************************************************************
  * Calibrations - implemented in iwl-calib.c
@@ -342,6 +380,9 @@ 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);
 
+int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
+                       u8 meta_flag);
+
 /*****************************************************
  * PCI                                              *
  *****************************************************/
@@ -354,6 +395,11 @@ void iwl_enable_interrupts(struct iwl_priv *priv);
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 void iwl_dump_nic_event_log(struct iwl_priv *priv);
 
+/*****************************************************
+*  GEOS
+******************************************************/
+int iwlcore_init_geos(struct iwl_priv *priv);
+void iwlcore_free_geos(struct iwl_priv *priv);
 
 /*************** DRIVER STATUS FUNCTIONS   *****/
 
@@ -422,6 +468,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
 }
 
 extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
+extern int iwl_send_bt_config(struct iwl_priv *priv);
 extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
 extern int iwl_verify_ucode(struct iwl_priv *priv);
 extern int iwl_send_lq_cmd(struct iwl_priv *priv,
index f34ede44ed109604d0463fac8a39d0a2ae9b483b..74d3d43fa67d66705669e751c7127f1d07127be8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 56c13b458de7fc7571298591ec3d2eb2b20bfc27..7192d3249caf2f91697cf96168faedcb0a873336 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project.
  *
 #ifndef __iwl_debug_h__
 #define __iwl_debug_h__
 
+struct iwl_priv;
+
+#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+
 #ifdef CONFIG_IWLWIFI_DEBUG
-#define IWL_DEBUG(level, fmt, args...) \
-do { if (priv->debug_level & (level)) \
-  dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
-        in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
+#define IWL_DEBUG(level, fmt, args...)                                     \
+do {                                                                       \
+       if (priv->debug_level & (level))                                    \
+               dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
+                          in_interrupt() ? 'I' : 'U', __func__ , ## args); \
+} while (0)
 
-#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-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_DEBUG_LIMIT(level, fmt, args...)                               \
+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 {                                                                   \
@@ -61,6 +72,7 @@ struct iwl_debugfs {
                struct dentry *file_tx_statistics;
                struct dentry *file_log_event;
                struct dentry *file_channels;
+               struct dentry *file_status;
        } dbgfs_data_files;
        struct dir_rf_files {
                struct dentry *file_disable_sensitivity;
@@ -117,84 +129,82 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
  * when CONFIG_IWLWIFI_DEBUG=y.
  */
 
+/* 0x0000000F - 0x00000001 */
 #define IWL_DL_INFO            (1 << 0)
 #define IWL_DL_MAC80211                (1 << 1)
 #define IWL_DL_HCMD            (1 << 2)
 #define IWL_DL_STATE           (1 << 3)
+/* 0x000000F0 - 0x00000010 */
 #define IWL_DL_MACDUMP         (1 << 4)
 #define IWL_DL_HCMD_DUMP       (1 << 5)
-#define IWL_DL_RADIO         (1 << 7)
-#define IWL_DL_POWER         (1 << 8)
-#define IWL_DL_TEMP          (1 << 9)
-
-#define IWL_DL_NOTIF         (1 << 10)
-#define IWL_DL_SCAN          (1 << 11)
-#define IWL_DL_ASSOC         (1 << 12)
-#define IWL_DL_DROP          (1 << 13)
-
-#define IWL_DL_TXPOWER       (1 << 14)
-
-#define IWL_DL_AP            (1 << 15)
-
-#define IWL_DL_FW            (1 << 16)
-#define IWL_DL_RF_KILL       (1 << 17)
-#define IWL_DL_FW_ERRORS     (1 << 18)
-
-#define IWL_DL_LED           (1 << 19)
-
-#define IWL_DL_RATE          (1 << 20)
-
-#define IWL_DL_CALIB         (1 << 21)
-#define IWL_DL_WEP           (1 << 22)
-#define IWL_DL_TX            (1 << 23)
-#define IWL_DL_RX            (1 << 24)
-#define IWL_DL_ISR           (1 << 25)
-#define IWL_DL_HT            (1 << 26)
-#define IWL_DL_IO            (1 << 27)
-#define IWL_DL_11H           (1 << 28)
-
-#define IWL_DL_STATS         (1 << 29)
-#define IWL_DL_TX_REPLY      (1 << 30)
-#define IWL_DL_QOS           (1 << 31)
-
-#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
-#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
-#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
-
-#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
-#define IWL_DEBUG_MACDUMP(f, a...)     IWL_DEBUG(IWL_DL_MACDUMP, f, ## a)
-#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
-#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
-#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
-#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
-#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
-#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
-#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
-#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a)
-#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a)
-#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
-#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
-#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
-#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
-#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
-#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
-#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
-       IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
-#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_DL_RADIO           (1 << 7)
+/* 0x00000F00 - 0x00000100 */
+#define IWL_DL_POWER           (1 << 8)
+#define IWL_DL_TEMP            (1 << 9)
+#define IWL_DL_NOTIF           (1 << 10)
+#define IWL_DL_SCAN            (1 << 11)
+/* 0x0000F000 - 0x00001000 */
+#define IWL_DL_ASSOC           (1 << 12)
+#define IWL_DL_DROP            (1 << 13)
+#define IWL_DL_TXPOWER         (1 << 14)
+#define IWL_DL_AP              (1 << 15)
+/* 0x000F0000 - 0x00010000 */
+#define IWL_DL_FW              (1 << 16)
+#define IWL_DL_RF_KILL         (1 << 17)
+#define IWL_DL_FW_ERRORS       (1 << 18)
+#define IWL_DL_LED             (1 << 19)
+/* 0x00F00000 - 0x00100000 */
+#define IWL_DL_RATE            (1 << 20)
+#define IWL_DL_CALIB           (1 << 21)
+#define IWL_DL_WEP             (1 << 22)
+#define IWL_DL_TX              (1 << 23)
+/* 0x0F000000 - 0x01000000 */
+#define IWL_DL_RX              (1 << 24)
+#define IWL_DL_ISR             (1 << 25)
+#define IWL_DL_HT              (1 << 26)
+#define IWL_DL_IO              (1 << 27)
+/* 0xF0000000 - 0x10000000 */
+#define IWL_DL_11H             (1 << 28)
+#define IWL_DL_STATS           (1 << 29)
+#define IWL_DL_TX_REPLY                (1 << 30)
+#define IWL_DL_QOS             (1 << 31)
+
+#define IWL_DEBUG_INFO(f, a...)                IWL_DEBUG(IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_MAC80211(f, a...)    IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
+#define IWL_DEBUG_MACDUMP(f, a...)     IWL_DEBUG(IWL_DL_MACDUMP, f, ## a)
+#define IWL_DEBUG_TEMP(f, a...)                IWL_DEBUG(IWL_DL_TEMP, f, ## a)
+#define IWL_DEBUG_SCAN(f, a...)                IWL_DEBUG(IWL_DL_SCAN, f, ## a)
+#define IWL_DEBUG_RX(f, a...)          IWL_DEBUG(IWL_DL_RX, f, ## a)
+#define IWL_DEBUG_TX(f, a...)          IWL_DEBUG(IWL_DL_TX, f, ## a)
+#define IWL_DEBUG_ISR(f, a...)         IWL_DEBUG(IWL_DL_ISR, f, ## a)
+#define IWL_DEBUG_LED(f, a...)         IWL_DEBUG(IWL_DL_LED, f, ## a)
+#define IWL_DEBUG_WEP(f, a...)         IWL_DEBUG(IWL_DL_WEP, f, ## a)
+#define IWL_DEBUG_HC(f, a...)          IWL_DEBUG(IWL_DL_HCMD, f, ## a)
+#define IWL_DEBUG_HC_DUMP(f, a...)     IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a)
+#define IWL_DEBUG_CALIB(f, a...)       IWL_DEBUG(IWL_DL_CALIB, f, ## a)
+#define IWL_DEBUG_FW(f, a...)          IWL_DEBUG(IWL_DL_FW, f, ## a)
+#define IWL_DEBUG_RF_KILL(f, a...)     IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
+#define IWL_DEBUG_DROP(f, a...)                IWL_DEBUG(IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_DROP_LIMIT(f, a...)  IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_AP(f, a...)          IWL_DEBUG(IWL_DL_AP, f, ## a)
+#define IWL_DEBUG_TXPOWER(f, a...)     IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_IO(f, a...)          IWL_DEBUG(IWL_DL_IO, f, ## a)
+#define IWL_DEBUG_RATE(f, a...)                IWL_DEBUG(IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_RATE_LIMIT(f, a...)  IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_NOTIF(f, a...)       IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
+#define IWL_DEBUG_ASSOC(f, a...)       \
+               IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
+               IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_HT(f, a...)          IWL_DEBUG(IWL_DL_HT, f, ## a)
+#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)
-#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, 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)
+#define IWL_DEBUG_11H(f, a...)         IWL_DEBUG(IWL_DL_11H, f, ## a)
 
 #endif
index d5253a179dec6fd35cd37a4d9687046899ca782a..36cfeccfafbcde17933cba2a1e6261a7c6023d04 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
                goto err;                                               \
 } while (0)
 
+#define DEBUGFS_ADD_X32(name, parent, ptr) do {                        \
+       dbgfs->dbgfs_##parent##_files.file_##name =                     \
+       debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr);     \
+       if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)           \
+                       || !dbgfs->dbgfs_##parent##_files.file_##name)  \
+               goto err;                                               \
+} while (0)
+
 #define DEBUGFS_REMOVE(name)  do {              \
        debugfs_remove(name);                   \
        name = NULL;                            \
@@ -164,9 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
        const size_t bufsz = sizeof(buf);
 
-       printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
-       priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
-
        iwl_grab_nic_access(priv);
        for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
                val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
@@ -301,14 +306,14 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
        buf_size = 4 * eeprom_len + 256;
 
        if (eeprom_len % 16) {
-               IWL_ERROR("EEPROM size is not multiple of 16.\n");
+               IWL_ERR(priv, "EEPROM size is not multiple of 16.\n");
                return -ENODATA;
        }
 
        /* 4 characters for byte 0xYY */
        buf = kzalloc(buf_size, GFP_KERNEL);
        if (!buf) {
-               IWL_ERROR("Can not allocate Buffer\n");
+               IWL_ERR(priv, "Can not allocate Buffer\n");
                return -ENOMEM;
        }
 
@@ -365,7 +370,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
 
        buf = kzalloc(bufsz, GFP_KERNEL);
        if (!buf) {
-               IWL_ERROR("Can not allocate Buffer\n");
+               IWL_ERR(priv, "Can not allocate Buffer\n");
                return -ENOMEM;
        }
 
@@ -420,7 +425,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
        return ret;
 }
 
-
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
 DEBUGFS_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(eeprom);
@@ -462,6 +466,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(rx_statistics, data);
        DEBUGFS_ADD_FILE(tx_statistics, data);
        DEBUGFS_ADD_FILE(channels, data);
+       DEBUGFS_ADD_X32(status, data, (u32 *)&priv->status);
        DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
        DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
                         &priv->disable_chain_noise_cal);
@@ -469,7 +474,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        return 0;
 
 err:
-       IWL_ERROR("Can't open the debugfs directory\n");
+       IWL_ERR(priv, "Can't open the debugfs directory\n");
        iwl_dbgfs_unregister(priv);
        return ret;
 }
index 0468fcc1ea98ed58d42e6988cb248a7a162a3589..437c05b9a335186fc44ebc9c1464c01f5babf314 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
 #include <linux/kernel.h>
 #include <net/ieee80211_radiotap.h>
 
-#define DRV_NAME        "iwlagn"
-#include "iwl-rfkill.h"
 #include "iwl-eeprom.h"
-#include "iwl-4965-hw.h"
 #include "iwl-csr.h"
 #include "iwl-prph.h"
+#include "iwl-fh.h"
 #include "iwl-debug.h"
+#include "iwl-rfkill.h"
+#include "iwl-4965-hw.h"
+#include "iwl-3945-hw.h"
+#include "iwl-3945-led.h"
 #include "iwl-led.h"
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
@@ -55,6 +57,16 @@ 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;
+extern struct iwl_cfg iwl6000_2ag_cfg;
+extern struct iwl_cfg iwl6000_2agn_cfg;
+extern struct iwl_cfg iwl6000_3agn_cfg;
+extern struct iwl_cfg iwl6050_2agn_cfg;
+extern struct iwl_cfg iwl6050_3agn_cfg;
+extern struct iwl_cfg iwl100_bgn_cfg;
+
+/* shared structures from iwl-5000.c */
+extern struct iwl_mod_params iwl50_mod_params;
+extern struct iwl_ops iwl5000_ops;
 
 /* CT-KILL constants */
 #define CT_KILL_THRESHOLD      110 /* in Celsius */
@@ -132,9 +144,12 @@ struct iwl_tx_info {
  * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
  * descriptors) and required locking structures.
  */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
 struct iwl_tx_queue {
        struct iwl_queue q;
-       struct iwl_tfd *tfds;
+       void *tfds;
        struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
        struct iwl_tx_info *txb;
        u8 need_update;
@@ -154,6 +169,36 @@ struct iwl4965_channel_tgh_info {
        s64 last_radar_time;
 };
 
+#define IWL4965_MAX_RATE (33)
+
+struct iwl3945_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];
+};
+
+/* current Tx power values to use, one for each rate for each channel.
+ * requested power is limited by:
+ * -- regulatory EEPROM limits for this channel
+ * -- hardware capabilities (clip-powers)
+ * -- spectrum management
+ * -- user preference (e.g. iwconfig)
+ * when requested power is set, base power index must also be set. */
+struct iwl3945_channel_power_info {
+       struct iwl3945_tx_power tpc;    /* actual radio and DSP gain settings */
+       s8 power_table_index;   /* actual (compenst'd) index into gain table */
+       s8 base_power_index;    /* gain index for power at factory temp. */
+       s8 requested_power;     /* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct iwl3945_scan_power_info {
+       struct iwl3945_tx_power tpc;    /* actual radio and DSP gain settings */
+       s8 power_table_index;   /* actual (compenst'd) index into gain table */
+       s8 requested_power;     /* scan pwr (dBm) requested for chnl/rate */
+};
+
 /*
  * One for each channel, holds all channel setup data
  * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
@@ -184,8 +229,15 @@ struct iwl_channel_info {
        s8 fat_scan_power;      /* (dBm) eeprom, direct scans, any rate */
        u8 fat_flags;           /* flags copied from EEPROM */
        u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
-};
 
+       /* Radio/DSP gain settings for each "normal" data Tx rate.
+        * These include, in addition to RF and DSP gain, a few fields for
+        *   remembering/modifying gain settings (indexes). */
+       struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
+
+       /* Radio/DSP gain settings for each scan rate, for directed scans. */
+       struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
+};
 
 #define IWL_TX_FIFO_AC0        0
 #define IWL_TX_FIFO_AC1        1
@@ -370,7 +422,7 @@ struct iwl_hw_key {
        u8 key[32];
 };
 
-union iwl4965_ht_rate_supp {
+union iwl_ht_rate_supp {
        u16 rates;
        struct {
                u8 siso_rate;
@@ -430,6 +482,24 @@ struct iwl_qos_info {
 #define STA_PS_STATUS_WAKE             0
 #define STA_PS_STATUS_SLEEP            1
 
+struct iwl3945_tid_data {
+       u16 seq_number;
+};
+
+struct iwl3945_hw_key {
+       enum ieee80211_key_alg alg;
+       int keylen;
+       u8 key[32];
+};
+
+struct iwl3945_station_entry {
+       struct iwl3945_addsta_cmd sta;
+       struct iwl3945_tid_data tid[MAX_TID_COUNT];
+       u8 used;
+       u8 ps_status;
+       struct iwl3945_hw_key keyinfo;
+};
+
 struct iwl_station_entry {
        struct iwl_addsta_cmd sta;
        struct iwl_tid_data tid[MAX_TID_COUNT];
@@ -497,11 +567,13 @@ struct iwl_sensitivity_ranges {
  * @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
+ * @tfd_size: TFD size
  * @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)
  * @max_rxq_log: Log-base-2 of max_rxq_size
  * @rx_buf_size: Rx buffer size
+ * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
  * @max_stations:
  * @bcast_sta_id:
  * @fat_channel: is 40MHz width possible in band 2.4
@@ -516,6 +588,7 @@ struct iwl_hw_params {
        u8 max_txq_num;
        u8 dma_chnl_num;
        u16 scd_bc_tbls_size;
+       u32 tfd_size;
        u8  tx_chains_num;
        u8  rx_chains_num;
        u8  valid_tx_ant;
@@ -523,6 +596,7 @@ struct iwl_hw_params {
        u16 max_rxq_size;
        u16 max_rxq_log;
        u32 rx_buf_size;
+       u32 rx_wrt_ptr_reg;
        u32 max_pkt_size;
        u8  max_stations;
        u8  bcast_sta_id;
@@ -755,7 +829,7 @@ struct iwl_priv {
 
        struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 
-#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
+#if defined(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT)
        /* spectrum measurement report caching */
        struct iwl_spectrum_notification measure_report;
        u8 measurement_status;
@@ -768,6 +842,10 @@ 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. 3945 only.*/
+       const struct iwl3945_clip_group clip39_groups[5];
+
        /* thermal calibration */
        s32 temperature;        /* degrees Kelvin */
        s32 last_temperature;
@@ -781,7 +859,7 @@ struct iwl_priv {
        unsigned long scan_start;
        unsigned long scan_pass_start;
        unsigned long scan_start_tsf;
-       struct iwl_scan_cmd *scan;
+       void *scan;
        int scan_bands;
        int one_direct_scan;
        u8 direct_ssid_len;
@@ -832,18 +910,25 @@ struct iwl_priv {
         * 4965's initialize alive response contains some calibration data. */
        struct iwl_init_alive_resp card_alive_init;
        struct iwl_alive_resp card_alive;
-#ifdef CONFIG_IWLWIFI_RFKILL
+#if defined(CONFIG_IWLWIFI_RFKILL) || defined(CONFIG_IWL3945_RFKILL)
        struct rfkill *rfkill;
 #endif
 
-#ifdef CONFIG_IWLWIFI_LEDS
-       struct iwl_led led[IWL_LED_TRG_MAX];
+#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS)
        unsigned long last_blink_time;
        u8 last_blink_rate;
        u8 allow_blinking;
        u64 led_tpt;
 #endif
 
+#ifdef CONFIG_IWLWIFI_LEDS
+       struct iwl_led led[IWL_LED_TRG_MAX];
+#endif
+
+#ifdef CONFIG_IWL3945_LEDS
+       struct iwl3945_led led39[IWL_LED_TRG_MAX];
+       unsigned int rxtxpackets;
+#endif
        u16 active_rate;
        u16 active_rate_basic;
 
@@ -893,7 +978,6 @@ struct iwl_priv {
        u16 rates_mask;
 
        u32 power_mode;
-       u32 antenna;
        u8 bssid[ETH_ALEN];
        u16 rts_threshold;
        u8 mac_addr[ETH_ALEN];
@@ -929,6 +1013,10 @@ struct iwl_priv {
        u16 beacon_int;
        struct ieee80211_vif *vif;
 
+       /*Added for 3945 */
+       void *shared_virt;
+       dma_addr_t shared_phys;
+       /*End*/
        struct iwl_hw_params hw_params;
 
 
@@ -960,6 +1048,11 @@ struct iwl_priv {
        struct delayed_work init_alive_start;
        struct delayed_work alive_start;
        struct delayed_work scan_check;
+
+       /*For 3945 only*/
+       struct delayed_work thermal_periodic;
+       struct delayed_work rfkill_poll;
+
        /* TX Power */
        s8 tx_power_user_lmt;
        s8 tx_power_channel_lmt;
@@ -982,6 +1075,22 @@ struct iwl_priv {
        u32 disable_tx_power_cal;
        struct work_struct run_time_calib_work;
        struct timer_list statistics_periodic;
+
+       /*For 3945*/
+#define IWL_DEFAULT_TX_POWER 0x0F
+       /* We declare this const so it can only be
+        * changed via explicit cast within the
+        * routines that actually update the physical
+        * hardware */
+       const struct iwl3945_rxon_cmd active39_rxon;
+       struct iwl3945_rxon_cmd staging39_rxon;
+       struct iwl3945_rxon_cmd recovery39_rxon;
+
+       struct iwl3945_notif_statistics statistics_39;
+
+       struct iwl3945_station_entry stations_39[IWL_STATION_COUNT];
+
+       u32 sta_supp_rates;
 }; /*iwl_priv */
 
 static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
index ce2f47306cea3bce863d7a87de4728d629c5c664..eaa658f9e54c7e425a6deaa46630143f42515344 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -145,7 +145,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
 {
        u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
        if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+               IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
                return -ENOENT;
        }
        return 0;
@@ -223,7 +223,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
 
        ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
        if (ret < 0) {
-               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+               IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
                ret = -ENOENT;
                goto err;
        }
@@ -231,7 +231,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
        /* Make sure driver (instead of uCode) is allowed to read EEPROM */
        ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
        if (ret < 0) {
-               IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
+               IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
                ret = -ENOENT;
                goto err;
        }
@@ -247,7 +247,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
                                          CSR_EEPROM_REG_READ_VALID_MSK,
                                          IWL_EEPROM_ACCESS_TIMEOUT);
                if (ret < 0) {
-                       IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
+                       IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
                        goto done;
                }
                r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
@@ -285,7 +285,7 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
 
        return 0;
 err:
-       IWL_ERROR("Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
+       IWL_ERR(priv, "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;
@@ -450,7 +450,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
        priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
                                     priv->channel_count, GFP_KERNEL);
        if (!priv->channel_info) {
-               IWL_ERROR("Could not allocate channel_info\n");
+               IWL_ERR(priv, "Could not allocate channel_info\n");
                priv->channel_count = 0;
                return -ENOMEM;
        }
@@ -520,7 +520,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
                                             flags & EEPROM_CHANNEL_RADAR))
                                       ? "" : "not ");
 
-                       /* Set the user_txpower_limit to the highest power
+                       /* Set the tx_power_user_lmt to the highest power
                         * supported by any channel */
                        if (eeprom_ch_info[ch].max_power_avg >
                                                priv->tx_power_user_lmt)
@@ -531,6 +531,13 @@ int iwl_init_channel_map(struct iwl_priv *priv)
                }
        }
 
+       /* Check if we do have FAT channels */
+       if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] >=
+           priv->cfg->eeprom_size &&
+           priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] >=
+           priv->cfg->eeprom_size)
+               return 0;
+
        /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
        for (band = 6; band <= 7; band++) {
                enum ieee80211_band ieeeband;
@@ -582,6 +589,7 @@ void iwl_free_channel_map(struct iwl_priv *priv)
        kfree(priv->channel_info);
        priv->channel_count = 0;
 }
+EXPORT_SYMBOL(iwl_free_channel_map);
 
 /**
  * iwl_get_channel_info - Find driver's private channel info
index 603c84bed6300b2e195082377c242f48b4a90930..17fed49f9d9618a8793b2c9f9371dffb62a2e3aa 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -118,6 +118,9 @@ struct iwl_eeprom_channel {
        s8 max_power_avg;       /* max power (dBm) on this chnl, limit 31 */
 } __attribute__ ((packed));
 
+/* 3945 Specific */
+#define EEPROM_3945_EEPROM_VERSION     (0x2f)
+
 /* 4965 has two radio transmitters (and 3 radio receivers) */
 #define EEPROM_TX_POWER_TX_CHAINS      (2)
 
index d7da1986455092ac6b5cfe47582630f436caeffb..65fa8a69fd5ab65fba6322182db3773804d4c3f6 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN   (0x00000002)
 
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+/* Size of one Rx buffer in host DRAM */
+#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */
+#define IWL_RX_BUF_SIZE_4K (4 * 1024)
+#define IWL_RX_BUF_SIZE_8K (8 * 1024)
+
 /**
  * struct iwl_rb_status - reseve buffer status
  *     host memory mapped FH registers
@@ -414,6 +429,7 @@ struct iwl_rb_status {
        __le16 closed_fr_num;
        __le16 finished_rb_num;
        __le16 finished_fr_nam;
+       __le32 __unused; /* 3945 only */
 } __attribute__ ((packed));
 
 
@@ -477,7 +493,6 @@ struct iwl_tfd {
        __le32 __pad;
 } __attribute__ ((packed));
 
-
 /* Keep Warm Size */
 #define IWL_KW_SIZE 0x1000     /* 4k */
 
index 4b35b30e493e8abc82a90aa393d018683fa2359b..65ae2af61c8d365fb8a50c04e896ddf94da10a1e 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
@@ -109,14 +109,14 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
        struct iwl_rx_packet *pkt = NULL;
 
        if (!skb) {
-               IWL_ERROR("Error: Response NULL in %s.\n",
+               IWL_ERR(priv, "Error: Response NULL in %s.\n",
                                get_cmd_string(cmd->hdr.cmd));
                return 1;
        }
 
        pkt = (struct iwl_rx_packet *)skb->data;
        if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from %s (0x%08X)\n",
+               IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
                        get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
                return 1;
        }
@@ -156,7 +156,7 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 
        ret = iwl_enqueue_hcmd(priv, cmd);
        if (ret < 0) {
-               IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
+               IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
                          get_cmd_string(cmd->id), ret);
                return ret;
        }
@@ -174,8 +174,9 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        BUG_ON(cmd->meta.u.callback != NULL);
 
        if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
-               IWL_ERROR("Error sending %s: Already sending a host command\n",
-                         get_cmd_string(cmd->id));
+               IWL_ERR(priv,
+                       "Error sending %s: Already sending a host command\n",
+                       get_cmd_string(cmd->id));
                ret = -EBUSY;
                goto out;
        }
@@ -188,7 +189,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        cmd_idx = iwl_enqueue_hcmd(priv, cmd);
        if (cmd_idx < 0) {
                ret = cmd_idx;
-               IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
+               IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
                          get_cmd_string(cmd->id), ret);
                goto out;
        }
@@ -198,9 +199,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                        HOST_COMPLETE_TIMEOUT);
        if (!ret) {
                if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-                       IWL_ERROR("Error sending %s: time out after %dms.\n",
-                                 get_cmd_string(cmd->id),
-                                 jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+                       IWL_ERR(priv,
+                               "Error sending %s: time out after %dms.\n",
+                               get_cmd_string(cmd->id),
+                               jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
 
                        clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
                        ret = -ETIMEDOUT;
@@ -221,7 +223,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                goto fail;
        }
        if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
-               IWL_ERROR("Error: Response NULL in '%s'\n",
+               IWL_ERR(priv, "Error: Response NULL in '%s'\n",
                          get_cmd_string(cmd->id));
                ret = -EIO;
                goto cancel;
index ca4f638ab9d0e8f4cd7b26712191c5162961d166..fb64d297dd4eb6e2cefdc68f90bdb4a216495c8f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
index 0a92e7431adaa023cc6a6916cdf454406c0ca6fc..7341a2da84310c9ffdd4697c0836552089d497d7 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project.
  *
@@ -165,9 +165,9 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
        ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
                           CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
                           (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-                           CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+                           CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
        if (ret < 0) {
-               IWL_ERROR("MAC is in deep sleep!\n");
+               IWL_ERR(priv, "MAC is in deep sleep!\n");
                return -EIO;
        }
 
@@ -182,7 +182,7 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l,
                                               struct iwl_priv *priv)
 {
        if (atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Grabbing access while already held %s %d.\n", f, l);
+               IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l);
 
        IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
        return _iwl_grab_nic_access(priv);
@@ -207,7 +207,7 @@ static inline void __iwl_release_nic_access(const char *f, u32 l,
                                            struct iwl_priv *priv)
 {
        if (atomic_read(&priv->restrict_refcnt) <= 0)
-               IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l);
+               IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l);
 
        IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
        _iwl_release_nic_access(priv);
@@ -229,7 +229,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l,
 {
        u32 value = _iwl_read_direct32(priv, reg);
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s %d\n", f, l);
+               IWL_ERR(priv, "Nic access not held from %s %d\n", f, l);
        IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
                     f, l);
        return value;
@@ -250,7 +250,7 @@ static void __iwl_write_direct32(const char *f , u32 line,
                                   struct iwl_priv *priv, u32 reg, u32 value)
 {
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s line %d\n", f, line);
+               IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
        _iwl_write_direct32(priv, reg, value);
 }
 #define iwl_write_direct32(priv, reg, value) \
@@ -308,7 +308,7 @@ static inline u32 __iwl_read_prph(const char *f, u32 line,
                                  struct iwl_priv *priv, u32 reg)
 {
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s line %d\n", f, line);
+               IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
        return _iwl_read_prph(priv, reg);
 }
 
@@ -331,7 +331,7 @@ static inline void __iwl_write_prph(const char *f, u32 line,
                                    struct iwl_priv *priv, u32 addr, u32 val)
 {
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s line %d\n", f, line);
+               IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
        _iwl_write_prph(priv, addr, val);
 }
 
@@ -349,7 +349,7 @@ static inline void __iwl_set_bits_prph(const char *f, u32 line,
                                       u32 reg, u32 mask)
 {
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s line %d\n", f, line);
+               IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
 
        _iwl_set_bits_prph(priv, reg, mask);
 }
@@ -367,7 +367,7 @@ static inline void __iwl_set_bits_mask_prph(const char *f, u32 line,
                struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
 {
        if (!atomic_read(&priv->restrict_refcnt))
-               IWL_ERROR("Nic access not held from %s line %d\n", f, line);
+               IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
        _iwl_set_bits_mask_prph(priv, reg, bits, mask);
 }
 #define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
index 11eccd7d268c2946cc13715ee93160314b8fa48a..501cffeff5f26955989f8eebcc9c1fccd837eea6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
@@ -254,7 +254,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
 
        ret = led_classdev_register(device, &led->led_dev);
        if (ret) {
-               IWL_ERROR("Error: failed to register led handler.\n");
+               IWL_ERR(priv, "Error: failed to register led handler.\n");
                return ret;
        }
 
index 021e00bcd1be1af1fa3296875ae5cba2fbe42365..1d798d086695dda11984d326eb457332f490dd01 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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
@@ -30,7 +30,7 @@
 
 struct iwl_priv;
 
-#ifdef CONFIG_IWLWIFI_LEDS
+#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS)
 #include <linux/leds.h>
 
 #define IWL_LED_SOLID 11
@@ -47,7 +47,9 @@ enum led_type {
        IWL_LED_TRG_RADIO,
        IWL_LED_TRG_MAX,
 };
+#endif
 
+#ifdef CONFIG_IWLWIFI_LEDS
 
 struct iwl_led {
        struct iwl_priv *priv;
index 75ca6a542174fd9ef847697b96605ea00403088a..a4634595c59f3819769dc69fef9385e2491704a2 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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.
 #define IWL_POWER_RANGE_1_MAX  (10)
 
 
-#define NOSLP __constant_cpu_to_le16(0), 0, 0
-#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
-#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
-#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
-                                    __constant_cpu_to_le32(X1), \
-                                    __constant_cpu_to_le32(X2), \
-                                    __constant_cpu_to_le32(X3), \
-                                    __constant_cpu_to_le32(X4)}
 
 #define IWL_POWER_ON_BATTERY           IWL_POWER_INDEX_5
 #define IWL_POWER_ON_AC_DISASSOC       IWL_POWER_MODE_CAM
@@ -149,7 +141,7 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
 }
 
 /* initialize to default */
-static int iwl_power_init_handle(struct iwl_priv *priv)
+static void iwl_power_init_handle(struct iwl_priv *priv)
 {
        struct iwl_power_mgr *pow_data;
        int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
@@ -159,7 +151,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
 
        IWL_DEBUG_POWER("Initialize power \n");
 
-       pow_data = &(priv->power_data);
+       pow_data = &priv->power_data;
 
        memset(pow_data, 0, sizeof(*pow_data));
 
@@ -179,26 +171,25 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
                else
                        cmd->flags |= IWL_POWER_PCI_PM_MSK;
        }
-       return 0;
 }
 
 /* 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)
+static int iwl_update_power_cmd(struct iwl_priv *priv,
+                               struct iwl_powertable_cmd *cmd, u16 mode)
 {
-       int ret = 0, i;
-       u8 skip;
-       u32 max_sleep = 0;
        struct iwl_power_vec_entry *range;
-       u8 period = 0;
        struct iwl_power_mgr *pow_data;
+       int i;
+       u32 max_sleep = 0;
+       u8 period;
+       bool skip;
 
        if (mode > IWL_POWER_INDEX_5) {
                IWL_DEBUG_POWER("Error invalid power mode \n");
-               return -1;
+               return -EINVAL;
        }
-       pow_data = &(priv->power_data);
+
+       pow_data = &priv->power_data;
 
        if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX)
                range = &pow_data->pwr_range_0[0];
@@ -212,14 +203,12 @@ static int iwl_update_power_command(struct iwl_priv *priv,
 
        if (period == 0) {
                period = 1;
-               skip = 0;
-       } else
-               skip = range[mode].no_dtim;
-
-       if (skip == 0) {
-               max_sleep = period;
-               cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
+               skip = false;
        } else {
+               skip = !!range[mode].no_dtim;
+       }
+
+       if (skip) {
                __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
                max_sleep = le32_to_cpu(slp_itrvl);
                if (max_sleep == 0xFF)
@@ -227,12 +216,14 @@ static int iwl_update_power_command(struct iwl_priv *priv,
                else if (max_sleep >  period)
                        max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
                cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
+       } else {
+               max_sleep = period;
+               cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
        }
 
-       for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
+       for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
                if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
                        cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
-       }
 
        IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
        IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
@@ -244,7 +235,7 @@ static int iwl_update_power_command(struct iwl_priv *priv,
                        le32_to_cpu(cmd->sleep_interval[3]),
                        le32_to_cpu(cmd->sleep_interval[4]));
 
-       return ret;
+       return 0;
 }
 
 
@@ -295,7 +286,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
                if (final_mode != IWL_POWER_MODE_CAM)
                        set_bit(STATUS_POWER_PMI, &priv->status);
 
-               iwl_update_power_command(priv, &cmd, final_mode);
+               iwl_update_power_cmd(priv, &cmd, final_mode);
                cmd.keep_alive_beacons = 0;
 
                if (final_mode == IWL_POWER_INDEX_5)
@@ -392,13 +383,11 @@ EXPORT_SYMBOL(iwl_power_set_system_mode);
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
-
        iwl_power_init_handle(priv);
        priv->power_data.user_power_setting = IWL_POWER_AUTO;
-       priv->power_data.power_disabled = 0;
        priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO;
-       priv->power_data.is_battery_active = 0;
        priv->power_data.power_disabled = 0;
+       priv->power_data.is_battery_active = 0;
        priv->power_data.critical_power_setting = 0;
 }
 EXPORT_SYMBOL(iwl_power_initialize);
@@ -407,8 +396,8 @@ EXPORT_SYMBOL(iwl_power_initialize);
 int iwl_power_temperature_change(struct iwl_priv *priv)
 {
        int ret = 0;
-       u16 new_critical = priv->power_data.critical_power_setting;
        s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature);
+       u16 new_critical = priv->power_data.critical_power_setting;
 
        if (temperature > IWL_CT_KILL_TEMPERATURE)
                return 0;
index fa098d8975cec38d84161e51a1f5db3a9ea006ad..859b60b5335c2b87f3ce1359b13897834ef792e3 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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.
@@ -42,7 +42,10 @@ enum {
        IWL_POWER_INDEX_5,
        IWL_POWER_AUTO,
        IWL_POWER_MAX = IWL_POWER_AUTO,
+       IWL39_POWER_AC = IWL_POWER_AUTO, /* 0x06 */
        IWL_POWER_AC,
+       IWL39_POWER_BATTERY = IWL_POWER_AC, /* 0x07 */
+       IWL39_POWER_LIMIT = IWL_POWER_AC,
        IWL_POWER_BATTERY,
 };
 
@@ -56,8 +59,21 @@ enum {
 #define IWL_POWER_MASK         0x0F
 #define IWL_POWER_ENABLED      0x10
 
+#define IWL_POWER_RANGE_0  (0)
+#define IWL_POWER_RANGE_1  (1)
+
+#define IWL_POWER_LEVEL(x)     ((x) & IWL_POWER_MASK)
+
 /* Power management (not Tx power) structures */
 
+#define NOSLP __constant_cpu_to_le16(0), 0, 0
+#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
+#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
+#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
+                                    __constant_cpu_to_le32(X1), \
+                                    __constant_cpu_to_le32(X2), \
+                                    __constant_cpu_to_le32(X3), \
+                                    __constant_cpu_to_le32(X4)}
 struct iwl_power_vec_entry {
        struct iwl_powertable_cmd cmd;
        u8 no_dtim;
index b7a5f23351c303c994a835124d5add570bb99ec6..3b9cac3fd216701e3d8b0e8e62f8bbffe1d53ab7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 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
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
index 4b69da30665c3b1bd74c93f0dd516aaf4e89809e..f67d7be10748c37955ff7f314eefde05f5beb837 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -62,7 +62,8 @@ 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 received unexpected RFKILL state %d\n", state);
+               IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
+                       state);
                break;
        }
 out_unlock:
@@ -81,7 +82,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_ERR(priv, "Unable to allocate RFKILL device.\n");
                ret = -ENOMEM;
                goto error;
        }
@@ -97,7 +98,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_ERR(priv, "Unable to register RFKILL: %d\n", ret);
                goto free_rfkill;
        }
 
index 86dc055a2e9400cf684ea212935789309c6ffa60..633dafb4bf1bac7b5126bd742418b7e802767f3e 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 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.
index c5f1aa0feac8c49ecb635e44b7b89e1c98681158..33145207fc15c23fb5419cc8742b0dc159ca243b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -125,9 +125,10 @@ EXPORT_SYMBOL(iwl_rx_queue_space);
  */
 int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
 {
-       u32 reg = 0;
-       int ret = 0;
        unsigned long flags;
+       u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
+       u32 reg;
+       int ret = 0;
 
        spin_lock_irqsave(&q->lock, flags);
 
@@ -149,15 +150,14 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
                        goto exit_unlock;
 
                /* Device expects a multiple of 8 */
-               iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
-                                    q->write & ~0x7);
+               iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write & ~0x7);
                iwl_release_nic_access(priv);
 
        /* Else device is assumed to be awake */
-       } else
+       } else {
                /* Device expects a multiple of 8 */
-               iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
-
+               iwl_write32(priv, rx_wrt_ptr_reg, q->write & ~0x7);
+       }
 
        q->need_update = 0;
 
@@ -262,8 +262,7 @@ void iwl_rx_allocate(struct iwl_priv *priv)
                rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
                                     GFP_KERNEL);
                if (!rxb->skb) {
-                       printk(KERN_CRIT DRV_NAME
-                                  "Can not allocate SKB buffers\n");
+                       IWL_CRIT(priv, "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 */
@@ -895,7 +894,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
                rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
 
        if (!rx_start) {
-               IWL_ERROR("MPDU frame without a PHY data\n");
+               IWL_ERR(priv, "MPDU frame without a PHY data\n");
                return;
        }
        if (include_phy) {
@@ -1021,7 +1020,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
        }
 
        if (!rx_start) {
-               IWL_ERROR("MPDU frame without a PHY data\n");
+               IWL_ERR(priv, "MPDU frame without a PHY data\n");
                return;
        }
 
index 3c803f6922efe0a03c498fe2efc53c78c4db5c50..c282d1d294e6208bb4fa04efe43016d1df743004 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2009 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
 #define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
 #define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
 
-/* For faster active scanning, scan will move to the next channel if fewer than
- * PLCP_QUIET_THRESH packets are heard on this channel within
- * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
- * time if it's a quiet channel (nothing responded to our probe, and there's
- * no other traffic).
- * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
-#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)  /* packets */
-#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(10)  /* msec */
-
 /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
  * Must be set longer than active dwell time.
  * For the most reliable scan, set > AP beacon interval (typically 100msec). */
@@ -63,7 +54,6 @@
 #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))))
 
 
 /**
@@ -119,7 +109,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
 }
 EXPORT_SYMBOL(iwl_scan_cancel_timeout);
 
-static int iwl_send_scan_abort(struct iwl_priv *priv)
+int iwl_send_scan_abort(struct iwl_priv *priv)
 {
        int ret = 0;
        struct iwl_rx_packet *res;
@@ -160,7 +150,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
 
        return ret;
 }
-
+EXPORT_SYMBOL(iwl_send_scan_abort);
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
 static void iwl_rx_reply_scan(struct iwl_priv *priv,
@@ -296,9 +286,9 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
 
-static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
-                                           enum ieee80211_band band,
-                                           u8 n_probes)
+inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
+                                    enum ieee80211_band band,
+                                    u8 n_probes)
 {
        if (band == IEEE80211_BAND_5GHZ)
                return IWL_ACTIVE_DWELL_TIME_52 +
@@ -307,9 +297,10 @@ static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
                return IWL_ACTIVE_DWELL_TIME_24 +
                        IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
+EXPORT_SYMBOL(iwl_get_active_dwell_time);
 
-static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
-                                     enum ieee80211_band band)
+u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
+                              enum ieee80211_band band)
 {
        u16 passive = (band == IEEE80211_BAND_2GHZ) ?
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
@@ -327,6 +318,7 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 
        return passive;
 }
+EXPORT_SYMBOL(iwl_get_passive_dwell_time);
 
 static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                                     enum ieee80211_band band,
@@ -450,7 +442,7 @@ EXPORT_SYMBOL(iwl_scan_initiate);
 
 #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
 
-static void iwl_bg_scan_check(struct work_struct *data)
+void iwl_bg_scan_check(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, scan_check.work);
@@ -470,6 +462,8 @@ static void iwl_bg_scan_check(struct work_struct *data)
        }
        mutex_unlock(&priv->mutex);
 }
+EXPORT_SYMBOL(iwl_bg_scan_check);
+
 /**
  * iwl_supported_rate_to_ie - fill in the supported rate in IE field
  *
@@ -527,10 +521,10 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
  * iwl_fill_probe_req - fill in all required fields and IE for probe request
  */
 
-static u16 iwl_fill_probe_req(struct iwl_priv *priv,
-                                 enum ieee80211_band band,
-                                 struct ieee80211_mgmt *frame,
-                                 int left)
+u16 iwl_fill_probe_req(struct iwl_priv *priv,
+                      enum ieee80211_band band,
+                      struct ieee80211_mgmt *frame,
+                      int left)
 {
        int len = 0;
        u8 *pos = NULL;
@@ -624,6 +618,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
 
        return (u16)len;
 }
+EXPORT_SYMBOL(iwl_fill_probe_req);
 
 static void iwl_bg_request_scan(struct work_struct *data)
 {
@@ -650,7 +645,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
        mutex_lock(&priv->mutex);
 
        if (!iwl_is_ready(priv)) {
-               IWL_WARNING("request scan called when driver not ready.\n");
+               IWL_WARN(priv, "request scan called when driver not ready.\n");
                goto done;
        }
 
@@ -773,7 +768,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
                if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
                        rx_chain = 0x6;
        } else {
-               IWL_WARNING("Invalid scan band count\n");
+               IWL_WARN(priv, "Invalid scan band count\n");
                goto done;
        }
 
@@ -839,7 +834,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
-static void iwl_bg_abort_scan(struct work_struct *work)
+void iwl_bg_abort_scan(struct work_struct *work)
 {
        struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
 
@@ -853,8 +848,9 @@ static void iwl_bg_abort_scan(struct work_struct *work)
 
        mutex_unlock(&priv->mutex);
 }
+EXPORT_SYMBOL(iwl_bg_abort_scan);
 
-static void iwl_bg_scan_completed(struct work_struct *work)
+void iwl_bg_scan_completed(struct work_struct *work)
 {
        struct iwl_priv *priv =
            container_of(work, struct iwl_priv, scan_completed);
@@ -872,7 +868,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
        iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
        mutex_unlock(&priv->mutex);
 }
-
+EXPORT_SYMBOL(iwl_bg_scan_completed);
 
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
 {
index 836c3c80b69ebbe712a9bd09c6cb3596eb2c1d95..aba1ef22fc6129d23bf5ac1dc8bf2116c92fd8fa 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -146,7 +146,7 @@ static int iwl_get_measurement(struct iwl_priv *priv,
 
        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");
+               IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
                rc = -EIO;
        }
 
index b7d7943e476b055ad7d6204b0fbd8f3ad7e342e5..a77c1e6190623bd536e287a2a762b5b464ee0ffa 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ieee80211 subsystem header files.
  *
index 412f66bac1afc0f4024169b719f179405345a86e..9bba98e5e056d24f1474e7dd83d1533a7430f5b4 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -86,8 +86,10 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 
        spin_lock_irqsave(&priv->sta_lock, flags);
 
-       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
-               IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
+       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+           !(priv->stations_39[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+               IWL_ERR(priv, "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: %pM\n",
@@ -105,13 +107,13 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
        u8 sta_id = addsta->sta.sta_id;
 
        if (!skb) {
-               IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
+               IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
                return 1;
        }
 
        res = (struct iwl_rx_packet *)skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
+               IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
                          res->hdr.flags);
                return 1;
        }
@@ -130,7 +132,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
        return 1;
 }
 
-static int iwl_send_add_sta(struct iwl_priv *priv,
+int iwl_send_add_sta(struct iwl_priv *priv,
                     struct iwl_addsta_cmd *sta, u8 flags)
 {
        struct iwl_rx_packet *res = NULL;
@@ -155,7 +157,7 @@ static int iwl_send_add_sta(struct iwl_priv *priv,
 
        res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
+               IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
                          res->hdr.flags);
                ret = -EIO;
        }
@@ -168,7 +170,7 @@ static int iwl_send_add_sta(struct iwl_priv *priv,
                        break;
                default:
                        ret = -EIO;
-                       IWL_WARNING("REPLY_ADD_STA failed\n");
+                       IWL_WARN(priv, "REPLY_ADD_STA failed\n");
                        break;
                }
        }
@@ -178,6 +180,7 @@ static 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_sta_ht_cap *sta_ht_inf)
@@ -204,7 +207,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
        case WLAN_HT_CAP_SM_PS_DISABLED:
                break;
        default:
-               IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode);
+               IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
                break;
        }
 
@@ -307,7 +310,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
 
        /* Ucode must be active and driver must be non active */
        if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE)
-               IWL_ERROR("removed non active STA %d\n", sta_id);
+               IWL_ERR(priv, "removed non active STA %d\n", sta_id);
 
        priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
 
@@ -324,13 +327,13 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
        const char *addr = rm_sta->addr;
 
        if (!skb) {
-               IWL_ERROR("Error: Response NULL in REPLY_REMOVE_STA.\n");
+               IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
                return 1;
        }
 
        res = (struct iwl_rx_packet *)skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+               IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
                res->hdr.flags);
                return 1;
        }
@@ -340,7 +343,7 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
                iwl_sta_ucode_deactivate(priv, addr);
                break;
        default:
-               IWL_ERROR("REPLY_REMOVE_STA failed\n");
+               IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
                break;
        }
 
@@ -378,7 +381,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
 
        res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+               IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
                          res->hdr.flags);
                ret = -EIO;
        }
@@ -391,7 +394,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
                        break;
                default:
                        ret = -EIO;
-                       IWL_ERROR("REPLY_REMOVE_STA failed\n");
+                       IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
                        break;
                }
        }
@@ -433,13 +436,13 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
                sta_id, addr);
 
        if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-               IWL_ERROR("Removing %pM but non DRIVER active\n",
+               IWL_ERR(priv, "Removing %pM but non DRIVER active\n",
                                addr);
                goto out;
        }
 
        if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
-               IWL_ERROR("Removing %pM but non UCODE active\n",
+               IWL_ERR(priv, "Removing %pM but non UCODE active\n",
                                addr);
                goto out;
        }
@@ -475,7 +478,7 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
        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");
+               IWL_ERR(priv, "Couldn't clear the station table\n");
 
        priv->num_stations = 0;
        memset(priv->stations, 0, sizeof(priv->stations));
@@ -548,7 +551,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
        spin_lock_irqsave(&priv->sta_lock, flags);
 
        if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
-               IWL_ERROR("index %d not used in uCode key table.\n",
+               IWL_ERR(priv, "index %d not used in uCode key table.\n",
                          keyconf->keyidx);
 
        priv->default_wep_key--;
@@ -582,7 +585,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
        priv->default_wep_key++;
 
        if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
-               IWL_ERROR("index %d already used in uCode key table.\n",
+               IWL_ERR(priv, "index %d already used in uCode key table.\n",
                        keyconf->keyidx);
 
        priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
@@ -638,7 +641,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
         * in uCode. */
 
        WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for new kew");
+               "no space for a new key");
 
        priv->stations[sta_id].sta.key.key_flags = key_flags;
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
@@ -686,7 +689,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
         * in uCode. */
 
        WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for new kew");
+               "no space for a new key");
 
        priv->stations[sta_id].sta.key.key_flags = key_flags;
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
@@ -722,7 +725,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
         * in uCode. */
 
        WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for new kew");
+               "no space for a new key");
 
        /* This copy is acutally not needed: we get the key with each TX */
        memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
@@ -812,7 +815,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        }
 
        if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
-               IWL_WARNING("Removing wrong key %d 0x%x\n",
+               IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
                            keyconf->keyidx, key_flags);
                spin_unlock_irqrestore(&priv->sta_lock, flags);
                return 0;
@@ -820,7 +823,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 
        if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
                &priv->ucode_key_table))
-               IWL_ERROR("index %d not used in uCode key table.\n",
+               IWL_ERR(priv, "index %d not used in uCode key table.\n",
                        priv->stations[sta_id].sta.key.key_offset);
        memset(&priv->stations[sta_id].keyinfo, 0,
                                        sizeof(struct iwl_hw_key));
@@ -857,7 +860,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
                ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
                break;
        default:
-               IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
+               IWL_ERR(priv,
+                       "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
                ret = -EINVAL;
        }
 
@@ -1069,7 +1073,8 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
                return priv->hw_params.bcast_sta_id;
 
        default:
-               IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
+               IWL_WARN(priv, "Unknown mode of operation: %d\n",
+                       priv->iw_mode);
                return priv->hw_params.bcast_sta_id;
        }
 }
index 9bb7cefc1f3cd2fc2157831c7958024ef5c7214e..97f6169007f8f282f75f082f2e03a70507b98db5 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -56,6 +56,8 @@ 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);
 int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
+int iwl_send_add_sta(struct iwl_priv *priv,
+                    struct iwl_addsta_cmd *sta, u8 flags);
 u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
                        int is_ap, u8 flags,
                        struct ieee80211_sta_ht_cap *ht_info);
index b0ee86c6268501754651206d88b87fdcfceb2401..7d2b6e11f73e0d21c280264c1d0866abe9954458 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
@@ -76,116 +76,6 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
        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 void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       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 num_tbs;
-
-       tfd = &tfd_tmp[index];
-
-       /* Sanity check on number of chunks */
-       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;
-       }
-
-       /* 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);
-
-       /* 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);
-
-               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;
-               }
-       }
-}
-
-static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                       struct iwl_tfd *tfd,
-                                       dma_addr_t addr, u16 len)
-{
-
-       u32 num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-       /* Each TFD can point to a maximum 20 Tx buffers */
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERROR("Error can not send more than %d chunks\n",
-                         IWL_NUM_OF_TBS);
-               return -EINVAL;
-       }
-
-       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_tfd_set_tb(tfd, num_tbs, addr, len);
-
-       return 0;
-}
-
 /**
  * iwl_txq_update_write_ptr - Send new write index to hardware
  */
@@ -241,7 +131,7 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr);
  * Free all buffers.
  * 0-fill, but do not free "txq" descriptor structure.
  */
-static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
+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;
@@ -254,7 +144,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
        /* first, empty all BD's */
        for (; q->write_ptr != q->read_ptr;
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
-               iwl_hw_txq_free_tfd(priv, txq);
+               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
 
        len = sizeof(struct iwl_cmd) * q->n_window;
 
@@ -264,7 +154,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
 
        /* De-alloc circular buffer of TFDs */
        if (txq->q.n_bd)
-               pci_free_consistent(dev, sizeof(struct iwl_tfd) *
+               pci_free_consistent(dev, priv->hw_params.tfd_size *
                                    txq->q.n_bd, txq->tfds, txq->q.dma_addr);
 
        /* De-alloc array of per-TFD driver data */
@@ -274,7 +164,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
        /* 0-fill queue descriptor structure */
        memset(txq, 0, sizeof(*txq));
 }
-
+EXPORT_SYMBOL(iwl_tx_queue_free);
 
 /**
  * iwl_cmd_queue_free - Deallocate DMA queue.
@@ -388,6 +278,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
                              struct iwl_tx_queue *txq, u32 id)
 {
        struct pci_dev *dev = priv->pci_dev;
+       size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
 
        /* Driver private data, only for Tx (not command) queues,
         * not shared with device. */
@@ -395,22 +286,20 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
                txq->txb = kmalloc(sizeof(txq->txb[0]) *
                                   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
                if (!txq->txb) {
-                       IWL_ERROR("kmalloc for auxiliary BD "
+                       IWL_ERR(priv, "kmalloc for auxiliary BD "
                                  "structures failed\n");
                        goto error;
                }
-       } else
+       } else {
                txq->txb = NULL;
+       }
 
        /* Circular buffer of transmit frame descriptors (TFDs),
         * shared with device */
-       txq->tfds = pci_alloc_consistent(dev,
-                       sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX,
-                       &txq->q.dma_addr);
+       txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr);
 
        if (!txq->tfds) {
-               IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
-                         sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX);
+               IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
                goto error;
        }
        txq->q.id = id;
@@ -424,42 +313,11 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
        return -ENOMEM;
 }
 
-/*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
-                               struct iwl_tx_queue *txq)
-{
-       int ret;
-       unsigned long flags;
-       int txq_id = txq->q.id;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       ret = iwl_grab_nic_access(priv);
-       if (ret) {
-               spin_unlock_irqrestore(&priv->lock, flags);
-               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);
-
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
-}
-
 /**
  * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
  */
-static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-                            int slots_num, u32 txq_id)
+int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+                     int slots_num, u32 txq_id)
 {
        int i, len;
        int ret;
@@ -501,7 +359,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
        iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
 
        /* Tell device where to find queue */
-       iwl_hw_tx_queue_init(priv, txq);
+       priv->cfg->ops->lib->txq_init(priv, txq);
 
        return 0;
 err:
@@ -516,6 +374,8 @@ err:
        }
        return -ENOMEM;
 }
+EXPORT_SYMBOL(iwl_tx_queue_init);
+
 /**
  * iwl_hw_txq_ctx_free - Free TXQ Context
  *
@@ -557,13 +417,13 @@ int iwl_txq_ctx_reset(struct iwl_priv *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");
+               IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
                goto error_bc_tbls;
        }
        /* Alloc keep-warm buffer */
        ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
        if (ret) {
-               IWL_ERROR("Keep Warm allocation failed\n");
+               IWL_ERR(priv, "Keep Warm allocation failed\n");
                goto error_kw;
        }
        spin_lock_irqsave(&priv->lock, flags);
@@ -589,7 +449,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
                ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
                                       txq_id);
                if (ret) {
-                       IWL_ERROR("Tx %d queue init failed\n", txq_id);
+                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
                        goto error;
                }
        }
@@ -802,7 +662,7 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
                break;
 
        default:
-               printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg);
+               IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg);
                break;
        }
 }
@@ -822,7 +682,6 @@ 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 *tfd;
        struct iwl_tx_queue *txq;
        struct iwl_queue *q;
        struct iwl_cmd *out_cmd;
@@ -850,7 +709,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) ==
             IWL_INVALID_RATE) {
-               IWL_ERROR("ERROR: No TX rate available.\n");
+               IWL_ERR(priv, "ERROR: No TX rate available.\n");
                goto drop_unlock;
        }
 
@@ -913,10 +772,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       /* Set up first empty TFD within this queue's circular TFD buffer */
-       tfd = &txq->tfds[q->write_ptr];
-       memset(tfd, 0, sizeof(*tfd));
-
        /* 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;
@@ -970,7 +825,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        /* 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);
+       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                  txcmd_phys, len, 1, 0);
 
        if (info->control.hw_key)
                iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
@@ -981,7 +837,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (len) {
                phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
                                           len, PCI_DMA_TODEVICE);
-               iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
+               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                          phys_addr, len,
+                                                          0, 0);
        }
 
        /* Tell NIC about any 2-byte padding after MAC header */
@@ -1063,7 +921,6 @@ 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 *tfd;
        struct iwl_cmd *out_cmd;
        dma_addr_t phys_addr;
        unsigned long flags;
@@ -1086,16 +943,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        }
 
        if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
-               IWL_ERROR("No space for Tx\n");
+               IWL_ERR(priv, "No space for Tx\n");
                return -ENOSPC;
        }
 
        spin_lock_irqsave(&priv->hcmd_lock, flags);
 
-       tfd = &txq->tfds[q->write_ptr];
-       memset(tfd, 0, sizeof(*tfd));
-
-
        idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
        out_cmd = txq->cmd[idx];
 
@@ -1120,7 +973,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        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);
+       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                  phys_addr, fix_size, 1,
+                                                  U32_PAD(cmd->len));
 
 #ifdef CONFIG_IWLWIFI_DEBUG
        switch (out_cmd->hdr.cmd) {
@@ -1144,8 +999,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 #endif
        txq->need_update = 1;
 
-       /* Set up entry in queue's byte count circular buffer */
-       priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+       if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl)
+               /* Set up entry in queue's byte count circular buffer */
+               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
 
        /* Increment and update queue's write index */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -1163,7 +1019,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
        int nfreed = 0;
 
        if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
-               IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
+               IWL_ERR(priv, "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);
                return 0;
@@ -1180,7 +1036,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
                if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
                        priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
 
-               iwl_hw_txq_free_tfd(priv, txq);
+               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
                nfreed++;
        }
        return nfreed;
@@ -1203,7 +1059,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
        int nfreed = 0;
 
        if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
-               IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
+               IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
                          "is out of range [0-%d] %d %d.\n", txq_id,
                          idx, q->n_bd, q->write_ptr, q->read_ptr);
                return;
@@ -1218,7 +1074,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
                if (nfreed++ > 0) {
-                       IWL_ERROR("HCMD skipped: index (%d) %d %d\n", idx,
+                       IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
                                        q->write_ptr, q->read_ptr);
                        queue_work(priv->workqueue, &priv->restart);
                }
@@ -1306,7 +1162,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
        else
                return -EINVAL;
 
-       IWL_WARNING("%s on ra = %pM tid = %d\n",
+       IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
                        __func__, ra, tid);
 
        sta_id = iwl_find_station(priv, ra);
@@ -1314,7 +1170,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                return -ENXIO;
 
        if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
-               IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n");
+               IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
                return -ENXIO;
        }
 
@@ -1334,7 +1190,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                return ret;
 
        if (tid_data->tfds_in_queue == 0) {
-               printk(KERN_ERR "HW queue is empty\n");
+               IWL_ERR(priv, "HW queue is empty\n");
                tid_data->agg.state = IWL_AGG_ON;
                ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid);
        } else {
@@ -1354,7 +1210,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
        unsigned long flags;
 
        if (!ra) {
-               IWL_ERROR("ra = NULL\n");
+               IWL_ERR(priv, "ra = NULL\n");
                return -EINVAL;
        }
 
@@ -1369,7 +1225,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
                return -ENXIO;
 
        if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
-               IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n");
+               IWL_WARN(priv, "Stopping AGG while state not IWL_AGG_ON\n");
 
        tid_data = &priv->stations[sta_id].tid[tid];
        ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
@@ -1455,7 +1311,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
        struct ieee80211_tx_info *info;
 
        if (unlikely(!agg->wait_for_ba))  {
-               IWL_ERROR("Received BA when not expected\n");
+               IWL_ERR(priv, "Received BA when not expected\n");
                return -EINVAL;
        }
 
@@ -1528,7 +1384,8 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
        u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
 
        if (scd_flow >= priv->hw_params.max_txq_num) {
-               IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n");
+               IWL_ERR(priv,
+                       "BUG_ON scd_flow is bigger than number of queues\n");
                return;
        }
 
index 95d01984c80ed13c746499b97da040fc3e3f65e4..25a350810a105e7a578b1b43c54801329d66627b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2009 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.
 
 #include <asm/div64.h>
 
-#include "iwl-3945-core.h"
+#define DRV_NAME       "iwl3945"
+
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
 #include "iwl-3945.h"
 #include "iwl-helpers.h"
-
-#ifdef CONFIG_IWL3945_DEBUG
-u32 iwl3945_debug_level;
-#endif
-
-static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
-                                 struct iwl3945_tx_queue *txq);
-
-/******************************************************************************
- *
- * module boiler plate
- *
- ******************************************************************************/
-
-/* module parameters */
-static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */
-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 */
-int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+#include "iwl-core.h"
+#include "iwl-dev.h"
 
 /*
  * module name, copyright, version, etc.
- * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
  */
 
 #define DRV_DESCRIPTION        \
 "Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
 
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
 #define VD "d"
 #else
 #define VD
@@ -91,10 +76,10 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
 #define VS
 #endif
 
-#define IWLWIFI_VERSION "1.2.26k" VD VS
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2008 Intel Corporation"
+#define IWL39_VERSION "1.2.26k" VD VS
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2009 Intel Corporation"
 #define DRV_AUTHOR     "<ilw@linux.intel.com>"
-#define DRV_VERSION     IWLWIFI_VERSION
+#define DRV_VERSION     IWL39_VERSION
 
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -102,235 +87,13 @@ MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 
-static const struct ieee80211_supported_band *iwl3945_get_band(
-               struct iwl3945_priv *priv, enum ieee80211_band band)
-{
-       return priv->hw->wiphy->bands[band];
-}
-
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill.  Driver and device exchange status of each
- * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
- *
- * The 3945 operates with six queues:  One receive queue, one transmit queue
- * (#4) for sending commands to the device firmware, and four transmit queues
- * (#0-3) for data tx via EDCA.  An additional 2 HCCA queues are unused.
- ***************************************************/
-
-int iwl3945_queue_space(const struct iwl3945_queue *q)
-{
-       int s = q->read_ptr - q->write_ptr;
-
-       if (q->read_ptr > q->write_ptr)
-               s -= q->n_bd;
-
-       if (s <= 0)
-               s += q->n_window;
-       /* keep some reserve to not confuse empty and full situations */
-       s -= 2;
-       if (s < 0)
-               s = 0;
-       return s;
-}
-
-int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i)
-{
-       return q->write_ptr > q->read_ptr ?
-               (i >= q->read_ptr && i < q->write_ptr) :
-               !(i < q->read_ptr && i >= q->write_ptr);
-}
-
-
-static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
-{
-       /* This is for scan command, the big buffer at end of command array */
-       if (is_huge)
-               return q->n_window;     /* must be power of 2 */
-
-       /* Otherwise, use normal size buffers */
-       return index & (q->n_window - 1);
-}
-
-/**
- * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q,
-                         int count, int slots_num, u32 id)
-{
-       q->n_bd = count;
-       q->n_window = slots_num;
-       q->id = id;
-
-       /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-        * and iwl_queue_dec_wrap are broken. */
-       BUG_ON(!is_power_of_2(count));
-
-       /* slots_num must be power-of-two size, otherwise
-        * get_cmd_index is broken. */
-       BUG_ON(!is_power_of_2(slots_num));
-
-       q->low_mark = q->n_window / 4;
-       if (q->low_mark < 4)
-               q->low_mark = 4;
-
-       q->high_mark = q->n_window / 8;
-       if (q->high_mark < 2)
-               q->high_mark = 2;
-
-       q->write_ptr = q->read_ptr = 0;
-
-       return 0;
-}
-
-/**
- * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
-static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
-                             struct iwl3945_tx_queue *txq, u32 id)
-{
-       struct pci_dev *dev = priv->pci_dev;
-
-       /* Driver private data, only for Tx (not command) queues,
-        * not shared with device. */
-       if (id != IWL_CMD_QUEUE_NUM) {
-               txq->txb = kmalloc(sizeof(txq->txb[0]) *
-                                  TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
-               if (!txq->txb) {
-                       IWL_ERROR("kmalloc for auxiliary BD "
-                                 "structures failed\n");
-                       goto error;
-               }
-       } else
-               txq->txb = NULL;
-
-       /* 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->q.dma_addr);
-
-       if (!txq->bd) {
-               IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
-                         sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
-               goto error;
-       }
-       txq->q.id = id;
-
-       return 0;
-
- error:
-       kfree(txq->txb);
-       txq->txb = NULL;
-
-       return -ENOMEM;
-}
-
-/**
- * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
-int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
-                     struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id)
-{
-       struct pci_dev *dev = priv->pci_dev;
-       int len;
-       int rc = 0;
-
-       /*
-        * Alloc buffer array for commands (Tx or other types of commands).
-        * For the command queue (#4), allocate command space + one big
-        * command for scan, since scan command is very huge; the system will
-        * not have two scans at the same time, so only one is needed.
-        * For data Tx queues (all other queues), no super-size command
-        * space is needed.
-        */
-       len = sizeof(struct iwl3945_cmd) * slots_num;
-       if (txq_id == IWL_CMD_QUEUE_NUM)
-               len +=  IWL_MAX_SCAN_SIZE;
-       txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
-       if (!txq->cmd)
-               return -ENOMEM;
-
-       /* Alloc driver data array and TFD circular buffer */
-       rc = iwl3945_tx_queue_alloc(priv, txq, txq_id);
-       if (rc) {
-               pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
-
-               return -ENOMEM;
-       }
-       txq->need_update = 0;
-
-       /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-        * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
-       BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
-       /* Initialize queue high/low-water, head/tail indexes */
-       iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-
-       /* Tell device where to find queue, enable DMA channel. */
-       iwl3945_hw_tx_queue_init(priv, txq);
-
-       return 0;
-}
-
-/**
- * iwl3945_tx_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.
- */
-void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
-{
-       struct iwl3945_queue *q = &txq->q;
-       struct pci_dev *dev = priv->pci_dev;
-       int len;
-
-       if (q->n_bd == 0)
-               return;
-
-       /* first, empty all BD's */
-       for (; q->write_ptr != q->read_ptr;
-            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
-               iwl3945_hw_txq_free_tfd(priv, txq);
-
-       len = sizeof(struct iwl3945_cmd) * q->n_window;
-       if (q->id == IWL_CMD_QUEUE_NUM)
-               len += IWL_MAX_SCAN_SIZE;
-
-       /* De-alloc array of command/tx buffers */
-       pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
-
-       /* De-alloc circular buffer of TFDs */
-       if (txq->q.n_bd)
-               pci_free_consistent(dev, sizeof(struct iwl3945_tfd_frame) *
-                                   txq->q.n_bd, txq->bd, txq->q.dma_addr);
-
-       /* De-alloc array of per-TFD driver data */
-       kfree(txq->txb);
-       txq->txb = NULL;
-
-       /* 0-fill queue descriptor structure */
-       memset(txq, 0, sizeof(*txq));
-}
-
-const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ /* module parameters */
+struct iwl_mod_params iwl3945_mod_params = {
+       .num_of_queues = IWL39_MAX_NUM_QUEUES,
+       .sw_crypto = 1,
+       .restart_fw = 1,
+       /* the rest are 0 by default */
+};
 
 /*************** STATION TABLE MANAGEMENT ****
  * mac80211 should be examined to determine if sta_info is duplicating
@@ -344,7 +107,7 @@ const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  *
  * NOTE:  This does not remove station from device's station table.
  */
-static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap)
+static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
 {
        int index = IWL_INVALID_STATION;
        int i;
@@ -355,11 +118,11 @@ static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int
        if (is_ap)
                index = IWL_AP_ID;
        else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_setting.bcast_sta_id;
+               index = priv->hw_params.bcast_sta_id;
        else
-               for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
-                       if (priv->stations[i].used &&
-                           !compare_ether_addr(priv->stations[i].sta.sta.addr,
+               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
+                       if (priv->stations_39[i].used &&
+                           !compare_ether_addr(priv->stations_39[i].sta.sta.addr,
                                                addr)) {
                                index = i;
                                break;
@@ -368,8 +131,8 @@ static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int
        if (unlikely(index == IWL_INVALID_STATION))
                goto out;
 
-       if (priv->stations[index].used) {
-               priv->stations[index].used = 0;
+       if (priv->stations_39[index].used) {
+               priv->stations_39[index].used = 0;
                priv->num_stations--;
        }
 
@@ -386,14 +149,14 @@ out:
  *
  * NOTE:  This does not clear or otherwise alter the device's station table.
  */
-static void iwl3945_clear_stations_table(struct iwl3945_priv *priv)
+static void iwl3945_clear_stations_table(struct iwl_priv *priv)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
 
        priv->num_stations = 0;
-       memset(priv->stations, 0, sizeof(priv->stations));
+       memset(priv->stations_39, 0, sizeof(priv->stations_39));
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
@@ -401,7 +164,7 @@ static void iwl3945_clear_stations_table(struct iwl3945_priv *priv)
 /**
  * iwl3945_add_station - Add station to station tables in driver and device
  */
-u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 flags)
+u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
 {
        int i;
        int index = IWL_INVALID_STATION;
@@ -413,16 +176,16 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
        if (is_ap)
                index = IWL_AP_ID;
        else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_setting.bcast_sta_id;
+               index = priv->hw_params.bcast_sta_id;
        else
-               for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) {
-                       if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+                       if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
                                                addr)) {
                                index = i;
                                break;
                        }
 
-                       if (!priv->stations[i].used &&
+                       if (!priv->stations_39[i].used &&
                            index == IWL_INVALID_STATION)
                                index = i;
                }
@@ -434,14 +197,14 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
                return index;
        }
 
-       if (priv->stations[index].used &&
-          !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
+       if (priv->stations_39[index].used &&
+          !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) {
                spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
                return index;
        }
 
        IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr);
-       station = &priv->stations[index];
+       station = &priv->stations_39[index];
        station->used = 1;
        priv->num_stations++;
 
@@ -460,353 +223,16 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
        /* Turn on both antennas for the station... */
        station->sta.rate_n_flags =
                        iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
-       station->current_rate.rate_n_flags =
-                       le16_to_cpu(station->sta.rate_n_flags);
 
        spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
        /* Add station to device's station table */
-       iwl3945_send_add_station(priv, &station->sta, flags);
+       iwl_send_add_sta(priv,
+                        (struct iwl_addsta_cmd *)&station->sta, flags);
        return index;
 
 }
 
-/*************** DRIVER STATUS FUNCTIONS   *****/
-
-static inline int iwl3945_is_ready(struct iwl3945_priv *priv)
-{
-       /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
-        * set but EXIT_PENDING is not */
-       return test_bit(STATUS_READY, &priv->status) &&
-              test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
-              !test_bit(STATUS_EXIT_PENDING, &priv->status);
-}
-
-static inline int iwl3945_is_alive(struct iwl3945_priv *priv)
-{
-       return test_bit(STATUS_ALIVE, &priv->status);
-}
-
-static inline int iwl3945_is_init(struct iwl3945_priv *priv)
-{
-       return test_bit(STATUS_INIT, &priv->status);
-}
-
-static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv)
-{
-       return test_bit(STATUS_RF_KILL_SW, &priv->status);
-}
-
-static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv)
-{
-       return test_bit(STATUS_RF_KILL_HW, &priv->status);
-}
-
-static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv)
-{
-       return iwl3945_is_rfkill_hw(priv) ||
-               iwl3945_is_rfkill_sw(priv);
-}
-
-static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
-{
-
-       if (iwl3945_is_rfkill(priv))
-               return 0;
-
-       return iwl3945_is_ready(priv);
-}
-
-/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
-
-#define IWL_CMD(x) case x: return #x
-
-static const char *get_cmd_string(u8 cmd)
-{
-       switch (cmd) {
-               IWL_CMD(REPLY_ALIVE);
-               IWL_CMD(REPLY_ERROR);
-               IWL_CMD(REPLY_RXON);
-               IWL_CMD(REPLY_RXON_ASSOC);
-               IWL_CMD(REPLY_QOS_PARAM);
-               IWL_CMD(REPLY_RXON_TIMING);
-               IWL_CMD(REPLY_ADD_STA);
-               IWL_CMD(REPLY_REMOVE_STA);
-               IWL_CMD(REPLY_REMOVE_ALL_STA);
-               IWL_CMD(REPLY_3945_RX);
-               IWL_CMD(REPLY_TX);
-               IWL_CMD(REPLY_RATE_SCALE);
-               IWL_CMD(REPLY_LEDS_CMD);
-               IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-               IWL_CMD(RADAR_NOTIFICATION);
-               IWL_CMD(REPLY_QUIET_CMD);
-               IWL_CMD(REPLY_CHANNEL_SWITCH);
-               IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-               IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-               IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-               IWL_CMD(POWER_TABLE_CMD);
-               IWL_CMD(PM_SLEEP_NOTIFICATION);
-               IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-               IWL_CMD(REPLY_SCAN_CMD);
-               IWL_CMD(REPLY_SCAN_ABORT_CMD);
-               IWL_CMD(SCAN_START_NOTIFICATION);
-               IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-               IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-               IWL_CMD(BEACON_NOTIFICATION);
-               IWL_CMD(REPLY_TX_BEACON);
-               IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-               IWL_CMD(QUIET_NOTIFICATION);
-               IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-               IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-               IWL_CMD(REPLY_BT_CONFIG);
-               IWL_CMD(REPLY_STATISTICS_CMD);
-               IWL_CMD(STATISTICS_NOTIFICATION);
-               IWL_CMD(REPLY_CARD_STATE_CMD);
-               IWL_CMD(CARD_STATE_NOTIFICATION);
-               IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-       default:
-               return "UNKNOWN";
-
-       }
-}
-
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
-/**
- * iwl3945_enqueue_hcmd - enqueue a uCode command
- * @priv: device private data point
- * @cmd: a point to the ucode command structure
- *
- * The function returns < 0 values to indicate the operation is
- * failed. On success, it turns the index (> 0) of command in the
- * command queue.
- */
-static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
-{
-       struct iwl3945_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
-       struct iwl3945_queue *q = &txq->q;
-       struct iwl3945_tfd_frame *tfd;
-       u32 *control_flags;
-       struct iwl3945_cmd *out_cmd;
-       u32 idx;
-       u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
-       dma_addr_t phys_addr;
-       int pad;
-       u16 count;
-       int ret;
-       unsigned long flags;
-
-       /* If any of the command structures end up being larger than
-        * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
-        * we will need to increase the size of the TFD entries */
-       BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
-              !(cmd->meta.flags & CMD_SIZE_HUGE));
-
-
-       if (iwl3945_is_rfkill(priv)) {
-               IWL_DEBUG_INFO("Not sending command - RF KILL");
-               return -EIO;
-       }
-
-       if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
-               IWL_ERROR("No space for Tx\n");
-               return -ENOSPC;
-       }
-
-       spin_lock_irqsave(&priv->hcmd_lock, flags);
-
-       tfd = &txq->bd[q->write_ptr];
-       memset(tfd, 0, sizeof(*tfd));
-
-       control_flags = (u32 *) tfd;
-
-       idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
-       out_cmd = &txq->cmd[idx];
-
-       out_cmd->hdr.cmd = cmd->id;
-       memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
-       memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
-
-       /* At this point, the out_cmd now has all of the incoming cmd
-        * information */
-
-       out_cmd->hdr.flags = 0;
-       out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
-                       INDEX_TO_SEQ(q->write_ptr));
-       if (out_cmd->meta.flags & CMD_SIZE_HUGE)
-               out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
-
-       phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
-                       offsetof(struct iwl3945_cmd, hdr);
-       iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
-
-       pad = U32_PAD(cmd->len);
-       count = TFD_CTL_COUNT_GET(*control_flags);
-       *control_flags = TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad);
-
-       IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
-                    "%d bytes at %d[%d]:%d\n",
-                    get_cmd_string(out_cmd->hdr.cmd),
-                    out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
-                    fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
-
-       txq->need_update = 1;
-
-       /* Increment and update queue's write index */
-       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-       ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
-
-       spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-       return ret ? ret : idx;
-}
-
-static int iwl3945_send_cmd_async(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
-{
-       int ret;
-
-       BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
-
-       /* An asynchronous command can not expect an SKB to be set. */
-       BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
-
-       /* An asynchronous command MUST have a callback. */
-       BUG_ON(!cmd->meta.u.callback);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return -EBUSY;
-
-       ret = iwl3945_enqueue_hcmd(priv, cmd);
-       if (ret < 0) {
-               IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
-                         get_cmd_string(cmd->id), ret);
-               return ret;
-       }
-       return 0;
-}
-
-static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
-{
-       int cmd_idx;
-       int ret;
-
-       BUG_ON(cmd->meta.flags & CMD_ASYNC);
-
-        /* A synchronous command can not have a callback set. */
-       BUG_ON(cmd->meta.u.callback != NULL);
-
-       if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
-               IWL_ERROR("Error sending %s: Already sending a host command\n",
-                         get_cmd_string(cmd->id));
-               ret = -EBUSY;
-               goto out;
-       }
-
-       set_bit(STATUS_HCMD_ACTIVE, &priv->status);
-
-       if (cmd->meta.flags & CMD_WANT_SKB)
-               cmd->meta.source = &cmd->meta;
-
-       cmd_idx = iwl3945_enqueue_hcmd(priv, cmd);
-       if (cmd_idx < 0) {
-               ret = cmd_idx;
-               IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
-                         get_cmd_string(cmd->id), ret);
-               goto out;
-       }
-
-       ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-                       !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
-                       HOST_COMPLETE_TIMEOUT);
-       if (!ret) {
-               if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-                       IWL_ERROR("Error sending %s: time out after %dms.\n",
-                                 get_cmd_string(cmd->id),
-                                 jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
-
-                       clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-                       ret = -ETIMEDOUT;
-                       goto cancel;
-               }
-       }
-
-       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-               IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
-                              get_cmd_string(cmd->id));
-               ret = -ECANCELED;
-               goto fail;
-       }
-       if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-               IWL_DEBUG_INFO("Command %s failed: FW Error\n",
-                              get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto fail;
-       }
-       if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
-               IWL_ERROR("Error: Response NULL in '%s'\n",
-                         get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto cancel;
-       }
-
-       ret = 0;
-       goto out;
-
-cancel:
-       if (cmd->meta.flags & CMD_WANT_SKB) {
-               struct iwl3945_cmd *qcmd;
-
-               /* Cancel the CMD_WANT_SKB flag for the cmd in the
-                * TX cmd queue. Otherwise in case the cmd comes
-                * in later, it will possibly set an invalid
-                * address (cmd->meta.source). */
-               qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
-               qcmd->meta.flags &= ~CMD_WANT_SKB;
-       }
-fail:
-       if (cmd->meta.u.skb) {
-               dev_kfree_skb_any(cmd->meta.u.skb);
-               cmd->meta.u.skb = NULL;
-       }
-out:
-       clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
-       return ret;
-}
-
-int iwl3945_send_cmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
-{
-       if (cmd->meta.flags & CMD_ASYNC)
-               return iwl3945_send_cmd_async(priv, cmd);
-
-       return iwl3945_send_cmd_sync(priv, cmd);
-}
-
-int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, const void *data)
-{
-       struct iwl3945_host_cmd cmd = {
-               .id = id,
-               .len = len,
-               .data = data,
-       };
-
-       return iwl3945_send_cmd_sync(priv, &cmd);
-}
-
-static int __must_check iwl3945_send_cmd_u32(struct iwl3945_priv *priv, u8 id, u32 val)
-{
-       struct iwl3945_host_cmd cmd = {
-               .id = id,
-               .len = sizeof(val),
-               .data = &val,
-       };
-
-       return iwl3945_send_cmd_sync(priv, &cmd);
-}
-
-int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
-{
-       return iwl3945_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
-}
-
 /**
  * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
  * @band: 2.4 or 5 GHz band
@@ -817,25 +243,25 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
  * in the staging RXON flag structure based on the band
  */
-static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
+static int iwl3945_set_rxon_channel(struct iwl_priv *priv,
                                    enum ieee80211_band band,
                                    u16 channel)
 {
-       if (!iwl3945_get_channel_info(priv, band, channel)) {
+       if (!iwl_get_channel_info(priv, band, channel)) {
                IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
                               channel, band);
                return -EINVAL;
        }
 
-       if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+       if ((le16_to_cpu(priv->staging39_rxon.channel) == channel) &&
            (priv->band == band))
                return 0;
 
-       priv->staging_rxon.channel = cpu_to_le16(channel);
+       priv->staging39_rxon.channel = cpu_to_le16(channel);
        if (band == IEEE80211_BAND_5GHZ)
-               priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+               priv->staging39_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
        else
-               priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK;
 
        priv->band = band;
 
@@ -851,73 +277,74 @@ static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
  * be #ifdef'd out once the driver is stable and folks aren't actively
  * making changes
  */
-static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon)
+static int iwl3945_check_rxon_cmd(struct iwl_priv *priv)
 {
        int error = 0;
        int counter = 1;
+       struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon;
 
        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",
+                       IWL_WARN(priv, "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",
+                       IWL_WARN(priv, "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",
+                       IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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);
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "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",
+               IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
                            counter++, error);
 
        if ((rxon->flags & RXON_FLG_DIS_DIV_MSK))
                error |= ((rxon->flags & (RXON_FLG_ANT_B_MSK |
                                RXON_FLG_ANT_A_MSK)) == 0);
        if (error)
-               IWL_WARNING("check antenna %d %d\n", counter++, error);
+               IWL_WARN(priv, "check antenna %d %d\n", counter++, error);
 
        if (error)
-               IWL_WARNING("Tuning to channel %d\n",
+               IWL_WARN(priv, "Tuning to channel %d\n",
                            le16_to_cpu(rxon->channel));
 
        if (error) {
-               IWL_ERROR("Not a valid iwl3945_rxon_assoc_cmd field values\n");
+               IWL_ERR(priv, "Not a valid rxon_assoc_cmd field values\n");
                return -1;
        }
        return 0;
@@ -931,22 +358,22 @@ static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon)
  * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
  * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
  */
-static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
+static int iwl3945_full_rxon_required(struct iwl_priv *priv)
 {
 
        /* These items are only settable from the full RXON command */
        if (!(iwl3945_is_associated(priv)) ||
-           compare_ether_addr(priv->staging_rxon.bssid_addr,
-                              priv->active_rxon.bssid_addr) ||
-           compare_ether_addr(priv->staging_rxon.node_addr,
-                              priv->active_rxon.node_addr) ||
-           compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
-                              priv->active_rxon.wlap_bssid_addr) ||
-           (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
-           (priv->staging_rxon.channel != priv->active_rxon.channel) ||
-           (priv->staging_rxon.air_propagation !=
-            priv->active_rxon.air_propagation) ||
-           (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
+           compare_ether_addr(priv->staging39_rxon.bssid_addr,
+                              priv->active39_rxon.bssid_addr) ||
+           compare_ether_addr(priv->staging39_rxon.node_addr,
+                              priv->active39_rxon.node_addr) ||
+           compare_ether_addr(priv->staging39_rxon.wlap_bssid_addr,
+                              priv->active39_rxon.wlap_bssid_addr) ||
+           (priv->staging39_rxon.dev_type != priv->active39_rxon.dev_type) ||
+           (priv->staging39_rxon.channel != priv->active39_rxon.channel) ||
+           (priv->staging39_rxon.air_propagation !=
+            priv->active39_rxon.air_propagation) ||
+           (priv->staging39_rxon.assoc_id != priv->active39_rxon.assoc_id))
                return 1;
 
        /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
@@ -954,31 +381,31 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
         * flag transitions are allowed using RXON_ASSOC */
 
        /* Check if we are not switching bands */
-       if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
-           (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
+       if ((priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
+           (priv->active39_rxon.flags & RXON_FLG_BAND_24G_MSK))
                return 1;
 
        /* Check if we are switching association toggle */
-       if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
-               (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
+       if ((priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
+               (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
                return 1;
 
        return 0;
 }
 
-static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv)
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
 {
        int rc = 0;
-       struct iwl3945_rx_packet *res = NULL;
+       struct iwl_rx_packet *res = NULL;
        struct iwl3945_rxon_assoc_cmd rxon_assoc;
-       struct iwl3945_host_cmd cmd = {
+       struct iwl_host_cmd cmd = {
                .id = REPLY_RXON_ASSOC,
                .len = sizeof(rxon_assoc),
                .meta.flags = CMD_WANT_SKB,
                .data = &rxon_assoc,
        };
-       const struct iwl3945_rxon_cmd *rxon1 = &priv->staging_rxon;
-       const struct iwl3945_rxon_cmd *rxon2 = &priv->active_rxon;
+       const struct iwl3945_rxon_cmd *rxon1 = &priv->staging39_rxon;
+       const struct iwl3945_rxon_cmd *rxon2 = &priv->active39_rxon;
 
        if ((rxon1->flags == rxon2->flags) &&
            (rxon1->filter_flags == rxon2->filter_flags) &&
@@ -988,19 +415,19 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv)
                return 0;
        }
 
-       rxon_assoc.flags = priv->staging_rxon.flags;
-       rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-       rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+       rxon_assoc.flags = priv->staging39_rxon.flags;
+       rxon_assoc.filter_flags = priv->staging39_rxon.filter_flags;
+       rxon_assoc.ofdm_basic_rates = priv->staging39_rxon.ofdm_basic_rates;
+       rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates;
        rxon_assoc.reserved = 0;
 
-       rc = iwl3945_send_cmd_sync(priv, &cmd);
+       rc = iwl_send_cmd_sync(priv, &cmd);
        if (rc)
                return rc;
 
-       res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
+       res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
        if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
+               IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
                rc = -EIO;
        }
 
@@ -1010,6 +437,43 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv)
        return rc;
 }
 
+/**
+ * iwl3945_get_antenna_flags - Get antenna flags for RXON command
+ * @priv: eeprom and antenna fields are used to determine antenna flags
+ *
+ * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
+ * iwl3945_mod_params.antenna specifies the antenna diversity mode:
+ *
+ * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
+ * IWL_ANTENNA_MAIN      - Force MAIN antenna
+ * IWL_ANTENNA_AUX       - Force AUX antenna
+ */
+__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
+{
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+       switch (iwl3945_mod_params.antenna) {
+       case IWL_ANTENNA_DIVERSITY:
+               return 0;
+
+       case IWL_ANTENNA_MAIN:
+               if (eeprom->antenna_switch_type)
+                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+
+       case IWL_ANTENNA_AUX:
+               if (eeprom->antenna_switch_type)
+                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+       }
+
+       /* bad antenna selector value */
+       IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
+               iwl3945_mod_params.antenna);
+
+       return 0;               /* "diversity" is default if error */
+}
+
 /**
  * iwl3945_commit_rxon - commit staging_rxon to hardware
  *
@@ -1018,26 +482,26 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv)
  * function correctly transitions out of the RXON_ASSOC_MSK state if
  * a HW tune is required based on the RXON structure changes.
  */
-static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
+static int iwl3945_commit_rxon(struct iwl_priv *priv)
 {
        /* cast away the const for active_rxon in this function */
-       struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+       struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active39_rxon;
        int rc = 0;
 
-       if (!iwl3945_is_alive(priv))
+       if (!iwl_is_alive(priv))
                return -1;
 
        /* always get timestamp with Rx frame */
-       priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+       priv->staging39_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
 
        /* select antenna */
-       priv->staging_rxon.flags &=
+       priv->staging39_rxon.flags &=
            ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-       priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv);
+       priv->staging39_rxon.flags |= iwl3945_get_antenna_flags(priv);
 
-       rc = iwl3945_check_rxon_cmd(&priv->staging_rxon);
+       rc = iwl3945_check_rxon_cmd(priv);
        if (rc) {
-               IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
+               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
                return -EINVAL;
        }
 
@@ -1047,12 +511,12 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
        if (!iwl3945_full_rxon_required(priv)) {
                rc = iwl3945_send_rxon_assoc(priv);
                if (rc) {
-                       IWL_ERROR("Error setting RXON_ASSOC "
+                       IWL_ERR(priv, "Error setting RXON_ASSOC "
                                  "configuration (%d).\n", rc);
                        return rc;
                }
 
-               memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
+               memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon));
 
                return 0;
        }
@@ -1062,19 +526,19 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
         * we must clear the associated from the active configuration
         * before we apply the new config */
        if (iwl3945_is_associated(priv) &&
-           (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+           (priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
                IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
-               rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
+               rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
                                      sizeof(struct iwl3945_rxon_cmd),
-                                     &priv->active_rxon);
+                                     &priv->active39_rxon);
 
                /* If the mask clearing failed then we set
                 * active_rxon back to what it was previously */
                if (rc) {
                        active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERROR("Error clearing ASSOC_MSK on current "
+                       IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
                                  "configuration (%d).\n", rc);
                        return rc;
                }
@@ -1084,35 +548,35 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
                       "* with%s RXON_FILTER_ASSOC_MSK\n"
                       "* channel = %d\n"
                       "* bssid = %pM\n",
-                      ((priv->staging_rxon.filter_flags &
+                      ((priv->staging39_rxon.filter_flags &
                         RXON_FILTER_ASSOC_MSK) ? "" : "out"),
-                      le16_to_cpu(priv->staging_rxon.channel),
+                      le16_to_cpu(priv->staging39_rxon.channel),
                       priv->staging_rxon.bssid_addr);
 
        /* Apply the new configuration */
-       rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
-                             sizeof(struct iwl3945_rxon_cmd), &priv->staging_rxon);
+       rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+                             sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon);
        if (rc) {
-               IWL_ERROR("Error setting new configuration (%d).\n", rc);
+               IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
                return rc;
        }
 
-       memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
+       memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon));
 
        iwl3945_clear_stations_table(priv);
 
        /* If we issue a new RXON command which required a tune then we must
         * send a new TXPOWER command or we won't be able to Tx any frames */
-       rc = iwl3945_hw_reg_send_txpower(priv);
+       rc = priv->cfg->ops->lib->send_tx_power(priv);
        if (rc) {
-               IWL_ERROR("Error setting Tx power (%d).\n", rc);
+               IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
                return rc;
        }
 
        /* Add the broadcast address so we can send broadcast frames */
-       if (iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0) ==
+       if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) ==
            IWL_INVALID_STATION) {
-               IWL_ERROR("Error adding BROADCAST address for transmit.\n");
+               IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
                return -EIO;
        }
 
@@ -1120,185 +584,23 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
         * add the IWL_AP_ID to the station rate table */
        if (iwl3945_is_associated(priv) &&
            (priv->iw_mode == NL80211_IFTYPE_STATION))
-               if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
+               if (iwl3945_add_station(priv, priv->active39_rxon.bssid_addr, 1, 0)
                    == IWL_INVALID_STATION) {
-                       IWL_ERROR("Error adding AP address for transmit.\n");
+                       IWL_ERR(priv, "Error adding AP address for transmit\n");
                        return -EIO;
                }
 
        /* Init the hardware's rate fallback order based on the band */
        rc = iwl3945_init_hw_rate_table(priv);
        if (rc) {
-               IWL_ERROR("Error setting HW rate table: %02X\n", rc);
+               IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
                return -EIO;
        }
 
        return 0;
 }
 
-static int iwl3945_send_bt_config(struct iwl3945_priv *priv)
-{
-       struct iwl3945_bt_cmd bt_cmd = {
-               .flags = 3,
-               .lead_time = 0xAA,
-               .max_kill = 1,
-               .kill_ack_mask = 0,
-               .kill_cts_mask = 0,
-       };
-
-       return iwl3945_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-                               sizeof(struct iwl3945_bt_cmd), &bt_cmd);
-}
-
-static int iwl3945_send_scan_abort(struct iwl3945_priv *priv)
-{
-       int rc = 0;
-       struct iwl3945_rx_packet *res;
-       struct iwl3945_host_cmd cmd = {
-               .id = REPLY_SCAN_ABORT_CMD,
-               .meta.flags = CMD_WANT_SKB,
-       };
-
-       /* If there isn't a scan actively going on in the hardware
-        * then we are in between scan bands and not actually
-        * actively scanning, so don't send the abort command */
-       if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-               clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-               return 0;
-       }
-
-       rc = iwl3945_send_cmd_sync(priv, &cmd);
-       if (rc) {
-               clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-               return rc;
-       }
-
-       res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
-       if (res->u.status != CAN_ABORT_STATUS) {
-               /* The scan abort will return 1 for success or
-                * 2 for "failure".  A failure condition can be
-                * due to simply not being in an active scan which
-                * can occur if we send the scan abort before we
-                * the microcode has notified us that a scan is
-                * completed. */
-               IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
-               clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-               clear_bit(STATUS_SCAN_HW, &priv->status);
-       }
-
-       dev_kfree_skb_any(cmd.meta.u.skb);
-
-       return rc;
-}
-
-static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv,
-                                       struct iwl3945_cmd *cmd,
-                                       struct sk_buff *skb)
-{
-       return 1;
-}
-
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-static int iwl3945_send_card_state(struct iwl3945_priv *priv, u32 flags, u8 meta_flag)
-{
-       struct iwl3945_host_cmd cmd = {
-               .id = REPLY_CARD_STATE_CMD,
-               .len = sizeof(u32),
-               .data = &flags,
-               .meta.flags = meta_flag,
-       };
-
-       if (meta_flag & CMD_ASYNC)
-               cmd.meta.u.callback = iwl3945_card_state_sync_callback;
-
-       return iwl3945_send_cmd(priv, &cmd);
-}
-
-static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv,
-                                    struct iwl3945_cmd *cmd, struct sk_buff *skb)
-{
-       struct iwl3945_rx_packet *res = NULL;
-
-       if (!skb) {
-               IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
-               return 1;
-       }
-
-       res = (struct iwl3945_rx_packet *)skb->data;
-       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
-                         res->hdr.flags);
-               return 1;
-       }
-
-       switch (res->u.add_sta.status) {
-       case ADD_STA_SUCCESS_MSK:
-               break;
-       default:
-               break;
-       }
-
-       /* We didn't cache the SKB; let the caller free it */
-       return 1;
-}
-
-int iwl3945_send_add_station(struct iwl3945_priv *priv,
-                        struct iwl3945_addsta_cmd *sta, u8 flags)
-{
-       struct iwl3945_rx_packet *res = NULL;
-       int rc = 0;
-       struct iwl3945_host_cmd cmd = {
-               .id = REPLY_ADD_STA,
-               .len = sizeof(struct iwl3945_addsta_cmd),
-               .meta.flags = flags,
-               .data = sta,
-       };
-
-       if (flags & CMD_ASYNC)
-               cmd.meta.u.callback = iwl3945_add_sta_sync_callback;
-       else
-               cmd.meta.flags |= CMD_WANT_SKB;
-
-       rc = iwl3945_send_cmd(priv, &cmd);
-
-       if (rc || (flags & CMD_ASYNC))
-               return rc;
-
-       res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
-       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
-                         res->hdr.flags);
-               rc = -EIO;
-       }
-
-       if (rc == 0) {
-               switch (res->u.add_sta.status) {
-               case ADD_STA_SUCCESS_MSK:
-                       IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
-                       break;
-               default:
-                       rc = -EIO;
-                       IWL_WARNING("REPLY_ADD_STA failed\n");
-                       break;
-               }
-       }
-
-       priv->alloc_rxb_skb--;
-       dev_kfree_skb_any(cmd.meta.u.skb);
-
-       return rc;
-}
-
-static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv,
+static int iwl3945_update_sta_key_info(struct iwl_priv *priv,
                                   struct ieee80211_key_conf *keyconf,
                                   u8 sta_id)
 {
@@ -1318,42 +620,45 @@ static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv,
                return -EINVAL;
        }
        spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-       priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-       memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+       priv->stations_39[sta_id].keyinfo.alg = keyconf->alg;
+       priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen;
+       memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key,
               keyconf->keylen);
 
-       memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+       memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
               keyconf->keylen);
-       priv->stations[sta_id].sta.key.key_flags = key_flags;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       priv->stations_39[sta_id].sta.key.key_flags = key_flags;
+       priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
-       iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+       iwl_send_add_sta(priv,
+               (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
        return 0;
 }
 
-static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id)
+static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
-       memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
-       memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl3945_keyinfo));
-       priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
+       memset(&priv->stations_39[sta_id].sta.key, 0,
+               sizeof(struct iwl4965_keyinfo));
+       priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+       priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
-       iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+       iwl_send_add_sta(priv,
+               (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
        return 0;
 }
 
-static void iwl3945_clear_free_frames(struct iwl3945_priv *priv)
+static void iwl3945_clear_free_frames(struct iwl_priv *priv)
 {
        struct list_head *element;
 
@@ -1368,20 +673,20 @@ static void iwl3945_clear_free_frames(struct iwl3945_priv *priv)
        }
 
        if (priv->frames_count) {
-               IWL_WARNING("%d frames still in use.  Did we lose one?\n",
+               IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
                            priv->frames_count);
                priv->frames_count = 0;
        }
 }
 
-static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl3945_priv *priv)
+static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
 {
        struct iwl3945_frame *frame;
        struct list_head *element;
        if (list_empty(&priv->free_frames)) {
                frame = kzalloc(sizeof(*frame), GFP_KERNEL);
                if (!frame) {
-                       IWL_ERROR("Could not allocate frame!\n");
+                       IWL_ERR(priv, "Could not allocate frame!\n");
                        return NULL;
                }
 
@@ -1394,13 +699,13 @@ static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl3945_priv *priv)
        return list_entry(element, struct iwl3945_frame, list);
 }
 
-static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame *frame)
+static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
 {
        memset(frame, 0, sizeof(*frame));
        list_add(&frame->list, &priv->free_frames);
 }
 
-unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
+unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
                                struct ieee80211_hdr *hdr,
                                int left)
 {
@@ -1418,13 +723,13 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
        return priv->ibss_beacon->len;
 }
 
-static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
+static u8 iwl3945_rate_get_lowest_plcp(struct iwl_priv *priv)
 {
        u8 i;
        int rate_mask;
 
        /* Set rate mask*/
-       if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+       if (priv->staging39_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;
@@ -1436,13 +741,13 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
        }
 
        /* No valid rate was found. Assign the lowest one */
-       if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+       if (priv->staging39_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)
+static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
 {
        struct iwl3945_frame *frame;
        unsigned int frame_size;
@@ -1452,7 +757,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
        frame = iwl3945_get_free_frame(priv);
 
        if (!frame) {
-               IWL_ERROR("Could not obtain free frame buffer for beacon "
+               IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
                          "command.\n");
                return -ENOMEM;
        }
@@ -1461,7 +766,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
 
        frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
 
-       rc = iwl3945_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+       rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
                              &frame->u.cmd[0]);
 
        iwl3945_free_frame(priv, frame);
@@ -1469,307 +774,27 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
        return rc;
 }
 
-/******************************************************************************
- *
- * EEPROM related functions
- *
- ******************************************************************************/
-
-static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
-{
-       memcpy(mac, priv->eeprom.mac_address, 6);
-}
-
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
-{
-       _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-       return 0;
-}
-
-/**
- * iwl3945_eeprom_init - read EEPROM contents
- *
- * Load the EEPROM contents from adapter into priv->eeprom
- *
- * NOTE:  This routine uses the non-debug IO access functions.
- */
-int iwl3945_eeprom_init(struct iwl3945_priv *priv)
-{
-       u16 *e = (u16 *)&priv->eeprom;
-       u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
-       int sz = sizeof(priv->eeprom);
-       int ret;
-       u16 addr;
-
-       /* The EEPROM structure has several padding buffers within it
-        * and when adding new EEPROM maps is subject to programmer errors
-        * which may be very difficult to identify without explicitly
-        * checking the resulting size of the eeprom map. */
-       BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
-
-       if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
-               return -ENOENT;
-       }
-
-       /* Make sure driver (instead of uCode) is allowed to read EEPROM */
-       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)) {
-               u32 r;
-
-               _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 ret;
-               }
-
-               r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
-               e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
-       }
-
-       return 0;
-}
-
-static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv)
+static void iwl3945_unset_hw_params(struct iwl_priv *priv)
 {
-       if (priv->hw_setting.shared_virt)
+       if (priv->shared_virt)
                pci_free_consistent(priv->pci_dev,
                                    sizeof(struct iwl3945_shared),
-                                   priv->hw_setting.shared_virt,
-                                   priv->hw_setting.shared_phys);
-}
-
-/**
- * iwl3945_supported_rate_to_ie - fill in the supported rate in IE field
- *
- * return : set the bit for each supported rate insert in ie
- */
-static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate,
-                                   u16 basic_rate, int *left)
-{
-       u16 ret_rates = 0, bit;
-       int i;
-       u8 *cnt = ie;
-       u8 *rates = ie + 1;
-
-       for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
-               if (bit & supported_rate) {
-                       ret_rates |= bit;
-                       rates[*cnt] = iwl3945_rates[i].ieee |
-                               ((bit & basic_rate) ? 0x80 : 0x00);
-                       (*cnt)++;
-                       (*left)--;
-                       if ((*left <= 0) ||
-                           (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
-                               break;
-               }
-       }
-
-       return ret_rates;
-}
-
-/**
- * iwl3945_fill_probe_req - fill in all required fields and IE for probe request
- */
-static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
-                             struct ieee80211_mgmt *frame,
-                             int left)
-{
-       int len = 0;
-       u8 *pos = NULL;
-       u16 active_rates, ret_rates, cck_rates;
-
-       /* Make sure there is enough space for the probe request,
-        * two mandatory IEs and the data */
-       left -= 24;
-       if (left < 0)
-               return 0;
-       len += 24;
-
-       frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-       memcpy(frame->da, iwl3945_broadcast_addr, ETH_ALEN);
-       memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
-       memcpy(frame->bssid, iwl3945_broadcast_addr, ETH_ALEN);
-       frame->seq_ctrl = 0;
-
-       /* fill in our indirect SSID IE */
-       /* ...next IE... */
-
-       left -= 2;
-       if (left < 0)
-               return 0;
-       len += 2;
-       pos = &(frame->u.probe_req.variable[0]);
-       *pos++ = WLAN_EID_SSID;
-       *pos++ = 0;
-
-       /* fill in supported rate */
-       /* ...next IE... */
-       left -= 2;
-       if (left < 0)
-               return 0;
-
-       /* ... fill it in... */
-       *pos++ = WLAN_EID_SUPP_RATES;
-       *pos = 0;
-
-       priv->active_rate = priv->rates_mask;
-       active_rates = priv->active_rate;
-       priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
-
-       cck_rates = IWL_CCK_RATES_MASK & active_rates;
-       ret_rates = iwl3945_supported_rate_to_ie(pos, cck_rates,
-                       priv->active_rate_basic, &left);
-       active_rates &= ~ret_rates;
-
-       ret_rates = iwl3945_supported_rate_to_ie(pos, active_rates,
-                                priv->active_rate_basic, &left);
-       active_rates &= ~ret_rates;
-
-       len += 2 + *pos;
-       pos += (*pos) + 1;
-       if (active_rates == 0)
-               goto fill_end;
-
-       /* fill in supported extended rate */
-       /* ...next IE... */
-       left -= 2;
-       if (left < 0)
-               return 0;
-       /* ... fill it in... */
-       *pos++ = WLAN_EID_EXT_SUPP_RATES;
-       *pos = 0;
-       iwl3945_supported_rate_to_ie(pos, active_rates,
-                                priv->active_rate_basic, &left);
-       if (*pos > 0)
-               len += 2 + *pos;
-
- fill_end:
-       return (u16)len;
+                                   priv->shared_virt,
+                                   priv->shared_phys);
 }
 
 /*
  * QoS  support
 */
-static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
-                                      struct iwl3945_qosparam_cmd *qos)
+static int iwl3945_send_qos_params_command(struct iwl_priv *priv,
+                                      struct iwl_qosparam_cmd *qos)
 {
 
-       return iwl3945_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-                               sizeof(struct iwl3945_qosparam_cmd), qos);
+       return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
+                               sizeof(struct iwl_qosparam_cmd), qos);
 }
 
-static void iwl3945_reset_qos(struct iwl3945_priv *priv)
-{
-       u16 cw_min = 15;
-       u16 cw_max = 1023;
-       u8 aifs = 2;
-       u8 is_legacy = 0;
-       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;
-
-
-       /* 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;
-       }
-
-       if (priv->qos_data.qos_active)
-               aifs = 3;
-
-       priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
-       priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
-       priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
-       priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
-       priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
-
-       if (priv->qos_data.qos_active) {
-               i = 1;
-               priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
-               priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
-               priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-
-               i = 2;
-               priv->qos_data.def_qos_parm.ac[i].cw_min =
-                       cpu_to_le16((cw_min + 1) / 2 - 1);
-               priv->qos_data.def_qos_parm.ac[i].cw_max =
-                       cpu_to_le16(cw_max);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-               if (is_legacy)
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(6016);
-               else
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(3008);
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-
-               i = 3;
-               priv->qos_data.def_qos_parm.ac[i].cw_min =
-                       cpu_to_le16((cw_min + 1) / 4 - 1);
-               priv->qos_data.def_qos_parm.ac[i].cw_max =
-                       cpu_to_le16((cw_max + 1) / 2 - 1);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               if (is_legacy)
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(3264);
-               else
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(1504);
-       } else {
-               for (i = 1; i < 4; i++) {
-                       priv->qos_data.def_qos_parm.ac[i].cw_min =
-                               cpu_to_le16(cw_min);
-                       priv->qos_data.def_qos_parm.ac[i].cw_max =
-                               cpu_to_le16(cw_max);
-                       priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-                       priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               }
-       }
-       IWL_DEBUG_QOS("set QoS to default \n");
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
+static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force)
 {
        unsigned long flags;
 
@@ -1804,56 +829,42 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
  */
 #define MSEC_TO_USEC 1024
 
-#define NOSLP __constant_cpu_to_le32(0)
-#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK
-#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
-#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
-                                    __constant_cpu_to_le32(X1), \
-                                    __constant_cpu_to_le32(X2), \
-                                    __constant_cpu_to_le32(X3), \
-                                    __constant_cpu_to_le32(X4)}
-
 
 /* default power management (not Tx power) table values */
 /* 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},
-       {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
-       {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0},
-       {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1},
-       {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
+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, 3, 4, 4)}, 0},
+       {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
+       {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0},
+       {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1},
+       {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
 };
 
 /* 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),
-                SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
-       {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300),
-                SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
-       {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100),
-                SLP_VEC(2, 6, 9, 9, 0xFF)}, 0},
-       {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
-       {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25),
-                SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
+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, 0xFF)}, 0},
+       {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
+       {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 0xFF)}, 0},
+       {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
+       {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
 };
 
-int iwl3945_power_init_handle(struct iwl3945_priv *priv)
+int iwl3945_power_init_handle(struct iwl_priv *priv)
 {
        int rc = 0, i;
-       struct iwl3945_power_mgr *pow_data;
-       int size = sizeof(struct iwl3945_power_vec_entry) * IWL_POWER_AC;
+       struct iwl_power_mgr *pow_data;
+       int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
        u16 pci_pm;
 
        IWL_DEBUG_POWER("Initialize power \n");
 
-       pow_data = &(priv->power_data);
+       pow_data = &priv->power_data;
 
        memset(pow_data, 0, sizeof(*pow_data));
 
-       pow_data->active_index = IWL_POWER_RANGE_0;
-       pow_data->dtim_val = 0xffff;
+       pow_data->dtim_period = 1;
 
        memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
        memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
@@ -1862,11 +873,11 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv)
        if (rc != 0)
                return 0;
        else {
-               struct iwl3945_powertable_cmd *cmd;
+               struct iwl_powertable_cmd *cmd;
 
                IWL_DEBUG_POWER("adjust power command flags\n");
 
-               for (i = 0; i < IWL_POWER_AC; i++) {
+               for (i = 0; i < IWL_POWER_MAX; i++) {
                        cmd = &pow_data->pwr_range_0[i].cmd;
 
                        if (pci_pm & 0x1)
@@ -1878,56 +889,49 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv)
        return rc;
 }
 
-static int iwl3945_update_power_cmd(struct iwl3945_priv *priv,
-                               struct iwl3945_powertable_cmd *cmd, u32 mode)
+static int iwl3945_update_power_cmd(struct iwl_priv *priv,
+                               struct iwl_powertable_cmd *cmd, u32 mode)
 {
-       int rc = 0, i;
-       u8 skip;
+       struct iwl_power_mgr *pow_data;
+       struct iwl_power_vec_entry *range;
        u32 max_sleep = 0;
-       struct iwl3945_power_vec_entry *range;
+       int i;
        u8 period = 0;
-       struct iwl3945_power_mgr *pow_data;
+       bool skip;
 
        if (mode > IWL_POWER_INDEX_5) {
                IWL_DEBUG_POWER("Error invalid power mode \n");
-               return -1;
+               return -EINVAL;
        }
-       pow_data = &(priv->power_data);
+       pow_data = &priv->power_data;
 
-       if (pow_data->active_index == IWL_POWER_RANGE_0)
+       if (pow_data->dtim_period < 10)
                range = &pow_data->pwr_range_0[0];
        else
                range = &pow_data->pwr_range_1[1];
 
        memcpy(cmd, &range[mode].cmd, sizeof(struct iwl3945_powertable_cmd));
 
-#ifdef IWL_MAC80211_DISABLE
-       if (priv->assoc_network != NULL) {
-               unsigned long flags;
-
-               period = priv->assoc_network->tim.tim_period;
-       }
-#endif /*IWL_MAC80211_DISABLE */
-       skip = range[mode].no_dtim;
 
        if (period == 0) {
                period = 1;
-               skip = 0;
+               skip = false;
+       } else {
+               skip = !!range[mode].no_dtim;
        }
 
-       if (skip == 0) {
-               max_sleep = period;
-               cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
-       } else {
+       if (skip) {
                __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
                max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
                cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
+       } else {
+               max_sleep = period;
+               cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
        }
 
-       for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
+       for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
                if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
                        cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
-       }
 
        IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
        IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
@@ -1939,92 +943,42 @@ static int iwl3945_update_power_cmd(struct iwl3945_priv *priv,
                        le32_to_cpu(cmd->sleep_interval[3]),
                        le32_to_cpu(cmd->sleep_interval[4]));
 
-       return rc;
+       return 0;
 }
 
-static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode)
+static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode)
 {
        u32 uninitialized_var(final_mode);
        int rc;
-       struct iwl3945_powertable_cmd cmd;
+       struct iwl_powertable_cmd cmd;
 
        /* If on battery, set to 3,
         * if plugged into AC power, set to CAM ("continuously aware mode"),
         * else user level */
        switch (mode) {
-       case IWL_POWER_BATTERY:
+       case IWL39_POWER_BATTERY:
                final_mode = IWL_POWER_INDEX_3;
                break;
-       case IWL_POWER_AC:
+       case IWL39_POWER_AC:
                final_mode = IWL_POWER_MODE_CAM;
                break;
-       default:
-               final_mode = mode;
-               break;
-       }
-
-       iwl3945_update_power_cmd(priv, &cmd, final_mode);
-
-       rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
-
-       if (final_mode == IWL_POWER_MODE_CAM)
-               clear_bit(STATUS_POWER_PMI, &priv->status);
-       else
-               set_bit(STATUS_POWER_PMI, &priv->status);
-
-       return rc;
-}
-
-/**
- * iwl3945_scan_cancel - Cancel any currently executing HW scan
- *
- * NOTE: priv->mutex is not required before calling this function
- */
-static int iwl3945_scan_cancel(struct iwl3945_priv *priv)
-{
-       if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-               clear_bit(STATUS_SCANNING, &priv->status);
-               return 0;
-       }
-
-       if (test_bit(STATUS_SCANNING, &priv->status)) {
-               if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-                       IWL_DEBUG_SCAN("Queuing scan abort.\n");
-                       set_bit(STATUS_SCAN_ABORTING, &priv->status);
-                       queue_work(priv->workqueue, &priv->abort_scan);
-
-               } else
-                       IWL_DEBUG_SCAN("Scan abort already in progress.\n");
-
-               return test_bit(STATUS_SCANNING, &priv->status);
+       default:
+               final_mode = mode;
+               break;
        }
 
-       return 0;
-}
-
-/**
- * iwl3945_scan_cancel_timeout - Cancel any currently executing HW scan
- * @ms: amount of time to wait (in milliseconds) for scan to abort
- *
- * NOTE: priv->mutex must be held before calling this function
- */
-static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long ms)
-{
-       unsigned long now = jiffies;
-       int ret;
+       iwl3945_update_power_cmd(priv, &cmd, final_mode);
 
-       ret = iwl3945_scan_cancel(priv);
-       if (ret && ms) {
-               mutex_unlock(&priv->mutex);
-               while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
-                               test_bit(STATUS_SCANNING, &priv->status))
-                       msleep(1);
-               mutex_lock(&priv->mutex);
+       /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */
+       rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+                             sizeof(struct iwl3945_powertable_cmd), &cmd);
 
-               return test_bit(STATUS_SCANNING, &priv->status);
-       }
+       if (final_mode == IWL_POWER_MODE_CAM)
+               clear_bit(STATUS_POWER_PMI, &priv->status);
+       else
+               set_bit(STATUS_POWER_PMI, &priv->status);
 
-       return ret;
+       return rc;
 }
 
 #define MAX_UCODE_BEACON_INTERVAL      1024
@@ -2043,7 +997,7 @@ static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
        return cpu_to_le16(new_val);
 }
 
-static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
+static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
 {
        u64 interval_tm_unit;
        u64 tsf, result;
@@ -2054,13 +1008,10 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_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->timestamp1);
-       priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
-
+       priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
        priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
 
-       tsf = priv->timestamp1;
-       tsf = ((tsf << 32) | priv->timestamp0);
+       tsf = priv->timestamp;
 
        beacon_int = priv->beacon_int;
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -2099,9 +1050,9 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
                le16_to_cpu(priv->rxon_timing.atim_window));
 }
 
-static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
+static int iwl3945_scan_initiate(struct iwl_priv *priv)
 {
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
                return -EIO;
        }
@@ -2131,9 +1082,9 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
        return 0;
 }
 
-static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
+static int iwl3945_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
 {
-       struct iwl3945_rxon_cmd *rxon = &priv->staging_rxon;
+       struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon;
 
        if (hw_decrypt)
                rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -2143,64 +1094,64 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
        return 0;
 }
 
-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
+static void iwl3945_set_flags_for_phymode(struct iwl_priv *priv,
                                          enum ieee80211_band band)
 {
        if (band == IEEE80211_BAND_5GHZ) {
-               priv->staging_rxon.flags &=
+               priv->staging39_rxon.flags &=
                    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
                      | RXON_FLG_CCK_MSK);
-               priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
        } else {
                /* Copied from iwl3945_bg_post_associate() */
                if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
-                       priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
                else
-                       priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
                if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
-                       priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-               priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
-               priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
-               priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
+               priv->staging39_rxon.flags &= ~RXON_FLG_CCK_MSK;
        }
 }
 
 /*
  * 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 iwl_priv *priv,
                                              int mode)
 {
-       const struct iwl3945_channel_info *ch_info;
+       const struct iwl_channel_info *ch_info;
 
-       memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
+       memset(&priv->staging39_rxon, 0, sizeof(priv->staging39_rxon));
 
        switch (mode) {
        case NL80211_IFTYPE_AP:
-               priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
+               priv->staging39_rxon.dev_type = RXON_DEV_TYPE_AP;
                break;
 
        case NL80211_IFTYPE_STATION:
-               priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
-               priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+               priv->staging39_rxon.dev_type = RXON_DEV_TYPE_ESS;
+               priv->staging39_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
                break;
 
        case NL80211_IFTYPE_ADHOC:
-               priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
-               priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
-               priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+               priv->staging39_rxon.dev_type = RXON_DEV_TYPE_IBSS;
+               priv->staging39_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+               priv->staging39_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
                                                  RXON_FILTER_ACCEPT_GRP_MSK;
                break;
 
        case NL80211_IFTYPE_MONITOR:
-               priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
-               priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
+               priv->staging39_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
+               priv->staging39_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
                    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
                break;
        default:
-               IWL_ERROR("Unsupported interface type %d\n", mode);
+               IWL_ERR(priv, "Unsupported interface type %d\n", mode);
                break;
        }
 
@@ -2208,13 +1159,13 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
        /* TODO:  Figure out when short_preamble would be set and cache from
         * that */
        if (!hw_to_local(priv->hw)->short_preamble)
-               priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+               priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
        else
-               priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 #endif
 
-       ch_info = iwl3945_get_channel_info(priv, priv->band,
-                                      le16_to_cpu(priv->active_rxon.channel));
+       ch_info = iwl_get_channel_info(priv, priv->band,
+                                      le16_to_cpu(priv->active39_rxon.channel));
 
        if (!ch_info)
                ch_info = &priv->channel_info[0];
@@ -2226,7 +1177,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
        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);
+       priv->staging39_rxon.channel = cpu_to_le16(ch_info->channel);
        if (is_channel_a_band(ch_info))
                priv->band = IEEE80211_BAND_5GHZ;
        else
@@ -2234,40 +1185,40 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
 
        iwl3945_set_flags_for_phymode(priv, priv->band);
 
-       priv->staging_rxon.ofdm_basic_rates =
+       priv->staging39_rxon.ofdm_basic_rates =
            (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-       priv->staging_rxon.cck_basic_rates =
+       priv->staging39_rxon.cck_basic_rates =
            (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 }
 
-static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
+static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
 {
        if (mode == NL80211_IFTYPE_ADHOC) {
-               const struct iwl3945_channel_info *ch_info;
+               const struct iwl_channel_info *ch_info;
 
-               ch_info = iwl3945_get_channel_info(priv,
+               ch_info = iwl_get_channel_info(priv,
                        priv->band,
-                       le16_to_cpu(priv->staging_rxon.channel));
+                       le16_to_cpu(priv->staging39_rxon.channel));
 
                if (!ch_info || !is_channel_ibss(ch_info)) {
-                       IWL_ERROR("channel %d not IBSS channel\n",
-                                 le16_to_cpu(priv->staging_rxon.channel));
+                       IWL_ERR(priv, "channel %d not IBSS channel\n",
+                                 le16_to_cpu(priv->staging39_rxon.channel));
                        return -EINVAL;
                }
        }
 
        iwl3945_connection_init_rx_config(priv, mode);
-       memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+       memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 
        iwl3945_clear_stations_table(priv);
 
        /* don't commit rxon if rf-kill is on*/
-       if (!iwl3945_is_ready_rf(priv))
+       if (!iwl_is_ready_rf(priv))
                return -EAGAIN;
 
        cancel_delayed_work(&priv->scan_check);
-       if (iwl3945_scan_cancel_timeout(priv, 100)) {
-               IWL_WARNING("Aborted scan still in progress after 100ms\n");
+       if (iwl_scan_cancel_timeout(priv, 100)) {
+               IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
                IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
                return -EAGAIN;
        }
@@ -2277,49 +1228,50 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
        return 0;
 }
 
-static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
+static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
                                      struct ieee80211_tx_info *info,
-                                     struct iwl3945_cmd *cmd,
+                                     struct iwl_cmd *cmd,
                                      struct sk_buff *skb_frag,
                                      int last_frag)
 {
+       struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
        struct iwl3945_hw_key *keyinfo =
-           &priv->stations[info->control.hw_key->hw_key_idx].keyinfo;
+           &priv->stations_39[info->control.hw_key->hw_key_idx].keyinfo;
 
        switch (keyinfo->alg) {
        case ALG_CCMP:
-               cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
-               memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
+               tx->sec_ctl = TX_CMD_SEC_CCM;
+               memcpy(tx->key, keyinfo->key, keyinfo->keylen);
                IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
                break;
 
        case ALG_TKIP:
 #if 0
-               cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
+               tx->sec_ctl = TX_CMD_SEC_TKIP;
 
                if (last_frag)
-                       memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
+                       memcpy(tx->tkip_mic.byte, skb_frag->tail - 8,
                               8);
                else
-                       memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
+                       memset(tx->tkip_mic.byte, 0, 8);
 #endif
                break;
 
        case ALG_WEP:
-               cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
+               tx->sec_ctl = TX_CMD_SEC_WEP |
                    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
 
                if (keyinfo->keylen == 13)
-                       cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
+                       tx->sec_ctl |= TX_CMD_SEC_KEY128;
 
-               memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
+               memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen);
 
                IWL_DEBUG_TX("Configuring packet for WEP encryption "
                             "with key %d\n", info->control.hw_key->hw_key_idx);
                break;
 
        default:
-               printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
+               IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
                break;
        }
 }
@@ -2327,17 +1279,17 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
 /*
  * handle build REPLY_TX command notification.
  */
-static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
-                                 struct iwl3945_cmd *cmd,
+static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
+                                 struct iwl_cmd *cmd,
                                  struct ieee80211_tx_info *info,
-                                 struct ieee80211_hdr *hdr,
-                                 int is_unicast, u8 std_id)
+                                 struct ieee80211_hdr *hdr, u8 std_id)
 {
+       struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+       __le32 tx_flags = tx->tx_flags;
        __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;
+       tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
                tx_flags |= TX_CMD_FLG_ACK_MSK;
                if (ieee80211_is_mgmt(fc))
@@ -2350,13 +1302,13 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
        }
 
-       cmd->cmd.tx.sta_id = std_id;
+       tx->sta_id = std_id;
        if (ieee80211_has_morefrags(fc))
                tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
 
        if (ieee80211_is_data_qos(fc)) {
                u8 *qc = ieee80211_get_qos_ctl(hdr);
-               cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
+               tx->tid_tspec = qc[0] & 0xf;
                tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
        } else {
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
@@ -2376,25 +1328,25 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
        tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
        if (ieee80211_is_mgmt(fc)) {
                if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-                       cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
+                       tx->timeout.pm_frame_timeout = cpu_to_le16(3);
                else
-                       cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
+                       tx->timeout.pm_frame_timeout = cpu_to_le16(2);
        } else {
-               cmd->cmd.tx.timeout.pm_frame_timeout = 0;
+               tx->timeout.pm_frame_timeout = 0;
 #ifdef CONFIG_IWL3945_LEDS
                priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
 #endif
        }
 
-       cmd->cmd.tx.driver_txop = 0;
-       cmd->cmd.tx.tx_flags = tx_flags;
-       cmd->cmd.tx.next_frame_len = 0;
+       tx->driver_txop = 0;
+       tx->tx_flags = tx_flags;
+       tx->next_frame_len = 0;
 }
 
 /**
  * iwl3945_get_sta_id - Find station's index within station table
  */
-static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr)
+static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
 {
        int sta_id;
        u16 fc = le16_to_cpu(hdr->frame_control);
@@ -2402,7 +1354,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
        /* If this frame is broadcast or management, use broadcast station id */
        if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
            is_multicast_ether_addr(hdr->addr1))
-               return priv->hw_setting.bcast_sta_id;
+               return priv->hw_params.bcast_sta_id;
 
        switch (priv->iw_mode) {
 
@@ -2416,7 +1368,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
                sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
                if (sta_id != IWL_INVALID_STATION)
                        return sta_id;
-               return priv->hw_setting.bcast_sta_id;
+               return priv->hw_params.bcast_sta_id;
 
        /* If this frame is going out to an IBSS network, find the station,
         * or create a new station table entry */
@@ -2434,35 +1386,35 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
                IWL_DEBUG_DROP("Station %pM not in station map. "
                               "Defaulting to broadcast...\n",
                               hdr->addr1);
-               iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-               return priv->hw_setting.bcast_sta_id;
+               iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+               return priv->hw_params.bcast_sta_id;
        }
        /* If we are in monitor mode, use BCAST. This is required for
         * packet injection. */
        case NL80211_IFTYPE_MONITOR:
-               return priv->hw_setting.bcast_sta_id;
+               return priv->hw_params.bcast_sta_id;
 
        default:
-               IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
-               return priv->hw_setting.bcast_sta_id;
+               IWL_WARN(priv, "Unknown mode of operation: %d\n",
+                       priv->iw_mode);
+               return priv->hw_params.bcast_sta_id;
        }
 }
 
 /*
  * start REPLY_TX command process
  */
-static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
+static int iwl3945_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 iwl3945_tfd_frame *tfd;
-       u32 *control_flags;
-       int txq_id = skb_get_queue_mapping(skb);
-       struct iwl3945_tx_queue *txq = NULL;
-       struct iwl3945_queue *q = NULL;
+       struct iwl3945_tx_cmd *tx;
+       struct iwl_tx_queue *txq = NULL;
+       struct iwl_queue *q = NULL;
+       struct iwl_cmd *out_cmd = NULL;
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
-       struct iwl3945_cmd *out_cmd = NULL;
+       int txq_id = skb_get_queue_mapping(skb);
        u16 len, idx, len_org, hdr_len;
        u8 id;
        u8 unicast;
@@ -2476,13 +1428,13 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
        int rc;
 
        spin_lock_irqsave(&priv->lock, flags);
-       if (iwl3945_is_rfkill(priv)) {
+       if (iwl_is_rfkill(priv)) {
                IWL_DEBUG_DROP("Dropping - RF KILL\n");
                goto drop_unlock;
        }
 
        if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
-               IWL_ERROR("ERROR: No TX rate available.\n");
+               IWL_ERR(priv, "ERROR: No TX rate available.\n");
                goto drop_unlock;
        }
 
@@ -2491,7 +1443,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
 
        fc = hdr->frame_control;
 
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
        if (ieee80211_is_auth(fc))
                IWL_DEBUG_TX("Sending AUTH frame\n");
        else if (ieee80211_is_assoc_req(fc))
@@ -2526,7 +1478,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               seq_number = priv->stations[sta_id].tid[tid].seq_number &
+               seq_number = priv->stations_39[sta_id].tid[tid].seq_number &
                                IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = cpu_to_le16(seq_number) |
                        (hdr->seq_ctrl &
@@ -2540,20 +1492,17 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       /* Set up first empty TFD within this queue's circular TFD buffer */
-       tfd = &txq->bd[q->write_ptr];
-       memset(tfd, 0, sizeof(*tfd));
-       control_flags = (u32 *) 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 iwl3945_tx_info));
+       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
        txq->txb[q->write_ptr].skb[0] = skb;
 
        /* Init first empty entry in queue's array of Tx/cmd buffers */
-       out_cmd = &txq->cmd[idx];
+       out_cmd = txq->cmd[idx];
+       tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
        memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-       memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
+       memset(tx, 0, sizeof(*tx));
 
        /*
         * Set up the Tx-command (not MAC!) header.
@@ -2566,7 +1515,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
                                INDEX_TO_SEQ(q->write_ptr)));
 
        /* Copy MAC header from skb into command buffer */
-       memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
+       memcpy(tx->hdr, hdr, hdr_len);
 
        /*
         * Use the first empty entry in this queue's command buffer array
@@ -2577,8 +1526,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
         * of the MAC header (device reads on dword boundaries).
         * We'll tell device about this padding later.
         */
-       len = priv->hw_setting.tx_cmd_len +
-               sizeof(struct iwl3945_cmd_header) + hdr_len;
+       len = sizeof(struct iwl3945_tx_cmd) +
+                       sizeof(struct iwl_cmd_header) + hdr_len;
 
        len_org = len;
        len = (len + 3) & ~3;
@@ -2590,12 +1539,19 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl3945_cmd) * idx +
-                    offsetof(struct iwl3945_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);
 
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
-       iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                  txcmd_phys, len, 1, 0);
 
        if (info->control.hw_key)
                iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0);
@@ -2606,60 +1562,52 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
        if (len) {
                phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
                                           len, PCI_DMA_TODEVICE);
-               iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
+               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+                                                          phys_addr, len,
+                                                          0, U32_PAD(len));
        }
 
-       if (!len)
-               /* If there is no payload, then we use only one Tx buffer */
-               *control_flags = TFD_CTL_COUNT_SET(1);
-       else
-               /* Else use 2 buffers.
-                * Tell 3945 about any padding after MAC header */
-               *control_flags = TFD_CTL_COUNT_SET(2) |
-                       TFD_CTL_PAD_SET(U32_PAD(len));
-
        /* Total # bytes to be transmitted */
        len = (u16)skb->len;
-       out_cmd->cmd.tx.len = cpu_to_le16(len);
+       tx->len = cpu_to_le16(len);
 
        /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, unicast, sta_id);
+       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
 
        /* set is_hcca to 0; it probably will never be implemented */
        iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
 
-       out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-       out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
 
        if (!ieee80211_has_morefrags(hdr->frame_control)) {
                txq->need_update = 1;
                if (qc)
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
+                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
        } else {
                wait_write_ptr = 1;
                txq->need_update = 0;
        }
 
-       iwl3945_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
-                          sizeof(out_cmd->cmd.tx));
+       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
 
-       iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
                           ieee80211_hdrlen(fc));
 
        /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-       rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
+       rc = iwl_txq_update_write_ptr(priv, txq);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        if (rc)
                return rc;
 
-       if ((iwl3945_queue_space(q) < q->high_mark)
+       if ((iwl_queue_space(q) < q->high_mark)
            && priv->mac80211_registered) {
                if (wait_write_ptr) {
                        spin_lock_irqsave(&priv->lock, flags);
                        txq->need_update = 1;
-                       iwl3945_tx_queue_update_write_ptr(priv, txq);
+                       iwl_txq_update_write_ptr(priv, txq);
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
 
@@ -2674,15 +1622,15 @@ drop:
        return -1;
 }
 
-static void iwl3945_set_rate(struct iwl3945_priv *priv)
+static void iwl3945_set_rate(struct iwl_priv *priv)
 {
        const struct ieee80211_supported_band *sband = NULL;
        struct ieee80211_rate *rate;
        int i;
 
-       sband = iwl3945_get_band(priv, priv->band);
+       sband = iwl_get_hw_mode(priv, priv->band);
        if (!sband) {
-               IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+               IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
                return;
        }
 
@@ -2711,24 +1659,24 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv)
         * OFDM
         */
        if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
-               priv->staging_rxon.cck_basic_rates =
+               priv->staging39_rxon.cck_basic_rates =
                    ((priv->active_rate_basic &
                      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
        else
-               priv->staging_rxon.cck_basic_rates =
+               priv->staging39_rxon.cck_basic_rates =
                    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 
        if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
-               priv->staging_rxon.ofdm_basic_rates =
+               priv->staging39_rxon.ofdm_basic_rates =
                    ((priv->active_rate_basic &
                      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
                      IWL_FIRST_OFDM_RATE) & 0xFF;
        else
-               priv->staging_rxon.ofdm_basic_rates =
+               priv->staging39_rxon.ofdm_basic_rates =
                   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 }
 
-static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
+static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
 {
        unsigned long flags;
 
@@ -2739,21 +1687,21 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
                          disable_radio ? "OFF" : "ON");
 
        if (disable_radio) {
-               iwl3945_scan_cancel(priv);
+               iwl_scan_cancel(priv);
                /* FIXME: This is a workaround for AP */
                if (priv->iw_mode != NL80211_IFTYPE_AP) {
                        spin_lock_irqsave(&priv->lock, flags);
-                       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
+                       iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
                                    CSR_UCODE_SW_BIT_RFKILL);
                        spin_unlock_irqrestore(&priv->lock, flags);
-                       iwl3945_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
+                       iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
                        set_bit(STATUS_RF_KILL_SW, &priv->status);
                }
                return;
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
        clear_bit(STATUS_RF_KILL_SW, &priv->status);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -2762,9 +1710,9 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
        msleep(10);
 
        spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
-       if (!iwl3945_grab_nic_access(priv))
-               iwl3945_release_nic_access(priv);
+       iwl_read32(priv, CSR_UCODE_DRV_GP1);
+       if (!iwl_grab_nic_access(priv))
+               iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
@@ -2778,13 +1726,13 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
        return;
 }
 
-void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
+void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
                            u32 decrypt_res, struct ieee80211_rx_status *stats)
 {
        u16 fc =
            le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control);
 
-       if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
+       if (priv->active39_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
                return;
 
        if (!(fc & IEEE80211_FCTL_PROTECTED))
@@ -2863,13 +1811,13 @@ static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
        return cpu_to_le32(res);
 }
 
-static int iwl3945_get_measurement(struct iwl3945_priv *priv,
+static int iwl3945_get_measurement(struct iwl_priv *priv,
                               struct ieee80211_measurement_params *params,
                               u8 type)
 {
-       struct iwl3945_spectrum_cmd spectrum;
-       struct iwl3945_rx_packet *res;
-       struct iwl3945_host_cmd cmd = {
+       struct iwl_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,
@@ -2905,17 +1853,17 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
        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)
+       if (priv->active39_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 = iwl3945_send_cmd_sync(priv, &cmd);
+       rc = iwl_send_cmd_sync(priv, &cmd);
        if (rc)
                return rc;
 
-       res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
+       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");
+               IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
                rc = -EIO;
        }
 
@@ -2942,11 +1890,11 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
 }
 #endif
 
-static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
-                              struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
+                              struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_alive_resp *palive;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_alive_resp *palive;
        struct delayed_work *pwork;
 
        palive = &pkt->u.alive_frame;
@@ -2958,14 +1906,13 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
 
        if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
                IWL_DEBUG_INFO("Initialization Alive received.\n");
-               memcpy(&priv->card_alive_init,
-                      &pkt->u.alive_frame,
-                      sizeof(struct iwl3945_init_alive_resp));
+               memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
+                      sizeof(struct iwl_alive_resp));
                pwork = &priv->init_alive_start;
        } else {
                IWL_DEBUG_INFO("Runtime Alive received.\n");
                memcpy(&priv->card_alive, &pkt->u.alive_frame,
-                      sizeof(struct iwl3945_alive_resp));
+                      sizeof(struct iwl_alive_resp));
                pwork = &priv->alive_start;
                iwl3945_disable_events(priv);
        }
@@ -2976,24 +1923,26 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
                queue_delayed_work(priv->workqueue, pwork,
                                   msecs_to_jiffies(5));
        else
-               IWL_WARNING("uCode did not respond OK.\n");
+               IWL_WARN(priv, "uCode did not respond OK.\n");
 }
 
-static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv,
-                                struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
+                                struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+#endif
 
        IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
        return;
 }
 
-static void iwl3945_rx_reply_error(struct iwl3945_priv *priv,
-                              struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_error(struct iwl_priv *priv,
+                              struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
 
-       IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
+       IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
                "seq 0x%04X ser 0x%08X\n",
                le32_to_cpu(pkt->u.err_resp.error_type),
                get_cmd_string(pkt->u.err_resp.cmd_id),
@@ -3004,23 +1953,23 @@ static void iwl3945_rx_reply_error(struct iwl3945_priv *priv,
 
 #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
 
-static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon;
-       struct iwl3945_csa_notification *csa = &(pkt->u.csa_notif);
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl3945_rxon_cmd *rxon = (void *)&priv->active39_rxon;
+       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;
+       priv->staging39_rxon.channel = csa->channel;
 }
 
-static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv,
-                                         struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv,
+                                         struct iwl_rx_mem_buffer *rxb)
 {
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_spectrum_notification *report = &(pkt->u.spectrum_notif);
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
 
        if (!report->state) {
                IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
@@ -3033,38 +1982,39 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv,
 #endif
 }
 
-static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv,
-                                 struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv,
+                                 struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWL3945_DEBUG
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_sleep_notification *sleep = &(pkt->u.sleep_notif);
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       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 iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv,
-                                            struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+                                            struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
                        "notification for %s:\n",
                        le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-       iwl3945_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+       iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw,
+                          le32_to_cpu(pkt->len));
 }
 
 static void iwl3945_bg_beacon_update(struct work_struct *work)
 {
-       struct iwl3945_priv *priv =
-               container_of(work, struct iwl3945_priv, beacon_update);
+       struct iwl_priv *priv =
+               container_of(work, struct iwl_priv, beacon_update);
        struct sk_buff *beacon;
 
        /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
        beacon = ieee80211_beacon_get(priv->hw, priv->vif);
 
        if (!beacon) {
-               IWL_ERROR("update beacon failed\n");
+               IWL_ERR(priv, "update beacon failed\n");
                return;
        }
 
@@ -3079,11 +2029,11 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
        iwl3945_send_beacon_cmd(priv);
 }
 
-static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
-                               struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
+                               struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWL3945_DEBUG
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
        u8 rate = beacon->beacon_notify_hdr.rate;
 
@@ -3102,25 +2052,25 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
 }
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv,
-                             struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_scan(struct iwl_priv *priv,
+                             struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWL3945_DEBUG
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_scanreq_notification *notif =
-           (struct iwl3945_scanreq_notification *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_scanreq_notification *notif =
+           (struct iwl_scanreq_notification *)pkt->u.raw;
 
        IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
 #endif
 }
 
 /* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv,
-                                   struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_scanstart_notification *notif =
-           (struct iwl3945_scanstart_notification *)pkt->u.raw;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_scanstart_notification *notif =
+           (struct iwl_scanstart_notification *)pkt->u.raw;
        priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
        IWL_DEBUG_SCAN("Scan start: "
                       "%d [802.11%s] "
@@ -3132,12 +2082,14 @@ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv,
 }
 
 /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv,
-                                     struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv,
+                                     struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_scanresults_notification *notif =
-           (struct iwl3945_scanresults_notification *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_scanresults_notification *notif =
+           (struct iwl_scanresults_notification *)pkt->u.raw;
+#endif
 
        IWL_DEBUG_SCAN("Scan ch.res: "
                       "%d [802.11%s] "
@@ -3157,11 +2109,13 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv,
 }
 
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,
-                                      struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv,
+                                      struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-       struct iwl3945_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+#endif
 
        IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
                       scan_notif->scanned_channels,
@@ -3220,10 +2174,10 @@ reschedule:
 
 /* Handle notification from uCode that card's power state is changing
  * due to software, hardware, or critical temperature RFKILL */
-static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv,
-                                   struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
        u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
        unsigned long status = priv->status;
 
@@ -3231,7 +2185,7 @@ static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv,
                          (flags & HW_CARD_DISABLED) ? "Kill" : "On",
                          (flags & SW_CARD_DISABLED) ? "Kill" : "On");
 
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
                    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
 
        if (flags & HW_CARD_DISABLED)
@@ -3245,7 +2199,7 @@ static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv,
        else
                clear_bit(STATUS_RF_KILL_SW, &priv->status);
 
-       iwl3945_scan_cancel(priv);
+       iwl_scan_cancel(priv);
 
        if ((test_bit(STATUS_RF_KILL_HW, &status) !=
             test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
@@ -3265,7 +2219,7 @@ static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv,
  * This function chains into the hardware specific files for them to setup
  * any hardware specific handlers as well.
  */
-static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
+static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
 {
        priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
        priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
@@ -3303,15 +2257,15 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
  * When FW advances 'R' index, all entries between old and new 'R' index
  * need to be reclaimed.
  */
-static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
+static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv,
                                      int txq_id, int index)
 {
-       struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl3945_queue *q = &txq->q;
+       struct iwl_tx_queue *txq = &priv->txq[txq_id];
+       struct iwl_queue *q = &txq->q;
        int nfreed = 0;
 
-       if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
-               IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
+       if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
+               IWL_ERR(priv, "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);
                return;
@@ -3320,7 +2274,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
        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)) {
                if (nfreed > 1) {
-                       IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
+                       IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", index,
                                        q->write_ptr, q->read_ptr);
                        queue_work(priv->workqueue, &priv->restart);
                        break;
@@ -3338,21 +2292,28 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
  * will be executed.  The attached skb (if present) will only be freed
  * if the callback returns 1
  */
-static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
-                               struct iwl3945_rx_mem_buffer *rxb)
+static void iwl3945_tx_cmd_complete(struct iwl_priv *priv,
+                               struct iwl_rx_mem_buffer *rxb)
 {
-       struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
+       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
        int txq_id = SEQ_TO_QUEUE(sequence);
        int index = SEQ_TO_INDEX(sequence);
-       int huge = sequence & SEQ_HUGE_FRAME;
+       int huge =  !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
        int cmd_index;
-       struct iwl3945_cmd *cmd;
-
-       BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
+       struct iwl_cmd *cmd;
+
+       if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
+                "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];
+       cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
 
        /* Input error checking is done when commands are added to queue. */
        if (cmd->meta.flags & CMD_WANT_SKB) {
@@ -3417,7 +2378,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
  *
  * Driver sequence:
  *
- * iwl3945_rx_queue_alloc()   Allocates rx_free
  * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
  *                            iwl3945_rx_queue_restock
  * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
@@ -3426,7 +2386,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
  *                            are available, schedules iwl3945_rx_replenish
  *
  * -- enable interrupts --
- * ISR - iwl3945_rx()         Detach iwl3945_rx_mem_buffers from pool up to the
+ * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
  *                            READ INDEX, detaching the SKB from the pool.
  *                            Moves the packet buffer from queue to rx_used.
  *                            Calls iwl3945_rx_queue_restock to refill any empty
@@ -3435,71 +2395,10 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
  *
  */
 
-/**
- * iwl3945_rx_queue_space - Return number of free slots available in queue.
- */
-static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q)
-{
-       int s = q->read - q->write;
-       if (s <= 0)
-               s += RX_QUEUE_SIZE;
-       /* keep some buffer to not confuse full and empty queue */
-       s -= 2;
-       if (s < 0)
-               s = 0;
-       return s;
-}
-
-/**
- * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_rx_queue *q)
-{
-       u32 reg = 0;
-       int rc = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&q->lock, flags);
-
-       if (q->need_update == 0)
-               goto exit_unlock;
-
-       /* If power-saving is in use, make sure device is awake */
-       if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-               reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
-
-               if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-                       iwl3945_set_bit(priv, CSR_GP_CNTRL,
-                                   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                       goto exit_unlock;
-               }
-
-               rc = iwl3945_grab_nic_access(priv);
-               if (rc)
-                       goto exit_unlock;
-
-               /* Device expects a multiple of 8 */
-               iwl3945_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
-                                    q->write & ~0x7);
-               iwl3945_release_nic_access(priv);
-
-       /* Else device is assumed to be awake */
-       } else
-               /* Device expects a multiple of 8 */
-               iwl3945_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
-
-
-       q->need_update = 0;
-
- exit_unlock:
-       spin_unlock_irqrestore(&q->lock, flags);
-       return rc;
-}
-
 /**
  * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
  */
-static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv,
+static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
                                          dma_addr_t dma_addr)
 {
        return cpu_to_le32((u32)dma_addr);
@@ -3516,24 +2415,24 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv,
  * also updates the memory address in the firmware to reference the new
  * target buffer.
  */
-static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
+static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
 {
-       struct iwl3945_rx_queue *rxq = &priv->rxq;
+       struct iwl_rx_queue *rxq = &priv->rxq;
        struct list_head *element;
-       struct iwl3945_rx_mem_buffer *rxb;
+       struct iwl_rx_mem_buffer *rxb;
        unsigned long flags;
        int write, rc;
 
        spin_lock_irqsave(&rxq->lock, flags);
        write = rxq->write & ~0x7;
-       while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+       while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
                /* Get next free Rx buffer, remove from free list */
                element = rxq->rx_free.next;
-               rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
+               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
                list_del(element);
 
                /* Point to Rx buffer via next RBD in circular buffer */
-               rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+               rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);
                rxq->queue[rxq->write] = rxb;
                rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
                rxq->free_count--;
@@ -3552,7 +2451,7 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
                spin_lock_irqsave(&rxq->lock, flags);
                rxq->need_update = 1;
                spin_unlock_irqrestore(&rxq->lock, flags);
-               rc = iwl3945_rx_queue_update_write_ptr(priv, rxq);
+               rc = iwl_rx_queue_update_write_ptr(priv, rxq);
                if (rc)
                        return rc;
        }
@@ -3568,24 +2467,24 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
  * Also restock the Rx queue via iwl3945_rx_queue_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
+static void iwl3945_rx_allocate(struct iwl_priv *priv)
 {
-       struct iwl3945_rx_queue *rxq = &priv->rxq;
+       struct iwl_rx_queue *rxq = &priv->rxq;
        struct list_head *element;
-       struct iwl3945_rx_mem_buffer *rxb;
+       struct iwl_rx_mem_buffer *rxb;
        unsigned long flags;
        spin_lock_irqsave(&rxq->lock, flags);
        while (!list_empty(&rxq->rx_used)) {
                element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
+               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
 
                /* Alloc a new receive buffer */
                rxb->skb =
-                   alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
+                   alloc_skb(priv->hw_params.rx_buf_size,
+                               __GFP_NOWARN | GFP_ATOMIC);
                if (!rxb->skb) {
                        if (net_ratelimit())
-                               printk(KERN_CRIT DRV_NAME
-                                      ": Can not allocate SKB buffers\n");
+                               IWL_CRIT(priv, ": 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 */
@@ -3604,9 +2503,10 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
                list_del(element);
 
                /* Get physical address of RB/SKB */
-               rxb->dma_addr =
-                   pci_map_single(priv->pci_dev, rxb->skb->data,
-                                  IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+               rxb->real_dma_addr = pci_map_single(priv->pci_dev,
+                                               rxb->skb->data,
+                                               priv->hw_params.rx_buf_size,
+                                               PCI_DMA_FROMDEVICE);
                list_add_tail(&rxb->list, &rxq->rx_free);
                rxq->free_count++;
        }
@@ -3618,7 +2518,7 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
  */
 static void __iwl3945_rx_replenish(void *data)
 {
-       struct iwl3945_priv *priv = data;
+       struct iwl_priv *priv = data;
 
        iwl3945_rx_allocate(priv);
        iwl3945_rx_queue_restock(priv);
@@ -3627,7 +2527,7 @@ static void __iwl3945_rx_replenish(void *data)
 
 void iwl3945_rx_replenish(void *data)
 {
-       struct iwl3945_priv *priv = data;
+       struct iwl_priv *priv = data;
        unsigned long flags;
 
        iwl3945_rx_allocate(priv);
@@ -3637,84 +2537,6 @@ void iwl3945_rx_replenish(void *data)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
-static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
-{
-       int i;
-       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-               if (rxq->pool[i].skb != NULL) {
-                       pci_unmap_single(priv->pci_dev,
-                                        rxq->pool[i].dma_addr,
-                                        IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb(rxq->pool[i].skb);
-               }
-       }
-
-       pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                           rxq->dma_addr);
-       rxq->bd = NULL;
-}
-
-int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv)
-{
-       struct iwl3945_rx_queue *rxq = &priv->rxq;
-       struct pci_dev *dev = priv->pci_dev;
-       int i;
-
-       spin_lock_init(&rxq->lock);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-
-       /* 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;
-
-       /* Fill the rx_used queue with _all_ of the Rx buffers */
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-
-       /* Set us so that we have processed and used all buffers, but have
-        * not restocked the Rx queue with fresh buffers */
-       rxq->read = rxq->write = 0;
-       rxq->free_count = 0;
-       rxq->need_update = 0;
-       return 0;
-}
-
-void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
-{
-       unsigned long flags;
-       int i;
-       spin_lock_irqsave(&rxq->lock, flags);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-       /* Fill the rx_used queue with _all_ of the Rx buffers */
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-               /* In the reset function, these buffers may have been allocated
-                * to an SKB, so we need to unmap and free potential storage */
-               if (rxq->pool[i].skb != NULL) {
-                       pci_unmap_single(priv->pci_dev,
-                                        rxq->pool[i].dma_addr,
-                                        IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       priv->alloc_rxb_skb--;
-                       dev_kfree_skb(rxq->pool[i].skb);
-                       rxq->pool[i].skb = NULL;
-               }
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-       }
-
-       /* Set us so that we have processed and used all buffers, but have
-        * not restocked the Rx queue with fresh buffers */
-       rxq->read = rxq->write = 0;
-       rxq->free_count = 0;
-       spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
 /* Convert linear signal-to-noise ratio into dB */
 static u8 ratio2dB[100] = {
 /*      0   1   2   3   4   5   6   7   8   9 */
@@ -3800,11 +2622,11 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
  * the appropriate handlers, including command responses,
  * frame-received notifications, and other notifications.
  */
-static void iwl3945_rx_handle(struct iwl3945_priv *priv)
+static void iwl3945_rx_handle(struct iwl_priv *priv)
 {
-       struct iwl3945_rx_mem_buffer *rxb;
-       struct iwl3945_rx_packet *pkt;
-       struct iwl3945_rx_queue *rxq = &priv->rxq;
+       struct iwl_rx_mem_buffer *rxb;
+       struct iwl_rx_packet *pkt;
+       struct iwl_rx_queue *rxq = &priv->rxq;
        u32 r, i;
        int reclaim;
        unsigned long flags;
@@ -3813,10 +2635,10 @@ static void iwl3945_rx_handle(struct iwl3945_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 = iwl3945_hw_get_rx_read(priv);
+       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
        i = rxq->read;
 
-       if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+       if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
                fill_rx = 1;
        /* Rx interrupt, but nothing sent from uCode */
        if (i == r)
@@ -3832,10 +2654,10 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
-                                           IWL_RX_BUF_SIZE,
+               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
+                                           priv->hw_params.rx_buf_size,
                                            PCI_DMA_FROMDEVICE);
-               pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
+               pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
                /* Reclaim a command buffer only if this packet is a response
                 *   to a (driver-originated) command.
@@ -3851,13 +2673,13 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
                 *   handle those that need handling via function in
                 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
                if (priv->rx_handlers[pkt->hdr.cmd]) {
-                       IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
+                       IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
                                "r = %d, i = %d, %s, 0x%02x\n", r, i,
                                get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
                        priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
                } else {
                        /* No handling needed */
-                       IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
+                       IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
                                "r %d i %d No handler needed for %s, 0x%02x\n",
                                r, i, get_cmd_string(pkt->hdr.cmd),
                                pkt->hdr.cmd);
@@ -3865,12 +2687,12 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
 
                if (reclaim) {
                        /* Invoke any callbacks, transfer the skb to caller, and
-                        * fire off the (possibly) blocking iwl3945_send_cmd()
+                        * fire off the (possibly) blocking iwl_send_cmd()
                         * as we reclaim the driver command queue */
                        if (rxb && rxb->skb)
                                iwl3945_tx_cmd_complete(priv, rxb);
                        else
-                               IWL_WARNING("Claim null rxb?\n");
+                               IWL_WARN(priv, "Claim null rxb?\n");
                }
 
                /* For now we just don't re-use anything.  We can tweak this
@@ -3882,8 +2704,9 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
                        rxb->skb = NULL;
                }
 
-               pci_unmap_single(priv->pci_dev, rxb->dma_addr,
-                                IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+                               priv->hw_params.rx_buf_size,
+                               PCI_DMA_FROMDEVICE);
                spin_lock_irqsave(&rxq->lock, flags);
                list_add_tail(&rxb->list, &priv->rxq.rx_used);
                spin_unlock_irqrestore(&rxq->lock, flags);
@@ -3905,57 +2728,12 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
        iwl3945_rx_queue_restock(priv);
 }
 
-/**
- * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware
- */
-static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
-                                 struct iwl3945_tx_queue *txq)
-{
-       u32 reg = 0;
-       int rc = 0;
-       int txq_id = txq->q.id;
-
-       if (txq->need_update == 0)
-               return rc;
-
-       /* if we're trying to save power */
-       if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-               /* wake up nic if it's powered down ...
-                * uCode will wake up, and interrupt us again, so next
-                * time we'll skip this part. */
-               reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
-
-               if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-                       IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
-                       iwl3945_set_bit(priv, CSR_GP_CNTRL,
-                                   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                       return rc;
-               }
-
-               /* restore this queue's parameters in nic hardware. */
-               rc = iwl3945_grab_nic_access(priv);
-               if (rc)
-                       return rc;
-               iwl3945_write_direct32(priv, HBUS_TARG_WRPTR,
-                                    txq->q.write_ptr | (txq_id << 8));
-               iwl3945_release_nic_access(priv);
-
-       /* else not in power-save mode, uCode will never sleep when we're
-        * trying to tx (during RFKILL, we're not trying to tx). */
-       } else
-               iwl3945_write32(priv, HBUS_TARG_WRPTR,
-                           txq->q.write_ptr | (txq_id << 8));
-
-       txq->need_update = 0;
-
-       return rc;
-}
-
-#ifdef CONFIG_IWL3945_DEBUG
-static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
+#ifdef CONFIG_IWLWIFI_DEBUG
+static void iwl3945_print_rx_config_cmd(struct iwl_priv *priv,
+                                       struct iwl3945_rxon_cmd *rxon)
 {
        IWL_DEBUG_RADIO("RX CONFIG:\n");
-       iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+       iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
        IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
        IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
        IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
@@ -3970,16 +2748,16 @@ static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
 }
 #endif
 
-static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
+static void iwl3945_enable_interrupts(struct iwl_priv *priv)
 {
        IWL_DEBUG_ISR("Enabling interrupts\n");
        set_bit(STATUS_INT_ENABLED, &priv->status);
-       iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+       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 iwl3945_priv *priv)
+static inline void iwl_synchronize_irq(struct iwl_priv *priv)
 {
        /* wait to make sure we flush pending tasklet*/
        synchronize_irq(priv->pci_dev->irq);
@@ -3987,17 +2765,17 @@ static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
 }
 
 
-static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv)
+static inline void iwl3945_disable_interrupts(struct iwl_priv *priv)
 {
        clear_bit(STATUS_INT_ENABLED, &priv->status);
 
        /* disable interrupts from uCode/NIC to host */
-       iwl3945_write32(priv, CSR_INT_MASK, 0x00000000);
+       iwl_write32(priv, CSR_INT_MASK, 0x00000000);
 
        /* acknowledge/clear/reset any interrupts still pending
         * from uCode or flow handler (Rx/Tx DMA) */
-       iwl3945_write32(priv, CSR_INT, 0xffffffff);
-       iwl3945_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+       iwl_write32(priv, CSR_INT, 0xffffffff);
+       iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
        IWL_DEBUG_ISR("Disabled interrupts\n");
 }
 
@@ -4024,7 +2802,7 @@ static const char *desc_lookup(int i)
 #define ERROR_START_OFFSET  (1 * sizeof(u32))
 #define ERROR_ELEM_SIZE     (7 * sizeof(u32))
 
-static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
+static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 {
        u32 i;
        u32 desc, time, count, base, data1;
@@ -4034,49 +2812,50 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
        base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 
        if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
+               IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
                return;
        }
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
+               IWL_WARN(priv, "Can not read from adapter at this time.\n");
                return;
        }
 
-       count = iwl3945_read_targ_mem(priv, base);
+       count = iwl_read_targ_mem(priv, base);
 
        if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-               IWL_ERROR("Start IWL Error Log Dump:\n");
-               IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+               IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+               IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+                       priv->status, count);
        }
 
-       IWL_ERROR("Desc       Time       asrtPC  blink2 "
+       IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
                  "ilink1  nmiPC   Line\n");
        for (i = ERROR_START_OFFSET;
             i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
             i += ERROR_ELEM_SIZE) {
-               desc = iwl3945_read_targ_mem(priv, base + i);
+               desc = iwl_read_targ_mem(priv, base + i);
                time =
-                   iwl3945_read_targ_mem(priv, base + i + 1 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32));
                blink1 =
-                   iwl3945_read_targ_mem(priv, base + i + 2 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32));
                blink2 =
-                   iwl3945_read_targ_mem(priv, base + i + 3 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32));
                ilink1 =
-                   iwl3945_read_targ_mem(priv, base + i + 4 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32));
                ilink2 =
-                   iwl3945_read_targ_mem(priv, base + i + 5 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32));
                data1 =
-                   iwl3945_read_targ_mem(priv, base + i + 6 * sizeof(u32));
+                   iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
 
-               IWL_ERROR
-                   ("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
-                    desc_lookup(desc), desc, time, blink1, blink2,
-                    ilink1, ilink2, data1);
+               IWL_ERR(priv,
+                       "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+                       desc_lookup(desc), desc, time, blink1, blink2,
+                       ilink1, ilink2, data1);
        }
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 
 }
 
@@ -4085,9 +2864,9 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
 /**
  * iwl3945_print_event_log - Dump error event log to syslog
  *
- * NOTE: Must be called with iwl3945_grab_nic_access() already obtained!
+ * NOTE: Must be called with iwl_grab_nic_access() already obtained!
  */
-static void iwl3945_print_event_log(struct iwl3945_priv *priv, u32 start_idx,
+static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
                                u32 num_events, u32 mode)
 {
        u32 i;
@@ -4111,21 +2890,22 @@ static void iwl3945_print_event_log(struct iwl3945_priv *priv, u32 start_idx,
        /* "time" is actually "data" for mode 0 (no timestamp).
         * place event id # at far right for easier visual parsing. */
        for (i = 0; i < num_events; i++) {
-               ev = iwl3945_read_targ_mem(priv, ptr);
+               ev = iwl_read_targ_mem(priv, ptr);
                ptr += sizeof(u32);
-               time = iwl3945_read_targ_mem(priv, ptr);
+               time = iwl_read_targ_mem(priv, ptr);
                ptr += sizeof(u32);
-               if (mode == 0)
-                       IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
-               else {
-                       data = iwl3945_read_targ_mem(priv, ptr);
+               if (mode == 0) {
+                       /* data, ev */
+                       IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
+               } else {
+                       data = iwl_read_targ_mem(priv, ptr);
                        ptr += sizeof(u32);
-                       IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
+                       IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
                }
        }
 }
 
-static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv)
+static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 {
        int rc;
        u32 base;       /* SRAM byte address of event log header */
@@ -4137,32 +2917,32 @@ static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv)
 
        base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
        if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+               IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
                return;
        }
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
+               IWL_WARN(priv, "Can not read from adapter at this time.\n");
                return;
        }
 
        /* event log header */
-       capacity = iwl3945_read_targ_mem(priv, base);
-       mode = iwl3945_read_targ_mem(priv, base + (1 * sizeof(u32)));
-       num_wraps = iwl3945_read_targ_mem(priv, base + (2 * sizeof(u32)));
-       next_entry = iwl3945_read_targ_mem(priv, base + (3 * sizeof(u32)));
+       capacity = iwl_read_targ_mem(priv, base);
+       mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+       num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+       next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 
        size = num_wraps ? capacity : next_entry;
 
        /* bail out if nothing in log */
        if (size == 0) {
-               IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
-               iwl3945_release_nic_access(priv);
+               IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+               iwl_release_nic_access(priv);
                return;
        }
 
-       IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
+       IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
                  size, num_wraps);
 
        /* if uCode has wrapped back to top of log, start at the oldest entry,
@@ -4174,13 +2954,13 @@ static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv)
        /* (then/else) start at top of log */
        iwl3945_print_event_log(priv, 0, next_entry, mode);
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 }
 
 /**
  * iwl3945_irq_handle_error - called for HW or SW error interrupt from card
  */
-static void iwl3945_irq_handle_error(struct iwl3945_priv *priv)
+static void iwl3945_irq_handle_error(struct iwl_priv *priv)
 {
        /* Set the FW error flag -- cleared on iwl3945_down */
        set_bit(STATUS_FW_ERROR, &priv->status);
@@ -4188,11 +2968,11 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv)
        /* Cancel currently queued command. */
        clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 
-#ifdef CONFIG_IWL3945_DEBUG
-       if (iwl3945_debug_level & IWL_DL_FW_ERRORS) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (priv->debug_level & IWL_DL_FW_ERRORS) {
                iwl3945_dump_nic_error_log(priv);
                iwl3945_dump_nic_event_log(priv);
-               iwl3945_print_rx_config_cmd(&priv->staging_rxon);
+               iwl3945_print_rx_config_cmd(priv, &priv->staging39_rxon);
        }
 #endif
 
@@ -4207,37 +2987,38 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv)
                          "Restarting adapter due to uCode error.\n");
 
                if (iwl3945_is_associated(priv)) {
-                       memcpy(&priv->recovery_rxon, &priv->active_rxon,
-                              sizeof(priv->recovery_rxon));
+                       memcpy(&priv->recovery39_rxon, &priv->active39_rxon,
+                              sizeof(priv->recovery39_rxon));
                        priv->error_recovering = 1;
                }
-               queue_work(priv->workqueue, &priv->restart);
+               if (priv->cfg->mod_params->restart_fw)
+                       queue_work(priv->workqueue, &priv->restart);
        }
 }
 
-static void iwl3945_error_recovery(struct iwl3945_priv *priv)
+static void iwl3945_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;
+       memcpy(&priv->staging39_rxon, &priv->recovery39_rxon,
+              sizeof(priv->staging39_rxon));
+       priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        iwl3945_commit_rxon(priv);
 
        iwl3945_add_station(priv, priv->bssid, 1, 0);
 
        spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
+       priv->assoc_id = le16_to_cpu(priv->staging39_rxon.assoc_id);
        priv->error_recovering = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta, handled = 0;
        u32 inta_fh;
        unsigned long flags;
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
        u32 inta_mask;
 #endif
 
@@ -4246,19 +3027,19 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
        /* Ack/clear/reset pending uCode interrupts.
         * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
         *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
-       inta = iwl3945_read32(priv, CSR_INT);
-       iwl3945_write32(priv, CSR_INT, inta);
+       inta = iwl_read32(priv, CSR_INT);
+       iwl_write32(priv, CSR_INT, inta);
 
        /* Ack/clear/reset pending flow-handler (DMA) interrupts.
         * Any new interrupts that happen after this, either while we're
         * in this tasklet, or later, will show up in next ISR/tasklet. */
-       inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
-       iwl3945_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+       inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+       iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
 
-#ifdef CONFIG_IWL3945_DEBUG
-       if (iwl3945_debug_level & IWL_DL_ISR) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (priv->debug_level & IWL_DL_ISR) {
                /* just for debug */
-               inta_mask = iwl3945_read32(priv, CSR_INT_MASK);
+               inta_mask = iwl_read32(priv, CSR_INT_MASK);
                IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
                              inta, inta_mask, inta_fh);
        }
@@ -4275,7 +3056,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 
        /* Now service all interrupt bits discovered above. */
        if (inta & CSR_INT_BIT_HW_ERR) {
-               IWL_ERROR("Microcode HW error detected.  Restarting.\n");
+               IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
 
                /* Tell the device to stop sending interrupts */
                iwl3945_disable_interrupts(priv);
@@ -4289,8 +3070,8 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
                return;
        }
 
-#ifdef CONFIG_IWL3945_DEBUG
-       if (iwl3945_debug_level & (IWL_DL_ISR)) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (priv->debug_level & (IWL_DL_ISR)) {
                /* NIC fires this, but we don't use it, redundant with WAKEUP */
                if (inta & CSR_INT_BIT_SCD)
                        IWL_DEBUG_ISR("Scheduler finished to transmit "
@@ -4306,461 +3087,149 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 
        /* Error detected by uCode */
        if (inta & CSR_INT_BIT_SW_ERR) {
-               IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
-                         inta);
+               IWL_ERR(priv, "Microcode SW error detected. "
+                       "Restarting 0x%X.\n", inta);
                iwl3945_irq_handle_error(priv);
                handled |= CSR_INT_BIT_SW_ERR;
        }
 
-       /* uCode wakes up after power-down sleep */
-       if (inta & CSR_INT_BIT_WAKEUP) {
-               IWL_DEBUG_ISR("Wakeup interrupt\n");
-               iwl3945_rx_queue_update_write_ptr(priv, &priv->rxq);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[3]);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[4]);
-               iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[5]);
-
-               handled |= CSR_INT_BIT_WAKEUP;
-       }
-
-       /* All uCode command responses, including Tx command responses,
-        * Rx "responses" (frame-received notification), and other
-        * notifications from uCode come through here*/
-       if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
-               iwl3945_rx_handle(priv);
-               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-       }
-
-       if (inta & CSR_INT_BIT_FH_TX) {
-               IWL_DEBUG_ISR("Tx interrupt\n");
-
-               iwl3945_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-               if (!iwl3945_grab_nic_access(priv)) {
-                       iwl3945_write_direct32(priv,
-                                            FH_TCSR_CREDIT
-                                            (ALM_FH_SRVC_CHNL), 0x0);
-                       iwl3945_release_nic_access(priv);
-               }
-               handled |= CSR_INT_BIT_FH_TX;
-       }
-
-       if (inta & ~handled)
-               IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
-
-       if (inta & ~CSR_INI_SET_MASK) {
-               IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~CSR_INI_SET_MASK);
-               IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
-       }
-
-       /* Re-enable all interrupts */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl3945_enable_interrupts(priv);
-
-#ifdef CONFIG_IWL3945_DEBUG
-       if (iwl3945_debug_level & (IWL_DL_ISR)) {
-               inta = iwl3945_read32(priv, CSR_INT);
-               inta_mask = iwl3945_read32(priv, CSR_INT_MASK);
-               inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
-               IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-                       "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-       }
-#endif
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static irqreturn_t iwl3945_isr(int irq, void *data)
-{
-       struct iwl3945_priv *priv = data;
-       u32 inta, inta_mask;
-       u32 inta_fh;
-       if (!priv)
-               return IRQ_NONE;
-
-       spin_lock(&priv->lock);
-
-       /* Disable (but don't clear!) interrupts here to avoid
-        *    back-to-back ISRs and sporadic interrupts from our NIC.
-        * If we have something to service, the tasklet will re-enable ints.
-        * If we *don't* have something, we'll re-enable before leaving here. */
-       inta_mask = iwl3945_read32(priv, CSR_INT_MASK);  /* just for debug */
-       iwl3945_write32(priv, CSR_INT_MASK, 0x00000000);
-
-       /* Discover which interrupts are active/pending */
-       inta = iwl3945_read32(priv, CSR_INT);
-       inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
-
-       /* Ignore interrupt if there's nothing in NIC to service.
-        * This may be due to IRQ shared with another device,
-        * or due to sporadic interrupts thrown from our NIC. */
-       if (!inta && !inta_fh) {
-               IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
-               goto none;
-       }
-
-       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-               /* Hardware disappeared */
-               IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
-               goto unplugged;
-       }
-
-       IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                     inta, inta_mask, inta_fh);
-
-       inta &= ~CSR_INT_BIT_SCD;
-
-       /* iwl3945_irq_tasklet() will service interrupts and re-enable them */
-       if (likely(inta || inta_fh))
-               tasklet_schedule(&priv->irq_tasklet);
-unplugged:
-       spin_unlock(&priv->lock);
-
-       return IRQ_HANDLED;
-
- none:
-       /* re-enable interrupts here since we don't have anything to service. */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl3945_enable_interrupts(priv);
-       spin_unlock(&priv->lock);
-       return IRQ_NONE;
-}
-
-/************************** EEPROM BANDS ****************************
- *
- * The iwl3945_eeprom_band definitions below provide the mapping from the
- * EEPROM contents to the specific channel number supported for each
- * band.
- *
- * For example, iwl3945_priv->eeprom.band_3_channels[4] from the band_3
- * definition below maps to physical channel 42 in the 5.2GHz spectrum.
- * The specific geography and calibration information for that channel
- * is contained in the eeprom map itself.
- *
- * During init, we copy the eeprom information and channel map
- * information into priv->channel_info_24/52 and priv->channel_map_24/52
- *
- * channel_map_24/52 provides the index in the channel_info array for a
- * given channel.  We have to have two separate maps as there is channel
- * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
- * band_2
- *
- * A value of 0xff stored in the channel_map indicates that the channel
- * is not supported by the hardware at all.
- *
- * A value of 0xfe in the channel_map indicates that the channel is not
- * valid for Tx with the current hardware.  This means that
- * while the system can tune and receive on a given channel, it may not
- * be able to associate or transmit any frames on that
- * channel.  There is no corresponding channel information for that
- * entry.
- *
- *********************************************************************/
-
-/* 2.4 GHz */
-static const u8 iwl3945_eeprom_band_1[14] = {
-       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-};
-
-/* 5.2 GHz bands */
-static const u8 iwl3945_eeprom_band_2[] = {    /* 4915-5080MHz */
-       183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
-};
-
-static const u8 iwl3945_eeprom_band_3[] = {    /* 5170-5320MHz */
-       34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-};
-
-static const u8 iwl3945_eeprom_band_4[] = {    /* 5500-5700MHz */
-       100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-};
-
-static const u8 iwl3945_eeprom_band_5[] = {    /* 5725-5825MHz */
-       145, 149, 153, 157, 161, 165
-};
-
-static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int band,
-                                   int *eeprom_ch_count,
-                                   const struct iwl3945_eeprom_channel
-                                   **eeprom_ch_info,
-                                   const u8 **eeprom_ch_index)
-{
-       switch (band) {
-       case 1:         /* 2.4GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_1);
-               *eeprom_ch_info = priv->eeprom.band_1_channels;
-               *eeprom_ch_index = iwl3945_eeprom_band_1;
-               break;
-       case 2:         /* 4.9GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2);
-               *eeprom_ch_info = priv->eeprom.band_2_channels;
-               *eeprom_ch_index = iwl3945_eeprom_band_2;
-               break;
-       case 3:         /* 5.2GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_3);
-               *eeprom_ch_info = priv->eeprom.band_3_channels;
-               *eeprom_ch_index = iwl3945_eeprom_band_3;
-               break;
-       case 4:         /* 5.5GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4);
-               *eeprom_ch_info = priv->eeprom.band_4_channels;
-               *eeprom_ch_index = iwl3945_eeprom_band_4;
-               break;
-       case 5:         /* 5.7GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5);
-               *eeprom_ch_info = priv->eeprom.band_5_channels;
-               *eeprom_ch_index = iwl3945_eeprom_band_5;
-               break;
-       default:
-               BUG();
-               return;
-       }
-}
-
-/**
- * iwl3945_get_channel_info - Find driver's private channel info
- *
- * Based on band and channel number.
- */
-const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
-                                                   enum ieee80211_band band, u16 channel)
-{
-       int i;
-
-       switch (band) {
-       case IEEE80211_BAND_5GHZ:
-               for (i = 14; i < priv->channel_count; i++) {
-                       if (priv->channel_info[i].channel == channel)
-                               return &priv->channel_info[i];
-               }
-               break;
-
-       case IEEE80211_BAND_2GHZ:
-               if (channel >= 1 && channel <= 14)
-                       return &priv->channel_info[channel - 1];
-               break;
-       case IEEE80211_NUM_BANDS:
-               WARN_ON(1);
-       }
-
-       return NULL;
-}
-
-#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
-                           ? # x " " : "")
-
-/**
- * iwl3945_init_channel_map - Set up driver's info for all possible channels
- */
-static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
-{
-       int eeprom_ch_count = 0;
-       const u8 *eeprom_ch_index = NULL;
-       const struct iwl3945_eeprom_channel *eeprom_ch_info = NULL;
-       int band, ch;
-       struct iwl3945_channel_info *ch_info;
-
-       if (priv->channel_count) {
-               IWL_DEBUG_INFO("Channel map already initialized.\n");
-               return 0;
-       }
-
-       if (priv->eeprom.version < 0x2f) {
-               IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
-                           priv->eeprom.version);
-               return -EINVAL;
-       }
-
-       IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
-
-       priv->channel_count =
-           ARRAY_SIZE(iwl3945_eeprom_band_1) +
-           ARRAY_SIZE(iwl3945_eeprom_band_2) +
-           ARRAY_SIZE(iwl3945_eeprom_band_3) +
-           ARRAY_SIZE(iwl3945_eeprom_band_4) +
-           ARRAY_SIZE(iwl3945_eeprom_band_5);
-
-       IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
+       /* uCode wakes up after power-down sleep */
+       if (inta & CSR_INT_BIT_WAKEUP) {
+               IWL_DEBUG_ISR("Wakeup interrupt\n");
+               iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
+               iwl_txq_update_write_ptr(priv, &priv->txq[0]);
+               iwl_txq_update_write_ptr(priv, &priv->txq[1]);
+               iwl_txq_update_write_ptr(priv, &priv->txq[2]);
+               iwl_txq_update_write_ptr(priv, &priv->txq[3]);
+               iwl_txq_update_write_ptr(priv, &priv->txq[4]);
+               iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
-       priv->channel_info = kzalloc(sizeof(struct iwl3945_channel_info) *
-                                    priv->channel_count, GFP_KERNEL);
-       if (!priv->channel_info) {
-               IWL_ERROR("Could not allocate channel_info\n");
-               priv->channel_count = 0;
-               return -ENOMEM;
+               handled |= CSR_INT_BIT_WAKEUP;
        }
 
-       ch_info = priv->channel_info;
-
-       /* Loop through the 5 EEPROM bands adding them in order to the
-        * channel map we maintain (that contains additional information than
-        * what just in the EEPROM) */
-       for (band = 1; band <= 5; band++) {
-
-               iwl3945_init_band_reference(priv, band, &eeprom_ch_count,
-                                       &eeprom_ch_info, &eeprom_ch_index);
-
-               /* Loop through each band adding each of the channels */
-               for (ch = 0; ch < eeprom_ch_count; ch++) {
-                       ch_info->channel = eeprom_ch_index[ch];
-                       ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
-                           IEEE80211_BAND_5GHZ;
+       /* All uCode command responses, including Tx command responses,
+        * Rx "responses" (frame-received notification), and other
+        * notifications from uCode come through here*/
+       if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+               iwl3945_rx_handle(priv);
+               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+       }
 
-                       /* permanently store EEPROM's channel regulatory flags
-                        *   and max power in channel info database. */
-                       ch_info->eeprom = eeprom_ch_info[ch];
+       if (inta & CSR_INT_BIT_FH_TX) {
+               IWL_DEBUG_ISR("Tx interrupt\n");
 
-                       /* Copy the run-time flags so they are there even on
-                        * invalid channels */
-                       ch_info->flags = eeprom_ch_info[ch].flags;
+               iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
+               if (!iwl_grab_nic_access(priv)) {
+                       iwl_write_direct32(priv, FH39_TCSR_CREDIT
+                                            (FH39_SRVC_CHNL), 0x0);
+                       iwl_release_nic_access(priv);
+               }
+               handled |= CSR_INT_BIT_FH_TX;
+       }
 
-                       if (!(is_channel_valid(ch_info))) {
-                               IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
-                                              "No traffic\n",
-                                              ch_info->channel,
-                                              ch_info->flags,
-                                              is_channel_a_band(ch_info) ?
-                                              "5.2" : "2.4");
-                               ch_info++;
-                               continue;
-                       }
+       if (inta & ~handled)
+               IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
 
-                       /* Initialize regulatory-based run-time data */
-                       ch_info->max_power_avg = ch_info->curr_txpow =
-                           eeprom_ch_info[ch].max_power_avg;
-                       ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
-                       ch_info->min_power = 0;
-
-                       IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-                                      " %ddBm): Ad-Hoc %ssupported\n",
-                                      ch_info->channel,
-                                      is_channel_a_band(ch_info) ?
-                                      "5.2" : "2.4",
-                                      CHECK_AND_PRINT(VALID),
-                                      CHECK_AND_PRINT(IBSS),
-                                      CHECK_AND_PRINT(ACTIVE),
-                                      CHECK_AND_PRINT(RADAR),
-                                      CHECK_AND_PRINT(WIDE),
-                                      CHECK_AND_PRINT(DFS),
-                                      eeprom_ch_info[ch].flags,
-                                      eeprom_ch_info[ch].max_power_avg,
-                                      ((eeprom_ch_info[ch].
-                                        flags & EEPROM_CHANNEL_IBSS)
-                                       && !(eeprom_ch_info[ch].
-                                            flags & EEPROM_CHANNEL_RADAR))
-                                      ? "" : "not ");
-
-                       /* Set the user_txpower_limit to the highest power
-                        * supported by any channel */
-                       if (eeprom_ch_info[ch].max_power_avg >
-                           priv->user_txpower_limit)
-                               priv->user_txpower_limit =
-                                   eeprom_ch_info[ch].max_power_avg;
-
-                       ch_info++;
-               }
+       if (inta & ~CSR_INI_SET_MASK) {
+               IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
+                        inta & ~CSR_INI_SET_MASK);
+               IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
        }
 
-       /* Set up txpower settings in driver for all channels */
-       if (iwl3945_txpower_set_from_eeprom(priv))
-               return -EIO;
+       /* Re-enable all interrupts */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(STATUS_INT_ENABLED, &priv->status))
+               iwl3945_enable_interrupts(priv);
 
-       return 0;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (priv->debug_level & (IWL_DL_ISR)) {
+               inta = iwl_read32(priv, CSR_INT);
+               inta_mask = iwl_read32(priv, CSR_INT_MASK);
+               inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+               IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+                       "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+       }
+#endif
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-/*
- * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map
- */
-static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+static irqreturn_t iwl3945_isr(int irq, void *data)
 {
-       kfree(priv->channel_info);
-       priv->channel_count = 0;
-}
+       struct iwl_priv *priv = data;
+       u32 inta, inta_mask;
+       u32 inta_fh;
+       if (!priv)
+               return IRQ_NONE;
 
-/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
- * sending probe req.  This should be set long enough to hear probe responses
- * from more than one AP.  */
-#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
-#define IWL_ACTIVE_DWELL_TIME_52    (20)
+       spin_lock(&priv->lock);
+
+       /* Disable (but don't clear!) interrupts here to avoid
+        *    back-to-back ISRs and sporadic interrupts from our NIC.
+        * If we have something to service, the tasklet will re-enable ints.
+        * If we *don't* have something, we'll re-enable before leaving here. */
+       inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+       iwl_write32(priv, CSR_INT_MASK, 0x00000000);
 
-#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
-#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
+       /* Discover which interrupts are active/pending */
+       inta = iwl_read32(priv, CSR_INT);
+       inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
 
-/* For faster active scanning, scan will move to the next channel if fewer than
- * PLCP_QUIET_THRESH packets are heard on this channel within
- * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
- * time if it's a quiet channel (nothing responded to our probe, and there's
- * no other traffic).
- * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
-#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)  /* packets */
-#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(10) /* msec */
+       /* Ignore interrupt if there's nothing in NIC to service.
+        * This may be due to IRQ shared with another device,
+        * or due to sporadic interrupts thrown from our NIC. */
+       if (!inta && !inta_fh) {
+               IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
+               goto none;
+       }
 
-/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
- * Must be set longer than active dwell time.
- * For the most reliable scan, set > AP beacon interval (typically 100msec). */
-#define IWL_PASSIVE_DWELL_TIME_24   (20)       /* all times in msec */
-#define IWL_PASSIVE_DWELL_TIME_52   (10)
-#define IWL_PASSIVE_DWELL_BASE      (100)
-#define IWL_CHANNEL_TUNE_TIME       5
+       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+               /* Hardware disappeared */
+               IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+               goto unplugged;
+       }
 
-#define IWL_SCAN_PROBE_MASK(n)  (BIT(n) | (BIT(n) - BIT(1)))
+       IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+                     inta, inta_mask, inta_fh);
 
-static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
-                                               enum ieee80211_band band,
-                                               u8 n_probes)
-{
-       if (band == IEEE80211_BAND_5GHZ)
-               return IWL_ACTIVE_DWELL_TIME_52 +
-                       IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
-       else
-               return IWL_ACTIVE_DWELL_TIME_24 +
-                       IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
-}
+       inta &= ~CSR_INT_BIT_SCD;
 
-static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
-                                         enum ieee80211_band band)
-{
-       u16 passive = (band == IEEE80211_BAND_2GHZ) ?
-           IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
-           IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+       /* iwl3945_irq_tasklet() will service interrupts and re-enable them */
+       if (likely(inta || inta_fh))
+               tasklet_schedule(&priv->irq_tasklet);
+unplugged:
+       spin_unlock(&priv->lock);
 
-       if (iwl3945_is_associated(priv)) {
-               /* If we're associated, we clamp the maximum passive
-                * dwell time to be 98% of the beacon interval (minus
-                * 2 * channel tune time) */
-               passive = priv->beacon_int;
-               if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
-                       passive = IWL_PASSIVE_DWELL_BASE;
-               passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
-       }
+       return IRQ_HANDLED;
 
-       return passive;
+ none:
+       /* re-enable interrupts here since we don't have anything to service. */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(STATUS_INT_ENABLED, &priv->status))
+               iwl3945_enable_interrupts(priv);
+       spin_unlock(&priv->lock);
+       return IRQ_NONE;
 }
 
-static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
+static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                         enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
                                     struct iwl3945_scan_channel *scan_ch)
 {
        const struct ieee80211_channel *channels = NULL;
        const struct ieee80211_supported_band *sband;
-       const struct iwl3945_channel_info *ch_info;
+       const struct iwl_channel_info *ch_info;
        u16 passive_dwell = 0;
        u16 active_dwell = 0;
        int added, i;
 
-       sband = iwl3945_get_band(priv, band);
+       sband = iwl_get_hw_mode(priv, band);
        if (!sband)
                return 0;
 
        channels = sband->channels;
 
-       active_dwell = iwl3945_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
+       active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band);
 
        if (passive_dwell <= active_dwell)
                passive_dwell = active_dwell + 1;
@@ -4771,7 +3240,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
 
                scan_ch->channel = channels[i].hw_value;
 
-               ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
+               ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
                if (!is_channel_valid(ch_info)) {
                        IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",
                                       scan_ch->channel);
@@ -4798,12 +3267,12 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
                 * hearing clear Rx packet).*/
                if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
                        if (n_probes)
-                               scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+                               scan_ch->type |= IWL39_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);
+                               scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
                }
 
                /* Set txpower levels to defaults */
@@ -4835,7 +3304,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
        return added;
 }
 
-static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
+static void iwl3945_init_hw_rates(struct iwl_priv *priv,
                              struct ieee80211_rate *rates)
 {
        int i;
@@ -4845,7 +3314,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
                rates[i].hw_value = i; /* Rate scaling will work on indexes */
                rates[i].hw_value_short = i;
                rates[i].flags = 0;
-               if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+               if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
                        /*
                         * If CCK != 1M then set short preamble rate flag.
                         */
@@ -4855,145 +3324,13 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
        }
 }
 
-/**
- * iwl3945_init_geos - Initialize mac80211's geo/channel info based from eeprom
- */
-static int iwl3945_init_geos(struct iwl3945_priv *priv)
-{
-       struct iwl3945_channel_info *ch;
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *channels;
-       struct ieee80211_channel *geo_ch;
-       struct ieee80211_rate *rates;
-       int i = 0;
-
-       if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
-           priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
-               IWL_DEBUG_INFO("Geography modes already initialized.\n");
-               set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-               return 0;
-       }
-
-       channels = kzalloc(sizeof(struct ieee80211_channel) *
-                          priv->channel_count, GFP_KERNEL);
-       if (!channels)
-               return -ENOMEM;
-
-       rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
-                       GFP_KERNEL);
-       if (!rates) {
-               kfree(channels);
-               return -ENOMEM;
-       }
-
-       /* 5.2GHz channels start after the 2.4GHz channels */
-       sband = &priv->bands[IEEE80211_BAND_5GHZ];
-       sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
-       /* just OFDM */
-       sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
-       sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
-
-       sband = &priv->bands[IEEE80211_BAND_2GHZ];
-       sband->channels = channels;
-       /* OFDM & CCK */
-       sband->bitrates = rates;
-       sband->n_bitrates = IWL_RATE_COUNT;
-
-       priv->ieee_channels = channels;
-       priv->ieee_rates = rates;
-
-       iwl3945_init_hw_rates(priv, rates);
-
-       for (i = 0;  i < priv->channel_count; i++) {
-               ch = &priv->channel_info[i];
-
-               /* FIXME: might be removed if scan is OK*/
-               if (!is_channel_valid(ch))
-                       continue;
-
-               if (is_channel_a_band(ch))
-                       sband =  &priv->bands[IEEE80211_BAND_5GHZ];
-               else
-                       sband =  &priv->bands[IEEE80211_BAND_2GHZ];
-
-               geo_ch = &sband->channels[sband->n_channels++];
-
-               geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
-               geo_ch->max_power = ch->max_power_avg;
-               geo_ch->max_antenna_gain = 0xff;
-               geo_ch->hw_value = ch->channel;
-
-               if (is_channel_valid(ch)) {
-                       if (!(ch->flags & EEPROM_CHANNEL_IBSS))
-                               geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
-
-                       if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
-                               geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
-                       if (ch->flags & EEPROM_CHANNEL_RADAR)
-                               geo_ch->flags |= IEEE80211_CHAN_RADAR;
-
-                       if (ch->max_power_avg > priv->max_channel_txpower_limit)
-                               priv->max_channel_txpower_limit =
-                                   ch->max_power_avg;
-               } else {
-                       geo_ch->flags |= IEEE80211_CHAN_DISABLED;
-               }
-
-               /* Save flags for reg domain usage */
-               geo_ch->orig_flags = geo_ch->flags;
-
-               IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
-                               ch->channel, geo_ch->center_freq,
-                               is_channel_a_band(ch) ?  "5.2" : "2.4",
-                               geo_ch->flags & IEEE80211_CHAN_DISABLED ?
-                               "restricted" : "valid",
-                                geo_ch->flags);
-       }
-
-       if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-            priv->cfg->sku & IWL_SKU_A) {
-               printk(KERN_INFO DRV_NAME
-                      ": Incorrectly detected BG card as ABG.  Please send "
-                      "your PCI ID 0x%04X:0x%04X to maintainer.\n",
-                      priv->pci_dev->device, priv->pci_dev->subsystem_device);
-                priv->cfg->sku &= ~IWL_SKU_A;
-       }
-
-       printk(KERN_INFO DRV_NAME
-              ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-              priv->bands[IEEE80211_BAND_2GHZ].n_channels,
-              priv->bands[IEEE80211_BAND_5GHZ].n_channels);
-
-       if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-                       &priv->bands[IEEE80211_BAND_2GHZ];
-       if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-                       &priv->bands[IEEE80211_BAND_5GHZ];
-
-       set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-
-       return 0;
-}
-
-/*
- * iwl3945_free_geos - undo allocations in iwl3945_init_geos
- */
-static void iwl3945_free_geos(struct iwl3945_priv *priv)
-{
-       kfree(priv->ieee_channels);
-       kfree(priv->ieee_rates);
-       clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
-}
-
 /******************************************************************************
  *
  * uCode download functions
  *
  ******************************************************************************/
 
-static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
+static void iwl3945_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);
@@ -5007,7 +3344,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
  * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
  *     looking at all data.
  */
-static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len)
+static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
 {
        u32 val;
        u32 save_len = len;
@@ -5016,20 +3353,21 @@ static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u3
 
        IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc)
                return rc;
 
-       iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+       iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+                              IWL39_RTC_INST_LOWER_BOUND);
 
        errcnt = 0;
        for (; len > 0; len -= sizeof(u32), image++) {
                /* read data comes through single port, auto-incr addr */
                /* NOTE: Use the debugless read so we don't flood kernel log
                 * if IWL_DL_IO is set */
-               val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+               val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
                if (val != le32_to_cpu(*image)) {
-                       IWL_ERROR("uCode INST section is invalid at "
+                       IWL_ERR(priv, "uCode INST section is invalid at "
                                  "offset 0x%x, is 0x%x, s/b 0x%x\n",
                                  save_len - len, val, le32_to_cpu(*image));
                        rc = -EIO;
@@ -5039,7 +3377,7 @@ static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u3
                }
        }
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 
        if (!errcnt)
                IWL_DEBUG_INFO("ucode image in INSTRUCTION memory is good\n");
@@ -5053,7 +3391,7 @@ static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u3
  *   using sample data 100 bytes apart.  If these sample points are good,
  *   it's a pretty good bet that everything between them is good, too.
  */
-static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image, u32 len)
+static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
 {
        u32 val;
        int rc = 0;
@@ -5062,7 +3400,7 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image,
 
        IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc)
                return rc;
 
@@ -5070,12 +3408,12 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image,
                /* read data comes through single port, auto-incr addr */
                /* NOTE: Use the debugless read so we don't flood kernel log
                 * if IWL_DL_IO is set */
-               iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                       i + RTC_INST_LOWER_BOUND);
-               val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+               iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+                       i + IWL39_RTC_INST_LOWER_BOUND);
+               val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
                if (val != le32_to_cpu(*image)) {
 #if 0 /* Enable this if you want to see details */
-                       IWL_ERROR("uCode INST section is invalid at "
+                       IWL_ERR(priv, "uCode INST section is invalid at "
                                  "offset 0x%x, is 0x%x, s/b 0x%x\n",
                                  i, val, *image);
 #endif
@@ -5086,7 +3424,7 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image,
                }
        }
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 
        return rc;
 }
@@ -5096,7 +3434,7 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image,
  * iwl3945_verify_ucode - determine which instruction image is in SRAM,
  *    and verify its contents
  */
-static int iwl3945_verify_ucode(struct iwl3945_priv *priv)
+static int iwl3945_verify_ucode(struct iwl_priv *priv)
 {
        __le32 *image;
        u32 len;
@@ -5129,7 +3467,7 @@ static int iwl3945_verify_ucode(struct iwl3945_priv *priv)
                return 0;
        }
 
-       IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+       IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
 
        /* Since nothing seems to match, show first several data entries in
         * instruction SRAM, so maybe visual inspection will give a clue.
@@ -5141,160 +3479,10 @@ static int iwl3945_verify_ucode(struct iwl3945_priv *priv)
        return rc;
 }
 
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl3945_verify_bsm(struct iwl3945_priv *priv)
-{
-       __le32 *image = priv->ucode_boot.v_addr;
-       u32 len = priv->ucode_boot.len;
-       u32 reg;
-       u32 val;
-
-       IWL_DEBUG_INFO("Begin verify bsm\n");
-
-       /* verify BSM SRAM contents */
-       val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG);
-       for (reg = BSM_SRAM_LOWER_BOUND;
-            reg < BSM_SRAM_LOWER_BOUND + len;
-            reg += sizeof(u32), image++) {
-               val = iwl3945_read_prph(priv, reg);
-               if (val != le32_to_cpu(*image)) {
-                       IWL_ERROR("BSM uCode verification failed at "
-                                 "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-                                 BSM_SRAM_LOWER_BOUND,
-                                 reg - BSM_SRAM_LOWER_BOUND, len,
-                                 val, le32_to_cpu(*image));
-                       return -EIO;
-               }
-       }
-
-       IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
-
-       return 0;
-}
-
-/**
- * iwl3945_load_bsm - Load bootstrap instructions
- *
- * BSM operation:
- *
- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
- * in special SRAM that does not power down during RFKILL.  When powering back
- * up after power-saving sleeps (or during initial uCode load), the BSM loads
- * the bootstrap program into the on-board processor, and starts it.
- *
- * The bootstrap program loads (via DMA) instructions and data for a new
- * program from host DRAM locations indicated by the host driver in the
- * BSM_DRAM_* registers.  Once the new program is loaded, it starts
- * automatically.
- *
- * When initializing the NIC, the host driver points the BSM to the
- * "initialize" uCode image.  This uCode sets up some internal data, then
- * notifies host via "initialize alive" that it is complete.
- *
- * The host then replaces the BSM_DRAM_* pointer values to point to the
- * normal runtime uCode instructions and a backup uCode data cache buffer
- * (filled initially with starting data values for the on-board processor),
- * then triggers the "initialize" uCode to load and launch the runtime uCode,
- * which begins normal operation.
- *
- * When doing a power-save shutdown, runtime uCode saves data SRAM into
- * the backup data cache in DRAM before SRAM is powered down.
- *
- * When powering back up, the BSM loads the bootstrap program.  This reloads
- * the runtime uCode instructions and the backup data cache into SRAM,
- * and re-launches the runtime uCode from where it left off.
- */
-static int iwl3945_load_bsm(struct iwl3945_priv *priv)
-{
-       __le32 *image = priv->ucode_boot.v_addr;
-       u32 len = priv->ucode_boot.len;
-       dma_addr_t pinst;
-       dma_addr_t pdata;
-       u32 inst_len;
-       u32 data_len;
-       int rc;
-       int i;
-       u32 done;
-       u32 reg_offset;
-
-       IWL_DEBUG_INFO("Begin load bsm\n");
-
-       /* make sure bootstrap program is no larger than BSM's SRAM size */
-       if (len > IWL_MAX_BSM_SIZE)
-               return -EINVAL;
-
-       /* Tell bootstrap uCode where to find the "Initialize" uCode
-        *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
-        * NOTE:  iwl3945_initialize_alive_start() will replace these values,
-        *        after the "initialize" uCode has run, to point to
-        *        runtime/protocol instructions and backup data cache. */
-       pinst = priv->ucode_init.p_addr;
-       pdata = priv->ucode_init_data.p_addr;
-       inst_len = priv->ucode_init.len;
-       data_len = priv->ucode_init_data.len;
-
-       rc = iwl3945_grab_nic_access(priv);
-       if (rc)
-               return rc;
-
-       iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-       iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
-       /* Fill BSM memory with bootstrap instructions */
-       for (reg_offset = BSM_SRAM_LOWER_BOUND;
-            reg_offset < BSM_SRAM_LOWER_BOUND + len;
-            reg_offset += sizeof(u32), image++)
-               _iwl3945_write_prph(priv, reg_offset,
-                                         le32_to_cpu(*image));
-
-       rc = iwl3945_verify_bsm(priv);
-       if (rc) {
-               iwl3945_release_nic_access(priv);
-               return rc;
-       }
-
-       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-       iwl3945_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-       iwl3945_write_prph(priv, BSM_WR_MEM_DST_REG,
-                                RTC_INST_LOWER_BOUND);
-       iwl3945_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-       /* Load bootstrap code into instruction SRAM now,
-        *   to prepare to load "initialize" uCode */
-       iwl3945_write_prph(priv, BSM_WR_CTRL_REG,
-               BSM_WR_CTRL_REG_BIT_START);
-
-       /* Wait for load of bootstrap uCode to finish */
-       for (i = 0; i < 100; i++) {
-               done = iwl3945_read_prph(priv, BSM_WR_CTRL_REG);
-               if (!(done & BSM_WR_CTRL_REG_BIT_START))
-                       break;
-               udelay(10);
-       }
-       if (i < 100)
-               IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
-       else {
-               IWL_ERROR("BSM write did not complete!\n");
-               return -EIO;
-       }
-
-       /* Enable future boot loads whenever power management unit triggers it
-        *   (e.g. when powering back up after power-save shutdown) */
-       iwl3945_write_prph(priv, BSM_WR_CTRL_REG,
-               BSM_WR_CTRL_REG_BIT_START_EN);
-
-       iwl3945_release_nic_access(priv);
-
-       return 0;
-}
-
-static void iwl3945_nic_start(struct iwl3945_priv *priv)
+static void iwl3945_nic_start(struct iwl_priv *priv)
 {
        /* Remove all resets to allow NIC to operate */
-       iwl3945_write32(priv, CSR_RESET, 0);
+       iwl_write32(priv, CSR_RESET, 0);
 }
 
 /**
@@ -5302,9 +3490,9 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
  *
  * Copy into buffers for card to fetch via bus-mastering
  */
-static int iwl3945_read_ucode(struct iwl3945_priv *priv)
+static int iwl3945_read_ucode(struct iwl_priv *priv)
 {
-       struct iwl3945_ucode *ucode;
+       struct iwl_ucode *ucode;
        int ret = -EINVAL, index;
        const struct firmware *ucode_raw;
        /* firmware file name contains uCode/driver compatibility version */
@@ -5322,7 +3510,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
                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",
+                       IWL_ERR(priv, "%s firmware file req failed: %d\n",
                                  buf, ret);
                        if (ret == -ENOENT)
                                continue;
@@ -5330,7 +3518,9 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
                                goto error;
                } else {
                        if (index < api_max)
-                               IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+                               IWL_ERR(priv, "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);
@@ -5343,7 +3533,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
 
        /* Make sure that we got at least our header! */
        if (ucode_raw->size < sizeof(*ucode)) {
-               IWL_ERROR("File size way too small!\n");
+               IWL_ERR(priv, "File size way too small!\n");
                ret = -EINVAL;
                goto err_release;
        }
@@ -5364,7 +3554,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
         * 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. "
+               IWL_ERR(priv, "Driver unable to support your firmware API. "
                          "Driver supports v%u, firmware is v%u.\n",
                          api_max, api_ver);
                priv->ucode_ver = 0;
@@ -5372,16 +3562,17 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
                goto err_release;
        }
        if (api_ver != api_max)
-               IWL_ERROR("Firmware has old API version. Expected %u, "
+               IWL_ERR(priv, "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_INFO(priv, "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);
@@ -5403,32 +3594,32 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        }
 
        /* Verify that uCode images will fit in card's SRAM */
-       if (inst_size > IWL_MAX_INST_SIZE) {
+       if (inst_size > IWL39_MAX_INST_SIZE) {
                IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
                               inst_size);
                ret = -EINVAL;
                goto err_release;
        }
 
-       if (data_size > IWL_MAX_DATA_SIZE) {
+       if (data_size > IWL39_MAX_DATA_SIZE) {
                IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
                               data_size);
                ret = -EINVAL;
                goto err_release;
        }
-       if (init_size > IWL_MAX_INST_SIZE) {
+       if (init_size > IWL39_MAX_INST_SIZE) {
                IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n",
                                init_size);
                ret = -EINVAL;
                goto err_release;
        }
-       if (init_data_size > IWL_MAX_DATA_SIZE) {
+       if (init_data_size > IWL39_MAX_DATA_SIZE) {
                IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n",
                                init_data_size);
                ret = -EINVAL;
                goto err_release;
        }
-       if (boot_size > IWL_MAX_BSM_SIZE) {
+       if (boot_size > IWL39_MAX_BSM_SIZE) {
                IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n",
                                boot_size);
                ret = -EINVAL;
@@ -5522,7 +3713,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
        return 0;
 
  err_pci_alloc:
-       IWL_ERROR("failed to allocate pci memory\n");
+       IWL_ERR(priv, "failed to allocate pci memory\n");
        ret = -ENOMEM;
        iwl3945_dealloc_ucode_pci(priv);
 
@@ -5543,7 +3734,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
  * We need to replace them to load runtime uCode inst and data,
  * and to save runtime data when powering down.
  */
-static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
+static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
 {
        dma_addr_t pinst;
        dma_addr_t pdata;
@@ -5555,24 +3746,24 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
        pdata = priv->ucode_data_backup.p_addr;
 
        spin_lock_irqsave(&priv->lock, flags);
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
                spin_unlock_irqrestore(&priv->lock, flags);
                return rc;
        }
 
        /* Tell bootstrap uCode where to find image to load */
-       iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+       iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+       iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+       iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
                                 priv->ucode_data.len);
 
        /* 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,
+       iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
                                 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
 
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -5588,7 +3779,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
  *
  * Tell "initialize" uCode to go ahead and load the runtime uCode.
  */
-static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
+static void iwl3945_init_alive_start(struct iwl_priv *priv)
 {
        /* Check alive response for "valid" sign from uCode */
        if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
@@ -5634,7 +3825,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
  *                   from protocol/runtime uCode (initialization uCode's
  *                   Alive gets handled by iwl3945_init_alive_start()).
  */
-static void iwl3945_alive_start(struct iwl3945_priv *priv)
+static void iwl3945_alive_start(struct iwl_priv *priv)
 {
        int rc = 0;
        int thermal_spin = 0;
@@ -5661,15 +3852,15 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 
        iwl3945_clear_stations_table(priv);
 
-       rc = iwl3945_grab_nic_access(priv);
+       rc = iwl_grab_nic_access(priv);
        if (rc) {
-               IWL_WARNING("Can not read RFKILL status from adapter\n");
+               IWL_WARN(priv, "Can not read RFKILL status from adapter\n");
                return;
        }
 
-       rfkill = iwl3945_read_prph(priv, APMG_RFKILL_REG);
+       rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
        IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill);
-       iwl3945_release_nic_access(priv);
+       iwl_release_nic_access(priv);
 
        if (rfkill & 0x1) {
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -5692,7 +3883,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        /* Clear out the uCode error bit if it is set */
        clear_bit(STATUS_FW_ERROR, &priv->status);
 
-       if (iwl3945_is_rfkill(priv))
+       if (iwl_is_rfkill(priv))
                return;
 
        ieee80211_wake_queues(priv->hw);
@@ -5704,19 +3895,19 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 
        if (iwl3945_is_associated(priv)) {
                struct iwl3945_rxon_cmd *active_rxon =
-                               (struct iwl3945_rxon_cmd *)(&priv->active_rxon);
+                               (struct iwl3945_rxon_cmd *)(&priv->active39_rxon);
 
-               memcpy(&priv->staging_rxon, &priv->active_rxon,
-                      sizeof(priv->staging_rxon));
+               memcpy(&priv->staging39_rxon, &priv->active39_rxon,
+                      sizeof(priv->staging39_rxon));
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        } else {
                /* Initialize our rx_config data */
                iwl3945_connection_init_rx_config(priv, priv->iw_mode);
-               memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+               memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN);
        }
 
        /* Configure Bluetooth device coexistence support */
-       iwl3945_send_bt_config(priv);
+       iwl_send_bt_config(priv);
 
        /* Configure the adapter for unassociated operation */
        iwl3945_commit_rxon(priv);
@@ -5746,9 +3937,9 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        queue_work(priv->workqueue, &priv->restart);
 }
 
-static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv);
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
 
-static void __iwl3945_down(struct iwl3945_priv *priv)
+static void __iwl3945_down(struct iwl_priv *priv)
 {
        unsigned long flags;
        int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -5773,7 +3964,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
        /* stop and reset the on-board processor */
-       iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+       iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
        /* tell the device to stop sending interrupts */
        spin_lock_irqsave(&priv->lock, flags);
@@ -5786,7 +3977,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
 
        /* If we have not previously called iwl3945_init() then
         * clear all bits but the RF Kill and SUSPEND bits and return */
-       if (!iwl3945_is_init(priv)) {
+       if (!iwl_is_init(priv)) {
                priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                        STATUS_RF_KILL_HW |
                               test_bit(STATUS_RF_KILL_SW, &priv->status) <<
@@ -5815,29 +4006,31 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
                        test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                STATUS_EXIT_PENDING;
 
+       priv->cfg->ops->lib->apm_ops.reset(priv);
        spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+       iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        iwl3945_hw_txq_ctx_stop(priv);
        iwl3945_hw_rxq_stop(priv);
 
        spin_lock_irqsave(&priv->lock, flags);
-       if (!iwl3945_grab_nic_access(priv)) {
-               iwl3945_write_prph(priv, APMG_CLK_DIS_REG,
+       if (!iwl_grab_nic_access(priv)) {
+               iwl_write_prph(priv, APMG_CLK_DIS_REG,
                                         APMG_CLK_VAL_DMA_CLK_RQT);
-               iwl3945_release_nic_access(priv);
+               iwl_release_nic_access(priv);
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
        udelay(5);
 
-       iwl3945_hw_nic_stop_master(priv);
-       iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-       iwl3945_hw_nic_reset(priv);
+       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+               priv->cfg->ops->lib->apm_ops.stop(priv);
+       else
+               priv->cfg->ops->lib->apm_ops.reset(priv);
 
  exit:
-       memset(&priv->card_alive, 0, sizeof(struct iwl3945_alive_resp));
+       memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
@@ -5847,7 +4040,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
        iwl3945_clear_free_frames(priv);
 }
 
-static void iwl3945_down(struct iwl3945_priv *priv)
+static void iwl3945_down(struct iwl_priv *priv)
 {
        mutex_lock(&priv->mutex);
        __iwl3945_down(priv);
@@ -5858,58 +4051,58 @@ static void iwl3945_down(struct iwl3945_priv *priv)
 
 #define MAX_HW_RESTARTS 5
 
-static int __iwl3945_up(struct iwl3945_priv *priv)
+static int __iwl3945_up(struct iwl_priv *priv)
 {
        int rc, i;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_WARNING("Exit pending; will not bring the NIC up\n");
+               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
                return -EIO;
        }
 
        if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-               IWL_WARNING("Radio disabled by SW RF kill (module "
+               IWL_WARN(priv, "Radio disabled by SW RF kill (module "
                            "parameter)\n");
                return -ENODEV;
        }
 
        if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERROR("ucode not available for device bring up\n");
+               IWL_ERR(priv, "ucode not available for device bring up\n");
                return -EIO;
        }
 
        /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl3945_read32(priv, CSR_GP_CNTRL) &
+       if (iwl_read32(priv, CSR_GP_CNTRL) &
                                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
        else {
                set_bit(STATUS_RF_KILL_HW, &priv->status);
                if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-                       IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+                       IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
                        return -ENODEV;
                }
        }
 
-       iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
+       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 
        rc = iwl3945_hw_nic_init(priv);
        if (rc) {
-               IWL_ERROR("Unable to int nic\n");
+               IWL_ERR(priv, "Unable to int nic\n");
                return rc;
        }
 
        /* make sure rfkill handshake bits are cleared */
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
                    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
 
        /* clear (again), then enable host interrupts */
-       iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
+       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
        iwl3945_enable_interrupts(priv);
 
        /* really make sure rfkill handshake bits are cleared */
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
        /* Copy original ucode data image from disk into backup cache.
         * This will be used to initialize the on-board processor's
@@ -5928,10 +4121,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
                /* load bootstrap state machine,
                 * load bootstrap program into processor's memory,
                 * prepare to load the "initialize" uCode */
-               rc = iwl3945_load_bsm(priv);
+               priv->cfg->ops->lib->load_ucode(priv);
 
                if (rc) {
-                       IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
+                       IWL_ERR(priv,
+                               "Unable to set up bootstrap uCode: %d\n", rc);
                        continue;
                }
 
@@ -5949,7 +4143,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
 
        /* tried to restart and config the device for as long as our
         * patience could withstand */
-       IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
+       IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
        return -EIO;
 }
 
@@ -5962,8 +4156,8 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
 
 static void iwl3945_bg_init_alive_start(struct work_struct *data)
 {
-       struct iwl3945_priv *priv =
-           container_of(data, struct iwl3945_priv, init_alive_start.work);
+       struct iwl_priv *priv =
+           container_of(data, struct iwl_priv, init_alive_start.work);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -5975,8 +4169,8 @@ static void iwl3945_bg_init_alive_start(struct work_struct *data)
 
 static void iwl3945_bg_alive_start(struct work_struct *data)
 {
-       struct iwl3945_priv *priv =
-           container_of(data, struct iwl3945_priv, alive_start.work);
+       struct iwl_priv *priv =
+           container_of(data, struct iwl_priv, alive_start.work);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -5986,66 +4180,31 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
-static void iwl3945_bg_rf_kill(struct work_struct *work)
+static void iwl3945_rfkill_poll(struct work_struct *data)
 {
-       struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, rf_kill);
-
-       wake_up_interruptible(&priv->wait_command_queue);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
+       struct iwl_priv *priv =
+           container_of(data, struct iwl_priv, rfkill_poll.work);
+       unsigned long status = priv->status;
 
-       mutex_lock(&priv->mutex);
+       if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(STATUS_RF_KILL_HW, &priv->status);
+       else
+               set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-       if (!iwl3945_is_rfkill(priv)) {
-               IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
-                         "HW and/or SW RF Kill no longer active, restarting "
-                         "device\n");
-               if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       queue_work(priv->workqueue, &priv->restart);
-       } else {
+       if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
+               queue_work(priv->workqueue, &priv->rf_kill);
 
-               if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-                       IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-                                         "disabled by SW switch\n");
-               else
-                       IWL_WARNING("Radio Frequency Kill Switch is On:\n"
-                                   "Kill switch must be turned off for "
-                                   "wireless networking to work.\n");
-       }
+       queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+                          round_jiffies_relative(2 * HZ));
 
-       mutex_unlock(&priv->mutex);
-       iwl3945_rfkill_set_hw_state(priv);
 }
 
 #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-
-static void iwl3945_bg_scan_check(struct work_struct *data)
-{
-       struct iwl3945_priv *priv =
-           container_of(data, struct iwl3945_priv, scan_check.work);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_SCANNING, &priv->status) ||
-           test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-               IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
-                         "Scan completion watchdog resetting adapter (%dms)\n",
-                         jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
-
-               if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       iwl3945_send_scan_abort(priv);
-       }
-       mutex_unlock(&priv->mutex);
-}
-
 static void iwl3945_bg_request_scan(struct work_struct *data)
 {
-       struct iwl3945_priv *priv =
-           container_of(data, struct iwl3945_priv, request_scan);
-       struct iwl3945_host_cmd cmd = {
+       struct iwl_priv *priv =
+           container_of(data, struct iwl_priv, request_scan);
+       struct iwl_host_cmd cmd = {
                .id = REPLY_SCAN_CMD,
                .len = sizeof(struct iwl3945_scan_cmd),
                .meta.flags = CMD_SIZE_HUGE,
@@ -6061,8 +4220,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        mutex_lock(&priv->mutex);
 
-       if (!iwl3945_is_ready(priv)) {
-               IWL_WARNING("request scan called when driver not ready.\n");
+       if (!iwl_is_ready(priv)) {
+               IWL_WARN(priv, "request scan called when driver not ready.\n");
                goto done;
        }
 
@@ -6090,7 +4249,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                goto done;
        }
 
-       if (iwl3945_is_rfkill(priv)) {
+       if (iwl_is_rfkill(priv)) {
                IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
                goto done;
        }
@@ -6168,11 +4327,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        /* We don't build a direct scan probe request; the uCode will do
         * 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)));
        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.sta_id = priv->hw_params.bcast_sta_id;
        scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 
        /* flags + rate selection */
@@ -6187,10 +4343,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                scan->good_CRC_th = IWL_GOOD_CRC_TH;
                band = IEEE80211_BAND_5GHZ;
        } else {
-               IWL_WARNING("Invalid scan band count\n");
+               IWL_WARN(priv, "Invalid scan band count\n");
                goto done;
        }
 
+       scan->tx_cmd.len = cpu_to_le16(
+               iwl_fill_probe_req(priv, band,
+                                  (struct ieee80211_mgmt *)scan->data,
+                                  IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
@@ -6213,7 +4374,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        scan->len = cpu_to_le16(cmd.len);
 
        set_bit(STATUS_SCAN_HW, &priv->status);
-       rc = iwl3945_send_cmd_sync(priv, &cmd);
+       rc = iwl_send_cmd_sync(priv, &cmd);
        if (rc)
                goto done;
 
@@ -6239,7 +4400,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 static void iwl3945_bg_up(struct work_struct *data)
 {
-       struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, up);
+       struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -6247,12 +4408,12 @@ static void iwl3945_bg_up(struct work_struct *data)
        mutex_lock(&priv->mutex);
        __iwl3945_up(priv);
        mutex_unlock(&priv->mutex);
-       iwl3945_rfkill_set_hw_state(priv);
+       iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
 {
-       struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, restart);
+       struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -6263,8 +4424,8 @@ static void iwl3945_bg_restart(struct work_struct *data)
 
 static void iwl3945_bg_rx_replenish(struct work_struct *data)
 {
-       struct iwl3945_priv *priv =
-           container_of(data, struct iwl3945_priv, rx_replenish);
+       struct iwl_priv *priv =
+           container_of(data, struct iwl_priv, rx_replenish);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -6276,19 +4437,19 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl3945_post_associate(struct iwl3945_priv *priv)
+static void iwl3945_post_associate(struct iwl_priv *priv)
 {
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
 
        if (priv->iw_mode == NL80211_IFTYPE_AP) {
-               IWL_ERROR("%s Should not be called in AP mode\n", __func__);
+               IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
                return;
        }
 
 
        IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
-                       priv->assoc_id, priv->active_rxon.bssid_addr);
+                       priv->assoc_id, priv->active39_rxon.bssid_addr);
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -6296,41 +4457,41 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
        if (!priv->vif || !priv->is_open)
                return;
 
-       iwl3945_scan_cancel_timeout(priv, 200);
+       iwl_scan_cancel_timeout(priv, 200);
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
        iwl3945_commit_rxon(priv);
 
-       memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd));
+       memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
        iwl3945_setup_rxon_timing(priv);
-       rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+       rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
                              sizeof(priv->rxon_timing), &priv->rxon_timing);
        if (rc)
-               IWL_WARNING("REPLY_RXON_TIMING failed - "
+               IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                            "Attempting to continue.\n");
 
-       priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+       priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
-       priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
+       priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
 
        IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n",
                        priv->assoc_id, priv->beacon_int);
 
        if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-               priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
        else
-               priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+               priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-       if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+       if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) {
                if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
-                       priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
                else
-                       priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
                if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
-                       priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
        }
 
@@ -6355,7 +4516,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
                break;
 
        default:
-                IWL_ERROR("%s Should not be called in %d mode\n",
+                IWL_ERR(priv, "%s Should not be called in %d mode\n",
                           __func__, priv->iw_mode);
                break;
        }
@@ -6366,45 +4527,8 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-static void iwl3945_bg_abort_scan(struct work_struct *work)
-{
-       struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, abort_scan);
-
-       if (!iwl3945_is_ready(priv))
-               return;
-
-       mutex_lock(&priv->mutex);
-
-       set_bit(STATUS_SCAN_ABORTING, &priv->status);
-       iwl3945_send_scan_abort(priv);
-
-       mutex_unlock(&priv->mutex);
-}
-
 static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
 
-static void iwl3945_bg_scan_completed(struct work_struct *work)
-{
-       struct iwl3945_priv *priv =
-           container_of(work, struct iwl3945_priv, scan_completed);
-
-       IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       if (test_bit(STATUS_CONF_PENDING, &priv->status))
-               iwl3945_mac_config(priv->hw, 0);
-
-       ieee80211_scan_completed(priv->hw);
-
-       /* Since setting the TXPOWER may have been deferred while
-        * performing the scan, fire one off */
-       mutex_lock(&priv->mutex);
-       iwl3945_hw_reg_send_txpower(priv);
-       mutex_unlock(&priv->mutex);
-}
-
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -6414,37 +4538,23 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
 #define UCODE_READY_TIMEOUT    (2 * HZ)
 
 static int iwl3945_mac_start(struct ieee80211_hw *hw)
-{
-       struct iwl3945_priv *priv = hw->priv;
-       int ret;
-
-       IWL_DEBUG_MAC80211("enter\n");
-
-       if (pci_enable_device(priv->pci_dev)) {
-               IWL_ERROR("Fail to pci_enable_device\n");
-               return -ENODEV;
-       }
-       pci_restore_state(priv->pci_dev);
-       pci_enable_msi(priv->pci_dev);
+{
+       struct iwl_priv *priv = hw->priv;
+       int ret;
 
-       ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
-                         DRV_NAME, priv);
-       if (ret) {
-               IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
-       }
+       IWL_DEBUG_MAC80211("enter\n");
 
        /* we should be verifying the device is ready to be opened */
        mutex_lock(&priv->mutex);
 
-       memset(&priv->staging_rxon, 0, sizeof(struct iwl3945_rxon_cmd));
+       memset(&priv->staging39_rxon, 0, sizeof(struct iwl3945_rxon_cmd));
        /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
         * ucode filename and max sizes are card-specific. */
 
        if (!priv->ucode_code.len) {
                ret = iwl3945_read_ucode(priv);
                if (ret) {
-                       IWL_ERROR("Could not read microcode: %d\n", ret);
+                       IWL_ERR(priv, "Could not read microcode: %d\n", ret);
                        mutex_unlock(&priv->mutex);
                        goto out_release_irq;
                }
@@ -6454,7 +4564,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
 
        mutex_unlock(&priv->mutex);
 
-       iwl3945_rfkill_set_hw_state(priv);
+       iwl_rfkill_set_hw_state(priv);
 
        if (ret)
                goto out_release_irq;
@@ -6471,22 +4581,23 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
                        UCODE_READY_TIMEOUT);
        if (!ret) {
                if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
-                                 jiffies_to_msecs(UCODE_READY_TIMEOUT));
+                       IWL_ERR(priv,
+                               "Wait for START_ALIVE timeout after %dms.\n",
+                               jiffies_to_msecs(UCODE_READY_TIMEOUT));
                        ret = -ETIMEDOUT;
                        goto out_release_irq;
                }
        }
 
+       /* ucode is running and will send rfkill notifications,
+        * no need to poll the killswitch state anymore */
+       cancel_delayed_work(&priv->rfkill_poll);
+
        priv->is_open = 1;
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
 
 out_release_irq:
-       free_irq(priv->pci_dev->irq, priv);
-out_disable_msi:
-       pci_disable_msi(priv->pci_dev);
-       pci_disable_device(priv->pci_dev);
        priv->is_open = 0;
        IWL_DEBUG_MAC80211("leave - failed\n");
        return ret;
@@ -6494,7 +4605,7 @@ out_disable_msi:
 
 static void iwl3945_mac_stop(struct ieee80211_hw *hw)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -6505,29 +4616,29 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
 
        priv->is_open = 0;
 
-       if (iwl3945_is_ready_rf(priv)) {
+       if (iwl_is_ready_rf(priv)) {
                /* stop mac, cancel any scan request and clear
                 * RXON_FILTER_ASSOC_MSK BIT
                 */
                mutex_lock(&priv->mutex);
-               iwl3945_scan_cancel_timeout(priv, 100);
+               iwl_scan_cancel_timeout(priv, 100);
                mutex_unlock(&priv->mutex);
        }
 
        iwl3945_down(priv);
 
        flush_workqueue(priv->workqueue);
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_save_state(priv->pci_dev);
-       pci_disable_device(priv->pci_dev);
+
+       /* start polling the killswitch state again */
+       queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+                          round_jiffies_relative(2 * HZ));
 
        IWL_DEBUG_MAC80211("leave\n");
 }
 
 static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -6544,7 +4655,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
                                 struct ieee80211_if_init_conf *conf)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        unsigned long flags;
 
        IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
@@ -6567,7 +4678,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
                memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
        }
 
-       if (iwl3945_is_ready(priv))
+       if (iwl_is_ready(priv))
                iwl3945_set_mode(priv, conf->type);
 
        mutex_unlock(&priv->mutex);
@@ -6585,8 +4696,8 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
  */
 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 iwl_priv *priv = hw->priv;
+       const struct iwl_channel_info *ch_info;
        struct ieee80211_conf *conf = &hw->conf;
        unsigned long flags;
        int ret = 0;
@@ -6594,13 +4705,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
 
-       if (!iwl3945_is_ready(priv)) {
+       if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
                ret = -EIO;
                goto out;
        }
 
-       if (unlikely(!iwl3945_param_disable_hw_scan &&
+       if (unlikely(!iwl3945_mod_params.disable_hw_scan &&
                     test_bit(STATUS_SCANNING, &priv->status))) {
                IWL_DEBUG_MAC80211("leave - scanning\n");
                set_bit(STATUS_CONF_PENDING, &priv->status);
@@ -6610,8 +4721,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
-                                          conf->channel->hw_value);
+       ch_info = iwl_get_channel_info(priv, conf->channel->band,
+                                      conf->channel->hw_value);
        if (!is_channel_valid(ch_info)) {
                IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n",
                               conf->channel->hw_value, conf->channel->band);
@@ -6646,7 +4757,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
                goto out;
        }
 
-       if (iwl3945_is_rfkill(priv)) {
+       if (iwl_is_rfkill(priv)) {
                IWL_DEBUG_MAC80211("leave - RF kill\n");
                ret = -EIO;
                goto out;
@@ -6654,8 +4765,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
 
        iwl3945_set_rate(priv);
 
-       if (memcmp(&priv->active_rxon,
-                  &priv->staging_rxon, sizeof(priv->staging_rxon)))
+       if (memcmp(&priv->active39_rxon,
+                  &priv->staging39_rxon, sizeof(priv->staging39_rxon)))
                iwl3945_commit_rxon(priv);
        else
                IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
@@ -6668,7 +4779,7 @@ out:
        return ret;
 }
 
-static void iwl3945_config_ap(struct iwl3945_priv *priv)
+static void iwl3945_config_ap(struct iwl_priv *priv)
 {
        int rc = 0;
 
@@ -6679,44 +4790,45 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
        if (!(iwl3945_is_associated(priv))) {
 
                /* RXON - unassoc (to set timing command) */
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
 
                /* RXON Timing */
-               memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd));
+               memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
                iwl3945_setup_rxon_timing(priv);
-               rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-                               sizeof(priv->rxon_timing), &priv->rxon_timing);
+               rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+                                     sizeof(priv->rxon_timing),
+                                     &priv->rxon_timing);
                if (rc)
-                       IWL_WARNING("REPLY_RXON_TIMING failed - "
+                       IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
                                        "Attempting to continue.\n");
 
                /* FIXME: what should be the assoc_id for AP? */
-               priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
+               priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
                if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-                       priv->staging_rxon.flags |=
+                       priv->staging39_rxon.flags |=
                                RXON_FLG_SHORT_PREAMBLE_MSK;
                else
-                       priv->staging_rxon.flags &=
+                       priv->staging39_rxon.flags &=
                                ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-               if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+               if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) {
                        if (priv->assoc_capability &
                                WLAN_CAPABILITY_SHORT_SLOT_TIME)
-                               priv->staging_rxon.flags |=
+                               priv->staging39_rxon.flags |=
                                        RXON_FLG_SHORT_SLOT_MSK;
                        else
-                               priv->staging_rxon.flags &=
+                               priv->staging39_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
 
                        if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
-                               priv->staging_rxon.flags &=
+                               priv->staging39_rxon.flags &=
                                        ~RXON_FLG_SHORT_SLOT_MSK;
                }
                /* restore RXON assoc */
-               priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
-               iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+               iwl3945_add_station(priv, iwl_bcast_addr, 0, 0);
        }
        iwl3945_send_beacon_cmd(priv);
 
@@ -6727,9 +4839,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
 
 static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                                        struct ieee80211_vif *vif,
-                                   struct ieee80211_if_conf *conf)
+                                       struct ieee80211_if_conf *conf)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        int rc;
 
        if (conf == NULL)
@@ -6753,7 +4865,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                        return rc;
        }
 
-       if (!iwl3945_is_alive(priv))
+       if (!iwl_is_alive(priv))
                return -EAGAIN;
 
        mutex_lock(&priv->mutex);
@@ -6781,21 +4893,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
        }
 
-       if (iwl3945_is_rfkill(priv))
+       if (iwl_is_rfkill(priv))
                goto done;
 
        if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
            !is_multicast_ether_addr(conf->bssid)) {
                /* If there is currently a HW scan going on in the background
                 * then we need to cancel it else the RXON below will fail. */
-               if (iwl3945_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARNING("Aborted scan still in progress "
+               if (iwl_scan_cancel_timeout(priv, 100)) {
+                       IWL_WARN(priv, "Aborted scan still in progress "
                                    "after 100ms\n");
                        IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
                        mutex_unlock(&priv->mutex);
                        return -EAGAIN;
                }
-               memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
+               memcpy(priv->staging39_rxon.bssid_addr, conf->bssid, ETH_ALEN);
 
                /* TODO: Audit driver for usage of these members and see
                 * if mac80211 deprecates them (priv->bssid looks like it
@@ -6809,12 +4921,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                        rc = iwl3945_commit_rxon(priv);
                        if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
                                iwl3945_add_station(priv,
-                                       priv->active_rxon.bssid_addr, 1, 0);
+                                       priv->active39_rxon.bssid_addr, 1, 0);
                }
 
        } else {
-               iwl3945_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               iwl_scan_cancel_timeout(priv, 100);
+               priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
        }
 
@@ -6830,8 +4942,8 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
                                 unsigned int *total_flags,
                                 int mc_count, struct dev_addr_list *mc_list)
 {
-       struct iwl3945_priv *priv = hw->priv;
-       __le32 *filter_flags = &priv->staging_rxon.filter_flags;
+       struct iwl_priv *priv = hw->priv;
+       __le32 *filter_flags = &priv->staging39_rxon.filter_flags;
 
        IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
                        changed_flags, *total_flags);
@@ -6874,15 +4986,15 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
 static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
                                     struct ieee80211_if_init_conf *conf)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
 
        IWL_DEBUG_MAC80211("enter\n");
 
        mutex_lock(&priv->mutex);
 
-       if (iwl3945_is_ready_rf(priv)) {
-               iwl3945_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       if (iwl_is_ready_rf(priv)) {
+               iwl_scan_cancel_timeout(priv, 100);
+               priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
        }
        if (priv->vif == conf->vif) {
@@ -6901,7 +5013,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
                                     struct ieee80211_bss_conf *bss_conf,
                                     u32 changes)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
 
        IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
 
@@ -6909,17 +5021,17 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
                IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
                                   bss_conf->use_short_preamble);
                if (bss_conf->use_short_preamble)
-                       priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+                       priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
                else
-                       priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
        }
 
        if (changes & BSS_CHANGED_ERP_CTS_PROT) {
                IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
                if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-                       priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+                       priv->staging39_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
                else
-                       priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+                       priv->staging39_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
        }
 
        if (changes & BSS_CHANGED_ASSOC) {
@@ -6931,10 +5043,9 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
                if (bss_conf->assoc) {
                        priv->assoc_id = bss_conf->aid;
                        priv->beacon_int = bss_conf->beacon_int;
-                       priv->timestamp0 = bss_conf->timestamp & 0xFFFFFFFF;
-                       priv->timestamp1 = (bss_conf->timestamp >> 32) &
-                                            0xFFFFFFFF;
+                       priv->timestamp = bss_conf->timestamp;
                        priv->assoc_capability = bss_conf->assoc_capability;
+                       priv->power_data.dtim_period = bss_conf->dtim_period;
                        priv->next_scan_jiffies = jiffies +
                                        IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
                        mutex_lock(&priv->mutex);
@@ -6955,7 +5066,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;
+       struct iwl_priv *priv = hw->priv;
        DECLARE_SSID_BUF(ssid_buf);
 
        IWL_DEBUG_MAC80211("enter\n");
@@ -6963,7 +5074,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
        mutex_lock(&priv->mutex);
        spin_lock_irqsave(&priv->lock, flags);
 
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                rc = -EIO;
                IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
                goto out_unlock;
@@ -7005,24 +5116,23 @@ out_unlock:
 }
 
 static int iwl3945_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 ieee80211_vif *vif,
+                              struct ieee80211_sta *sta,
+                              struct ieee80211_key_conf *key)
 {
-       struct iwl3945_priv *priv = hw->priv;
-       int rc = 0;
+       struct iwl_priv *priv = hw->priv;
+       const u8 *addr;
+       int ret;
        u8 sta_id;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (!iwl3945_param_hwcrypto) {
+       if (iwl3945_mod_params.sw_crypto) {
                IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
                return -EOPNOTSUPP;
        }
 
-       if (is_zero_ether_addr(addr))
-               /* only support pairwise keys */
-               return -EOPNOTSUPP;
-
+       addr = sta ? sta->addr : iwl_bcast_addr;
        sta_id = iwl3945_hw_find_station(priv, addr);
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
@@ -7032,12 +5142,12 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        mutex_lock(&priv->mutex);
 
-       iwl3945_scan_cancel_timeout(priv, 100);
+       iwl_scan_cancel_timeout(priv, 100);
 
        switch (cmd) {
        case  SET_KEY:
-               rc = iwl3945_update_sta_key_info(priv, key, sta_id);
-               if (!rc) {
+               ret = iwl3945_update_sta_key_info(priv, key, sta_id);
+               if (!ret) {
                        iwl3945_set_rxon_hwcrypto(priv, 1);
                        iwl3945_commit_rxon(priv);
                        key->hw_key_idx = sta_id;
@@ -7046,33 +5156,33 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                }
                break;
        case DISABLE_KEY:
-               rc = iwl3945_clear_sta_key_info(priv, sta_id);
-               if (!rc) {
+               ret = iwl3945_clear_sta_key_info(priv, sta_id);
+               if (!ret) {
                        iwl3945_set_rxon_hwcrypto(priv, 0);
                        iwl3945_commit_rxon(priv);
                        IWL_DEBUG_MAC80211("disable hwcrypto key\n");
                }
                break;
        default:
-               rc = -EINVAL;
+               ret = -EINVAL;
        }
 
        IWL_DEBUG_MAC80211("leave\n");
        mutex_unlock(&priv->mutex);
 
-       return rc;
+       return ret;
 }
 
 static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                           const struct ieee80211_tx_queue_params *params)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        unsigned long flags;
        int q;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                IWL_DEBUG_MAC80211("leave - RF not ready\n");
                return -EIO;
        }
@@ -7112,15 +5222,15 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
                                struct ieee80211_tx_queue_stats *stats)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        int i, avail;
-       struct iwl3945_tx_queue *txq;
-       struct iwl3945_queue *q;
+       struct iwl_tx_queue *txq;
+       struct iwl_queue *q;
        unsigned long flags;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                IWL_DEBUG_MAC80211("leave - RF not ready\n");
                return -EIO;
        }
@@ -7130,7 +5240,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
        for (i = 0; i < AC_NUM; i++) {
                txq = &priv->txq[i];
                q = &txq->q;
-               avail = iwl3945_queue_space(q);
+               avail = iwl_queue_space(q);
 
                stats[i].len = q->n_window - avail;
                stats[i].limit = q->n_window - q->high_mark;
@@ -7144,29 +5254,19 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
        return 0;
 }
 
-static int iwl3945_mac_get_stats(struct ieee80211_hw *hw,
-                            struct ieee80211_low_level_stats *stats)
-{
-       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;
+       struct iwl_priv *priv = hw->priv;
        unsigned long flags;
 
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter\n");
 
-       iwl3945_reset_qos(priv);
+       iwl_reset_qos(priv);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = 0;
        priv->assoc_capability = 0;
-       priv->call_post_assoc_from_beacon = 0;
 
        /* new association get rid of ibss beacon skb */
        if (priv->ibss_beacon)
@@ -7175,14 +5275,13 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
        priv->ibss_beacon = NULL;
 
        priv->beacon_int = priv->hw->conf.beacon_int;
-       priv->timestamp1 = 0;
-       priv->timestamp0 = 0;
+       priv->timestamp = 0;
        if ((priv->iw_mode == NL80211_IFTYPE_STATION))
                priv->beacon_int = 0;
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
                mutex_unlock(&priv->mutex);
                return;
@@ -7192,8 +5291,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
         * clear RXON_FILTER_ASSOC_MSK bit
        */
        if (priv->iw_mode != NL80211_IFTYPE_AP) {
-               iwl3945_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               iwl_scan_cancel_timeout(priv, 100);
+               priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl3945_commit_rxon(priv);
        }
 
@@ -7215,12 +5314,12 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 
 static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-       struct iwl3945_priv *priv = hw->priv;
+       struct iwl_priv *priv = hw->priv;
        unsigned long flags;
 
        IWL_DEBUG_MAC80211("enter\n");
 
-       if (!iwl3945_is_ready_rf(priv)) {
+       if (!iwl_is_ready_rf(priv)) {
                IWL_DEBUG_MAC80211("leave - RF not ready\n");
                return -EIO;
        }
@@ -7242,7 +5341,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
        IWL_DEBUG_MAC80211("leave\n");
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       iwl3945_reset_qos(priv);
+       iwl_reset_qos(priv);
 
        iwl3945_post_associate(priv);
 
@@ -7256,7 +5355,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
  *
  *****************************************************************************/
 
-#ifdef CONFIG_IWL3945_DEBUG
+#ifdef CONFIG_IWLWIFI_DEBUG
 
 /*
  * The following adds a new attribute to the sysfs representation
@@ -7265,38 +5364,41 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
  *
  * See the level definitions in iwl for details.
  */
-
-static ssize_t show_debug_level(struct device_driver *d, char *buf)
+static ssize_t show_debug_level(struct device *d,
+                               struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "0x%08X\n", iwl3945_debug_level);
+       struct iwl_priv *priv = d->driver_data;
+
+       return sprintf(buf, "0x%08X\n", priv->debug_level);
 }
-static ssize_t store_debug_level(struct device_driver *d,
+static ssize_t store_debug_level(struct device *d,
+                               struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       char *p = (char *)buf;
-       u32 val;
+       struct iwl_priv *priv = d->driver_data;
+       unsigned long val;
+       int ret;
 
-       val = simple_strtoul(p, &p, 0);
-       if (p == buf)
-               printk(KERN_INFO DRV_NAME
-                      ": %s is not in hex or decimal form.\n", buf);
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
        else
-               iwl3945_debug_level = val;
+               priv->debug_level = val;
 
        return strnlen(buf, count);
 }
 
-static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                  show_debug_level, store_debug_level);
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+                       show_debug_level, store_debug_level);
 
-#endif /* CONFIG_IWL3945_DEBUG */
+#endif /* CONFIG_IWLWIFI_DEBUG */
 
 static ssize_t show_temperature(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 
-       if (!iwl3945_is_alive(priv))
+       if (!iwl_is_alive(priv))
                return -EAGAIN;
 
        return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
@@ -7307,22 +5409,21 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
 static ssize_t show_tx_power(struct device *d,
                             struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-       return sprintf(buf, "%d\n", priv->user_txpower_limit);
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
 }
 
 static ssize_t store_tx_power(struct device *d,
                              struct device_attribute *attr,
                              const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
        char *p = (char *)buf;
        u32 val;
 
        val = simple_strtoul(p, &p, 10);
        if (p == buf)
-               printk(KERN_INFO DRV_NAME
-                      ": %s is not in decimal form.\n", buf);
+               IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
        else
                iwl3945_hw_reg_set_txpower(priv, val);
 
@@ -7334,27 +5435,27 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
 static ssize_t show_flags(struct device *d,
                          struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 
-       return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
+       return sprintf(buf, "0x%04X\n", priv->active39_rxon.flags);
 }
 
 static ssize_t store_flags(struct device *d,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
        u32 flags = simple_strtoul(buf, NULL, 0);
 
        mutex_lock(&priv->mutex);
-       if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
+       if (le32_to_cpu(priv->staging39_rxon.flags) != flags) {
                /* Cancel any currently running scans... */
-               if (iwl3945_scan_cancel_timeout(priv, 100))
-                       IWL_WARNING("Could not cancel scan.\n");
+               if (iwl_scan_cancel_timeout(priv, 100))
+                       IWL_WARN(priv, "Could not cancel scan.\n");
                else {
                        IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
                                       flags);
-                       priv->staging_rxon.flags = cpu_to_le32(flags);
+                       priv->staging39_rxon.flags = cpu_to_le32(flags);
                        iwl3945_commit_rxon(priv);
                }
        }
@@ -7368,28 +5469,28 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
 static ssize_t show_filter_flags(struct device *d,
                                 struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 
        return sprintf(buf, "0x%04X\n",
-               le32_to_cpu(priv->active_rxon.filter_flags));
+               le32_to_cpu(priv->active39_rxon.filter_flags));
 }
 
 static ssize_t store_filter_flags(struct device *d,
                                  struct device_attribute *attr,
                                  const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
        u32 filter_flags = simple_strtoul(buf, NULL, 0);
 
        mutex_lock(&priv->mutex);
-       if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
+       if (le32_to_cpu(priv->staging39_rxon.filter_flags) != filter_flags) {
                /* Cancel any currently running scans... */
-               if (iwl3945_scan_cancel_timeout(priv, 100))
-                       IWL_WARNING("Could not cancel scan.\n");
+               if (iwl_scan_cancel_timeout(priv, 100))
+                       IWL_WARN(priv, "Could not cancel scan.\n");
                else {
                        IWL_DEBUG_INFO("Committing rxon.filter_flags = "
                                       "0x%04X\n", filter_flags);
-                       priv->staging_rxon.filter_flags =
+                       priv->staging39_rxon.filter_flags =
                                cpu_to_le32(filter_flags);
                        iwl3945_commit_rxon(priv);
                }
@@ -7407,8 +5508,8 @@ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
 static ssize_t show_measurement(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
-       struct iwl3945_spectrum_notification measure_report;
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       struct iwl_spectrum_notification measure_report;
        u32 size = sizeof(measure_report), len = 0, ofs = 0;
        u8 *data = (u8 *)&measure_report;
        unsigned long flags;
@@ -7440,9 +5541,9 @@ static ssize_t store_measurement(struct device *d,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
        struct ieee80211_measurement_params params = {
-               .channel = le16_to_cpu(priv->active_rxon.channel),
+               .channel = le16_to_cpu(priv->active39_rxon.channel),
                .start_time = cpu_to_le64(priv->last_tsf),
                .duration = cpu_to_le16(1),
        };
@@ -7479,7 +5580,7 @@ static ssize_t store_retry_rate(struct device *d,
                                struct device_attribute *attr,
                                const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
        priv->retry_rate = simple_strtoul(buf, NULL, 0);
        if (priv->retry_rate <= 0)
@@ -7491,7 +5592,7 @@ static ssize_t store_retry_rate(struct device *d,
 static ssize_t show_retry_rate(struct device *d,
                               struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
        return sprintf(buf, "%d", priv->retry_rate);
 }
 
@@ -7502,20 +5603,21 @@ static ssize_t store_power_level(struct device *d,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
        int rc;
        int mode;
 
        mode = simple_strtoul(buf, NULL, 0);
        mutex_lock(&priv->mutex);
 
-       if (!iwl3945_is_ready(priv)) {
+       if (!iwl_is_ready(priv)) {
                rc = -EAGAIN;
                goto out;
        }
 
-       if ((mode < 1) || (mode > IWL_POWER_LIMIT) || (mode == IWL_POWER_AC))
-               mode = IWL_POWER_AC;
+       if ((mode < 1) || (mode > IWL39_POWER_LIMIT) ||
+           (mode == IWL39_POWER_AC))
+               mode = IWL39_POWER_AC;
        else
                mode |= IWL_POWER_ENABLED;
 
@@ -7556,17 +5658,17 @@ static const s32 period_duration[] = {
 static ssize_t show_power_level(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
        int level = IWL_POWER_LEVEL(priv->power_mode);
        char *p = buf;
 
        p += sprintf(p, "%d ", level);
        switch (level) {
        case IWL_POWER_MODE_CAM:
-       case IWL_POWER_AC:
+       case IWL39_POWER_AC:
                p += sprintf(p, "(AC)");
                break;
-       case IWL_POWER_BATTERY:
+       case IWL39_POWER_BATTERY:
                p += sprintf(p, "(BATTERY)");
                break;
        default:
@@ -7600,17 +5702,17 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
 static ssize_t show_statistics(struct device *d,
                               struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
        u32 size = sizeof(struct iwl3945_notif_statistics);
        u32 len = 0, ofs = 0;
-       u8 *data = (u8 *)&priv->statistics;
+       u8 *data = (u8 *)&priv->statistics_39;
        int rc = 0;
 
-       if (!iwl3945_is_alive(priv))
+       if (!iwl_is_alive(priv))
                return -EAGAIN;
 
        mutex_lock(&priv->mutex);
-       rc = iwl3945_send_statistics_request(priv);
+       rc = iwl_send_statistics_request(priv, 0);
        mutex_unlock(&priv->mutex);
 
        if (rc) {
@@ -7638,12 +5740,12 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
 static ssize_t show_antenna(struct device *d,
                            struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
-       if (!iwl3945_is_alive(priv))
+       if (!iwl_is_alive(priv))
                return -EAGAIN;
 
-       return sprintf(buf, "%d\n", priv->antenna);
+       return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
 }
 
 static ssize_t store_antenna(struct device *d,
@@ -7651,7 +5753,7 @@ static ssize_t store_antenna(struct device *d,
                             const char *buf, size_t count)
 {
        int ant;
-       struct iwl3945_priv *priv = dev_get_drvdata(d);
+       struct iwl_priv *priv = dev_get_drvdata(d);
 
        if (count == 0)
                return 0;
@@ -7663,7 +5765,7 @@ static ssize_t store_antenna(struct device *d,
 
        if ((ant >= 0) && (ant <= 2)) {
                IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
-               priv->antenna = (enum iwl3945_antenna)ant;
+               iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
        } else
                IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
 
@@ -7676,8 +5778,8 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
 static ssize_t show_status(struct device *d,
                           struct device_attribute *attr, char *buf)
 {
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-       if (!iwl3945_is_alive(priv))
+       struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+       if (!iwl_is_alive(priv))
                return -EAGAIN;
        return sprintf(buf, "0x%08x\n", (int)priv->status);
 }
@@ -7691,7 +5793,7 @@ static ssize_t dump_error_log(struct device *d,
        char *p = (char *)buf;
 
        if (p[0] == '1')
-               iwl3945_dump_nic_error_log((struct iwl3945_priv *)d->driver_data);
+               iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data);
 
        return strnlen(buf, count);
 }
@@ -7705,7 +5807,7 @@ static ssize_t dump_event_log(struct device *d,
        char *p = (char *)buf;
 
        if (p[0] == '1')
-               iwl3945_dump_nic_event_log((struct iwl3945_priv *)d->driver_data);
+               iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data);
 
        return strnlen(buf, count);
 }
@@ -7718,7 +5820,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
  *
  *****************************************************************************/
 
-static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
+static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
 {
        priv->workqueue = create_workqueue(DRV_NAME);
 
@@ -7727,14 +5829,15 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
        INIT_WORK(&priv->up, iwl3945_bg_up);
        INIT_WORK(&priv->restart, iwl3945_bg_restart);
        INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-       INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed);
-       INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
-       INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
-       INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
+       INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
        INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
        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);
+       INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
+       INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
+       INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
+       INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
+       INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 
        iwl3945_hw_setup_deferred_work(priv);
 
@@ -7742,7 +5845,7 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
                     iwl3945_irq_tasklet, (unsigned long)priv);
 }
 
-static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv)
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
 {
        iwl3945_hw_cancel_deferred_work(priv);
 
@@ -7768,7 +5871,9 @@ static struct attribute *iwl3945_sysfs_entries[] = {
        &dev_attr_status.attr,
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
-
+#ifdef CONFIG_IWLWIFI_DEBUG
+       &dev_attr_debug_level.attr,
+#endif
        NULL
 };
 
@@ -7787,7 +5892,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .config_interface = iwl3945_mac_config_interface,
        .configure_filter = iwl3945_configure_filter,
        .set_key = iwl3945_mac_set_key,
-       .get_stats = iwl3945_mac_get_stats,
        .get_tx_stats = iwl3945_mac_get_tx_stats,
        .conf_tx = iwl3945_mac_conf_tx,
        .reset_tsf = iwl3945_mac_reset_tsf,
@@ -7795,59 +5899,136 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .hw_scan = iwl3945_mac_hw_scan
 };
 
+static int iwl3945_init_drv(struct iwl_priv *priv)
+{
+       int ret;
+       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+       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;
+
+       iwl_reset_qos(priv);
+
+       priv->qos_data.qos_active = 0;
+       priv->qos_data.qos_cap.val = 0;
+
+       priv->rates_mask = IWL_RATES_MASK;
+       /* If power management is turned on, default to AC mode */
+       priv->power_mode = IWL39_POWER_AC;
+       priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
+
+       if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
+               IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
+                        eeprom->version);
+               ret = -EINVAL;
+               goto err;
+       }
+       ret = iwl_init_channel_map(priv);
+       if (ret) {
+               IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
+               goto err;
+       }
+
+       /* Set up txpower settings in driver for all channels */
+       if (iwl3945_txpower_set_from_eeprom(priv)) {
+               ret = -EIO;
+               goto err_free_channel_map;
+       }
+
+       ret = iwlcore_init_geos(priv);
+       if (ret) {
+               IWL_ERR(priv, "initializing geos failed: %d\n", ret);
+               goto err_free_channel_map;
+       }
+       iwl3945_init_hw_rates(priv, priv->ieee_rates);
+
+       if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+               priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                       &priv->bands[IEEE80211_BAND_2GHZ];
+       if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+               priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                       &priv->bands[IEEE80211_BAND_5GHZ];
+
+       return 0;
+
+err_free_channel_map:
+       iwl_free_channel_map(priv);
+err:
+       return ret;
+}
+
 static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = 0;
-       struct iwl3945_priv *priv;
+       struct iwl_priv *priv;
        struct ieee80211_hw *hw;
-       struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
+       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+       struct iwl3945_eeprom *eeprom;
        unsigned long flags;
 
        /***********************
         * 1. Allocating HW data
         * ********************/
 
-       /* Disabling hardware scan means that mac80211 will perform scans
-        * "the hard way", rather than using device's scan. */
-       if (iwl3945_param_disable_hw_scan) {
-               IWL_DEBUG_INFO("Disabling hw_scan\n");
-               iwl3945_hw_ops.hw_scan = NULL;
-       }
-
-       if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) ||
-           (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
-               IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-                         IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
-               err = -EINVAL;
-               goto out;
-       }
-
        /* mac80211 allocates memory for this device instance, including
         *   space for this driver's private structure */
-       hw = ieee80211_alloc_hw(sizeof(struct iwl3945_priv), &iwl3945_hw_ops);
+       hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
        if (hw == NULL) {
-               IWL_ERROR("Can not allocate network device\n");
+               printk(KERN_ERR DRV_NAME "Can not allocate network device\n");
                err = -ENOMEM;
                goto out;
        }
-
+       priv = hw->priv;
        SET_IEEE80211_DEV(hw, &pdev->dev);
 
-       priv = hw->priv;
-       priv->hw = hw;
-       priv->pci_dev = pdev;
-       priv->cfg = cfg;
+       if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
+            (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) {
+               IWL_ERR(priv,
+                       "invalid queues_num, should be between %d and %d\n",
+                       IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
+               err = -EINVAL;
+               goto out;
+       }
+
+       /*
+        * Disabling hardware scan means that mac80211 will perform scans
+        * "the hard way", rather than using device's scan.
+        */
+       if (iwl3945_mod_params.disable_hw_scan) {
+               IWL_DEBUG_INFO("Disabling hw_scan\n");
+               iwl3945_hw_ops.hw_scan = NULL;
+       }
+
 
        IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
-       hw->rate_control_algorithm = "iwl-3945-rs";
-       hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+       priv->cfg = cfg;
+       priv->pci_dev = pdev;
 
-       /* 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;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       priv->debug_level = iwl3945_mod_params.debug;
        atomic_set(&priv->restrict_refcnt, 0);
 #endif
+       hw->rate_control_algorithm = "iwl-3945-rs";
+       hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
 
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
@@ -7857,7 +6038,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->fw_handles_regulatory = true;
+       hw->wiphy->custom_regulatory = true;
 
        /* 4 EDCA QOS priorities */
        hw->queues = 4;
@@ -7876,7 +6057,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if (!err)
                err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
        if (err) {
-               printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
+               IWL_WARN(priv, "No suitable DMA available.\n");
                goto out_pci_disable_device;
        }
 
@@ -7902,29 +6083,26 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
         * PCI Tx retries from interfering with C3 CPU state */
        pci_write_config_byte(pdev, 0x41, 0x00);
 
-       /* 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_direct_bit(priv, CSR_GP_CNTRL,
-                               CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+       /* amp init */
+       err = priv->cfg->ops->lib->apm_ops.init(priv);
        if (err < 0) {
-               IWL_DEBUG_INFO("Failed to init the card\n");
-               goto out_remove_sysfs;
+               IWL_DEBUG_INFO("Failed to init APMG\n");
+               goto out_iounmap;
        }
 
        /***********************
         * 4. Read EEPROM
         * ********************/
+
        /* Read the EEPROM */
-       err = iwl3945_eeprom_init(priv);
+       err = iwl_eeprom_init(priv);
        if (err) {
-               IWL_ERROR("Unable to init EEPROM\n");
+               IWL_ERR(priv, "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);
+       eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+       memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN);
        IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
        SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
@@ -7932,60 +6110,23 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
         * 5. Setup HW Constants
         * ********************/
        /* Device-specific setup */
-       if (iwl3945_hw_set_hw_setting(priv)) {
-               IWL_ERROR("failed to set hw settings\n");
+       if (iwl3945_hw_set_hw_params(priv)) {
+               IWL_ERR(priv, "failed to set hw settings\n");
                goto out_iounmap;
        }
 
        /***********************
         * 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;
-
-
-       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;
-
-       err = iwl3945_init_channel_map(priv);
-       if (err) {
-               IWL_ERROR("initializing regulatory failed: %d\n", err);
-               goto out_release_irq;
-       }
 
-       err = iwl3945_init_geos(priv);
+       err = iwl3945_init_drv(priv);
        if (err) {
-               IWL_ERROR("initializing geos failed: %d\n", err);
-               goto out_free_channel_map;
+               IWL_ERR(priv, "initializing driver failed\n");
+               goto out_free_geos;
        }
 
-       printk(KERN_INFO DRV_NAME
-               ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+       IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
+               priv->cfg->name);
 
        /***********************************
         * 7. Initialize Module Parameters
@@ -7993,7 +6134,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        /* Initialize module parameter values here */
        /* Disable radio (SW RF KILL) via parameter when loading driver */
-       if (iwl3945_param_disable) {
+       if (iwl3945_mod_params.disable) {
                set_bit(STATUS_RF_KILL_SW, &priv->status);
                IWL_DEBUG_INFO("Radio disabled.\n");
        }
@@ -8007,56 +6148,61 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        iwl3945_disable_interrupts(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       pci_enable_msi(priv->pci_dev);
+
+       err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
+                         DRV_NAME, priv);
+       if (err) {
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+               goto out_disable_msi;
+       }
+
        err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
        if (err) {
-               IWL_ERROR("failed to create sysfs device attributes\n");
-               goto out_free_geos;
+               IWL_ERR(priv, "failed to create sysfs device attributes\n");
+               goto out_release_irq;
        }
 
        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
+        * 9. Setup and Register mac80211
         * *******************************/
 
        err = ieee80211_register_hw(priv->hw);
        if (err) {
-               IWL_ERROR("Failed to register network device (error %d)\n", err);
+               IWL_ERR(priv, "Failed to register network device: %d\n", err);
                goto  out_remove_sysfs;
        }
 
        priv->hw->conf.beacon_int = 100;
        priv->mac80211_registered = 1;
 
-
-       err = iwl3945_rfkill_init(priv);
+       err = iwl_rfkill_init(priv);
        if (err)
-               IWL_ERROR("Unable to initialize RFKILL system. "
+               IWL_ERR(priv, "Unable to initialize RFKILL system. "
                                  "Ignoring error: %d\n", err);
 
+       /* Start monitoring the killswitch */
+       queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+                          2 * HZ);
+
        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);
-
+       iwlcore_free_geos(priv);
 
  out_release_irq:
+       free_irq(priv->pci_dev->irq, priv);
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       iwl3945_unset_hw_setting(priv);
-
+       iwl3945_unset_hw_params(priv);
+ out_disable_msi:
+       pci_disable_msi(priv->pci_dev);
  out_iounmap:
        pci_iounmap(pdev, priv->hw_base);
  out_pci_release_regions:
@@ -8072,7 +6218,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 {
-       struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
        unsigned long flags;
 
        if (!priv)
@@ -8082,7 +6228,12 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 
-       iwl3945_down(priv);
+       if (priv->mac80211_registered) {
+               ieee80211_unregister_hw(priv->hw);
+               priv->mac80211_registered = 0;
+       } else {
+               iwl3945_down(priv);
+       }
 
        /* make sure we flush any pending irq or
         * tasklet for the driver
@@ -8095,19 +6246,18 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
-       iwl3945_rfkill_unregister(priv);
+       iwl_rfkill_unregister(priv);
+       cancel_delayed_work(&priv->rfkill_poll);
+
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
-               iwl3945_rx_queue_free(priv, &priv->rxq);
+               iwl_rx_queue_free(priv, &priv->rxq);
        iwl3945_hw_txq_ctx_free(priv);
 
-       iwl3945_unset_hw_setting(priv);
+       iwl3945_unset_hw_params(priv);
        iwl3945_clear_stations_table(priv);
 
-       if (priv->mac80211_registered)
-               ieee80211_unregister_hw(priv->hw);
-
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
 
@@ -8117,13 +6267,16 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
 
+       free_irq(pdev->irq, priv);
+       pci_disable_msi(pdev);
+
        pci_iounmap(pdev, priv->hw_base);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 
-       iwl3945_free_channel_map(priv);
-       iwl3945_free_geos(priv);
+       iwl_free_channel_map(priv);
+       iwlcore_free_geos(priv);
        kfree(priv->scan);
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
@@ -8135,14 +6288,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
 static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-       struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
 
        if (priv->is_open) {
                set_bit(STATUS_IN_SUSPEND, &priv->status);
                iwl3945_mac_stop(priv->hw);
                priv->is_open = 1;
        }
-
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
@@ -8150,9 +6304,11 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 
 static int iwl3945_pci_resume(struct pci_dev *pdev)
 {
-       struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
 
        pci_set_power_state(pdev, PCI_D0);
+       pci_enable_device(pdev);
+       pci_restore_state(pdev);
 
        if (priv->is_open)
                iwl3945_mac_start(priv->hw);
@@ -8163,114 +6319,6 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
 
 #endif /* CONFIG_PM */
 
-/*************** RFKILL FUNCTIONS **********/
-#ifdef CONFIG_IWL3945_RFKILL
-/* software rf-kill from user */
-static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
-{
-       struct iwl3945_priv *priv = data;
-       int err = 0;
-
-       if (!priv->rfkill)
-       return 0;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return 0;
-
-       IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
-       mutex_lock(&priv->mutex);
-
-       switch (state) {
-       case RFKILL_STATE_UNBLOCKED:
-               if (iwl3945_is_rfkill_hw(priv)) {
-                       err = -EBUSY;
-                       goto out_unlock;
-               }
-               iwl3945_radio_kill_sw(priv, 0);
-               break;
-       case RFKILL_STATE_SOFT_BLOCKED:
-               iwl3945_radio_kill_sw(priv, 1);
-               break;
-       default:
-               IWL_WARNING("we received unexpected RFKILL state %d\n", state);
-               break;
-       }
-out_unlock:
-       mutex_unlock(&priv->mutex);
-
-       return err;
-}
-
-int iwl3945_rfkill_init(struct iwl3945_priv *priv)
-{
-       struct device *device = wiphy_dev(priv->hw->wiphy);
-       int ret = 0;
-
-       BUG_ON(device == NULL);
-
-       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");
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       priv->rfkill->name = priv->cfg->name;
-       priv->rfkill->data = priv;
-       priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
-       priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill;
-       priv->rfkill->user_claim_unsupported = 1;
-
-       priv->rfkill->dev.class->suspend = NULL;
-       priv->rfkill->dev.class->resume = NULL;
-
-       ret = rfkill_register(priv->rfkill);
-       if (ret) {
-               IWL_ERROR("Unable to register rfkill: %d\n", ret);
-               goto freed_rfkill;
-       }
-
-       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
-       return ret;
-
-freed_rfkill:
-       if (priv->rfkill != NULL)
-               rfkill_free(priv->rfkill);
-       priv->rfkill = NULL;
-
-error:
-       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
-       return ret;
-}
-
-void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
-{
-       if (priv->rfkill)
-               rfkill_unregister(priv->rfkill);
-
-       priv->rfkill = NULL;
-}
-
-/* set rf-kill to the right state. */
-void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
-{
-
-       if (!priv->rfkill)
-               return;
-
-       if (iwl3945_is_rfkill_hw(priv)) {
-               rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
-               return;
-       }
-
-       if (!iwl3945_is_rfkill_sw(priv))
-               rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
-       else
-               rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
-}
-#endif
-
 /*****************************************************************************
  *
  * driver and module entry point
@@ -8297,29 +6345,19 @@ static int __init iwl3945_init(void)
 
        ret = iwl3945_rate_control_register();
        if (ret) {
-               IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
+               printk(KERN_ERR DRV_NAME
+                      "Unable to register rate control algorithm: %d\n", ret);
                return ret;
        }
 
        ret = pci_register_driver(&iwl3945_driver);
        if (ret) {
-               IWL_ERROR("Unable to initialize PCI module\n");
+               printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
                goto error_register;
        }
-#ifdef CONFIG_IWL3945_DEBUG
-       ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level);
-       if (ret) {
-               IWL_ERROR("Unable to create driver sysfs file\n");
-               goto error_debug;
-       }
-#endif
 
        return ret;
 
-#ifdef CONFIG_IWL3945_DEBUG
-error_debug:
-       pci_unregister_driver(&iwl3945_driver);
-#endif
 error_register:
        iwl3945_rate_control_unregister();
        return ret;
@@ -8327,29 +6365,29 @@ error_register:
 
 static void __exit iwl3945_exit(void)
 {
-#ifdef CONFIG_IWL3945_DEBUG
-       driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level);
-#endif
        pci_unregister_driver(&iwl3945_driver);
        iwl3945_rate_control_unregister();
 }
 
 MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
 
-module_param_named(antenna, iwl3945_param_antenna, int, 0444);
+module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl3945_param_disable, int, 0444);
+module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
 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, uint, 0444);
+module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
+MODULE_PARM_DESC(swcrypto,
+                "using software crypto (default 1 [software])\n");
+module_param_named(debug, iwl3945_mod_params.debug, uint, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
-module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444);
+module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
 MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
 
-module_param_named(queues_num, iwl3945_param_queues_num, int, 0444);
+module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444);
 MODULE_PARM_DESC(queues_num, "number of hw queues.");
 
+module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
+MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
+
 module_exit(iwl3945_exit);
 module_init(iwl3945_init);
index 02080a3682a91787a6e5dffb2986d826f97272b9..0b6918584503b836d2cc49196f09e81725f31977 100644 (file)
@@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o  \
 usb8xxx-objs += if_usb.o
 libertas_cs-objs += if_cs.o
 libertas_sdio-objs += if_sdio.o
+libertas_spi-objs += if_spi.o
 
 obj-$(CONFIG_LIBERTAS)     += libertas.o
 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
 obj-$(CONFIG_LIBERTAS_CS)  += libertas_cs.o
 obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
+obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
index ec4efd7ff3c85064929fe67a6dee3c10f3c2148a..50e28a0cdfeeb0fc60397a146a14c2edad97f1f9 100644 (file)
@@ -629,7 +629,7 @@ static ssize_t lbs_rdrf_write(struct file *file,
                res = -EFAULT;
                goto out_unlock;
        }
-       priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
+       priv->rf_offset = simple_strtoul(buf, NULL, 16);
        res = count;
 out_unlock:
        free_page(addr);
@@ -680,12 +680,12 @@ out_unlock:
 }
 
 struct lbs_debugfs_files {
-       char *name;
+       const char *name;
        int perm;
        struct file_operations fops;
 };
 
-static struct lbs_debugfs_files debugfs_files[] = {
+static const struct lbs_debugfs_files debugfs_files[] = {
        { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
        { "getscantable", 0444, FOPS(lbs_getscantable,
                                        write_file_dummy), },
@@ -693,7 +693,7 @@ static struct lbs_debugfs_files debugfs_files[] = {
                                lbs_sleepparams_write), },
 };
 
-static struct lbs_debugfs_files debugfs_events_files[] = {
+static const struct lbs_debugfs_files debugfs_events_files[] = {
        {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
                                lbs_lowrssi_write), },
        {"low_snr", 0644, FOPS(lbs_lowsnr_read,
@@ -708,7 +708,7 @@ static struct lbs_debugfs_files debugfs_events_files[] = {
                                lbs_highsnr_write), },
 };
 
-static struct lbs_debugfs_files debugfs_regs_files[] = {
+static const struct lbs_debugfs_files debugfs_regs_files[] = {
        {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
        {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
        {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
@@ -735,7 +735,7 @@ void lbs_debugfs_remove(void)
 void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
 {
        int i;
-       struct lbs_debugfs_files *files;
+       const struct lbs_debugfs_files *files;
        if (!lbs_dir)
                goto exit;
 
@@ -938,7 +938,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
        return (ssize_t)cnt;
 }
 
-static struct file_operations lbs_debug_fops = {
+static const struct file_operations lbs_debug_fops = {
        .owner = THIS_MODULE,
        .open = open_file_generic,
        .write = lbs_debugfs_write,
index c364e4c01d1b7183f53290206a997e41051b6135..6388b05df4fcdd9f7da04bc5aaaaf79b4852178c 100644 (file)
@@ -41,6 +41,7 @@
 #define LBS_DEB_HEX    0x00200000
 #define LBS_DEB_SDIO   0x00400000
 #define LBS_DEB_SYSFS  0x00800000
+#define LBS_DEB_SPI    0x01000000
 
 extern unsigned int lbs_debug;
 
@@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
 #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)
 #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
+#define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
 
 #define lbs_pr_info(format, args...) \
        printk(KERN_INFO DRV_NAME": " format, ## args)
index 277ff1975bde8e22ea1009268cf45f94920f39f5..d4457ef808a647c8c174de7d015b27ec01622127 100644 (file)
@@ -66,6 +66,7 @@
 #define CMD_802_11_LED_GPIO_CTRL               0x004e
 #define CMD_802_11_EEPROM_ACCESS               0x0059
 #define CMD_802_11_BAND_CONFIG                 0x0058
+#define CMD_GSPI_BUS_CONFIG                    0x005a
 #define CMD_802_11D_DOMAIN_INFO                        0x005b
 #define CMD_802_11_KEY_MATERIAL                        0x005e
 #define CMD_802_11_SLEEP_PARAMS                        0x0066
index f6a79a653b7ba5bfb00e14588963ae6692429221..a899aeb676bbbeb744dadb0bc313fe427611fd86 100644 (file)
@@ -221,6 +221,14 @@ struct cmd_ds_mac_multicast_adr {
        u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
 } __attribute__ ((packed));
 
+struct cmd_ds_gspi_bus_config {
+       struct cmd_header hdr;
+       __le16 action;
+       __le16 bus_delay_mode;
+       __le16 host_time_delay_to_read_port;
+       __le16 host_time_delay_to_read_register;
+} __attribute__ ((packed));
+
 struct cmd_ds_802_11_authenticate {
        u8 macaddr[ETH_ALEN];
        u8 authtype;
index 842a08d1f1063427a1550062c436b62e2fde8701..8f8934a5ba3a9954b255437e0244f2135168abaf 100644 (file)
@@ -151,7 +151,7 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
        for (i = 0; i < 100000; i++) {
                u8 val = if_cs_read8(card, addr);
                if (val == reg)
-                       return i;
+                       return 0;
                udelay(5);
        }
        return -ETIME;
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
new file mode 100644 (file)
index 0000000..7c02ea3
--- /dev/null
@@ -0,0 +1,1203 @@
+/*
+ *     linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *     Driver for Marvell SPI WLAN cards.
+ *
+ *     Copyright 2008 Analog Devices Inc.
+ *
+ *     Authors:
+ *     Andrey Yurovsky <andrey@cozybit.com>
+ *     Colin McCabe <colin@cozybit.com>
+ *
+ *     Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman
+ *
+ * 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/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/spi/libertas_spi.h>
+#include <linux/spi/spi.h>
+
+#include "host.h"
+#include "decl.h"
+#include "defs.h"
+#include "dev.h"
+#include "if_spi.h"
+
+struct if_spi_packet {
+       struct list_head                list;
+       u16                             blen;
+       u8                              buffer[0] __attribute__((aligned(4)));
+};
+
+struct if_spi_card {
+       struct spi_device               *spi;
+       struct lbs_private              *priv;
+
+       char                            helper_fw_name[FIRMWARE_NAME_MAX];
+       char                            main_fw_name[FIRMWARE_NAME_MAX];
+
+       /* The card ID and card revision, as reported by the hardware. */
+       u16                             card_id;
+       u8                              card_rev;
+
+       /* Pin number for our GPIO chip-select. */
+       /* TODO: Once the generic SPI layer has some additional features, we
+        * should take this out and use the normal chip select here.
+        * We need support for chip select delays, and not dropping chipselect
+        * after each word. */
+       int                             gpio_cs;
+
+       /* The last time that we initiated an SPU operation */
+       unsigned long                   prev_xfer_time;
+
+       int                             use_dummy_writes;
+       unsigned long                   spu_port_delay;
+       unsigned long                   spu_reg_delay;
+
+       /* Handles all SPI communication (except for FW load) */
+       struct task_struct              *spi_thread;
+       int                             run_thread;
+
+       /* Used to wake up the spi_thread */
+       struct semaphore                spi_ready;
+       struct semaphore                spi_thread_terminated;
+
+       u8                              cmd_buffer[IF_SPI_CMD_BUF_SIZE];
+
+       /* A buffer of incoming packets from libertas core.
+        * Since we can't sleep in hw_host_to_card, we have to buffer
+        * them. */
+       struct list_head                cmd_packet_list;
+       struct list_head                data_packet_list;
+
+       /* Protects cmd_packet_list and data_packet_list */
+       spinlock_t                      buffer_lock;
+};
+
+static void free_if_spi_card(struct if_spi_card *card)
+{
+       struct list_head *cursor, *next;
+       struct if_spi_packet *packet;
+
+       BUG_ON(card->run_thread);
+       list_for_each_safe(cursor, next, &card->cmd_packet_list) {
+               packet = container_of(cursor, struct if_spi_packet, list);
+               list_del(&packet->list);
+               kfree(packet);
+       }
+       list_for_each_safe(cursor, next, &card->data_packet_list) {
+               packet = container_of(cursor, struct if_spi_packet, list);
+               list_del(&packet->list);
+               kfree(packet);
+       }
+       spi_set_drvdata(card->spi, NULL);
+       kfree(card);
+}
+
+static struct chip_ident chip_id_to_device_name[] = {
+       { .chip_id = 0x04, .name = 8385 },
+       { .chip_id = 0x0b, .name = 8686 },
+};
+
+/*
+ * SPI Interface Unit Routines
+ *
+ * The SPU sits between the host and the WLAN module.
+ * All communication with the firmware is through SPU transactions.
+ *
+ * First we have to put a SPU register name on the bus. Then we can
+ * either read from or write to that register.
+ *
+ * For 16-bit transactions, byte order on the bus is big-endian.
+ * We don't have to worry about that here, though.
+ * The translation takes place in the SPI routines.
+ */
+
+static void spu_transaction_init(struct if_spi_card *card)
+{
+       if (!time_after(jiffies, card->prev_xfer_time + 1)) {
+               /* Unfortunately, the SPU requires a delay between successive
+                * transactions. If our last transaction was more than a jiffy
+                * ago, we have obviously already delayed enough.
+                * If not, we have to busy-wait to be on the safe side. */
+               ndelay(400);
+       }
+       gpio_set_value(card->gpio_cs, 0); /* assert CS */
+}
+
+static void spu_transaction_finish(struct if_spi_card *card)
+{
+       gpio_set_value(card->gpio_cs, 1); /* drop CS */
+       card->prev_xfer_time = jiffies;
+}
+
+/* Write out a byte buffer to an SPI register,
+ * using a series of 16-bit transfers. */
+static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
+{
+       int err = 0;
+       u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
+
+       /* You must give an even number of bytes to the SPU, even if it
+        * doesn't care about the last one.  */
+       BUG_ON(len & 0x1);
+
+       spu_transaction_init(card);
+
+       /* write SPU register index */
+       err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+       if (err)
+               goto out;
+
+       err = spi_write(card->spi, buf, len);
+
+out:
+       spu_transaction_finish(card);
+       return err;
+}
+
+static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
+{
+       return spu_write(card, reg, (u8 *)&val, sizeof(u16));
+}
+
+static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
+{
+       /* The lower 16 bits are written first. */
+       u16 out[2];
+       out[0] = val & 0xffff;
+       out[1] = (val & 0xffff0000) >> 16;
+       return spu_write(card, reg, (u8 *)&out, sizeof(u32));
+}
+
+static inline int spu_reg_is_port_reg(u16 reg)
+{
+       switch (reg) {
+       case IF_SPI_IO_RDWRPORT_REG:
+       case IF_SPI_CMD_RDWRPORT_REG:
+       case IF_SPI_DATA_RDWRPORT_REG:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
+{
+       unsigned int i, delay;
+       int err = 0;
+       u16 zero = 0;
+       u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
+
+       /* You must take an even number of bytes from the SPU, even if you
+        * don't care about the last one.  */
+       BUG_ON(len & 0x1);
+
+       spu_transaction_init(card);
+
+       /* write SPU register index */
+       err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+       if (err)
+               goto out;
+
+       delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
+                                               card->spu_reg_delay;
+       if (card->use_dummy_writes) {
+               /* Clock in dummy cycles while the SPU fills the FIFO */
+               for (i = 0; i < delay / 16; ++i) {
+                       err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
+                       if (err)
+                               return err;
+               }
+       } else {
+               /* Busy-wait while the SPU fills the FIFO */
+               ndelay(100 + (delay * 10));
+       }
+
+       /* read in data */
+       err = spi_read(card->spi, buf, len);
+
+out:
+       spu_transaction_finish(card);
+       return err;
+}
+
+/* Read 16 bits from an SPI register */
+static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
+{
+       return spu_read(card, reg, (u8 *)val, sizeof(u16));
+}
+
+/* Read 32 bits from an SPI register.
+ * The low 16 bits are read first. */
+static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
+{
+       u16 buf[2];
+       int err;
+       err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
+       if (!err)
+               *val = buf[0] | (buf[1] << 16);
+       return err;
+}
+
+/* Keep reading 16 bits from an SPI register until you get the correct result.
+ *
+ * If mask = 0, the correct result is any non-zero number.
+ * If mask != 0, the correct result is any number where
+ * number & target_mask == target
+ *
+ * Returns -ETIMEDOUT if a second passes without the correct result. */
+static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
+                       u16 target_mask, u16 target)
+{
+       int err;
+       unsigned long timeout = jiffies + 5*HZ;
+       while (1) {
+               u16 val;
+               err = spu_read_u16(card, reg, &val);
+               if (err)
+                       return err;
+               if (target_mask) {
+                       if ((val & target_mask) == target)
+                               return 0;
+               } else {
+                       if (val)
+                               return 0;
+               }
+               udelay(100);
+               if (time_after(jiffies, timeout)) {
+                       lbs_pr_err("%s: timeout with val=%02x, "
+                              "target_mask=%02x, target=%02x\n",
+                              __func__, val, target_mask, target);
+                       return -ETIMEDOUT;
+               }
+       }
+}
+
+/* Read 16 bits from an SPI register until you receive a specific value.
+ * Returns -ETIMEDOUT if a 4 tries pass without success. */
+static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
+{
+       int err, try;
+       for (try = 0; try < 4; ++try) {
+               u32 val = 0;
+               err = spu_read_u32(card, reg, &val);
+               if (err)
+                       return err;
+               if (val == target)
+                       return 0;
+               mdelay(100);
+       }
+       return -ETIMEDOUT;
+}
+
+static int spu_set_interrupt_mode(struct if_spi_card *card,
+                          int suppress_host_int,
+                          int auto_int)
+{
+       int err = 0;
+
+       /* We can suppress a host interrupt by clearing the appropriate
+        * bit in the "host interrupt status mask" register */
+       if (suppress_host_int) {
+               err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+               if (err)
+                       return err;
+       } else {
+               err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG,
+                             IF_SPI_HISM_TX_DOWNLOAD_RDY |
+                             IF_SPI_HISM_RX_UPLOAD_RDY |
+                             IF_SPI_HISM_CMD_DOWNLOAD_RDY |
+                             IF_SPI_HISM_CARDEVENT |
+                             IF_SPI_HISM_CMD_UPLOAD_RDY);
+               if (err)
+                       return err;
+       }
+
+       /* If auto-interrupts are on, the completion of certain transactions
+        * will trigger an interrupt automatically. If auto-interrupts
+        * are off, we need to set the "Card Interrupt Cause" register to
+        * trigger a card interrupt. */
+       if (auto_int) {
+               err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
+                               IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
+                               IF_SPI_HICT_RX_UPLOAD_OVER_AUTO |
+                               IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO |
+                               IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO);
+               if (err)
+                       return err;
+       } else {
+               err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+               if (err)
+                       return err;
+       }
+       return err;
+}
+
+static int spu_get_chip_revision(struct if_spi_card *card,
+                                 u16 *card_id, u8 *card_rev)
+{
+       int err = 0;
+       u32 dev_ctrl;
+       err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl);
+       if (err)
+               return err;
+       *card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl);
+       *card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl);
+       return err;
+}
+
+static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
+{
+       int err = 0;
+       u16 rval;
+       /* set bus mode */
+       err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode);
+       if (err)
+               return err;
+       /* Check that we were able to read back what we just wrote. */
+       err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
+       if (err)
+               return err;
+       if (rval != mode) {
+               lbs_pr_err("Can't read bus mode register.\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+static int spu_init(struct if_spi_card *card, int use_dummy_writes)
+{
+       int err = 0;
+       u32 delay;
+
+       /* We have to start up in timed delay mode so that we can safely
+        * read the Delay Read Register. */
+       card->use_dummy_writes = 0;
+       err = spu_set_bus_mode(card,
+                               IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+                               IF_SPI_BUS_MODE_DELAY_METHOD_TIMED |
+                               IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+       if (err)
+               return err;
+       card->spu_port_delay = 1000;
+       card->spu_reg_delay = 1000;
+       err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay);
+       if (err)
+               return err;
+       card->spu_port_delay = delay & 0x0000ffff;
+       card->spu_reg_delay = (delay & 0xffff0000) >> 16;
+
+       /* If dummy clock delay mode has been requested, switch to it now */
+       if (use_dummy_writes) {
+               card->use_dummy_writes = 1;
+               err = spu_set_bus_mode(card,
+                               IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+                               IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK |
+                               IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+               if (err)
+                       return err;
+       }
+
+       lbs_deb_spi("Initialized SPU unit. "
+                   "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n",
+                   card->spu_port_delay, card->spu_reg_delay);
+       return err;
+}
+
+/*
+ * Firmware Loading
+ */
+
+static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+{
+       int err = 0;
+       const struct firmware *firmware = NULL;
+       int bytes_remaining;
+       const u8 *fw;
+       u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
+       struct spi_device *spi = card->spi;
+
+       lbs_deb_enter(LBS_DEB_SPI);
+
+       err = spu_set_interrupt_mode(card, 1, 0);
+       if (err)
+               goto out;
+       /* Get helper firmware image */
+       err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
+       if (err) {
+               lbs_pr_err("request_firmware failed with err = %d\n", err);
+               goto out;
+       }
+       bytes_remaining = firmware->size;
+       fw = firmware->data;
+
+       /* Load helper firmware image */
+       while (bytes_remaining > 0) {
+               /* Scratch pad 1 should contain the number of bytes we
+                * want to download to the firmware */
+               err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
+                                       HELPER_FW_LOAD_CHUNK_SZ);
+               if (err)
+                       goto release_firmware;
+
+               err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+                                       IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+                                       IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+               if (err)
+                       goto release_firmware;
+
+               /* Feed the data into the command read/write port reg
+                * in chunks of 64 bytes */
+               memset(temp, 0, sizeof(temp));
+               memcpy(temp, fw,
+                      min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
+               mdelay(10);
+               err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+                                       temp, HELPER_FW_LOAD_CHUNK_SZ);
+               if (err)
+                       goto release_firmware;
+
+               /* Interrupt the boot code */
+               err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+               if (err)
+                       goto release_firmware;
+               err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+                                      IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+               if (err)
+                       goto release_firmware;
+               bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
+               fw += HELPER_FW_LOAD_CHUNK_SZ;
+       }
+
+       /* Once the helper / single stage firmware download is complete,
+        * write 0 to scratch pad 1 and interrupt the
+        * bootloader. This completes the helper download. */
+       err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
+       if (err)
+               goto release_firmware;
+       err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+       if (err)
+               goto release_firmware;
+       err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+                               IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+               goto release_firmware;
+
+       lbs_deb_spi("waiting for helper to boot...\n");
+
+release_firmware:
+       release_firmware(firmware);
+out:
+       if (err)
+               lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
+       lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+       return err;
+}
+
+/* Returns the length of the next packet the firmware expects us to send
+ * Sets crc_err if the previous transfer had a CRC error. */
+static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
+                                               int *crc_err)
+{
+       u16 len;
+       int err = 0;
+
+       /* wait until the host interrupt status register indicates
+        * that we are ready to download */
+       err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+                               IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+                               IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+       if (err) {
+               lbs_pr_err("timed out waiting for host_int_status\n");
+               return err;
+       }
+
+       /* Ask the device how many bytes of firmware it wants. */
+       err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+       if (err)
+               return err;
+
+       if (len > IF_SPI_CMD_BUF_SIZE) {
+               lbs_pr_err("firmware load device requested a larger "
+                          "tranfer than we are prepared to "
+                          "handle. (len = %d)\n", len);
+               return -EIO;
+       }
+       if (len & 0x1) {
+               lbs_deb_spi("%s: crc error\n", __func__);
+               len &= ~0x1;
+               *crc_err = 1;
+       } else
+               *crc_err = 0;
+
+       return len;
+}
+
+static int if_spi_prog_main_firmware(struct if_spi_card *card)
+{
+       int len, prev_len;
+       int bytes, crc_err = 0, err = 0;
+       const struct firmware *firmware = NULL;
+       const u8 *fw;
+       struct spi_device *spi = card->spi;
+       u16 num_crc_errs;
+
+       lbs_deb_enter(LBS_DEB_SPI);
+
+       err = spu_set_interrupt_mode(card, 1, 0);
+       if (err)
+               goto out;
+
+       /* Get firmware image */
+       err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
+       if (err) {
+               lbs_pr_err("%s: can't get firmware '%s' from kernel. "
+                       "err = %d\n", __func__, card->main_fw_name, err);
+               goto out;
+       }
+
+       err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
+       if (err) {
+               lbs_pr_err("%s: timed out waiting for initial "
+                          "scratch reg = 0\n", __func__);
+               goto release_firmware;
+       }
+
+       num_crc_errs = 0;
+       prev_len = 0;
+       bytes = firmware->size;
+       fw = firmware->data;
+       while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
+               if (len < 0) {
+                       err = len;
+                       goto release_firmware;
+               }
+               if (bytes < 0) {
+                       /* If there are no more bytes left, we would normally
+                        * expect to have terminated with len = 0 */
+                       lbs_pr_err("Firmware load wants more bytes "
+                                  "than we have to offer.\n");
+                       break;
+               }
+               if (crc_err) {
+                       /* Previous transfer failed. */
+                       if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
+                               lbs_pr_err("Too many CRC errors encountered "
+                                          "in firmware load.\n");
+                               err = -EIO;
+                               goto release_firmware;
+                       }
+               } else {
+                       /* Previous transfer succeeded. Advance counters. */
+                       bytes -= prev_len;
+                       fw += prev_len;
+               }
+               if (bytes < len) {
+                       memset(card->cmd_buffer, 0, len);
+                       memcpy(card->cmd_buffer, fw, bytes);
+               } else
+                       memcpy(card->cmd_buffer, fw, len);
+
+               err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+               if (err)
+                       goto release_firmware;
+               err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+                               card->cmd_buffer, len);
+               if (err)
+                       goto release_firmware;
+               err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
+                                       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+               if (err)
+                       goto release_firmware;
+               prev_len = len;
+       }
+       if (bytes > prev_len) {
+               lbs_pr_err("firmware load wants fewer bytes than "
+                          "we have to offer.\n");
+       }
+
+       /* Confirm firmware download */
+       err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
+                                       SUCCESSFUL_FW_DOWNLOAD_MAGIC);
+       if (err) {
+               lbs_pr_err("failed to confirm the firmware download\n");
+               goto release_firmware;
+       }
+
+release_firmware:
+       release_firmware(firmware);
+
+out:
+       if (err)
+               lbs_pr_err("failed to load firmware (err=%d)\n", err);
+       lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+       return err;
+}
+
+/*
+ * SPI Transfer Thread
+ *
+ * The SPI thread handles all SPI transfers, so there is no need for a lock.
+ */
+
+/* Move a command from the card to the host */
+static int if_spi_c2h_cmd(struct if_spi_card *card)
+{
+       struct lbs_private *priv = card->priv;
+       unsigned long flags;
+       int err = 0;
+       u16 len;
+       u8 i;
+
+       /* We need a buffer big enough to handle whatever people send to
+        * hw_host_to_card */
+       BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
+       BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
+
+       /* It's just annoying if the buffer size isn't a multiple of 4, because
+        * then we might have len <  IF_SPI_CMD_BUF_SIZE but
+        * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
+       BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
+
+       lbs_deb_enter(LBS_DEB_SPI);
+
+       /* How many bytes are there to read? */
+       err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
+       if (err)
+               goto out;
+       if (!len) {
+               lbs_pr_err("%s: error: card has no data for host\n",
+                          __func__);
+               err = -EINVAL;
+               goto out;
+       } else if (len > IF_SPI_CMD_BUF_SIZE) {
+               lbs_pr_err("%s: error: response packet too large: "
+                          "%d bytes, but maximum is %d\n",
+                          __func__, len, IF_SPI_CMD_BUF_SIZE);
+               err = -EINVAL;
+               goto out;
+       }
+
+       /* Read the data from the WLAN module into our command buffer */
+       err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG,
+                               card->cmd_buffer, ALIGN(len, 4));
+       if (err)
+               goto out;
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       i = (priv->resp_idx == 0) ? 1 : 0;
+       BUG_ON(priv->resp_len[i]);
+       priv->resp_len[i] = len;
+       memcpy(priv->resp_buf[i], card->cmd_buffer, len);
+       lbs_notify_command_response(priv, i);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+       if (err)
+               lbs_pr_err("%s: err=%d\n", __func__, err);
+       lbs_deb_leave(LBS_DEB_SPI);
+       return err;
+}
+
+/* Move data from the card to the host */
+static int if_spi_c2h_data(struct if_spi_card *card)
+{
+       struct sk_buff *skb;
+       char *data;
+       u16 len;
+       int err = 0;
+
+       lbs_deb_enter(LBS_DEB_SPI);
+
+       /* How many bytes are there to read? */
+       err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+       if (err)
+               goto out;
+       if (!len) {
+               lbs_pr_err("%s: error: card has no data for host\n",
+                          __func__);
+               err = -EINVAL;
+               goto out;
+       } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+               lbs_pr_err("%s: error: card has %d bytes of data, but "
+                          "our maximum skb size is %u\n",
+                          __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+               err = -EINVAL;
+               goto out;
+       }
+
+       /* TODO: should we allocate a smaller skb if we have less data? */
+       skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+       if (!skb) {
+               err = -ENOBUFS;
+               goto out;
+       }
+       skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
+       data = skb_put(skb, len);
+
+       /* Read the data from the WLAN module into our skb... */
+       err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));
+       if (err)
+               goto free_skb;
+
+       /* pass the SKB to libertas */
+       err = lbs_process_rxed_packet(card->priv, skb);
+       if (err)
+               goto free_skb;
+
+       /* success */
+       goto out;
+
+free_skb:
+       dev_kfree_skb(skb);
+out:
+       if (err)
+               lbs_pr_err("%s: err=%d\n", __func__, err);
+       lbs_deb_leave(LBS_DEB_SPI);
+       return err;
+}
+
+/* Move data or a command from the host to the card. */
+static void if_spi_h2c(struct if_spi_card *card,
+                       struct if_spi_packet *packet, int type)
+{
+       int err = 0;
+       u16 int_type, port_reg;
+
+       switch (type) {
+       case MVMS_DAT:
+               int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
+               port_reg = IF_SPI_DATA_RDWRPORT_REG;
+               break;
+       case MVMS_CMD:
+               int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
+               port_reg = IF_SPI_CMD_RDWRPORT_REG;
+               break;
+       default:
+               lbs_pr_err("can't transfer buffer of type %d\n", type);
+               err = -EINVAL;
+               goto out;
+       }
+
+       /* Write the data to the card */
+       err = spu_write(card, port_reg, packet->buffer, packet->blen);
+       if (err)
+               goto out;
+
+out:
+       kfree(packet);
+
+       if (err)
+               lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+/* Inform the host about a card event */
+static void if_spi_e2h(struct if_spi_card *card)
+{
+       int err = 0;
+       unsigned long flags;
+       u32 cause;
+       struct lbs_private *priv = card->priv;
+
+       err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause);
+       if (err)
+               goto out;
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       lbs_queue_event(priv, cause & 0xff);
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+       if (err)
+               lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+static int lbs_spi_thread(void *data)
+{
+       int err;
+       struct if_spi_card *card = data;
+       u16 hiStatus;
+       unsigned long flags;
+       struct if_spi_packet *packet;
+
+       while (1) {
+               /* Wait to be woken up by one of two things.  First, our ISR
+                * could tell us that something happened on the WLAN.
+                * Secondly, libertas could call hw_host_to_card with more
+                * data, which we might be able to send.
+                */
+               do {
+                       err = down_interruptible(&card->spi_ready);
+                       if (!card->run_thread) {
+                               up(&card->spi_thread_terminated);
+                               do_exit(0);
+                       }
+               } while (err == EINTR);
+
+               /* Read the host interrupt status register to see what we
+                * can do. */
+               err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+                                       &hiStatus);
+               if (err) {
+                       lbs_pr_err("I/O error\n");
+                       goto err;
+               }
+
+               if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
+                       err = if_spi_c2h_cmd(card);
+                       if (err)
+                               goto err;
+               if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
+                       err = if_spi_c2h_data(card);
+                       if (err)
+                               goto err;
+               if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
+                       /* This means two things. First of all,
+                        * if there was a previous command sent, the card has
+                        * successfully received it.
+                        * Secondly, it is now ready to download another
+                        * command.
+                        */
+                       lbs_host_to_card_done(card->priv);
+
+                       /* Do we have any command packets from the host to
+                        * send? */
+                       packet = NULL;
+                       spin_lock_irqsave(&card->buffer_lock, flags);
+                       if (!list_empty(&card->cmd_packet_list)) {
+                               packet = (struct if_spi_packet *)(card->
+                                               cmd_packet_list.next);
+                               list_del(&packet->list);
+                       }
+                       spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+                       if (packet)
+                               if_spi_h2c(card, packet, MVMS_CMD);
+               }
+               if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
+                       /* Do we have any data packets from the host to
+                        * send? */
+                       packet = NULL;
+                       spin_lock_irqsave(&card->buffer_lock, flags);
+                       if (!list_empty(&card->data_packet_list)) {
+                               packet = (struct if_spi_packet *)(card->
+                                               data_packet_list.next);
+                               list_del(&packet->list);
+                       }
+                       spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+                       if (packet)
+                               if_spi_h2c(card, packet, MVMS_DAT);
+               }
+               if (hiStatus & IF_SPI_HIST_CARD_EVENT)
+                       if_spi_e2h(card);
+
+err:
+               if (err)
+                       lbs_pr_err("%s: got error %d\n", __func__, err);
+       }
+}
+
+/* Block until lbs_spi_thread thread has terminated */
+static void if_spi_terminate_spi_thread(struct if_spi_card *card)
+{
+       /* It would be nice to use kthread_stop here, but that function
+        * can't wake threads waiting for a semaphore. */
+       card->run_thread = 0;
+       up(&card->spi_ready);
+       down(&card->spi_thread_terminated);
+}
+
+/*
+ * Host to Card
+ *
+ * Called from Libertas to transfer some data to the WLAN device
+ * We can't sleep here. */
+static int if_spi_host_to_card(struct lbs_private *priv,
+                               u8 type, u8 *buf, u16 nb)
+{
+       int err = 0;
+       unsigned long flags;
+       struct if_spi_card *card = priv->card;
+       struct if_spi_packet *packet;
+       u16 blen;
+
+       lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
+
+       if (nb == 0) {
+               lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+               err = -EINVAL;
+               goto out;
+       }
+       blen = ALIGN(nb, 4);
+       packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
+       if (!packet) {
+               err = -ENOMEM;
+               goto out;
+       }
+       packet->blen = blen;
+       memcpy(packet->buffer, buf, nb);
+       memset(packet->buffer + nb, 0, blen - nb);
+
+       switch (type) {
+       case MVMS_CMD:
+               priv->dnld_sent = DNLD_CMD_SENT;
+               spin_lock_irqsave(&card->buffer_lock, flags);
+               list_add_tail(&packet->list, &card->cmd_packet_list);
+               spin_unlock_irqrestore(&card->buffer_lock, flags);
+               break;
+       case MVMS_DAT:
+               priv->dnld_sent = DNLD_DATA_SENT;
+               spin_lock_irqsave(&card->buffer_lock, flags);
+               list_add_tail(&packet->list, &card->data_packet_list);
+               spin_unlock_irqrestore(&card->buffer_lock, flags);
+               break;
+       default:
+               lbs_pr_err("can't transfer buffer of type %d", type);
+               err = -EINVAL;
+               break;
+       }
+
+       /* Wake up the spi thread */
+       up(&card->spi_ready);
+out:
+       lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
+       return err;
+}
+
+/*
+ * Host Interrupts
+ *
+ * Service incoming interrupts from the WLAN device. We can't sleep here, so
+ * don't try to talk on the SPI bus, just wake up the SPI thread.
+ */
+static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
+{
+       struct if_spi_card *card = dev_id;
+
+       up(&card->spi_ready);
+       return IRQ_HANDLED;
+}
+
+/*
+ * SPI callbacks
+ */
+
+static int if_spi_calculate_fw_names(u16 card_id,
+                             char *helper_fw, char *main_fw)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
+               if (card_id == chip_id_to_device_name[i].chip_id)
+                       break;
+       }
+       if (i == ARRAY_SIZE(chip_id_to_device_name)) {
+               lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
+               return -EAFNOSUPPORT;
+       }
+       snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin",
+                chip_id_to_device_name[i].name);
+       snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin",
+                chip_id_to_device_name[i].name);
+       return 0;
+}
+
+static int __devinit if_spi_probe(struct spi_device *spi)
+{
+       struct if_spi_card *card;
+       struct lbs_private *priv = NULL;
+       struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+       int err = 0;
+       u32 scratch;
+
+       lbs_deb_enter(LBS_DEB_SPI);
+
+       /* Allocate card structure to represent this specific device */
+       card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
+       if (!card) {
+               err = -ENOMEM;
+               goto out;
+       }
+       spi_set_drvdata(spi, card);
+       card->spi = spi;
+       card->gpio_cs = pdata->gpio_cs;
+       card->prev_xfer_time = jiffies;
+
+       sema_init(&card->spi_ready, 0);
+       sema_init(&card->spi_thread_terminated, 0);
+       INIT_LIST_HEAD(&card->cmd_packet_list);
+       INIT_LIST_HEAD(&card->data_packet_list);
+       spin_lock_init(&card->buffer_lock);
+
+       /* set up GPIO CS line. TODO: use  regular CS line */
+       err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
+       if (err)
+               goto free_card;
+       err = gpio_direction_output(card->gpio_cs, 1);
+       if (err)
+               goto free_gpio;
+
+       /* Initialize the SPI Interface Unit */
+       err = spu_init(card, pdata->use_dummy_writes);
+       if (err)
+               goto free_gpio;
+       err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
+       if (err)
+               goto free_gpio;
+
+       /* Firmware load */
+       err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
+       if (err)
+               goto free_gpio;
+       if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
+               lbs_deb_spi("Firmware is already loaded for "
+                           "Marvell WLAN 802.11 adapter\n");
+       else {
+               err = if_spi_calculate_fw_names(card->card_id,
+                               card->helper_fw_name, card->main_fw_name);
+               if (err)
+                       goto free_gpio;
+
+               lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
+                               "(chip_id = 0x%04x, chip_rev = 0x%02x) "
+                               "attached to SPI bus_num %d, chip_select %d. "
+                               "spi->max_speed_hz=%d\n",
+                               card->card_id, card->card_rev,
+                               spi->master->bus_num, spi->chip_select,
+                               spi->max_speed_hz);
+               err = if_spi_prog_helper_firmware(card);
+               if (err)
+                       goto free_gpio;
+               err = if_spi_prog_main_firmware(card);
+               if (err)
+                       goto free_gpio;
+               lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
+       }
+
+       err = spu_set_interrupt_mode(card, 0, 1);
+       if (err)
+               goto free_gpio;
+
+       /* Register our card with libertas.
+        * This will call alloc_etherdev */
+       priv = lbs_add_card(card, &spi->dev);
+       if (!priv) {
+               err = -ENOMEM;
+               goto free_gpio;
+       }
+       card->priv = priv;
+       priv->card = card;
+       priv->hw_host_to_card = if_spi_host_to_card;
+       priv->fw_ready = 1;
+       priv->ps_supported = 1;
+
+       /* Initialize interrupt handling stuff. */
+       card->run_thread = 1;
+       card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
+       if (IS_ERR(card->spi_thread)) {
+               card->run_thread = 0;
+               err = PTR_ERR(card->spi_thread);
+               lbs_pr_err("error creating SPI thread: err=%d\n", err);
+               goto remove_card;
+       }
+       err = request_irq(spi->irq, if_spi_host_interrupt,
+                       IRQF_TRIGGER_FALLING, "libertas_spi", card);
+       if (err) {
+               lbs_pr_err("can't get host irq line-- request_irq failed\n");
+               goto terminate_thread;
+       }
+
+       /* Start the card.
+        * This will call register_netdev, and we'll start
+        * getting interrupts... */
+       err = lbs_start_card(priv);
+       if (err)
+               goto release_irq;
+
+       lbs_deb_spi("Finished initializing WLAN module.\n");
+
+       /* successful exit */
+       goto out;
+
+release_irq:
+       free_irq(spi->irq, card);
+terminate_thread:
+       if_spi_terminate_spi_thread(card);
+remove_card:
+       lbs_remove_card(priv); /* will call free_netdev */
+free_gpio:
+       gpio_free(card->gpio_cs);
+free_card:
+       free_if_spi_card(card);
+out:
+       lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
+       return err;
+}
+
+static int __devexit libertas_spi_remove(struct spi_device *spi)
+{
+       struct if_spi_card *card = spi_get_drvdata(spi);
+       struct lbs_private *priv = card->priv;
+
+       lbs_deb_spi("libertas_spi_remove\n");
+       lbs_deb_enter(LBS_DEB_SPI);
+       priv->surpriseremoved = 1;
+
+       lbs_stop_card(priv);
+       free_irq(spi->irq, card);
+       if_spi_terminate_spi_thread(card);
+       lbs_remove_card(priv); /* will call free_netdev */
+       gpio_free(card->gpio_cs);
+       free_if_spi_card(card);
+       lbs_deb_leave(LBS_DEB_SPI);
+       return 0;
+}
+
+static struct spi_driver libertas_spi_driver = {
+       .probe  = if_spi_probe,
+       .remove = __devexit_p(libertas_spi_remove),
+       .driver = {
+               .name   = "libertas_spi",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+};
+
+/*
+ * Module functions
+ */
+
+static int __init if_spi_init_module(void)
+{
+       int ret = 0;
+       lbs_deb_enter(LBS_DEB_SPI);
+       printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
+       ret = spi_register_driver(&libertas_spi_driver);
+       lbs_deb_leave(LBS_DEB_SPI);
+       return ret;
+}
+
+static void __exit if_spi_exit_module(void)
+{
+       lbs_deb_enter(LBS_DEB_SPI);
+       spi_unregister_driver(&libertas_spi_driver);
+       lbs_deb_leave(LBS_DEB_SPI);
+}
+
+module_init(if_spi_init_module);
+module_exit(if_spi_exit_module);
+
+MODULE_DESCRIPTION("Libertas SPI WLAN Driver");
+MODULE_AUTHOR("Andrey Yurovsky <andrey@cozybit.com>, "
+             "Colin McCabe <colin@cozybit.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
new file mode 100644 (file)
index 0000000..2103869
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *     linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *     Driver for Marvell SPI WLAN cards.
+ *
+ *     Copyright 2008 Analog Devices Inc.
+ *
+ *     Authors:
+ *     Andrey Yurovsky <andrey@cozybit.com>
+ *     Colin McCabe <colin@cozybit.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _LBS_IF_SPI_H_
+#define _LBS_IF_SPI_H_
+
+#define IPFIELD_ALIGN_OFFSET 2
+#define IF_SPI_CMD_BUF_SIZE 2400
+
+/***************** Firmware *****************/
+struct chip_ident {
+       u16 chip_id;
+       u16 name;
+};
+
+#define MAX_MAIN_FW_LOAD_CRC_ERR 10
+
+/* Chunk size when loading the helper firmware */
+#define HELPER_FW_LOAD_CHUNK_SZ 64
+
+/* Value to write to indicate end of helper firmware dnld */
+#define FIRMWARE_DNLD_OK 0x0000
+
+/* Value to check once the main firmware is downloaded */
+#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
+
+/***************** SPI Interface Unit *****************/
+/* Masks used in SPI register read/write operations */
+#define IF_SPI_READ_OPERATION_MASK 0x0
+#define IF_SPI_WRITE_OPERATION_MASK 0x8000
+
+/* SPI register offsets. 4-byte aligned. */
+#define IF_SPI_DEVICEID_CTRL_REG 0x00  /* DeviceID controller reg */
+#define IF_SPI_IO_READBASE_REG 0x04    /* Read I/O base reg */
+#define IF_SPI_IO_WRITEBASE_REG 0x08   /* Write I/O base reg */
+#define IF_SPI_IO_RDWRPORT_REG 0x0C    /* Read/Write I/O port reg */
+
+#define IF_SPI_CMD_READBASE_REG 0x10   /* Read command base reg */
+#define IF_SPI_CMD_WRITEBASE_REG 0x14  /* Write command base reg */
+#define IF_SPI_CMD_RDWRPORT_REG 0x18   /* Read/Write command port reg */
+
+#define IF_SPI_DATA_READBASE_REG 0x1C  /* Read data base reg */
+#define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */
+#define IF_SPI_DATA_RDWRPORT_REG 0x24  /* Read/Write data port reg */
+
+#define IF_SPI_SCRATCH_1_REG 0x28      /* Scratch reg 1 */
+#define IF_SPI_SCRATCH_2_REG 0x2C      /* Scratch reg 2 */
+#define IF_SPI_SCRATCH_3_REG 0x30      /* Scratch reg 3 */
+#define IF_SPI_SCRATCH_4_REG 0x34      /* Scratch reg 4 */
+
+#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
+#define IF_SPI_TX_FRAME_STATUS_REG 0x3C        /* Tx frame status reg */
+
+#define IF_SPI_HOST_INT_CTRL_REG 0x40  /* Host interrupt controller reg */
+
+#define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */
+#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
+#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
+#define IF_SPI_CARD_INT_STATUS_MASK_REG        0x50 /* Card interrupt status mask */
+
+#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
+
+#define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */
+#define IF_SPI_HOST_INT_STATUS_REG 0x5C        /* Host interrupt status reg */
+#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
+#define IF_SPI_HOST_INT_STATUS_MASK_REG        0x64 /* Host interrupt status mask */
+#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
+
+#define IF_SPI_DELAY_READ_REG 0x6C     /* Delay read reg */
+#define IF_SPI_SPU_BUS_MODE_REG 0x70   /* SPU BUS mode reg */
+
+/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
+
+/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
+/** Host Interrupt Control bit : Wake up */
+#define IF_SPI_HICT_WAKE_UP                            (1<<0)
+/** Host Interrupt Control bit : WLAN ready */
+#define IF_SPI_HICT_WLAN_READY                         (1<<1)
+/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY            (1<<2) */
+/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY           (1<<3) */
+/*#define IF_SPI_HICT_IRQSRC_WLAN                      (1<<4) */
+/** Host Interrupt Control bit : Tx auto download */
+#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO              (1<<5)
+/** Host Interrupt Control bit : Rx auto upload */
+#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO                        (1<<6)
+/** Host Interrupt Control bit : Command auto download */
+#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO             (1<<7)
+/** Host Interrupt Control bit : Command auto upload */
+#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO               (1<<8)
+
+/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
+/** Card Interrupt Case bit : Tx download over */
+#define IF_SPI_CIC_TX_DOWNLOAD_OVER                    (1<<0)
+/** Card Interrupt Case bit : Rx upload over */
+#define IF_SPI_CIC_RX_UPLOAD_OVER                      (1<<1)
+/** Card Interrupt Case bit : Command download over */
+#define IF_SPI_CIC_CMD_DOWNLOAD_OVER                   (1<<2)
+/** Card Interrupt Case bit : Host event */
+#define IF_SPI_CIC_HOST_EVENT                          (1<<3)
+/** Card Interrupt Case bit : Command upload over */
+#define IF_SPI_CIC_CMD_UPLOAD_OVER                     (1<<4)
+/** Card Interrupt Case bit : Power down */
+#define IF_SPI_CIC_POWER_DOWN                          (1<<5)
+
+/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
+#define IF_SPI_CIS_TX_DOWNLOAD_OVER                    (1<<0)
+#define IF_SPI_CIS_RX_UPLOAD_OVER                      (1<<1)
+#define IF_SPI_CIS_CMD_DOWNLOAD_OVER                   (1<<2)
+#define IF_SPI_CIS_HOST_EVENT                          (1<<3)
+#define IF_SPI_CIS_CMD_UPLOAD_OVER                     (1<<4)
+#define IF_SPI_CIS_POWER_DOWN                          (1<<5)
+
+/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
+#define IF_SPI_HICU_TX_DOWNLOAD_RDY                    (1<<0)
+#define IF_SPI_HICU_RX_UPLOAD_RDY                      (1<<1)
+#define IF_SPI_HICU_CMD_DOWNLOAD_RDY                   (1<<2)
+#define IF_SPI_HICU_CARD_EVENT                         (1<<3)
+#define IF_SPI_HICU_CMD_UPLOAD_RDY                     (1<<4)
+#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW                        (1<<5)
+#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW               (1<<6)
+#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW              (1<<7)
+#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW             (1<<8)
+#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW               (1<<9)
+#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW              (1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
+/** Host Interrupt Status bit : Tx download ready */
+#define IF_SPI_HIST_TX_DOWNLOAD_RDY                    (1<<0)
+/** Host Interrupt Status bit : Rx upload ready */
+#define IF_SPI_HIST_RX_UPLOAD_RDY                      (1<<1)
+/** Host Interrupt Status bit : Command download ready */
+#define IF_SPI_HIST_CMD_DOWNLOAD_RDY                   (1<<2)
+/** Host Interrupt Status bit : Card event */
+#define IF_SPI_HIST_CARD_EVENT                         (1<<3)
+/** Host Interrupt Status bit : Command upload ready */
+#define IF_SPI_HIST_CMD_UPLOAD_RDY                     (1<<4)
+/** Host Interrupt Status bit : I/O write FIFO overflow */
+#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW                        (1<<5)
+/** Host Interrupt Status bit : I/O read FIFO underflow */
+#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW                        (1<<6)
+/** Host Interrupt Status bit : Data write FIFO overflow */
+#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW              (1<<7)
+/** Host Interrupt Status bit : Data read FIFO underflow */
+#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW             (1<<8)
+/** Host Interrupt Status bit : Command write FIFO overflow */
+#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW               (1<<9)
+/** Host Interrupt Status bit : Command read FIFO underflow */
+#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW              (1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
+/** Host Interrupt Status Mask bit : Tx download ready */
+#define IF_SPI_HISM_TX_DOWNLOAD_RDY                    (1<<0)
+/** Host Interrupt Status Mask bit : Rx upload ready */
+#define IF_SPI_HISM_RX_UPLOAD_RDY                      (1<<1)
+/** Host Interrupt Status Mask bit : Command download ready */
+#define IF_SPI_HISM_CMD_DOWNLOAD_RDY                   (1<<2)
+/** Host Interrupt Status Mask bit : Card event */
+#define IF_SPI_HISM_CARDEVENT                          (1<<3)
+/** Host Interrupt Status Mask bit : Command upload ready */
+#define IF_SPI_HISM_CMD_UPLOAD_RDY                     (1<<4)
+/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
+#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW                        (1<<5)
+/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
+#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW               (1<<6)
+/** Host Interrupt Status Mask bit : Data write FIFO overflow */
+#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW              (1<<7)
+/** Host Interrupt Status Mask bit : Data write FIFO underflow */
+#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW             (1<<8)
+/** Host Interrupt Status Mask bit : Command write FIFO overflow */
+#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW               (1<<9)
+/** Host Interrupt Status Mask bit : Command write FIFO underflow */
+#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW              (1<<10)
+
+/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
+/* SCK edge on which the WLAN module outputs data on MISO */
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
+
+/* In a SPU read operation, there is a delay between writing the SPU
+ * register name and getting back data from the WLAN module.
+ * This can be specified in terms of nanoseconds or in terms of dummy
+ * clock cycles which the master must output before receiving a response. */
+#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
+#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
+
+/* Some different modes of SPI operation */
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
+
+#endif
index 4e0007d200308d72741d5580eb0396684e636524..8a7eb2778eb680c5f17d5c5ed5b9840745b3825c 100644 (file)
@@ -1006,9 +1006,8 @@ void lbs_resume(struct lbs_private *priv)
 EXPORT_SYMBOL_GPL(lbs_resume);
 
 /**
- *  @brief This function downloads firmware image, gets
- *  HW spec from firmware and set basic parameters to
- *  firmware.
+ * @brief This function gets the HW spec from the firmware and sets
+ *        some basic parameters.
  *
  *  @param priv    A pointer to struct lbs_private structure
  *  @return       0 or -1
index 3d3914c83b145388c6d2afc6c6c6fc124f8b2469..28790e03dc43ef797a2150d9cbb48a1afdf99a76 100644 (file)
@@ -286,7 +286,7 @@ void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
        lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
 }
 
-void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid)
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
 {
        struct cmd_ds_set_bssid cmd;
 
index 8995cd7c29bf4ce1ef15cc95c5e614a43e456f4a..4cc42dd5a005258f10055bcaae3e61617e3bb2e9 100644 (file)
@@ -463,7 +463,7 @@ int lbtf_set_radio_control(struct lbtf_private *priv);
 int lbtf_update_hw_spec(struct lbtf_private *priv);
 int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv);
 void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode);
-void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid);
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid);
 int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr);
 
 int lbtf_set_channel(struct lbtf_private *priv, u8 channel);
index f83d69e813d3a23cf46c8aefd94833147ab05d9f..fce49ba061d55cb57166b4935ef9de275f7b25cb 100644 (file)
@@ -779,6 +779,8 @@ static int __init init_mac80211_hwsim(void)
                        BIT(NL80211_IFTYPE_MESH_POINT);
                hw->ampdu_queues = 1;
 
+               hw->flags = IEEE80211_HW_MFP_CAPABLE;
+
                /* ask mac80211 to reserve space for magic */
                hw->vif_data_size = sizeof(struct hwsim_vif_priv);
                hw->sta_data_size = sizeof(struct hwsim_sta_priv);
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig
new file mode 100644 (file)
index 0000000..44411eb
--- /dev/null
@@ -0,0 +1,120 @@
+config HERMES
+       tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
+       depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
+       select WIRELESS_EXT
+       select FW_LOADER
+       select CRYPTO
+       select CRYPTO_MICHAEL_MIC
+       ---help---
+         A driver for 802.11b wireless cards based on the "Hermes" or
+         Intersil HFA384x (Prism 2) MAC controller.  This includes the vast
+         majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
+         - except for the Cisco/Aironet cards.  Cards supported include the
+         Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
+         Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
+         IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
+         MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
+         IPW2011, and Symbol Spectrum24 High Rate amongst others.
+
+         This option includes the guts of the driver, but in order to
+         actually use a card you will also need to enable support for PCMCIA
+         Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
+
+         You will also very likely also need the Wireless Tools in order to
+         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
+       help
+         Say Y here to support the Airport 802.11b wireless Ethernet hardware
+         built into the Macintosh iBook and other recent PowerPC-based
+         Macintosh machines. This is essentially a Lucent Orinoco card with
+         a non-standard interface.
+
+         This driver does not support the Airport Extreme (802.11b/g). Use
+         the BCM43xx driver for Airport Extreme cards.
+
+config PLX_HERMES
+       tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+       depends on PCI && HERMES
+       help
+         Enable support for PCMCIA cards supported by the "Hermes" (aka
+         orinoco) driver when used in PLX9052 based PCI adaptors.  These
+         adaptors are not a full PCMCIA controller but act as a more limited
+         PCI <-> PCMCIA bridge.  Several vendors sell such adaptors so that
+         802.11b PCMCIA cards can be used in desktop machines.  The Netgear
+         MA301 is such an adaptor.
+
+config TMD_HERMES
+       tristate "Hermes in TMD7160 based PCI adaptor support"
+       depends on PCI && HERMES
+       help
+         Enable support for PCMCIA cards supported by the "Hermes" (aka
+         orinoco) driver when used in TMD7160 based PCI adaptors.  These
+         adaptors are not a full PCMCIA controller but act as a more limited
+         PCI <-> PCMCIA bridge.  Several vendors sell such adaptors so that
+         802.11b PCMCIA cards can be used in desktop machines.
+
+config NORTEL_HERMES
+       tristate "Nortel emobility PCI adaptor support"
+       depends on PCI && HERMES
+       help
+         Enable support for PCMCIA cards supported by the "Hermes" (aka
+         orinoco) driver when used in Nortel emobility PCI adaptors.  These
+         adaptors are not full PCMCIA controllers, but act as a more limited
+         PCI <-> PCMCIA bridge.
+
+config PCI_HERMES
+       tristate "Prism 2.5 PCI 802.11b adaptor support"
+       depends on PCI && HERMES
+       help
+         Enable support for PCI and mini-PCI 802.11b wireless NICs based on
+         the Prism 2.5 chipset.  These are true PCI cards, not the 802.11b
+         PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
+         common.  Some of the built-in wireless adaptors in laptops are of
+         this variety.
+
+config PCMCIA_HERMES
+       tristate "Hermes PCMCIA card support"
+       depends on PCMCIA && HERMES
+       ---help---
+         A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+         as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+         EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
+         others).  It should also be usable on various Prism II based cards
+         such as the Linksys, D-Link and Farallon Skyline.  It should also
+         work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
+
+         You will very likely need the Wireless Tools in order to
+         configure your card and that /etc/pcmcia/wireless.opts works:
+         <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+config PCMCIA_SPECTRUM
+       tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+       depends on PCMCIA && HERMES
+       ---help---
+
+         This is a driver for 802.11b cards using RAM-loadable Symbol
+         firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+         cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+         This driver requires firmware download on startup.  Utilities
+         for downloading Symbol firmware are available at
+         <http://sourceforge.net/projects/orinoco/>
index 45a04faa7818e7ead799eeee65030bd08ede0592..6514e4611b966c327426cd158e9e054a5864bad4 100644 (file)
@@ -178,12 +178,7 @@ static const struct ethtool_ops orinoco_ethtool_ops;
 /* Data tables                                                      */
 /********************************************************************/
 
-/* The frequency of each channel in MHz */
-static const long channel_frequency[] = {
-       2412, 2417, 2422, 2427, 2432, 2437, 2442,
-       2447, 2452, 2457, 2462, 2467, 2472, 2484
-};
-#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
+#define NUM_CHANNELS 14
 
 /* This tables gives the actual meanings of the bitrate IDs returned
  * by the firmware. */
@@ -240,6 +235,12 @@ struct hermes_rx_descriptor {
        __le16 data_len;
 } __attribute__ ((packed));
 
+struct orinoco_rx_data {
+       struct hermes_rx_descriptor *desc;
+       struct sk_buff *skb;
+       struct list_head list;
+};
+
 /********************************************************************/
 /* Function prototypes                                              */
 /********************************************************************/
@@ -3582,6 +3583,17 @@ static int orinoco_init(struct net_device *dev)
        return err;
 }
 
+static const struct net_device_ops orinoco_netdev_ops = {
+       .ndo_init               = orinoco_init,
+       .ndo_open               = orinoco_open,
+       .ndo_stop               = orinoco_stop,
+       .ndo_start_xmit         = orinoco_xmit,
+       .ndo_set_multicast_list = orinoco_set_multicast_list,
+       .ndo_change_mtu         = orinoco_change_mtu,
+       .ndo_tx_timeout         = orinoco_tx_timeout,
+       .ndo_get_stats          = orinoco_get_stats,
+};
+
 struct net_device
 *alloc_orinocodev(int sizeof_card,
                  struct device *device,
@@ -3592,7 +3604,7 @@ struct net_device
        struct orinoco_private *priv;
 
        dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
-       if (! dev)
+       if (!dev)
                return NULL;
        priv = netdev_priv(dev);
        priv->ndev = dev;
@@ -3604,27 +3616,20 @@ struct net_device
        priv->dev = device;
 
        /* Setup / override net_device fields */
-       dev->init = orinoco_init;
-       dev->hard_start_xmit = orinoco_xmit;
-       dev->tx_timeout = orinoco_tx_timeout;
+       dev->netdev_ops = &orinoco_netdev_ops;
        dev->watchdog_timeo = HZ; /* 1 second timeout */
-       dev->get_stats = orinoco_get_stats;
        dev->ethtool_ops = &orinoco_ethtool_ops;
-       dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+       dev->wireless_handlers = &orinoco_handler_def;
 #ifdef WIRELESS_SPY
        priv->wireless_data.spy_data = &priv->spy_data;
        dev->wireless_data = &priv->wireless_data;
 #endif
-       dev->change_mtu = orinoco_change_mtu;
-       dev->set_multicast_list = orinoco_set_multicast_list;
        /* we use the default eth_mac_addr for setting the MAC addr */
 
        /* Reserve space in skb for the SNAP header */
        dev->hard_header_len += ENCAPS_OVERHEAD;
 
        /* Set up default callbacks */
-       dev->open = orinoco_open;
-       dev->stop = orinoco_stop;
        priv->hard_reset = hard_reset;
        priv->stop_fw = stop_fw;
 
@@ -3742,13 +3747,13 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
        return err;       
 }
 
-static long orinoco_hw_get_freq(struct orinoco_private *priv)
+static int orinoco_hw_get_freq(struct orinoco_private *priv)
 {
        
        hermes_t *hw = &priv->hw;
        int err = 0;
        u16 channel;
-       long freq = 0;
+       int freq = 0;
        unsigned long flags;
 
        if (orinoco_lock(priv, &flags) != 0)
@@ -3771,7 +3776,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
                goto out;
 
        }
-       freq = channel_frequency[channel-1] * 100000;
+       freq = ieee80211_dsss_chan_to_freq(channel);
 
  out:
        orinoco_unlock(priv, &flags);
@@ -3998,7 +4003,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
        for (i = 0; i < NUM_CHANNELS; i++) {
                if (priv->channel_mask & (1 << i)) {
                        range->freq[k].i = i + 1;
-                       range->freq[k].m = channel_frequency[i] * 100000;
+                       range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) *
+                                           100000);
                        range->freq[k].e = 1;
                        k++;
                }
@@ -4346,16 +4352,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
                /* Setting by channel number */
                chan = frq->m;
        } else {
-               /* Setting by frequency - search the table */
-               int mult = 1;
+               /* Setting by frequency */
+               int denom = 1;
                int i;
 
+               /* Calculate denominator to rescale to MHz */
                for (i = 0; i < (6 - frq->e); i++)
-                       mult *= 10;
+                       denom *= 10;
 
-               for (i = 0; i < NUM_CHANNELS; i++)
-                       if (frq->m == (channel_frequency[i] * mult))
-                               chan = i+1;
+               chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
        }
 
        if ( (chan < 1) || (chan > NUM_CHANNELS) ||
@@ -4392,7 +4397,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev,
                return tmp;
        }
 
-       frq->m = tmp;
+       frq->m = tmp * 100000;
        frq->e = 1;
 
        return 0;
@@ -5609,7 +5614,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                                  &iwe, IW_EV_FREQ_LEN);
 
-               iwe.u.freq.m = channel_frequency[channel-1] * 100000;
+               iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
                iwe.u.freq.e = 1;
                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                                  &iwe, IW_EV_FREQ_LEN);
@@ -5760,7 +5765,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                                  &iwe, IW_EV_FREQ_LEN);
 
-               iwe.u.freq.m = channel_frequency[channel-1] * 100000;
+               iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
                iwe.u.freq.e = 1;
                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                                  &iwe, IW_EV_FREQ_LEN);
index 00750c8ba7db4019a5ea36a6c46632cbd1aad1db..c653816ef5fe343ba416929731d1df5b8205d08e 100644 (file)
@@ -59,14 +59,6 @@ struct xbss_element {
        struct list_head list;
 };
 
-struct hermes_rx_descriptor;
-
-struct orinoco_rx_data {
-       struct hermes_rx_descriptor *desc;
-       struct sk_buff *skb;
-       struct list_head list;
-};
-
 struct firmware;
 
 struct orinoco_private {
@@ -83,7 +75,6 @@ struct orinoco_private {
        /* Interrupt tasklets */
        struct tasklet_struct rx_tasklet;
        struct list_head rx_list;
-       struct orinoco_rx_data *rx_data;
 
        /* driver state */
        int open;
index d3469d08f966961599789772b97d0827491254a7..cfc5f41aa1361e31a5ec5bfefe131eb41bdd713a 100644 (file)
@@ -61,3 +61,13 @@ config P54_PCI
          http://prism54.org/
 
          If you choose to build a module, it'll be called p54pci.
+
+config P54_SPI
+       tristate "Prism54 SPI (stlc45xx) support"
+       depends on P54_COMMON && SPI_MASTER
+       ---help---
+         This driver is for stlc4550 or stlc4560 based wireless chips.
+         This driver is experimental, untested and will probably only work on
+         Nokia's N800/N810 Portable Internet Tablet.
+
+         If you choose to build a module, it'll be called p54spi.
index 4fa9ce7173602a7df09abf1c7698c861d3104397..c2050dee62937abd8a5f41dbade4112753665213 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_P54_COMMON)       += p54common.o
 obj-$(CONFIG_P54_USB)          += p54usb.o
 obj-$(CONFIG_P54_PCI)          += p54pci.o
+obj-$(CONFIG_P54_SPI)          += p54spi.o
index ab79e32f0b27c495c3c20eb43310882ff1aaa8b9..94c3acd1fcaf41e0058e53e79537b39c3296df5c 100644 (file)
@@ -44,6 +44,18 @@ enum p54_control_frame_types {
        P54_CONTROL_TYPE_BT_OPTIONS = 35
 };
 
+/* provide 16 bytes for the transport back-end */
+#define P54_TX_INFO_DATA_SIZE          16
+
+/* stored in ieee80211_tx_info's rate_driver_data */
+struct p54_tx_info {
+       u32 start_addr;
+       u32 end_addr;
+       void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)];
+};
+
+#define P54_MAX_CTRL_FRAME_LEN         0x1000
+
 #define P54_HDR_FLAG_CONTROL           BIT(15)
 #define P54_HDR_FLAG_CONTROL_OPSET     (BIT(15) + BIT(0))
 
@@ -75,6 +87,14 @@ struct p54_rssi_linear_approximation {
        s16 longbow_unk2;
 };
 
+struct p54_cal_database {
+       size_t entries;
+       size_t entry_size;
+       size_t offset;
+       size_t len;
+       u8 data[0];
+};
+
 #define EEPROM_READBACK_LEN 0x3fc
 
 #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
@@ -84,6 +104,14 @@ struct p54_rssi_linear_approximation {
 #define FW_LM87 0x4c4d3837
 #define FW_LM20 0x4c4d3230
 
+enum fw_state {
+       FW_STATE_OFF,
+       FW_STATE_BOOTING,
+       FW_STATE_READY,
+       FW_STATE_RESET,
+       FW_STATE_RESETTING,
+};
+
 struct p54_common {
        struct ieee80211_hw *hw;
        u32 rx_start;
@@ -99,11 +127,12 @@ struct p54_common {
        struct mutex conf_mutex;
        u8 mac_addr[ETH_ALEN];
        u8 bssid[ETH_ALEN];
+       u8 rx_diversity_mask;
+       u8 tx_diversity_mask;
        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_cal_database *output_limit;
+       struct p54_cal_database *curve_data;
        struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
        unsigned int filter_flags;
        bool use_short_slot;
@@ -115,7 +144,7 @@ struct p54_common {
        unsigned int output_power;
        u32 tsf_low32;
        u32 tsf_high32;
-       u64 basic_rate_mask;
+       u32 basic_rate_mask;
        u16 wakeup_timer;
        u16 aid;
        struct ieee80211_tx_queue_stats tx_stats[8];
@@ -133,6 +162,7 @@ struct p54_common {
 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_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
 int p54_read_eeprom(struct ieee80211_hw *dev);
 struct ieee80211_hw *p54_init_common(size_t priv_data_len);
 void p54_free_common(struct ieee80211_hw *dev);
index 34561e6e816be3dcefcf6f63caa709a9b9673b8e..45c2e7ad3acdfb83e0921ab8428a7aa90de45590 100644 (file)
@@ -239,11 +239,11 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
 
        if (priv->fw_var >= 0x300) {
                /* Firmware supports QoS, use it! */
-               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;
+               priv->tx_stats[P54_QUEUE_AC_VO].limit = 3;
+               priv->tx_stats[P54_QUEUE_AC_VI].limit = 4;
+               priv->tx_stats[P54_QUEUE_AC_BE].limit = 3;
+               priv->tx_stats[P54_QUEUE_AC_BK].limit = 2;
+               dev->queues = P54_QUEUE_AC_NUM;
        }
 
        if (!modparam_nohwcrypt)
@@ -272,13 +272,19 @@ static int p54_convert_rev0(struct ieee80211_hw *dev,
        unsigned int i, j;
        void *source, *target;
 
-       priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
+       priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
+                                  GFP_KERNEL);
        if (!priv->curve_data)
                return -ENOMEM;
 
-       memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
+       priv->curve_data->entries = curve_data->channels;
+       priv->curve_data->entry_size = sizeof(__le16) +
+               sizeof(*dst) * curve_data->points_per_channel;
+       priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
+       priv->curve_data->len = cd_len;
+       memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
        source = curve_data->data;
-       target = priv->curve_data->data;
+       target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
        for (i = 0; i < curve_data->channels; i++) {
                __le16 *freq = source;
                source += sizeof(__le16);
@@ -318,13 +324,19 @@ static int p54_convert_rev1(struct ieee80211_hw *dev,
        unsigned int i, j;
        void *source, *target;
 
-       priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
+       priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
+                                  GFP_KERNEL);
        if (!priv->curve_data)
                return -ENOMEM;
 
-       memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
+       priv->curve_data->entries = curve_data->channels;
+       priv->curve_data->entry_size = sizeof(__le16) +
+               sizeof(*dst) * curve_data->points_per_channel;
+       priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
+       priv->curve_data->len = cd_len;
+       memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
        source = curve_data->data;
-       target = priv->curve_data->data;
+       target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
        for (i = 0; i < curve_data->channels; i++) {
                __le16 *freq = source;
                source += sizeof(__le16);
@@ -376,7 +388,102 @@ static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
        }
 }
 
-static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
+static void p54_parse_default_country(struct ieee80211_hw *dev,
+                                     void *data, int len)
+{
+       struct pda_country *country;
+
+       if (len != sizeof(*country)) {
+               printk(KERN_ERR "%s: found possible invalid default country "
+                               "eeprom entry. (entry size: %d)\n",
+                      wiphy_name(dev->wiphy), len);
+
+               print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
+                                    data, len);
+
+               printk(KERN_ERR "%s: please report this issue.\n",
+                       wiphy_name(dev->wiphy));
+               return;
+       }
+
+       country = (struct pda_country *) data;
+       if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
+               regulatory_hint(dev->wiphy, country->alpha2);
+       else {
+               /* TODO:
+                * write a shared/common function that converts
+                * "Regulatory domain codes" (802.11-2007 14.8.2.2)
+                * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
+                */
+       }
+}
+
+static int p54_convert_output_limits(struct ieee80211_hw *dev,
+                                    u8 *data, size_t len)
+{
+       struct p54_common *priv = dev->priv;
+
+       if (len < 2)
+               return -EINVAL;
+
+       if (data[0] != 0) {
+               printk(KERN_ERR "%s: unknown output power db revision:%x\n",
+                      wiphy_name(dev->wiphy), data[0]);
+               return -EINVAL;
+       }
+
+       if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
+               return -EINVAL;
+
+       priv->output_limit = kmalloc(data[1] *
+               sizeof(struct pda_channel_output_limit) +
+               sizeof(*priv->output_limit), GFP_KERNEL);
+
+       if (!priv->output_limit)
+               return -ENOMEM;
+
+       priv->output_limit->offset = 0;
+       priv->output_limit->entries = data[1];
+       priv->output_limit->entry_size =
+               sizeof(struct pda_channel_output_limit);
+       priv->output_limit->len = priv->output_limit->entry_size *
+                                 priv->output_limit->entries +
+                                 priv->output_limit->offset;
+
+       memcpy(priv->output_limit->data, &data[2],
+              data[1] * sizeof(struct pda_channel_output_limit));
+
+       return 0;
+}
+
+static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
+                                              size_t total_len)
+{
+       struct p54_cal_database *dst;
+       size_t payload_len, entries, entry_size, offset;
+
+       payload_len = le16_to_cpu(src->len);
+       entries = le16_to_cpu(src->entries);
+       entry_size = le16_to_cpu(src->entry_size);
+       offset = le16_to_cpu(src->offset);
+       if (((entries * entry_size + offset) != payload_len) ||
+            (payload_len + sizeof(*src) != total_len))
+               return NULL;
+
+       dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
+       if (!dst)
+               return NULL;
+
+       dst->entries = entries;
+       dst->entry_size = entry_size;
+       dst->offset = offset;
+       dst->len = payload_len;
+
+       memcpy(dst->data, src->data, payload_len);
+       return dst;
+}
+
+int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
 {
        struct p54_common *priv = dev->priv;
        struct eeprom_pda_wrap *wrap = NULL;
@@ -401,30 +508,17 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
 
                switch (le16_to_cpu(entry->code)) {
                case PDR_MAC_ADDRESS:
+                       if (data_len != ETH_ALEN)
+                               break;
                        SET_IEEE80211_PERM_ADDR(dev, entry->data);
                        break;
                case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
-                       if (data_len < 2) {
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       priv->output_limit = kmalloc(entry->data[1] *
-                               sizeof(*priv->output_limit), GFP_KERNEL);
-
-                       if (!priv->output_limit) {
-                               err = -ENOMEM;
+                       if (priv->output_limit)
+                               break;
+                       err = p54_convert_output_limits(dev, entry->data,
+                                                       data_len);
+                       if (err)
                                goto err;
-                       }
-
-                       memcpy(priv->output_limit, &entry->data[2],
-                              entry->data[1]*sizeof(*priv->output_limit));
-                       priv->output_limit_len = entry->data[1];
                        break;
                case PDR_PRISM_PA_CAL_CURVE_DATA: {
                        struct pda_pa_curve_data *curve_data =
@@ -463,6 +557,9 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                        memcpy(priv->iq_autocal, entry->data, data_len);
                        priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
                        break;
+               case PDR_DEFAULT_COUNTRY:
+                       p54_parse_default_country(dev, entry->data, data_len);
+                       break;
                case PDR_INTERFACE_LIST:
                        tmp = entry->data;
                        while ((u8 *)tmp < entry->data + data_len) {
@@ -473,6 +570,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                        }
                        break;
                case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
+                       if (data_len < 2)
+                               break;
                        priv->version = *(u8 *)(entry->data + 1);
                        break;
                case PDR_RSSI_LINEAR_APPROXIMATION:
@@ -481,6 +580,34 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                        p54_parse_rssical(dev, entry->data, data_len,
                                          le16_to_cpu(entry->code));
                        break;
+               case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
+                       __le16 *src = (void *) entry->data;
+                       s16 *dst = (void *) &priv->rssical_db;
+                       int i;
+
+                       if (data_len != sizeof(priv->rssical_db)) {
+                               err = -EINVAL;
+                               goto err;
+                       }
+                       for (i = 0; i < sizeof(priv->rssical_db) /
+                                       sizeof(*src); i++)
+                               *(dst++) = (s16) le16_to_cpu(*(src++));
+                       }
+                       break;
+               case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
+                       struct pda_custom_wrapper *pda = (void *) entry->data;
+                       if (priv->output_limit || data_len < sizeof(*pda))
+                               break;
+                       priv->output_limit = p54_convert_db(pda, data_len);
+                       }
+                       break;
+               case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
+                       struct pda_custom_wrapper *pda = (void *) entry->data;
+                       if (priv->curve_data || data_len < sizeof(*pda))
+                               break;
+                       priv->curve_data = p54_convert_db(pda, data_len);
+                       }
+                       break;
                case PDR_END:
                        /* make it overrun */
                        entry_len = len;
@@ -497,7 +624,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                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:
@@ -525,12 +651,16 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
        }
 
        priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
-       if (priv->rxhw == 4)
+       if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
                p54_init_xbow_synth(dev);
        if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
                dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
        if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
                dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
+       if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
+               priv->rx_diversity_mask = 3;
+       if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
+               priv->tx_diversity_mask = 3;
 
        if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
                u8 perm_addr[ETH_ALEN];
@@ -568,13 +698,21 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
                wiphy_name(dev->wiphy));
        return err;
 }
+EXPORT_SYMBOL_GPL(p54_parse_eeprom);
 
 static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
 {
        struct p54_common *priv = dev->priv;
        int band = dev->conf.channel->band;
 
-       return ((rssi * priv->rssical_db[band].mul) / 64 +
+       if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW)
+               return ((rssi * priv->rssical_db[band].mul) / 64 +
+                        priv->rssical_db[band].add) / 4;
+       else
+               /*
+                * TODO: find the correct formula
+                */
+               return ((rssi * priv->rssical_db[band].mul) / 64 +
                         priv->rssical_db[band].add) / 4;
 }
 
@@ -655,7 +793,8 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
                return ;
 
        for (i = 0; i < dev->queues; i++)
-               if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
+               if (priv->tx_stats[i + P54_QUEUE_DATA].len <
+                   priv->tx_stats[i + P54_QUEUE_DATA].limit)
                        ieee80211_wake_queue(dev, i);
 }
 
@@ -663,7 +802,7 @@ 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;
+       struct p54_tx_info *range;
        unsigned long flags;
        u32 freed = 0, last_addr = priv->rx_start;
 
@@ -681,18 +820,18 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
        range = (void *)info->rate_driver_data;
        if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
                struct ieee80211_tx_info *ni;
-               struct memrecord *mr;
+               struct p54_tx_info *mr;
 
                ni = IEEE80211_SKB_CB(skb->prev);
-               mr = (struct memrecord *)ni->rate_driver_data;
+               mr = (struct p54_tx_info *)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;
+               struct p54_tx_info *mr;
 
                ni = IEEE80211_SKB_CB(skb->next);
-               mr = (struct memrecord *)ni->rate_driver_data;
+               mr = (struct p54_tx_info *)ni->rate_driver_data;
                freed = mr->start_addr - last_addr;
        } else
                freed = priv->rx_end - last_addr;
@@ -734,7 +873,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
        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;
+       struct p54_tx_info *range = NULL;
        u32 freed = 0;
        u32 last_addr = priv->rx_start;
        unsigned long flags;
@@ -756,10 +895,10 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
 
                if (entry->next != (struct sk_buff *)&priv->tx_queue) {
                        struct ieee80211_tx_info *ni;
-                       struct memrecord *mr;
+                       struct p54_tx_info *mr;
 
                        ni = IEEE80211_SKB_CB(entry->next);
-                       mr = (struct memrecord *)ni->rate_driver_data;
+                       mr = (struct p54_tx_info *)ni->rate_driver_data;
                        freed = mr->start_addr - last_addr;
                } else
                        freed = priv->rx_end - last_addr;
@@ -774,9 +913,16 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
                priv->tx_stats[entry_data->hw_queue].len--;
                priv->stats.dot11ACKFailureCount += payload->tries - 1;
 
-               if (unlikely(entry == priv->cached_beacon)) {
+               /*
+                * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
+                * generated by the driver. Therefore tx_status is bogus
+                * and we don't want to confuse the mac80211 stack.
+                */
+               if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) {
+                       if (entry_data->hw_queue == P54_QUEUE_BEACON)
+                               priv->cached_beacon = NULL;
+
                        kfree_skb(entry);
-                       priv->cached_beacon = NULL;
                        goto out;
                }
 
@@ -969,8 +1115,8 @@ EXPORT_SYMBOL_GPL(p54_rx);
  * can find some unused memory to upload our packets to. However, data that we
  * want the card to TX needs to stay intact until the card has told us that
  * it is done with it. This function finds empty places we can upload to and
- * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
- * allocated areas.
+ * marks allocated areas as reserved if necessary. p54_rx_frame_sent or
+ * p54_free_skb frees allocated areas.
  */
 static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
                               struct p54_hdr *data, u32 len)
@@ -979,7 +1125,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
        struct sk_buff *entry = priv->tx_queue.next;
        struct sk_buff *target_skb = NULL;
        struct ieee80211_tx_info *info;
-       struct memrecord *range;
+       struct p54_tx_info *range;
        u32 last_addr = priv->rx_start;
        u32 largest_hole = 0;
        u32 target_addr = priv->rx_start;
@@ -1060,25 +1206,29 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
        return 0;
 }
 
-static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev,
-               u16 hdr_flags, u16 len, u16 type, gfp_t memflags)
+static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, u16 hdr_flags,
+                                    u16 payload_len, u16 type, gfp_t memflags)
 {
        struct p54_common *priv = dev->priv;
        struct p54_hdr *hdr;
        struct sk_buff *skb;
+       size_t frame_len = sizeof(*hdr) + payload_len;
+
+       if (frame_len > P54_MAX_CTRL_FRAME_LEN)
+               return NULL;
 
-       skb = __dev_alloc_skb(len + priv->tx_hdr_len, memflags);
+       skb = __dev_alloc_skb(priv->tx_hdr_len + frame_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->len = cpu_to_le16(payload_len);
        hdr->type = cpu_to_le16(type);
        hdr->tries = hdr->rts_tries = 0;
 
-       if (unlikely(p54_assign_address(dev, skb, hdr, len))) {
+       if (p54_assign_address(dev, skb, hdr, frame_len)) {
                kfree_skb(skb);
                return NULL;
        }
@@ -1088,7 +1238,6 @@ static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev,
 int p54_read_eeprom(struct ieee80211_hw *dev)
 {
        struct p54_common *priv = dev->priv;
-       struct p54_hdr *hdr = NULL;
        struct p54_eeprom_lm86 *eeprom_hdr;
        struct sk_buff *skb;
        size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
@@ -1101,9 +1250,9 @@ int p54_read_eeprom(struct ieee80211_hw *dev)
        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);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*eeprom_hdr) +
+                           maxblocksize, P54_CONTROL_TYPE_EEPROM_READBACK,
+                           GFP_KERNEL);
        if (!skb)
                goto free;
        priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
@@ -1159,9 +1308,8 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
        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_ATOMIC);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim),
+                           P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1178,9 +1326,8 @@ static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
        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);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta),
+                           P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1220,9 +1367,8 @@ static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry)
        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);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel),
+                           P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1239,46 +1385,73 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
 {
        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;
-       }
+       int ret = 1;
 
        switch (priv->mode) {
+       case NL80211_IFTYPE_MONITOR:
+               /*
+                * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for
+                * every frame in promiscuous/monitor mode.
+                * see STSW45x0C LMAC API - page 12.
+                */
+               *aid = 0;
+               *flags = P54_HDR_FLAG_DATA_OUT_PROMISC;
+               *queue += P54_QUEUE_DATA;
+               break;
        case NL80211_IFTYPE_STATION:
                *aid = 1;
+               if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
+                       *queue = P54_QUEUE_MGMT;
+                       ret = 0;
+               } else
+                       *queue += P54_QUEUE_DATA;
                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;
+                       *queue = P54_QUEUE_CAB;
                        return 0;
                }
+
+               if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
+                       if (ieee80211_is_probe_resp(hdr->frame_control)) {
+                               *aid = 0;
+                               *queue = P54_QUEUE_MGMT;
+                               *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
+                                        P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+                               return 0;
+                       } else if (ieee80211_is_beacon(hdr->frame_control)) {
+                               *aid = 0;
+
+                               if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+                                       /*
+                                        * Injecting beacons on top of a AP is
+                                        * not a good idea... nevertheless,
+                                        * it should be doable.
+                                        */
+
+                                       *queue += P54_QUEUE_DATA;
+                                       return 1;
+                               }
+
+                               *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
+                               *queue = P54_QUEUE_BEACON;
+                               *extra_len = IEEE80211_MAX_TIM_LEN;
+                               return 0;
+                       } else {
+                               *queue = P54_QUEUE_MGMT;
+                               ret = 0;
+                       }
+               } else
+                       *queue += P54_QUEUE_DATA;
+
                if (info->control.sta)
                        *aid = info->control.sta->aid;
                else
                        *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+               break;
        }
        return ret;
 }
@@ -1300,7 +1473,7 @@ static u8 p54_convert_algo(enum ieee80211_key_alg alg)
 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 = NULL;
+       struct ieee80211_tx_queue_stats *current_queue;
        struct p54_common *priv = dev->priv;
        struct p54_hdr *hdr;
        struct p54_tx_data *txhdr;
@@ -1443,15 +1616,17 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        }
        txhdr->crypt_offset = crypt_offset;
        txhdr->hw_queue = queue;
-       if (current_queue)
-               txhdr->backlog = current_queue->len;
-       else
-               txhdr->backlog = 0;
+       txhdr->backlog = current_queue->len;
        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 = cts_rate;
+       txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ?
+               2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask;
+       if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+               txhdr->longbow.cts_rate = cts_rate;
+               txhdr->longbow.output_power = cpu_to_le16(priv->output_power);
+       } else {
+               txhdr->normal.output_power = priv->output_power;
+               txhdr->normal.cts_rate = cts_rate;
+       }
        if (padding)
                txhdr->align[0] = padding;
 
@@ -1464,14 +1639,12 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        queue_delayed_work(dev->workqueue, &priv->work,
                           msecs_to_jiffies(P54_TX_FRAME_LIFETIME));
 
-       return 0;
+       return NETDEV_TX_OK;
 
  err:
        skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
-       if (current_queue) {
-               current_queue->len--;
-               current_queue->count--;
-       }
+       current_queue->len--;
+       current_queue->count--;
        return NETDEV_TX_BUSY;
 }
 
@@ -1482,9 +1655,8 @@ static int p54_setup_mac(struct ieee80211_hw *dev)
        struct p54_setup_mac *setup;
        u16 mode;
 
-       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup) +
-                           sizeof(struct p54_hdr), P54_CONTROL_TYPE_SETUP,
-                           GFP_ATOMIC);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup),
+                           P54_CONTROL_TYPE_SETUP, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1501,11 +1673,21 @@ static int p54_setup_mac(struct ieee80211_hw *dev)
                case NL80211_IFTYPE_MESH_POINT:
                        mode = P54_FILTER_TYPE_IBSS;
                        break;
+               case NL80211_IFTYPE_MONITOR:
+                       mode = P54_FILTER_TYPE_PROMISCUOUS;
+                       break;
                default:
                        mode = P54_FILTER_TYPE_NONE;
                        break;
                }
-               if (priv->filter_flags & FIF_PROMISC_IN_BSS)
+
+               /*
+                * "TRANSPARENT and PROMISCUOUS are mutually exclusive"
+                * STSW45X0C LMAC API - page 12
+                */
+               if (((priv->filter_flags & FIF_PROMISC_IN_BSS) ||
+                    (priv->filter_flags & FIF_OTHER_BSS)) &&
+                   (mode != P54_FILTER_TYPE_PROMISCUOUS))
                        mode |= P54_FILTER_TYPE_TRANSPARENT;
        } else
                mode = P54_FILTER_TYPE_RX_DISABLED;
@@ -1513,7 +1695,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev)
        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_antenna = 2 & priv->rx_diversity_mask; /* automatic */
        setup->rx_align = 0;
        if (priv->fw_var < 0x500) {
                setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
@@ -1546,79 +1728,137 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
 {
        struct p54_common *priv = dev->priv;
        struct sk_buff *skb;
-       struct p54_scan *chan;
+       struct p54_hdr *hdr;
+       struct p54_scan_head *head;
+       struct p54_iq_autocal_entry *iq_autocal;
+       union p54_scan_body_union *body;
+       struct p54_scan_tail_rate *rate;
+       struct pda_rssi_cal_entry *rssi;
        unsigned int i;
        void *entry;
-       __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
        int band = dev->conf.channel->band;
+       __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
 
-       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) +
-                           sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN,
-                           GFP_ATOMIC);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
+                           2 + sizeof(*iq_autocal) + sizeof(*body) +
+                           sizeof(*rate) + 2 * sizeof(*rssi),
+                           P54_CONTROL_TYPE_SCAN, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
-       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);
+       head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
+       memset(head->scan_params, 0, sizeof(head->scan_params));
+       head->mode = cpu_to_le16(mode);
+       head->dwell = cpu_to_le16(dwell);
+       head->freq = freq;
+
+       if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+               __le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
+               *pa_power_points = cpu_to_le16(0x0c);
+       }
 
+       iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
        for (i = 0; i < priv->iq_autocal_len; i++) {
                if (priv->iq_autocal[i].freq != freq)
                        continue;
 
-               memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
-                      sizeof(*priv->iq_autocal));
+               memcpy(iq_autocal, &priv->iq_autocal[i].params,
+                      sizeof(struct p54_iq_autocal_entry));
                break;
        }
        if (i == priv->iq_autocal_len)
                goto err;
 
-       for (i = 0; i < priv->output_limit_len; i++) {
-               if (priv->output_limit[i].freq != freq)
+       if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
+               body = (void *) skb_put(skb, sizeof(body->longbow));
+       else
+               body = (void *) skb_put(skb, sizeof(body->normal));
+
+       for (i = 0; i < priv->output_limit->entries; i++) {
+               __le16 *entry_freq = (void *) (priv->output_limit->data +
+                                    priv->output_limit->entry_size * i);
+
+               if (*entry_freq != freq)
                        continue;
 
-               chan->val_barker = 0x38;
-               chan->val_bpsk = chan->dup_bpsk =
-                       priv->output_limit[i].val_bpsk;
-               chan->val_qpsk = chan->dup_qpsk =
-                       priv->output_limit[i].val_qpsk;
-               chan->val_16qam = chan->dup_16qam =
-                       priv->output_limit[i].val_16qam;
-               chan->val_64qam = chan->dup_64qam =
-                       priv->output_limit[i].val_64qam;
+               if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+                       memcpy(&body->longbow.power_limits,
+                              (void *) entry_freq + sizeof(__le16),
+                              priv->output_limit->entry_size);
+               } else {
+                       struct pda_channel_output_limit *limits =
+                              (void *) entry_freq;
+
+                       body->normal.val_barker = 0x38;
+                       body->normal.val_bpsk = body->normal.dup_bpsk =
+                               limits->val_bpsk;
+                       body->normal.val_qpsk = body->normal.dup_qpsk =
+                               limits->val_qpsk;
+                       body->normal.val_16qam = body->normal.dup_16qam =
+                               limits->val_16qam;
+                       body->normal.val_64qam = body->normal.dup_64qam =
+                               limits->val_64qam;
+               }
                break;
        }
-       if (i == priv->output_limit_len)
+       if (i == priv->output_limit->entries)
                goto err;
 
-       entry = priv->curve_data->data;
-       for (i = 0; i < priv->curve_data->channels; i++) {
+       entry = (void *)(priv->curve_data->data + priv->curve_data->offset);
+       for (i = 0; i < priv->curve_data->entries; i++) {
                if (*((__le16 *)entry) != freq) {
-                       entry += sizeof(__le16);
-                       entry += sizeof(struct p54_pa_curve_data_sample) *
-                                priv->curve_data->points_per_channel;
+                       entry += priv->curve_data->entry_size;
                        continue;
                }
 
-               entry += sizeof(__le16);
-               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));
+               if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+                       memcpy(&body->longbow.curve_data,
+                               (void *) entry + sizeof(__le16),
+                               priv->curve_data->entry_size);
+               } else {
+                       struct p54_scan_body *chan = &body->normal;
+                       struct pda_pa_curve_data *curve_data =
+                               (void *) priv->curve_data->data;
+
+                       entry += sizeof(__le16);
+                       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, curve_data->points_per_channel));
+               }
                break;
        }
+       if (i == priv->curve_data->entries)
+               goto err;
 
-       if (priv->fw_var < 0x500) {
-               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 {
-               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);
+       if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
+               rate = (void *) skb_put(skb, sizeof(*rate));
+               rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+               for (i = 0; i < sizeof(rate->rts_rates); i++)
+                       rate->rts_rates[i] = i;
        }
+
+       rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
+       rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
+       rssi->add = cpu_to_le16(priv->rssical_db[band].add);
+       if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+               /* Longbow frontend needs ever more */
+               rssi = (void *) skb_put(skb, sizeof(*rssi));
+               rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
+               rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
+       }
+
+       if (priv->fw_var >= 0x509) {
+               rate = (void *) skb_put(skb, sizeof(*rate));
+               rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+               for (i = 0; i < sizeof(rate->rts_rates); i++)
+                       rate->rts_rates[i] = i;
+       }
+
+       hdr = (struct p54_hdr *) skb->data;
+       hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
+
        priv->tx(dev, skb);
        return 0;
 
@@ -1634,9 +1874,8 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
        struct sk_buff *skb;
        struct p54_led *led;
 
-       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led) +
-                       sizeof(struct p54_hdr), P54_CONTROL_TYPE_LED,
-                       GFP_ATOMIC);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led),
+                           P54_CONTROL_TYPE_LED, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1663,9 +1902,8 @@ static int p54_set_edcf(struct ieee80211_hw *dev)
        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);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
+                           P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1689,6 +1927,42 @@ static int p54_set_edcf(struct ieee80211_hw *dev)
        return 0;
 }
 
+static int p54_set_ps(struct ieee80211_hw *dev)
+{
+       struct p54_common *priv = dev->priv;
+       struct sk_buff *skb;
+       struct p54_psm *psm;
+       u16 mode;
+       int i;
+
+       if (dev->conf.flags & IEEE80211_CONF_PS)
+               mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC;
+       else
+               mode = P54_PSM_CAM;
+
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm),
+                           P54_CONTROL_TYPE_PSM, GFP_ATOMIC);
+       if (!skb)
+               return -ENOMEM;
+
+       psm = (struct p54_psm *)skb_put(skb, sizeof(*psm));
+       psm->mode = cpu_to_le16(mode);
+       psm->aid = cpu_to_le16(priv->aid);
+       for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) {
+               psm->intervals[i].interval =
+                       cpu_to_le16(dev->conf.listen_interval);
+               psm->intervals[i].periods = cpu_to_le16(1);
+       }
+
+       psm->beacon_rssi_skip_max = 60;
+       psm->rssi_delta_threshold = 0;
+       psm->nr = 0;
+
+       priv->tx(dev, skb);
+
+       return 0;
+}
+
 static int p54_beacon_tim(struct sk_buff *skb)
 {
        /*
@@ -1881,6 +2155,11 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
                if (ret)
                        goto out;
        }
+       if (changed & IEEE80211_CONF_CHANGE_PS) {
+               ret = p54_set_ps(dev);
+               if (ret)
+                       goto out;
+       }
 
 out:
        mutex_unlock(&priv->conf_mutex);
@@ -1932,12 +2211,13 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
        struct p54_common *priv = dev->priv;
 
        *total_flags &= FIF_PROMISC_IN_BSS |
+                       FIF_OTHER_BSS |
                        (*total_flags & FIF_PROMISC_IN_BSS) ?
                                FIF_FCSFAIL : 0;
 
        priv->filter_flags = *total_flags;
 
-       if (changed_flags & FIF_PROMISC_IN_BSS)
+       if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
                p54_setup_mac(dev);
 }
 
@@ -1964,10 +2244,8 @@ static int p54_init_xbow_synth(struct ieee80211_hw *dev)
        struct sk_buff *skb;
        struct p54_xbow_synth *xbow;
 
-       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow) +
-                           sizeof(struct p54_hdr),
-                           P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
-                           GFP_KERNEL);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow),
+                           P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
 
@@ -1996,7 +2274,7 @@ static void p54_work(struct work_struct *work)
         *      2. cancel stuck frames / reset the device if necessary.
         */
 
-       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_hdr) +
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL,
                            sizeof(struct p54_statistics),
                            P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
        if (!skb)
@@ -2019,8 +2297,8 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
 {
        struct p54_common *priv = dev->priv;
 
-       memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues);
-
+       memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
+              sizeof(stats[0]) * dev->queues);
        return 0;
 }
 
@@ -2056,7 +2334,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
 }
 
 static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
-                      const u8 *local_address, const u8 *address,
+                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                       struct ieee80211_key_conf *key)
 {
        struct p54_common *priv = dev->priv;
@@ -2107,9 +2385,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
        }
 
        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);
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey),
+                           P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC);
        if (!skb) {
                mutex_unlock(&priv->conf_mutex);
                return -ENOMEM;
@@ -2120,8 +2397,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
        rxkey->entry = key->keyidx;
        rxkey->key_id = key->keyidx;
        rxkey->key_type = algo;
-       if (address)
-               memcpy(rxkey->mac, address, ETH_ALEN);
+       if (sta)
+               memcpy(rxkey->mac, sta->addr, ETH_ALEN);
        else
                memset(rxkey->mac, ~0, ETH_ALEN);
        if (key->alg != ALG_TKIP) {
@@ -2181,11 +2458,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
                                      BIT(NL80211_IFTYPE_MESH_POINT);
 
        dev->channel_change_time = 1000;        /* TODO: find actual value */
-       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 */
+       priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
+       priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
+       priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
+       priv->tx_stats[P54_QUEUE_CAB].limit = 3;
+       priv->tx_stats[P54_QUEUE_DATA].limit = 5;
        dev->queues = 1;
        priv->noise = -94;
        /*
index f5729de83fe118eaeb36ea55c9f9cecdacd2c40b..def23b1f49ec4c261b40ca0fac5fde6053e775ca 100644 (file)
@@ -26,12 +26,17 @@ struct bootrec {
 } __attribute__((packed));
 
 #define PDR_SYNTH_FRONTEND_MASK                0x0007
+#define PDR_SYNTH_FRONTEND_DUETTE3     0x0001
+#define PDR_SYNTH_FRONTEND_DUETTE2     0x0002
+#define PDR_SYNTH_FRONTEND_FRISBEE     0x0003
+#define PDR_SYNTH_FRONTEND_XBOW                0x0004
+#define PDR_SYNTH_FRONTEND_LONGBOW     0x0005
 #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_FAA_SWITCH_ENABLED   0x0020
 #define PDR_SYNTH_24_GHZ_MASK          0x0040
 #define PDR_SYNTH_24_GHZ_DISABLED      0x0040
 #define PDR_SYNTH_5_GHZ_MASK           0x0080
@@ -125,9 +130,13 @@ struct eeprom_pda_wrap {
        u8 data[0];
 } __attribute__ ((packed));
 
+struct p54_iq_autocal_entry {
+       __le16 iq_param[4];
+} __attribute__ ((packed));
+
 struct pda_iq_autocal_entry {
         __le16 freq;
-        __le16 iq_param[4];
+       struct p54_iq_autocal_entry params;
 } __attribute__ ((packed));
 
 struct pda_channel_output_limit {
@@ -180,6 +189,35 @@ struct pda_rssi_cal_entry {
        __le16 add;
 } __attribute__ ((packed));
 
+struct pda_country {
+       u8 regdomain;
+       u8 alpha2[2];
+       u8 flags;
+} __attribute__ ((packed));
+
+/*
+ * Warning: Longbow's structures are bogus.
+ */
+struct p54_channel_output_limit_longbow {
+       __le16 rf_power_points[12];
+} __attribute__ ((packed));
+
+struct p54_pa_curve_data_sample_longbow {
+       __le16 rf_power;
+       __le16 pa_detector;
+       struct {
+               __le16 data[4];
+       } points[3] __attribute__ ((packed));
+} __attribute__ ((packed));
+
+struct pda_custom_wrapper {
+       __le16 entries;
+       __le16 entry_size;
+       __le16 offset;
+       __le16 len;
+       u8 data[0];
+} __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
@@ -225,8 +263,13 @@ struct pda_rssi_cal_entry {
 /* reserved range (0x2000 - 0x7fff) */
 
 /* customer range (0x8000 - 0xffff) */
-#define PDR_BASEBAND_REGISTERS                 0x8000
-#define PDR_PER_CHANNEL_BASEBAND_REGISTERS     0x8001
+#define PDR_BASEBAND_REGISTERS                         0x8000
+#define PDR_PER_CHANNEL_BASEBAND_REGISTERS             0x8001
+
+/* used by our modificated eeprom image */
+#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM           0xDEAD
+#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM    0xBEEF
+#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM             0xB05D
 
 /* PDR definitions for default country & country list */
 #define PDR_COUNTRY_CERT_CODE          0x80
@@ -241,12 +284,6 @@ struct pda_rssi_cal_entry {
 #define PDR_COUNTRY_CERT_IODOOR_OUTDOOR        0x30
 #define PDR_COUNTRY_CERT_INDEX         0x0F
 
-/* stored in skb->cb */
-struct memrecord {
-       u32 start_addr;
-       u32 end_addr;
-};
-
 struct p54_eeprom_lm86 {
        union {
                struct {
@@ -329,7 +366,7 @@ struct p54_frame_sent {
        u8 padding;
 } __attribute__ ((packed));
 
-enum  p54_tx_data_crypt {
+enum p54_tx_data_crypt {
        P54_CRYPTO_NONE = 0,
        P54_CRYPTO_WEP,
        P54_CRYPTO_TKIP,
@@ -340,6 +377,23 @@ enum  p54_tx_data_crypt {
        P54_CRYPTO_AESCCMP
 };
 
+enum p54_tx_data_queue {
+       P54_QUEUE_BEACON        = 0,
+       P54_QUEUE_FWSCAN        = 1,
+       P54_QUEUE_MGMT          = 2,
+       P54_QUEUE_CAB           = 3,
+       P54_QUEUE_DATA          = 4,
+
+       P54_QUEUE_AC_NUM        = 4,
+       P54_QUEUE_AC_VO         = 4,
+       P54_QUEUE_AC_VI         = 5,
+       P54_QUEUE_AC_BE         = 6,
+       P54_QUEUE_AC_BK         = 7,
+
+       /* keep last */
+       P54_QUEUE_NUM           = 8,
+};
+
 struct p54_tx_data {
        u8 rateset[8];
        u8 rts_rate_idx;
@@ -351,9 +405,18 @@ struct p54_tx_data {
        u8 backlog;
        __le16 durations[4];
        u8 tx_antenna;
-       u8 output_power;
-       u8 cts_rate;
-       u8 unalloc2[3];
+       union {
+               struct {
+                       u8 cts_rate;
+                       __le16 output_power;
+               } __attribute__((packed)) longbow;
+               struct {
+                       u8 output_power;
+                       u8 cts_rate;
+                       u8 unalloc;
+               } __attribute__ ((packed)) normal;
+       } __attribute__ ((packed));
+       u8 unalloc2[2];
        u8 align[0];
 } __attribute__ ((packed));
 
@@ -414,11 +477,14 @@ struct p54_setup_mac {
 #define P54_SCAN_ACTIVE BIT(2)
 #define P54_SCAN_FILTER BIT(3)
 
-struct p54_scan {
+struct p54_scan_head {
        __le16 mode;
        __le16 dwell;
-       u8 padding1[20];
-       struct pda_iq_autocal_entry iq_autocal;
+       u8 scan_params[20];
+       __le16 freq;
+} __attribute__ ((packed));
+
+struct p54_scan_body {
        u8 pa_points_per_curve;
        u8 val_barker;
        u8 val_bpsk;
@@ -430,19 +496,23 @@ struct p54_scan {
        u8 dup_qpsk;
        u8 dup_16qam;
        u8 dup_64qam;
-       union {
-               struct pda_rssi_cal_entry v1_rssi;
+} __attribute__ ((packed));
 
-               struct {
-                       __le32 basic_rate_mask;
-                       u8 rts_rates[8];
-                       struct pda_rssi_cal_entry rssi;
-               } v2 __attribute__ ((packed));
-       } __attribute__ ((packed));
+struct p54_scan_body_longbow {
+       struct p54_channel_output_limit_longbow power_limits;
+       struct p54_pa_curve_data_sample_longbow curve_data[8];
+       __le16 unkn[6];         /* maybe more power_limits or rate_mask */
+} __attribute__ ((packed));
+
+union p54_scan_body_union {
+       struct p54_scan_body normal;
+       struct p54_scan_body_longbow longbow;
 } __attribute__ ((packed));
 
-#define P54_SCAN_V1_LEN 0x70
-#define P54_SCAN_V2_LEN 0x7c
+struct p54_scan_tail_rate {
+       __le32 basic_rate_mask;
+       u8 rts_rates[8];
+} __attribute__ ((packed));
 
 struct p54_led {
        __le16 mode;
@@ -511,6 +581,7 @@ struct p54_psm_interval {
        __le16 periods;
 } __attribute__ ((packed));
 
+#define P54_PSM_CAM                    0
 #define P54_PSM                                BIT(0)
 #define P54_PSM_DTIM                   BIT(1)
 #define P54_PSM_MCBC                   BIT(2)
index aa367a0ddc49139ac51a097730a0f464d97c24e0..3f9a6b04ea95f34a7f1b5e8e57be4c2ead029bfe 100644 (file)
@@ -79,6 +79,12 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
        if (err)
                return err;
 
+       if (priv->common.fw_interface != FW_LM86) {
+               dev_err(&priv->pdev->dev, "wrong firmware, "
+                       "please get a LM86(PCI) firmware a try again.\n");
+               return -EINVAL;
+       }
+
        data = (__le32 *) priv->firmware->data;
        remains = priv->firmware->size;
        device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
new file mode 100644 (file)
index 0000000..7fde243
--- /dev/null
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2008 Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008       Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This driver is a port from stlc45xx:
+ *     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 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/etherdevice.h>
+#include <linux/gpio.h>
+
+#include "p54spi.h"
+#include "p54spi_eeprom.h"
+#include "p54.h"
+
+#include "p54common.h"
+
+MODULE_FIRMWARE("3826.arm");
+MODULE_ALIAS("stlc45xx");
+
+/*
+ * gpios should be handled in board files and provided via platform data,
+ * but because it's currently impossible for p54spi to have a header file
+ * in include/linux, let's use module paramaters for now
+ */
+
+static int p54spi_gpio_power = 97;
+module_param(p54spi_gpio_power, int, 0444);
+MODULE_PARM_DESC(p54spi_gpio_power, "gpio number for power line");
+
+static int p54spi_gpio_irq = 87;
+module_param(p54spi_gpio_irq, int, 0444);
+MODULE_PARM_DESC(p54spi_gpio_irq, "gpio number for irq line");
+
+static void p54spi_spi_read(struct p54s_priv *priv, u8 address,
+                             void *buf, size_t len)
+{
+       struct spi_transfer t[2];
+       struct spi_message m;
+       __le16 addr;
+
+       /* We first push the address */
+       addr = cpu_to_le16(address << 8 | SPI_ADRS_READ_BIT_15);
+
+       spi_message_init(&m);
+       memset(t, 0, sizeof(t));
+
+       t[0].tx_buf = &addr;
+       t[0].len = sizeof(addr);
+       spi_message_add_tail(&t[0], &m);
+
+       t[1].rx_buf = buf;
+       t[1].len = len;
+       spi_message_add_tail(&t[1], &m);
+
+       spi_sync(priv->spi, &m);
+}
+
+
+static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
+                            const void *buf, size_t len)
+{
+       struct spi_transfer t[3];
+       struct spi_message m;
+       __le16 addr;
+
+       /* We first push the address */
+       addr = cpu_to_le16(address << 8);
+
+       spi_message_init(&m);
+       memset(t, 0, sizeof(t));
+
+       t[0].tx_buf = &addr;
+       t[0].len = sizeof(addr);
+       spi_message_add_tail(&t[0], &m);
+
+       t[1].tx_buf = buf;
+       t[1].len = len;
+       spi_message_add_tail(&t[1], &m);
+
+       if (len % 2) {
+               __le16 last_word;
+               last_word = cpu_to_le16(((u8 *)buf)[len - 1]);
+
+               t[2].tx_buf = &last_word;
+               t[2].len = sizeof(last_word);
+               spi_message_add_tail(&t[2], &m);
+       }
+
+       spi_sync(priv->spi, &m);
+}
+
+static u16 p54spi_read16(struct p54s_priv *priv, u8 addr)
+{
+       __le16 val;
+
+       p54spi_spi_read(priv, addr, &val, sizeof(val));
+
+       return le16_to_cpu(val);
+}
+
+static u32 p54spi_read32(struct p54s_priv *priv, u8 addr)
+{
+       __le32 val;
+
+       p54spi_spi_read(priv, addr, &val, sizeof(val));
+
+       return le32_to_cpu(val);
+}
+
+static inline void p54spi_write16(struct p54s_priv *priv, u8 addr, __le16 val)
+{
+       p54spi_spi_write(priv, addr, &val, sizeof(val));
+}
+
+static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val)
+{
+       p54spi_spi_write(priv, addr, &val, sizeof(val));
+}
+
+struct p54spi_spi_reg {
+       u16 address;            /* __le16 ? */
+       u16 length;
+       char *name;
+};
+
+static const struct p54spi_spi_reg p54spi_registers_array[] =
+{
+       { SPI_ADRS_ARM_INTERRUPTS,      32, "ARM_INT     " },
+       { SPI_ADRS_ARM_INT_EN,          32, "ARM_INT_ENA " },
+       { SPI_ADRS_HOST_INTERRUPTS,     32, "HOST_INT    " },
+       { SPI_ADRS_HOST_INT_EN,         32, "HOST_INT_ENA" },
+       { SPI_ADRS_HOST_INT_ACK,        32, "HOST_INT_ACK" },
+       { SPI_ADRS_GEN_PURP_1,          32, "GP1_COMM    " },
+       { SPI_ADRS_GEN_PURP_2,          32, "GP2_COMM    " },
+       { SPI_ADRS_DEV_CTRL_STAT,       32, "DEV_CTRL_STA" },
+       { SPI_ADRS_DMA_DATA,            16, "DMA_DATA    " },
+       { SPI_ADRS_DMA_WRITE_CTRL,      16, "DMA_WR_CTRL " },
+       { SPI_ADRS_DMA_WRITE_LEN,       16, "DMA_WR_LEN  " },
+       { SPI_ADRS_DMA_WRITE_BASE,      32, "DMA_WR_BASE " },
+       { SPI_ADRS_DMA_READ_CTRL,       16, "DMA_RD_CTRL " },
+       { SPI_ADRS_DMA_READ_LEN,        16, "DMA_RD_LEN  " },
+       { SPI_ADRS_DMA_WRITE_BASE,      32, "DMA_RD_BASE " }
+};
+
+static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
+{
+       int i;
+       __le32 buffer;
+
+       for (i = 0; i < 2000; i++) {
+               p54spi_spi_read(priv, reg, &buffer, sizeof(buffer));
+               if (buffer == bits)
+                       return 1;
+
+               msleep(1);
+       }
+       return 0;
+}
+
+static int p54spi_request_firmware(struct ieee80211_hw *dev)
+{
+       struct p54s_priv *priv = dev->priv;
+       int ret;
+
+       /* FIXME: should driver use it's own struct device? */
+       ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev);
+
+       if (ret < 0) {
+               dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret);
+               return ret;
+       }
+
+       ret = p54_parse_firmware(dev, priv->firmware);
+       if (ret) {
+               release_firmware(priv->firmware);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int p54spi_request_eeprom(struct ieee80211_hw *dev)
+{
+       struct p54s_priv *priv = dev->priv;
+       const struct firmware *eeprom;
+       int ret;
+
+       /*
+        * allow users to customize their eeprom.
+        */
+
+       ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
+       if (ret < 0) {
+               dev_info(&priv->spi->dev, "loading default eeprom...\n");
+               ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom,
+                                      sizeof(p54spi_eeprom));
+       } else {
+               dev_info(&priv->spi->dev, "loading user eeprom...\n");
+               ret = p54_parse_eeprom(dev, (void *) eeprom->data,
+                                      (int)eeprom->size);
+               release_firmware(eeprom);
+       }
+       return ret;
+}
+
+static int p54spi_upload_firmware(struct ieee80211_hw *dev)
+{
+       struct p54s_priv *priv = dev->priv;
+       unsigned long fw_len, fw_addr;
+       long _fw_len;
+
+       /* stop the device */
+       p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
+                      SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET |
+                      SPI_CTRL_STAT_START_HALTED));
+
+       msleep(TARGET_BOOT_SLEEP);
+
+       p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
+                      SPI_CTRL_STAT_HOST_OVERRIDE |
+                      SPI_CTRL_STAT_START_HALTED));
+
+       msleep(TARGET_BOOT_SLEEP);
+
+       fw_addr = ISL38XX_DEV_FIRMWARE_ADDR;
+       fw_len = priv->firmware->size;
+
+       while (fw_len > 0) {
+               _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE);
+
+               p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
+                              cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
+
+               if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
+                                   cpu_to_le32(HOST_ALLOWED)) == 0) {
+                       dev_err(&priv->spi->dev, "fw_upload not allowed "
+                               "to DMA write.");
+                       return -EAGAIN;
+               }
+
+               p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN,
+                              cpu_to_le16(_fw_len));
+               p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE,
+                              cpu_to_le32(fw_addr));
+
+               p54spi_spi_write(priv, SPI_ADRS_DMA_DATA,
+                                &priv->firmware->data, _fw_len);
+
+               fw_len -= _fw_len;
+               fw_addr += _fw_len;
+
+               /* FIXME: I think this doesn't work if firmware is large,
+                * this loop goes to second round. fw->data is not
+                * increased at all! */
+       }
+
+       BUG_ON(fw_len != 0);
+
+       /* enable host interrupts */
+       p54spi_write32(priv, SPI_ADRS_HOST_INT_EN,
+                      cpu_to_le32(SPI_HOST_INTS_DEFAULT));
+
+       /* boot the device */
+       p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
+                      SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET |
+                      SPI_CTRL_STAT_RAM_BOOT));
+
+       msleep(TARGET_BOOT_SLEEP);
+
+       p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
+                      SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT));
+       msleep(TARGET_BOOT_SLEEP);
+       return 0;
+}
+
+static void p54spi_power_off(struct p54s_priv *priv)
+{
+       disable_irq(gpio_to_irq(p54spi_gpio_irq));
+       gpio_set_value(p54spi_gpio_power, 0);
+}
+
+static void p54spi_power_on(struct p54s_priv *priv)
+{
+       gpio_set_value(p54spi_gpio_power, 1);
+       enable_irq(gpio_to_irq(p54spi_gpio_irq));
+
+       /*
+        * need to wait a while before device can be accessed, the lenght
+        * is just a guess
+        */
+       msleep(10);
+}
+
+static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val)
+{
+       p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val));
+}
+
+static void p54spi_wakeup(struct p54s_priv *priv)
+{
+       unsigned long timeout;
+       u32 ints;
+
+       /* wake the chip */
+       p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
+                      cpu_to_le32(SPI_TARGET_INT_WAKEUP));
+
+       /* And wait for the READY interrupt */
+       timeout = jiffies + HZ;
+
+       ints =  p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+       while (!(ints & SPI_HOST_INT_READY)) {
+               if (time_after(jiffies, timeout))
+                               goto out;
+               ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+       }
+
+       p54spi_int_ack(priv, SPI_HOST_INT_READY);
+
+out:
+       return;
+}
+
+static inline void p54spi_sleep(struct p54s_priv *priv)
+{
+       p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
+                      cpu_to_le32(SPI_TARGET_INT_SLEEP));
+}
+
+static void p54spi_int_ready(struct p54s_priv *priv)
+{
+       p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, cpu_to_le32(
+                      SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE));
+
+       switch (priv->fw_state) {
+       case FW_STATE_BOOTING:
+               priv->fw_state = FW_STATE_READY;
+               complete(&priv->fw_comp);
+               break;
+       case FW_STATE_RESETTING:
+               priv->fw_state = FW_STATE_READY;
+               /* TODO: reinitialize state */
+               break;
+       default:
+               break;
+       }
+}
+
+static int p54spi_rx(struct p54s_priv *priv)
+{
+       struct sk_buff *skb;
+       u16 len;
+
+       p54spi_wakeup(priv);
+
+       /* dummy read to flush SPI DMA controller bug */
+       p54spi_read16(priv, SPI_ADRS_GEN_PURP_1);
+
+       len = p54spi_read16(priv, SPI_ADRS_DMA_DATA);
+
+       if (len == 0) {
+               dev_err(&priv->spi->dev, "rx request of zero bytes");
+               return 0;
+       }
+
+       skb = dev_alloc_skb(len);
+       if (!skb) {
+               dev_err(&priv->spi->dev, "could not alloc skb");
+               return 0;
+       }
+
+       p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len);
+       p54spi_sleep(priv);
+
+       if (p54_rx(priv->hw, skb) == 0)
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+
+static irqreturn_t p54spi_interrupt(int irq, void *config)
+{
+       struct spi_device *spi = config;
+       struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
+
+       queue_work(priv->hw->workqueue, &priv->work);
+
+       return IRQ_HANDLED;
+}
+
+static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
+{
+       struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+       struct p54s_dma_regs dma_regs;
+       unsigned long timeout;
+       int ret = 0;
+       u32 ints;
+
+       p54spi_wakeup(priv);
+
+       dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE);
+       dma_regs.len = cpu_to_le16(skb->len);
+       dma_regs.addr = hdr->req_id;
+
+       p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs,
+                          sizeof(dma_regs));
+
+       p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len);
+
+       timeout = jiffies + 2 * HZ;
+       ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+       while (!(ints & SPI_HOST_INT_WR_READY)) {
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&priv->spi->dev, "WR_READY timeout");
+                       ret = -1;
+                       goto out;
+               }
+               ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+       }
+
+       p54spi_int_ack(priv, SPI_HOST_INT_WR_READY);
+       p54spi_sleep(priv);
+
+out:
+       if (FREE_AFTER_TX(skb))
+               p54_free_skb(priv->hw, skb);
+       return ret;
+}
+
+static int p54spi_wq_tx(struct p54s_priv *priv)
+{
+       struct p54s_tx_info *entry;
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *info;
+       struct p54_tx_info *minfo;
+       struct p54s_tx_info *dinfo;
+       int ret = 0;
+
+       spin_lock_bh(&priv->tx_lock);
+
+       while (!list_empty(&priv->tx_pending)) {
+               entry = list_entry(priv->tx_pending.next,
+                                  struct p54s_tx_info, tx_list);
+
+               list_del_init(&entry->tx_list);
+
+               spin_unlock_bh(&priv->tx_lock);
+
+               dinfo = container_of((void *) entry, struct p54s_tx_info,
+                                    tx_list);
+               minfo = container_of((void *) dinfo, struct p54_tx_info,
+                                    data);
+               info = container_of((void *) minfo, struct ieee80211_tx_info,
+                                   rate_driver_data);
+               skb = container_of((void *) info, struct sk_buff, cb);
+
+               ret = p54spi_tx_frame(priv, skb);
+
+               spin_lock_bh(&priv->tx_lock);
+
+               if (ret < 0) {
+                       p54_free_skb(priv->hw, skb);
+                       goto out;
+               }
+       }
+
+out:
+       spin_unlock_bh(&priv->tx_lock);
+       return ret;
+}
+
+static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+       struct p54s_priv *priv = dev->priv;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data;
+       struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data;
+
+       BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data)));
+
+       spin_lock_bh(&priv->tx_lock);
+       list_add_tail(&di->tx_list, &priv->tx_pending);
+       spin_unlock_bh(&priv->tx_lock);
+
+       queue_work(priv->hw->workqueue, &priv->work);
+}
+
+static void p54spi_work(struct work_struct *work)
+{
+       struct p54s_priv *priv = container_of(work, struct p54s_priv, work);
+       u32 ints;
+       int ret;
+
+       mutex_lock(&priv->mutex);
+
+       if (priv->fw_state == FW_STATE_OFF &&
+           priv->fw_state == FW_STATE_RESET)
+               goto out;
+
+       ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+
+       if (ints & SPI_HOST_INT_READY) {
+               p54spi_int_ready(priv);
+               p54spi_int_ack(priv, SPI_HOST_INT_READY);
+       }
+
+       if (priv->fw_state != FW_STATE_READY)
+               goto out;
+
+       if (ints & SPI_HOST_INT_UPDATE) {
+               p54spi_int_ack(priv, SPI_HOST_INT_UPDATE);
+               ret = p54spi_rx(priv);
+               if (ret < 0)
+                       goto out;
+       }
+       if (ints & SPI_HOST_INT_SW_UPDATE) {
+               p54spi_int_ack(priv, SPI_HOST_INT_SW_UPDATE);
+               ret = p54spi_rx(priv);
+               if (ret < 0)
+                       goto out;
+       }
+
+       ret = p54spi_wq_tx(priv);
+       if (ret < 0)
+               goto out;
+
+       ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+
+out:
+       mutex_unlock(&priv->mutex);
+}
+
+static int p54spi_op_start(struct ieee80211_hw *dev)
+{
+       struct p54s_priv *priv = dev->priv;
+       unsigned long timeout;
+       int ret = 0;
+
+       if (mutex_lock_interruptible(&priv->mutex)) {
+               ret = -EINTR;
+               goto out;
+       }
+
+       priv->fw_state = FW_STATE_BOOTING;
+
+       p54spi_power_on(priv);
+
+       ret = p54spi_upload_firmware(dev);
+       if (ret < 0) {
+               p54spi_power_off(priv);
+               goto out_unlock;
+       }
+
+       mutex_unlock(&priv->mutex);
+
+       timeout = msecs_to_jiffies(2000);
+       timeout = wait_for_completion_interruptible_timeout(&priv->fw_comp,
+                                                           timeout);
+       if (!timeout) {
+               dev_err(&priv->spi->dev, "firmware boot failed");
+               p54spi_power_off(priv);
+               ret = -1;
+               goto out;
+       }
+
+       if (mutex_lock_interruptible(&priv->mutex)) {
+               ret = -EINTR;
+               p54spi_power_off(priv);
+               goto out;
+       }
+
+       WARN_ON(priv->fw_state != FW_STATE_READY);
+
+out_unlock:
+       mutex_unlock(&priv->mutex);
+
+out:
+       return ret;
+}
+
+static void p54spi_op_stop(struct ieee80211_hw *dev)
+{
+       struct p54s_priv *priv = dev->priv;
+
+       if (mutex_lock_interruptible(&priv->mutex)) {
+               /* FIXME: how to handle this error? */
+               return;
+       }
+
+       WARN_ON(priv->fw_state != FW_STATE_READY);
+
+       cancel_work_sync(&priv->work);
+
+       p54spi_power_off(priv);
+       spin_lock_bh(&priv->tx_lock);
+       INIT_LIST_HEAD(&priv->tx_pending);
+       spin_unlock_bh(&priv->tx_lock);
+
+       priv->fw_state = FW_STATE_OFF;
+       mutex_unlock(&priv->mutex);
+}
+
+static int __devinit p54spi_probe(struct spi_device *spi)
+{
+       struct p54s_priv *priv = NULL;
+       struct ieee80211_hw *hw;
+       int ret = -EINVAL;
+
+       hw = p54_init_common(sizeof(*priv));
+       if (!hw) {
+               dev_err(&priv->spi->dev, "could not alloc ieee80211_hw");
+               return -ENOMEM;
+       }
+
+       priv = hw->priv;
+       priv->hw = hw;
+       dev_set_drvdata(&spi->dev, priv);
+       priv->spi = spi;
+
+       spi->bits_per_word = 16;
+       spi->max_speed_hz = 24000000;
+
+       ret = spi_setup(spi);
+       if (ret < 0) {
+               dev_err(&priv->spi->dev, "spi_setup failed");
+               goto err_free_common;
+       }
+
+       ret = gpio_request(p54spi_gpio_power, "p54spi power");
+       if (ret < 0) {
+               dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
+               goto err_free_common;
+       }
+
+       ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
+       if (ret < 0) {
+               dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
+               goto err_free_common;
+       }
+
+       gpio_direction_output(p54spi_gpio_power, 0);
+       gpio_direction_input(p54spi_gpio_irq);
+
+       ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
+                         p54spi_interrupt, IRQF_DISABLED, "p54spi",
+                         priv->spi);
+       if (ret < 0) {
+               dev_err(&priv->spi->dev, "request_irq() failed");
+               goto err_free_common;
+       }
+
+       set_irq_type(gpio_to_irq(p54spi_gpio_irq),
+                    IRQ_TYPE_EDGE_RISING);
+
+       disable_irq(gpio_to_irq(p54spi_gpio_irq));
+
+       INIT_WORK(&priv->work, p54spi_work);
+       init_completion(&priv->fw_comp);
+       INIT_LIST_HEAD(&priv->tx_pending);
+       mutex_init(&priv->mutex);
+       SET_IEEE80211_DEV(hw, &spi->dev);
+       priv->common.open = p54spi_op_start;
+       priv->common.stop = p54spi_op_stop;
+       priv->common.tx = p54spi_op_tx;
+
+       ret = p54spi_request_firmware(hw);
+       if (ret < 0)
+               goto err_free_common;
+
+       ret = p54spi_request_eeprom(hw);
+       if (ret)
+               goto err_free_common;
+
+       ret = ieee80211_register_hw(hw);
+       if (ret) {
+               dev_err(&priv->spi->dev, "unable to register "
+                                        "mac80211 hw: %d", ret);
+               goto err_free_common;
+       }
+
+       dev_info(&priv->spi->dev, "device is bound to %s\n",
+                wiphy_name(hw->wiphy));
+       return 0;
+
+err_free_common:
+       p54_free_common(priv->hw);
+       return ret;
+}
+
+static int __devexit p54spi_remove(struct spi_device *spi)
+{
+       struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
+
+       ieee80211_unregister_hw(priv->hw);
+
+       free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+
+       gpio_free(p54spi_gpio_power);
+       gpio_free(p54spi_gpio_irq);
+       release_firmware(priv->firmware);
+
+       mutex_destroy(&priv->mutex);
+
+       p54_free_common(priv->hw);
+       ieee80211_free_hw(priv->hw);
+
+       return 0;
+}
+
+
+static struct spi_driver p54spi_driver = {
+       .driver = {
+               /* use cx3110x name because board-n800.c uses that for the
+                * SPI port */
+               .name           = "cx3110x",
+               .bus            = &spi_bus_type,
+               .owner          = THIS_MODULE,
+       },
+
+       .probe          = p54spi_probe,
+       .remove         = __devexit_p(p54spi_remove),
+};
+
+static int __init p54spi_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&p54spi_driver);
+       if (ret < 0) {
+               printk(KERN_ERR "failed to register SPI driver: %d", ret);
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+static void __exit p54spi_exit(void)
+{
+       spi_unregister_driver(&p54spi_driver);
+}
+
+module_init(p54spi_init);
+module_exit(p54spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
diff --git a/drivers/net/wireless/p54/p54spi.h b/drivers/net/wireless/p54/p54spi.h
new file mode 100644 (file)
index 0000000..7fbe8d8
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008 Christian Lamparter <chunkeey@web.de>
+ *
+ * This driver is a port from stlc45xx:
+ *     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 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef P54SPI_H
+#define P54SPI_H
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <net/mac80211.h>
+
+#include "p54.h"
+
+/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */
+#define SPI_ADRS_READ_BIT_15           0x8000
+
+#define SPI_ADRS_ARM_INTERRUPTS                0x00
+#define SPI_ADRS_ARM_INT_EN            0x04
+
+#define SPI_ADRS_HOST_INTERRUPTS       0x08
+#define SPI_ADRS_HOST_INT_EN           0x0c
+#define SPI_ADRS_HOST_INT_ACK          0x10
+
+#define SPI_ADRS_GEN_PURP_1            0x14
+#define SPI_ADRS_GEN_PURP_2            0x18
+
+#define SPI_ADRS_DEV_CTRL_STAT         0x26    /* high word */
+
+#define SPI_ADRS_DMA_DATA              0x28
+
+#define SPI_ADRS_DMA_WRITE_CTRL                0x2c
+#define SPI_ADRS_DMA_WRITE_LEN         0x2e
+#define SPI_ADRS_DMA_WRITE_BASE                0x30
+
+#define SPI_ADRS_DMA_READ_CTRL         0x34
+#define SPI_ADRS_DMA_READ_LEN          0x36
+#define SPI_ADRS_DMA_READ_BASE         0x38
+
+#define SPI_CTRL_STAT_HOST_OVERRIDE    0x8000
+#define SPI_CTRL_STAT_START_HALTED     0x4000
+#define SPI_CTRL_STAT_RAM_BOOT         0x2000
+#define SPI_CTRL_STAT_HOST_RESET       0x1000
+#define SPI_CTRL_STAT_HOST_CPU_EN      0x0800
+
+#define SPI_DMA_WRITE_CTRL_ENABLE      0x0001
+#define SPI_DMA_READ_CTRL_ENABLE       0x0001
+#define HOST_ALLOWED                   (1 << 7)
+
+#define SPI_TIMEOUT                    100         /* msec */
+
+#define SPI_MAX_TX_PACKETS             32
+
+#define SPI_MAX_PACKET_SIZE            32767
+
+#define SPI_TARGET_INT_WAKEUP          0x00000001
+#define SPI_TARGET_INT_SLEEP           0x00000002
+#define SPI_TARGET_INT_RDDONE          0x00000004
+
+#define SPI_TARGET_INT_CTS             0x00004000
+#define SPI_TARGET_INT_DR              0x00008000
+
+#define SPI_HOST_INT_READY             0x00000001
+#define SPI_HOST_INT_WR_READY          0x00000002
+#define SPI_HOST_INT_SW_UPDATE         0x00000004
+#define SPI_HOST_INT_UPDATE            0x10000000
+
+/* clear to send */
+#define SPI_HOST_INT_CR                        0x00004000
+
+/* data ready */
+#define SPI_HOST_INT_DR                        0x00008000
+
+#define SPI_HOST_INTS_DEFAULT                                              \
+       (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)
+
+#define TARGET_BOOT_SLEEP 50
+
+struct p54s_dma_regs {
+       __le16 cmd;
+       __le16 len;
+       __le32 addr;
+} __attribute__ ((packed));
+
+struct p54s_tx_info {
+       struct list_head tx_list;
+};
+
+struct p54s_priv {
+       /* p54_common has to be the first entry */
+       struct p54_common common;
+       struct ieee80211_hw *hw;
+       struct spi_device *spi;
+
+       struct work_struct work;
+
+       struct mutex mutex;
+       struct completion fw_comp;
+
+       spinlock_t tx_lock;
+
+       /* protected by tx_lock */
+       struct list_head tx_pending;
+
+       enum fw_state fw_state;
+       const struct firmware *firmware;
+};
+
+#endif /* P54SPI_H */
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h
new file mode 100644 (file)
index 0000000..1ea1050
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2003 Conexant Americas Inc. All Rights Reserved.
+ * Copyright (C) 2004, 2005, 2006 Nokia Corporation
+ * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008 Christian Lamparter <chunkeey@web.de>
+ *
+ * based on:
+ *  - cx3110x's pda.h from Nokia
+ *  - cx3110-transfer.log by Johannes Berg
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef P54SPI_EEPROM_H
+#define P54SPI_EEPROM_H
+
+static unsigned char p54spi_eeprom[] = {
+
+/* struct eeprom_pda_wrap */
+0x47, 0x4d, 0x55, 0xaa,        /* magic */
+0x00, 0x00,            /* pad */
+0x00, 0x00,            /* eeprom_pda_data_wrap length */
+0x00, 0x00, 0x00, 0x00,        /* arm opcode */
+
+/* bogus MAC address */
+0x04, 0x00, 0x01, 0x01,                /* PDR_MAC_ADDRESS */
+       0x00, 0x02, 0xee, 0xc0, 0xff, 0xee,
+
+/* struct bootrec_exp_if */
+0x06, 0x00, 0x01, 0x10,                /* PDR_INTERFACE_LIST */
+       0x00, 0x00,                     /* role */
+       0x0f, 0x00,                     /* if_id */
+       0x85, 0x00,                     /* variant = Longbow RF, 2GHz */
+       0x01, 0x00,                     /* btm_compat */
+       0x1f, 0x00,                     /* top_compat */
+
+0x03, 0x00, 0x02, 0x10,                /* PDR_HARDWARE_PLATFORM_COMPONENT_ID */
+       0x03, 0x20, 0x00, 0x43,
+
+/* struct pda_country[6] */
+0x0d, 0x00, 0x07, 0x10,                /* PDR_COUNTRY_LIST */
+       0x10, 0x00, 0x00, 0x00,
+       0x20, 0x00, 0x00, 0x00,
+       0x30, 0x00, 0x00, 0x00,
+       0x31, 0x00, 0x00, 0x00,
+       0x32, 0x00, 0x00, 0x00,
+       0x40, 0x00, 0x00, 0x00,
+
+/* struct pda_country */
+0x03, 0x00, 0x08, 0x10,                /* PDR_DEFAULT_COUNTRY */
+       0x30, 0x00, 0x00, 0x00,         /* ETSI */
+
+0x03, 0x00, 0x00, 0x11,                /* PDR_ANTENNA_GAIN */
+       0x08, 0x08, 0x08, 0x08,
+
+0x09, 0x00, 0xad, 0xde,                /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */
+       0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+/* struct pda_custom_wrapper */
+0x10, 0x06, 0x5d, 0xb0,                /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */
+       0x0d, 0x00, 0xee, 0x00,         /* 13 entries, 238 bytes per entry */
+       0x00, 0x00, 0x16, 0x0c,         /* no offset, 3094 total len */
+               /* 2412 MHz */
+               0x6c, 0x09,
+                       0x10, 0x01, 0x9a, 0x84,
+                               0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a,
+                               0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6,
+                               0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6,
+                       0xf0, 0x00, 0x94, 0x6c,
+                               0x99, 0x82, 0x99, 0x82, 0x99, 0x82, 0x99, 0x82,
+                               0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae,
+                               0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae,
+                       0xd0, 0x00, 0xaa, 0x5a,
+                               0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a,
+                               0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6,
+                               0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6,
+                       0xa0, 0x00, 0xf3, 0x47,
+                               0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e,
+                               0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a,
+                               0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a,
+                       0x50, 0x00, 0x59, 0x36,
+                               0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a,
+                               0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85,
+                               0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85,
+                       0x00, 0x00, 0xe4, 0x2d,
+                               0x18, 0x46, 0x18, 0x46, 0x18, 0x46, 0x18, 0x46,
+                               0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71,
+                               0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2417 MHz */
+               0x71, 0x09,
+                       0x10, 0x01, 0xb9, 0x83,
+                               0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a,
+                               0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6,
+                               0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6,
+                       0xf0, 0x00, 0x2e, 0x6c,
+                               0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82,
+                               0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad,
+                               0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad,
+                       0xd0, 0x00, 0x8d, 0x5a,
+                               0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a,
+                               0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5,
+                               0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5,
+                       0xa0, 0x00, 0x0a, 0x48,
+                               0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e,
+                               0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99,
+                               0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99,
+                       0x50, 0x00, 0x7c, 0x36,
+                               0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59,
+                               0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85,
+                               0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85,
+                       0x00, 0x00, 0xf5, 0x2d,
+                               0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45,
+                               0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71,
+                               0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2422 MHz */
+               0x76, 0x09,
+                       0x10, 0x01, 0xb9, 0x83,
+                               0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a,
+                               0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6,
+                               0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6,
+                       0xf0, 0x00, 0x2e, 0x6c,
+                               0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82,
+                               0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad,
+                               0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad,
+                       0xd0, 0x00, 0x8d, 0x5a,
+                               0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a,
+                               0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5,
+                               0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5,
+                       0xa0, 0x00, 0x0a, 0x48,
+                               0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e,
+                               0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99,
+                               0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99,
+                       0x50, 0x00, 0x7c, 0x36,
+                               0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59,
+                               0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85,
+                               0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85,
+                       0x00, 0x00, 0xf5, 0x2d,
+                               0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45,
+                               0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71,
+                               0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2427 MHz */
+               0x7b, 0x09,
+                       0x10, 0x01, 0x48, 0x83,
+                               0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a,
+                               0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5,
+                               0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5,
+                       0xf0, 0x00, 0xfb, 0x6b,
+                               0x50, 0x82, 0x50, 0x82, 0x50, 0x82, 0x50, 0x82,
+                               0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad,
+                               0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad,
+                       0xd0, 0x00, 0x7e, 0x5a,
+                               0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a,
+                               0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5,
+                               0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5,
+                       0xa0, 0x00, 0x15, 0x48,
+                               0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e,
+                               0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99,
+                               0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99,
+                       0x50, 0x00, 0x8e, 0x36,
+                               0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59,
+                               0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85,
+                               0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85,
+                       0x00, 0x00, 0xfe, 0x2d,
+                               0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45,
+                               0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71,
+                               0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2432 MHz */
+               0x80, 0x09,
+                       0x10, 0x01, 0xd7, 0x82,
+                               0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a,
+                               0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5,
+                               0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5,
+                       0xf0, 0x00, 0xc8, 0x6b,
+                               0x37, 0x82, 0x37, 0x82, 0x37, 0x82, 0x37, 0x82,
+                               0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad,
+                               0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad,
+                       0xd0, 0x00, 0x6f, 0x5a,
+                               0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a,
+                               0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5,
+                               0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5,
+                       0xa0, 0x00, 0x20, 0x48,
+                               0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d,
+                               0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99,
+                               0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99,
+                       0x50, 0x00, 0x9f, 0x36,
+                               0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59,
+                               0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85,
+                               0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85,
+                       0x00, 0x00, 0x06, 0x2e,
+                               0x74, 0x45, 0x74, 0x45, 0x74, 0x45, 0x74, 0x45,
+                               0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71,
+                               0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2437 MHz */
+               0x85, 0x09,
+                       0x10, 0x01, 0x67, 0x82,
+                               0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a,
+                               0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5,
+                               0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5,
+                       0xf0, 0x00, 0x95, 0x6b,
+                               0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82,
+                               0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad,
+                               0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad,
+                       0xd0, 0x00, 0x61, 0x5a,
+                               0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a,
+                               0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5,
+                               0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5,
+                       0xa0, 0x00, 0x2c, 0x48,
+                               0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d,
+                               0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99,
+                               0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99,
+                       0x50, 0x00, 0xb1, 0x36,
+                               0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59,
+                               0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85,
+                               0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85,
+                       0x00, 0x00, 0x0f, 0x2e,
+                               0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45,
+                               0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70,
+                               0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2442 MHz */
+               0x8a, 0x09,
+                       0x10, 0x01, 0xf6, 0x81,
+                               0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a,
+                               0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5,
+                               0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5,
+                       0xf0, 0x00, 0x62, 0x6b,
+                               0x06, 0x82, 0x06, 0x82, 0x06, 0x82, 0x06, 0x82,
+                               0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad,
+                               0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad,
+                       0xd0, 0x00, 0x52, 0x5a,
+                               0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79,
+                               0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5,
+                               0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5,
+                       0xa0, 0x00, 0x37, 0x48,
+                               0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d,
+                               0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99,
+                               0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99,
+                       0x50, 0x00, 0xc2, 0x36,
+                               0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59,
+                               0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85,
+                               0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85,
+                       0x00, 0x00, 0x17, 0x2e,
+                               0x22, 0x45, 0x22, 0x45, 0x22, 0x45, 0x22, 0x45,
+                               0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70,
+                               0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2447 MHz */
+               0x8f, 0x09,
+                       0x10, 0x01, 0x75, 0x83,
+                               0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a,
+                               0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5,
+                               0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5,
+                       0xf0, 0x00, 0x4b, 0x6c,
+                               0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82,
+                               0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad,
+                               0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad,
+                       0xd0, 0x00, 0xda, 0x5a,
+                               0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a,
+                               0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5,
+                               0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5,
+                       0xa0, 0x00, 0x6d, 0x48,
+                               0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d,
+                               0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99,
+                               0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99,
+                       0x50, 0x00, 0xc6, 0x36,
+                               0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59,
+                               0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85,
+                               0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85,
+                       0x00, 0x00, 0x15, 0x2e,
+                               0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45,
+                               0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70,
+                               0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2452 MHz */
+               0x94, 0x09,
+                       0x10, 0x01, 0xf4, 0x84,
+                               0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a,
+                               0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6,
+                               0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6,
+                       0xf0, 0x00, 0x34, 0x6d,
+                               0x77, 0x82, 0x77, 0x82, 0x77, 0x82, 0x77, 0x82,
+                               0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae,
+                               0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae,
+                       0xd0, 0x00, 0x62, 0x5b,
+                               0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a,
+                               0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5,
+                               0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5,
+                       0xa0, 0x00, 0xa2, 0x48,
+                               0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e,
+                               0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99,
+                               0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99,
+                       0x50, 0x00, 0xc9, 0x36,
+                               0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59,
+                               0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85,
+                               0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85,
+                       0x00, 0x00, 0x12, 0x2e,
+                               0x57, 0x45, 0x57, 0x45, 0x57, 0x45, 0x57, 0x45,
+                               0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70,
+                               0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2452 MHz */
+               0x99, 0x09,
+                       0x10, 0x01, 0x74, 0x86,
+                               0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a,
+                               0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6,
+                               0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6,
+                       0xf0, 0x00, 0x1e, 0x6e,
+                               0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82,
+                               0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae,
+                               0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae,
+                       0xd0, 0x00, 0xeb, 0x5b,
+                               0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a,
+                               0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6,
+                               0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6,
+                       0xa0, 0x00, 0xd8, 0x48,
+                               0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e,
+                               0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99,
+                               0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99,
+                       0x50, 0x00, 0xcd, 0x36,
+                               0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59,
+                               0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85,
+                               0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85,
+                       0x00, 0x00, 0x10, 0x2e,
+                               0x71, 0x45, 0x71, 0x45, 0x71, 0x45, 0x71, 0x45,
+                               0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71,
+                               0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2557 MHz */
+               0x9e, 0x09,
+                       0x10, 0x01, 0xf3, 0x87,
+                               0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b,
+                               0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6,
+                               0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6,
+                       0xf0, 0x00, 0x07, 0x6f,
+                               0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82,
+                               0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae,
+                               0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae,
+                       0xd0, 0x00, 0x73, 0x5c,
+                               0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a,
+                               0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6,
+                               0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6,
+                       0xa0, 0x00, 0x0d, 0x49,
+                               0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e,
+                               0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a,
+                               0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a,
+                       0x50, 0x00, 0xd1, 0x36,
+                               0xff, 0x59, 0xff, 0x59, 0xff, 0x59, 0xff, 0x59,
+                               0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85,
+                               0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85,
+                       0x00, 0x00, 0x0e, 0x2e,
+                               0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45,
+                               0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71,
+                               0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2562 MHz */
+               0xa3, 0x09,
+                       0x10, 0x01, 0x72, 0x89,
+                               0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b,
+                               0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6,
+                               0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6,
+                       0xf0, 0x00, 0xf0, 0x6f,
+                               0x21, 0x83, 0x21, 0x83, 0x21, 0x83, 0x21, 0x83,
+                               0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae,
+                               0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae,
+                       0xd0, 0x00, 0xfb, 0x5c,
+                               0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a,
+                               0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6,
+                               0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6,
+                       0xa0, 0x00, 0x43, 0x49,
+                               0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e,
+                               0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a,
+                               0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a,
+                       0x50, 0x00, 0xd4, 0x36,
+                               0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a,
+                               0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85,
+                               0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85,
+                       0x00, 0x00, 0x0b, 0x2e,
+                               0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45,
+                               0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71,
+                               0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+               /* 2572 MHz */
+               0xa8, 0x09,
+                       0x10, 0x01, 0xf1, 0x8a,
+                               0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b,
+                               0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7,
+                               0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7,
+                       0xf0, 0x00, 0xd9, 0x70,
+                               0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83,
+                               0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae,
+                               0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae,
+                       0xd0, 0x00, 0x83, 0x5d,
+                               0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b,
+                               0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6,
+                               0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6,
+                       0xa0, 0x00, 0x78, 0x49,
+                               0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e,
+                               0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a,
+                               0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a,
+                       0x50, 0x00, 0xd8, 0x36,
+                               0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a,
+                               0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85,
+                               0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85,
+                       0x00, 0x00, 0x09, 0x2e,
+                               0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45,
+                               0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71,
+                               0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x80, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
+
+/*
+ * Not really sure if this is actually the power_limit database,
+ * it looks a bit "related" to PDR_PRISM_ZIF_TX_IQ_CALIBRATION
+ */
+/* struct pda_custom_wrapper */
+0xae, 0x00, 0xef, 0xbe,      /* PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM */
+       0x0d, 0x00, 0x1a, 0x00,         /* 13 entries, 26 bytes per entry */
+       0x00, 0x00, 0x52, 0x01,         /* no offset, 338 bytes total */
+
+               /* 2412 MHz */
+               0x6c, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2417 MHz */
+               0x71, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2422 MHz */
+               0x76, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2427 MHz */
+               0x7b, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2432 MHz */
+               0x80, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2437 MHz */
+               0x85, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2442 MHz */
+               0x8a, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2447 MHz */
+               0x8f, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2452 MHz */
+               0x94, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2457 MHz */
+               0x99, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2462 MHz */
+               0x9e, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2467 MHz */
+               0xa3, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+               /* 2472 MHz */
+               0xa8, 0x09,
+                       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+                       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
+                       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
+
+/* struct pda_iq_autocal_entry[13] */
+0x42, 0x00, 0x06, 0x19,                /* PDR_PRISM_ZIF_TX_IQ_CALIBRATION */
+       /* 2412 MHz */
+       0x6c, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2417 MHz */
+       0x71, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2422 MHz */
+       0x76, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2427 MHz */
+       0x7b, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2432 MHz */
+       0x80, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2437 MHz */
+       0x85, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2442 MHz */
+       0x8a, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2447 MHz */
+       0x8f, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2452 MHz */
+       0x94, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00,
+       /* 2457 MHz */
+       0x99, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
+       /* 2462 MHz */
+       0x9e, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
+       /* 2467 MHz */
+       0xa3, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
+       /* 2472 MHz */
+       0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
+
+0x02, 0x00, 0x00, 0x00,                /* PDR_END */
+       0xa8, 0xf5                      /* bogus data */
+};
+
+#endif /* P54SPI_EEPROM_H */
+
index 5de2ebfb28c7ef9b722c3a4028a2c6e5c7c25497..9539ddcf379ff08cedc0a2b93daf05594a97f425 100644 (file)
@@ -424,9 +424,46 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
                            data, len, &alen, 2000);
 }
 
+static const char p54u_romboot_3887[] = "~~~~";
+static const char p54u_firmware_upload_3887[] = "<\r";
+
+static int p54u_device_reset_3887(struct ieee80211_hw *dev)
+{
+       struct p54u_priv *priv = dev->priv;
+       int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
+       u8 buf[4];
+
+       if (lock) {
+               ret = usb_lock_device_for_reset(priv->udev, priv->intf);
+               if (ret < 0) {
+                       dev_err(&priv->udev->dev, "(p54usb) unable to lock "
+                               " device for reset: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = usb_reset_device(priv->udev);
+       if (lock)
+               usb_unlock_device(priv->udev);
+
+       if (ret) {
+               dev_err(&priv->udev->dev, "(p54usb) unable to reset "
+                       "device: %d\n", ret);
+               return ret;
+       }
+
+       memcpy(&buf, p54u_romboot_3887, sizeof(buf));
+       ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
+                           buf, sizeof(buf));
+       if (ret)
+               dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
+                       "boot ROM: %d\n", ret);
+
+       return ret;
+}
+
 static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
 {
-       static char start_string[] = "~~~~<\r";
        struct p54u_priv *priv = dev->priv;
        const struct firmware *fw_entry = NULL;
        int err, alen;
@@ -445,12 +482,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
                goto err_bufalloc;
        }
 
-       memcpy(buf, start_string, 4);
-       err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
-       if (err) {
-               dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
+       err = p54u_device_reset_3887(dev);
+       if (err)
                goto err_reset;
-       }
 
        err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
        if (err) {
@@ -466,15 +500,22 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
        if (err)
                goto err_upload_failed;
 
+       if (priv->common.fw_interface != FW_LM87) {
+               dev_err(&priv->udev->dev, "wrong firmware, "
+                       "please get a LM87 firmware and try again.\n");
+               err = -EINVAL;
+               goto err_upload_failed;
+       }
+
        left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
-       strcpy(buf, start_string);
-       left -= strlen(start_string);
-       tmp += strlen(start_string);
+       strcpy(buf, p54u_firmware_upload_3887);
+       left -= strlen(p54u_firmware_upload_3887);
+       tmp += strlen(p54u_firmware_upload_3887);
 
        data = fw_entry->data;
        remains = fw_entry->size;
 
-       hdr = (struct x2_header *)(buf + strlen(start_string));
+       hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
        memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
        hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
        hdr->fw_length = cpu_to_le32(fw_entry->size);
@@ -616,6 +657,14 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
                return err;
        }
 
+       if (priv->common.fw_interface != FW_LM86) {
+               dev_err(&priv->udev->dev, "wrong firmware, "
+                       "please get a LM86(USB) firmware and try again.\n");
+               kfree(buf);
+               release_firmware(fw_entry);
+               return -EINVAL;
+       }
+
 #define P54U_WRITE(type, addr, data) \
        do {\
                err = p54u_write(priv, buf, type,\
@@ -876,6 +925,9 @@ static int __devinit p54u_probe(struct usb_interface *intf,
        SET_IEEE80211_DEV(dev, &intf->dev);
        usb_set_intfdata(intf, dev);
        priv->udev = udev;
+       priv->intf = intf;
+       skb_queue_head_init(&priv->rx_queue);
+       init_usb_anchor(&priv->submitted);
 
        usb_get_dev(udev);
 
@@ -918,9 +970,6 @@ static int __devinit p54u_probe(struct usb_interface *intf,
        if (err)
                goto err_free_dev;
 
-       skb_queue_head_init(&priv->rx_queue);
-       init_usb_anchor(&priv->submitted);
-
        p54u_open(dev);
        err = p54_read_eeprom(dev);
        p54u_stop(dev);
@@ -958,11 +1007,23 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
        ieee80211_free_hw(dev);
 }
 
+static int p54u_pre_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int p54u_post_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
 static struct usb_driver p54u_driver = {
        .name   = "p54usb",
        .id_table = p54u_table,
        .probe = p54u_probe,
        .disconnect = p54u_disconnect,
+       .pre_reset = p54u_pre_reset,
+       .post_reset = p54u_post_reset,
 };
 
 static int __init p54u_init(void)
index 54ee738bf2af66c8503ea549d21ff1797b0de4b7..8bc58982d8dd703ea3478882920dd1adcae68d71 100644 (file)
@@ -126,6 +126,7 @@ struct p54u_rx_info {
 struct p54u_priv {
        struct p54_common common;
        struct usb_device *udev;
+       struct usb_interface *intf;
        enum {
                P54U_NET2280 = 0,
                P54U_3887
index e43bae97ed8f66a6bc9ccb9eeb86a66a6db0302c..88895bd9e495b024847ba2ed221224c79328a454 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
+#include <asm/byteorder.h>
 
 #include "prismcompat.h"
 #include "isl_38xx.h"
@@ -471,8 +472,8 @@ islpci_eth_receive(islpci_private *priv)
                wmb();
 
                /* increment the driver read pointer */
-               add_le32p(&control_block->
-                         driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1);
+               le32_add_cpu(&control_block->
+                            driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1);
        }
 
        /* trigger the device */
index f91a88fc1e35b0023faf78daf85780fafb17f495..87a1734663dac15fb91b5ce599e20970cf3a1d8a 100644 (file)
@@ -85,12 +85,6 @@ extern int pc_debug;
 #define PIMFOR_FLAG_APPLIC_ORIGIN               0x01
 #define PIMFOR_FLAG_LITTLE_ENDIAN               0x02
 
-static inline void
-add_le32p(__le32 * le_number, u32 add)
-{
-       *le_number = cpu_to_le32(le32_to_cpup(le_number) + add);
-}
-
 void display_buffer(char *, int);
 
 /*
index ed93ac41297f036caf6c7cff6d7ad797008007d4..105f214e21f4794f9f89e82c8c9dc373fee653f0 100644 (file)
@@ -369,9 +369,6 @@ struct rndis_wext_private {
 };
 
 
-static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-                               2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-
 static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
 
 static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
@@ -640,8 +637,8 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
 static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
 {
        if (freq->m < 1000 && freq->e == 0) {
-               if (freq->m >= 1 && freq->m <= ARRAY_SIZE(freq_chan))
-                       *dsconfig = freq_chan[freq->m - 1] * 1000;
+               if (freq->m >= 1 && freq->m <= 14)
+                       *dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000;
                else
                        return -1;
        } else {
@@ -1178,11 +1175,11 @@ static int rndis_iw_get_range(struct net_device *dev,
                range->throughput = 11 * 1000 * 1000 / 2;
        }
 
-       range->num_channels = ARRAY_SIZE(freq_chan);
+       range->num_channels = 14;
 
-       for (i = 0; i < ARRAY_SIZE(freq_chan) && i < IW_MAX_FREQUENCIES; i++) {
+       for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) {
                range->freq[i].i = i + 1;
-               range->freq[i].m = freq_chan[i] * 100000;
+               range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
                range->freq[i].e = 1;
        }
        range->num_frequency = i;
index 178b313293b4537a45d3f00f7e6a9b6078802439..bfc5d9cf716e83b52e5c5a5aa749ff1491dfb15f 100644 (file)
@@ -97,10 +97,11 @@ config RT2X00_LIB_CRYPTO
 
 config RT2X00_LIB_RFKILL
        boolean
-       default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n)
+       default y if (RT2X00_LIB=y && INPUT=y) || (RT2X00_LIB=m && INPUT!=n)
+       select INPUT_POLLDEV
 
-comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00"
-       depends on RT2X00_LIB=y && RFKILL=m
+comment "rt2x00 rfkill support disabled due to modularized INPUT and built-in rt2x00"
+       depends on RT2X00_LIB=y && INPUT=m
 
 config RT2X00_LIB_LEDS
        boolean
index 917cb4f3b038948792bd241dc3c1ce3b49e130d2..f22d808d8c511bb8958d1f52268b0db02af3f823 100644 (file)
@@ -2,6 +2,7 @@ rt2x00lib-y                             += rt2x00dev.o
 rt2x00lib-y                            += rt2x00mac.o
 rt2x00lib-y                            += rt2x00config.o
 rt2x00lib-y                            += rt2x00queue.o
+rt2x00lib-y                            += rt2x00link.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)  += rt2x00crypto.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL)  += rt2x00rfkill.o
index 6a977679124d549a954eb78a27b89b9cf7c304c3..4a2c0b971ca8e25c8f276da2e1fdf9a21799811a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -524,6 +524,32 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, CSR12, reg);
 }
 
+static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
+                                  (libconf->conf->beacon_int - 20) * 16);
+               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
 static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
                             struct rt2x00lib_conf *libconf,
                             const unsigned int flags)
@@ -537,6 +563,8 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
                rt2400pci_config_retry_limit(rt2x00dev, libconf);
        if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
                rt2400pci_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2400pci_config_ps(rt2x00dev, libconf);
 }
 
 static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
@@ -572,35 +600,37 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
        qual->false_cca = bbp;
 }
 
-static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                    struct link_qual *qual, u8 vgc_level)
 {
-       rt2400pci_bbp_write(rt2x00dev, 13, 0x08);
-       rt2x00dev->link.vgc_level = 0x08;
+       rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
+       qual->vgc_level = vgc_level;
+       qual->vgc_level_reg = vgc_level;
 }
 
-static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
 {
-       u8 reg;
+       rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
+}
 
+static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual, const u32 count)
+{
        /*
         * The link tuner should not run longer then 60 seconds,
         * and should run once every 2 seconds.
         */
-       if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1))
+       if (count > 60 || !(count & 1))
                return;
 
        /*
         * Base r13 link tuning on the false cca count.
         */
-       rt2400pci_bbp_read(rt2x00dev, 13, &reg);
-
-       if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) {
-               rt2400pci_bbp_write(rt2x00dev, 13, ++reg);
-               rt2x00dev->link.vgc_level = reg;
-       } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) {
-               rt2400pci_bbp_write(rt2x00dev, 13, --reg);
-               rt2x00dev->link.vgc_level = reg;
-       }
+       if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
+               rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+       else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
+               rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
 }
 
 /*
@@ -1365,7 +1395,9 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
 
        rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY)
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
                rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
                                   LED_TYPE_ACTIVITY);
 #endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -1419,7 +1451,9 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
         * Initialize all hw fields.
         */
        rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                              IEEE80211_HW_SIGNAL_DBM;
+                              IEEE80211_HW_SIGNAL_DBM |
+                              IEEE80211_HW_SUPPORTS_PS |
+                              IEEE80211_HW_PS_NULLFUNC_STACK;
        rt2x00dev->hw->extra_tx_headroom = 0;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
index 9aefda4ab3c263c4163543fff32a7853b8139ec8..72ac31c3cb759db0672024cdbfec2248ceaa9db4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index d3bc218ec85cc2debcd5dfd52e8c00fcdf4124bf..b9104e28bc2eced9ef61a22e298c7ed7ffa890e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -573,6 +573,32 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, CSR12, reg);
 }
 
+static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
+                                  (libconf->conf->beacon_int - 20) * 16);
+               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
 static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
                             struct rt2x00lib_conf *libconf,
                             const unsigned int flags)
@@ -588,6 +614,8 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
                rt2500pci_config_retry_limit(rt2x00dev, libconf);
        if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
                rt2500pci_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2500pci_config_ps(rt2x00dev, libconf);
 }
 
 /*
@@ -611,29 +639,33 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
        qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
 }
 
-static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                    struct link_qual *qual, u8 vgc_level)
 {
-       rt2500pci_bbp_write(rt2x00dev, 17, 0x48);
-       rt2x00dev->link.vgc_level = 0x48;
+       if (qual->vgc_level_reg != vgc_level) {
+               rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level_reg = vgc_level;
+       }
 }
 
-static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
 {
-       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-       u8 r17;
+       rt2500pci_set_vgc(rt2x00dev, qual, 0x48);
+}
 
+static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual, const u32 count)
+{
        /*
         * To prevent collisions with MAC ASIC on chipsets
         * up to version C the link tuning should halt after 20
         * seconds while being associated.
         */
        if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
-           rt2x00dev->intf_associated &&
-           rt2x00dev->link.count > 20)
+           rt2x00dev->intf_associated && count > 20)
                return;
 
-       rt2500pci_bbp_read(rt2x00dev, 17, &r17);
-
        /*
         * Chipset versions C and lower should directly continue
         * to the dynamic CCA tuning. Chipset version D and higher
@@ -649,29 +681,25 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
         * then corrupt the R17 tuning. To remidy this the tuning should
         * be stopped (While making sure the R17 value will not exceed limits)
         */
-       if (rssi < -80 && rt2x00dev->link.count > 20) {
-               if (r17 >= 0x41) {
-                       r17 = rt2x00dev->link.vgc_level;
-                       rt2500pci_bbp_write(rt2x00dev, 17, r17);
-               }
+       if (qual->rssi < -80 && count > 20) {
+               if (qual->vgc_level_reg >= 0x41)
+                       rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
                return;
        }
 
        /*
         * Special big-R17 for short distance
         */
-       if (rssi >= -58) {
-               if (r17 != 0x50)
-                       rt2500pci_bbp_write(rt2x00dev, 17, 0x50);
+       if (qual->rssi >= -58) {
+               rt2500pci_set_vgc(rt2x00dev, qual, 0x50);
                return;
        }
 
        /*
         * Special mid-R17 for middle distance
         */
-       if (rssi >= -74) {
-               if (r17 != 0x41)
-                       rt2500pci_bbp_write(rt2x00dev, 17, 0x41);
+       if (qual->rssi >= -74) {
+               rt2500pci_set_vgc(rt2x00dev, qual, 0x41);
                return;
        }
 
@@ -679,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
         * Leave short or middle distance condition, restore r17
         * to the dynamic tuning range.
         */
-       if (r17 >= 0x41) {
-               rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.vgc_level);
+       if (qual->vgc_level_reg >= 0x41) {
+               rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
                return;
        }
 
@@ -690,12 +718,12 @@ dynamic_cca_tune:
         * R17 is inside the dynamic tuning range,
         * start tuning the link based on the false cca counter.
         */
-       if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) {
-               rt2500pci_bbp_write(rt2x00dev, 17, ++r17);
-               rt2x00dev->link.vgc_level = r17;
-       } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) {
-               rt2500pci_bbp_write(rt2x00dev, 17, --r17);
-               rt2x00dev->link.vgc_level = r17;
+       if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) {
+               rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg);
+               qual->vgc_level = qual->vgc_level_reg;
+       } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) {
+               rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
+               qual->vgc_level = qual->vgc_level_reg;
        }
 }
 
@@ -1205,7 +1233,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
@@ -1524,7 +1552,9 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
 
        rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY)
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
                rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
                                   LED_TYPE_ACTIVITY);
 #endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -1721,7 +1751,9 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
         * Initialize all hw fields.
         */
        rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                              IEEE80211_HW_SIGNAL_DBM;
+                              IEEE80211_HW_SIGNAL_DBM |
+                              IEEE80211_HW_SUPPORTS_PS |
+                              IEEE80211_HW_PS_NULLFUNC_STACK;
 
        rt2x00dev->hw->extra_tx_headroom = 0;
 
index e135247f7f89d6aae25fefc4bdb7673e54bfc706..17a0c9c8c18468e7592ed341ef9296e46db7711b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index af6b5847be5ce4362a5c4256ad64d35238d9433b..c526e737fcadd533232b6192c893c67475fca534 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -280,6 +280,18 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
 };
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u16 reg;
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       return rt2x00_get_field32(reg, MAC_CSR19_BIT7);
+}
+#else
+#define rt2500usb_rfkill_poll  NULL
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
 #ifdef CONFIG_RT2X00_LIB_LEDS
 static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
                                     enum led_brightness brightness)
@@ -634,6 +646,32 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
        rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 }
 
+static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u16 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
+                                  libconf->conf->beacon_int - 20);
+               rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
 static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
                             struct rt2x00lib_conf *libconf,
                             const unsigned int flags)
@@ -647,6 +685,8 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
                                         libconf->conf->power_level);
        if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
                rt2500usb_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2500usb_config_ps(rt2x00dev, libconf);
 }
 
 /*
@@ -670,7 +710,8 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
        qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
 }
 
-static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
 {
        u16 eeprom;
        u16 value;
@@ -691,7 +732,7 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
        value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
        rt2500usb_bbp_write(rt2x00dev, 17, value);
 
-       rt2x00dev->link.vgc_level = value;
+       qual->vgc_level = value;
 }
 
 /*
@@ -1176,7 +1217,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
        rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
                           test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
@@ -1562,11 +1603,21 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
 
        rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY)
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
                rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
                                   LED_TYPE_ACTIVITY);
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
        /*
         * Check if the BBP tuning should be disabled.
         */
@@ -1752,7 +1803,9 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        rt2x00dev->hw->flags =
            IEEE80211_HW_RX_INCLUDES_FCS |
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-           IEEE80211_HW_SIGNAL_DBM;
+           IEEE80211_HW_SIGNAL_DBM |
+           IEEE80211_HW_SUPPORTS_PS |
+           IEEE80211_HW_PS_NULLFUNC_STACK;
 
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 
@@ -1839,7 +1892,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        __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(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
        }
        __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags);
 
@@ -1873,6 +1926,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .uninitialize           = rt2x00usb_uninitialize,
        .clear_entry            = rt2x00usb_clear_entry,
        .set_device_state       = rt2500usb_set_device_state,
+       .rfkill_poll            = rt2500usb_rfkill_poll,
        .link_stats             = rt2500usb_link_stats,
        .reset_tuner            = rt2500usb_reset_tuner,
        .link_tuner             = rt2500usb_link_tuner,
index 4347dfdabcd4f0525a1e9f2cbed5457848cf1d2b..afce0e0322c3e5a74438c742ee319b683bccb7d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
  * MAC_CSR19: GPIO control register.
  */
 #define MAC_CSR19                      0x0426
+#define MAC_CSR19_BIT0                 FIELD32(0x0001)
+#define MAC_CSR19_BIT1                 FIELD32(0x0002)
+#define MAC_CSR19_BIT2                 FIELD32(0x0004)
+#define MAC_CSR19_BIT3                 FIELD32(0x0008)
+#define MAC_CSR19_BIT4                 FIELD32(0x0010)
+#define MAC_CSR19_BIT5                 FIELD32(0x0020)
+#define MAC_CSR19_BIT6                 FIELD32(0x0040)
+#define MAC_CSR19_BIT7                 FIELD32(0x0080)
 
 /*
  * MAC_CSR20: LED control register.
index 39ecf3b82ca1ca0b6895be3eb266c883b9e2e42f..d0a825638188a4bed970073427914164b19121a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -33,6 +33,7 @@
 #include <linux/leds.h>
 #include <linux/mutex.h>
 #include <linux/etherdevice.h>
+#include <linux/input-polldev.h>
 
 #include <net/mac80211.h>
 
@@ -44,7 +45,7 @@
 /*
  * Module information.
  */
-#define DRV_VERSION    "2.2.3"
+#define DRV_VERSION    "2.3.0"
 #define DRV_PROJECT    "http://rt2x00.serialmonkey.com"
 
 /*
@@ -177,52 +178,41 @@ struct antenna_setup {
  */
 struct link_qual {
        /*
-        * Statistics required for Link tuning.
-        * For the average RSSI value we use the "Walking average" approach.
-        * When adding RSSI to the average value the following calculation
-        * is needed:
-        *
-        *        avg_rssi = ((avg_rssi * 7) + rssi) / 8;
-        *
-        * The advantage of this approach is that we only need 1 variable
-        * to store the average in (No need for a count and a total).
-        * But more importantly, normal average values will over time
-        * move less and less towards newly added values this results
-        * that with link tuning, the device can have a very good RSSI
-        * for a few minutes but when the device is moved away from the AP
-        * the average will not decrease fast enough to compensate.
-        * The walking average compensates this and will move towards
-        * the new values correctly allowing a effective link tuning.
+        * Statistics required for Link tuning by driver
+        * The rssi value is provided by rt2x00lib during the
+        * link_tuner() callback function.
+        * The false_cca field is filled during the link_stats()
+        * callback function and could be used during the
+        * link_tuner() callback function.
         */
-       int avg_rssi;
+       int rssi;
        int false_cca;
 
        /*
-        * Statistics required for Signal quality calculation.
-        * For calculating the Signal quality we have to determine
-        * the total number of success and failed RX and TX frames.
-        * After that we also use the average RSSI value to help
-        * determining the signal quality.
-        * For the calculation we will use the following algorithm:
-        *
-        *         rssi_percentage = (avg_rssi * 100) / rssi_offset
-        *         rx_percentage = (rx_success * 100) / rx_total
-        *         tx_percentage = (tx_success * 100) / tx_total
-        *         avg_signal = ((WEIGHT_RSSI * avg_rssi) +
-        *                       (WEIGHT_TX * tx_percentage) +
-        *                       (WEIGHT_RX * rx_percentage)) / 100
+        * VGC levels
+        * Hardware driver will tune the VGC level during each call
+        * to the link_tuner() callback function. This vgc_level is
+        * is determined based on the link quality statistics like
+        * average RSSI and the false CCA count.
         *
-        * This value should then be checked to not be greated then 100.
+        * In some cases the drivers need to differentiate between
+        * the currently "desired" VGC level and the level configured
+        * in the hardware. The latter is important to reduce the
+        * number of BBP register reads to reduce register access
+        * overhead. For this reason we store both values here.
+        */
+       u8 vgc_level;
+       u8 vgc_level_reg;
+
+       /*
+        * Statistics required for Signal quality calculation.
+        * These fields might be changed during the link_stats()
+        * callback function.
         */
-       int rx_percentage;
        int rx_success;
        int rx_failed;
-       int tx_percentage;
        int tx_success;
        int tx_failed;
-#define WEIGHT_RSSI    20
-#define WEIGHT_RX      40
-#define WEIGHT_TX      40
 };
 
 /*
@@ -286,9 +276,16 @@ struct link {
        struct link_ant ant;
 
        /*
-        * Active VGC level
+        * Currently active average RSSI value
+        */
+       int avg_rssi;
+
+       /*
+        * Currently precalculated percentages of successful
+        * TX and RX frames.
         */
-       int vgc_level;
+       int rx_percentage;
+       int tx_percentage;
 
        /*
         * Work structure for scheduling periodic link tuning.
@@ -296,55 +293,6 @@ struct link {
        struct delayed_work work;
 };
 
-/*
- * Small helper macro to work with moving/walking averages.
- */
-#define MOVING_AVERAGE(__avg, __val, __samples) \
-       ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
-
-/*
- * When we lack RSSI information return something less then -80 to
- * tell the driver to tune the device to maximum sensitivity.
- */
-#define DEFAULT_RSSI   ( -128 )
-
-/*
- * Link quality access functions.
- */
-static inline int rt2x00_get_link_rssi(struct link *link)
-{
-       if (link->qual.avg_rssi && link->qual.rx_success)
-               return link->qual.avg_rssi;
-       return DEFAULT_RSSI;
-}
-
-static inline int rt2x00_get_link_ant_rssi(struct link *link)
-{
-       if (link->ant.rssi_ant && link->qual.rx_success)
-               return link->ant.rssi_ant;
-       return DEFAULT_RSSI;
-}
-
-static inline void rt2x00_reset_link_ant_rssi(struct link *link)
-{
-       link->ant.rssi_ant = 0;
-}
-
-static inline int rt2x00_get_link_ant_rssi_history(struct link *link,
-                                                  enum antenna ant)
-{
-       if (link->ant.rssi_history[ant - ANTENNA_A])
-               return link->ant.rssi_history[ant - ANTENNA_A];
-       return DEFAULT_RSSI;
-}
-
-static inline int rt2x00_update_ant_rssi(struct link *link, int rssi)
-{
-       int old_rssi = link->ant.rssi_history[link->ant.active.rx - ANTENNA_A];
-       link->ant.rssi_history[link->ant.active.rx - ANTENNA_A] = rssi;
-       return old_rssi;
-}
-
 /*
  * Interface structure
  * Per interface configuration details, this structure
@@ -448,7 +396,7 @@ struct rt2x00lib_erp {
        int ack_timeout;
        int ack_consume_time;
 
-       u64 basic_rates;
+       u32 basic_rates;
 
        int slot_time;
 
@@ -544,8 +492,10 @@ struct rt2x00lib_ops {
        int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev);
        void (*link_stats) (struct rt2x00_dev *rt2x00dev,
                            struct link_qual *qual);
-       void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
-       void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
+       void (*reset_tuner) (struct rt2x00_dev *rt2x00dev,
+                            struct link_qual *qual);
+       void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
+                           struct link_qual *qual, const u32 count);
 
        /*
         * TX control handlers
@@ -625,7 +575,6 @@ enum rt2x00_flags {
        DEVICE_STATE_REGISTERED_HW,
        DEVICE_STATE_INITIALIZED,
        DEVICE_STATE_STARTED,
-       DEVICE_STATE_STARTED_SUSPEND,
        DEVICE_STATE_ENABLED_RADIO,
        DEVICE_STATE_DISABLED_RADIO_HW,
 
@@ -637,6 +586,7 @@ enum rt2x00_flags {
        DRIVER_REQUIRE_ATIM_QUEUE,
        DRIVER_REQUIRE_SCHEDULED,
        DRIVER_REQUIRE_DMA,
+       DRIVER_REQUIRE_COPY_IV,
 
        /*
         * Driver features
@@ -653,7 +603,6 @@ enum rt2x00_flags {
        CONFIG_EXTERNAL_LNA_BG,
        CONFIG_DOUBLE_ANTENNA,
        CONFIG_DISABLE_LINK_TUNING,
-       CONFIG_CRYPTO_COPY_IV,
 };
 
 /*
@@ -689,8 +638,8 @@ struct rt2x00_dev {
        unsigned long rfkill_state;
 #define RFKILL_STATE_ALLOCATED         1
 #define RFKILL_STATE_REGISTERED                2
-       struct rfkill *rfkill;
-       struct delayed_work rfkill_work;
+#define RFKILL_STATE_BLOCKED           3
+       struct input_polled_dev *rfkill_poll_dev;
 #endif /* CONFIG_RT2X00_LIB_RFKILL */
 
        /*
@@ -918,7 +867,7 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)
        return (chipset->rf == chip);
 }
 
-static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
+static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset)
 {
        return chipset->rev;
 }
@@ -982,7 +931,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
                                int mc_count, struct dev_addr_list *mc_list);
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
 int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                     const u8 *local_address, const u8 *address,
+                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                      struct ieee80211_key_conf *key);
 #else
 #define rt2x00mac_set_key      NULL
index e66fb316cd61fda7fae8add82217d06e01213628..9c2f5517af2a453784dc8cd6e96a92279ff6311d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
 void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
                           struct rt2x00_intf *intf,
                           enum nl80211_iftype type,
-                          u8 *mac, u8 *bssid)
+                          const u8 *mac, const u8 *bssid)
 {
        struct rt2x00intf_conf conf;
        unsigned int flags = 0;
@@ -42,6 +42,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
        switch (type) {
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_WDS:
                conf.sync = TSF_SYNC_BEACON;
                break;
        case NL80211_IFTYPE_STATION:
@@ -152,8 +154,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
         */
        rt2x00dev->ops->lib->config_ant(rt2x00dev, ant);
 
-       rt2x00lib_reset_link_tuner(rt2x00dev);
-       rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
+       rt2x00link_reset_tuner(rt2x00dev, true);
 
        memcpy(active, ant, sizeof(*ant));
 
@@ -191,7 +192,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
         * which means we need to reset the link tuner.
         */
        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt2x00lib_reset_link_tuner(rt2x00dev);
+               rt2x00link_reset_tuner(rt2x00dev, false);
 
        rt2x00dev->curr_band = conf->channel->band;
        rt2x00dev->tx_power = conf->power_level;
index aee9cba13eb3c3e97ea816841d0ed84059b3fbca..0b41845d9543a1653d3893e22d7f4c56d1719c35 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -49,9 +49,14 @@ 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 rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
        struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 
+       if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
+           !hw_key || entry->skb->do_not_encrypt)
+               return;
+
        __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
 
        txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
@@ -69,11 +74,17 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
                __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
 }
 
-unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
+unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb)
 {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_key_conf *key = tx_info->control.hw_key;
        unsigned int overhead = 0;
 
+       if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
+           !key || skb->do_not_encrypt)
+               return overhead;
+
        /*
         * Extend frame length to include IV/EIV/ICV/MMIC,
         * note that these lengths should only be added when
index 54dd10060bf1a56a8b318ee5e135463b796cc358..dcdce7f746b5eb5db8d83abba464cd8e2de90f7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -130,9 +130,11 @@ struct rt2x00debug_intf {
 };
 
 void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                              enum cipher cipher, enum rx_crypto status)
+                              struct rxdone_entry_desc *rxdesc)
 {
        struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+       enum cipher cipher = rxdesc->cipher;
+       enum rx_crypto status = rxdesc->cipher_status;
 
        if (cipher == CIPHER_TKIP_NO_MIC)
                cipher = CIPHER_TKIP;
index a92104dfee9a6836d90b7ee2270b3c407fc873e8..035cbc98c59344a3f75beb2cff6023a9ee20db7a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 87c0f2c8307752be2521032a6904b82ce9530942..e1b40545a9be9d43227a8dc3eac66d84ea3fa3bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
 #include "rt2x00.h"
 #include "rt2x00lib.h"
 
-/*
- * Link tuning handlers
- */
-void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Reset link information.
-        * Both the currently active vgc level as well as
-        * the link tuner counter should be reset. Resetting
-        * the counter is important for devices where the
-        * device should only perform link tuning during the
-        * first minute after being enabled.
-        */
-       rt2x00dev->link.count = 0;
-       rt2x00dev->link.vgc_level = 0;
-
-       /*
-        * Reset the link tuner.
-        */
-       rt2x00dev->ops->lib->reset_tuner(rt2x00dev);
-}
-
-static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Clear all (possibly) pre-existing quality statistics.
-        */
-       memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual));
-
-       /*
-        * The RX and TX percentage should start at 50%
-        * this will assure we will get at least get some
-        * decent value when the link tuner starts.
-        * The value will be dropped and overwritten with
-        * the correct (measured )value anyway during the
-        * first run of the link tuner.
-        */
-       rt2x00dev->link.qual.rx_percentage = 50;
-       rt2x00dev->link.qual.tx_percentage = 50;
-
-       rt2x00lib_reset_link_tuner(rt2x00dev);
-
-       queue_delayed_work(rt2x00dev->hw->workqueue,
-                          &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
-}
-
-static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev)
-{
-       cancel_delayed_work_sync(&rt2x00dev->link.work);
-}
-
 /*
  * Radio control handlers.
  */
@@ -161,238 +107,15 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
         * When we are disabling the RX, we should also stop the link tuner.
         */
        if (state == STATE_RADIO_RX_OFF)
-               rt2x00lib_stop_link_tuner(rt2x00dev);
+               rt2x00link_stop_tuner(rt2x00dev);
 
        rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
 
        /*
         * When we are enabling the RX, we should also start the link tuner.
         */
-       if (state == STATE_RADIO_RX_ON &&
-           (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
-               rt2x00lib_start_link_tuner(rt2x00dev);
-}
-
-static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
-{
-       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.
-        */
-       rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE;
-
-       /*
-        * During the last period we have sampled the RSSI
-        * from both antenna's. It now is time to determine
-        * which antenna demonstrated the best performance.
-        * When we are already on the antenna with the best
-        * performance, then there really is nothing for us
-        * left to do.
-        */
-       if (sample_a == sample_b)
-               return;
-
-       if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
-               ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
-
-       if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
-               ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
-
-       rt2x00lib_config_antenna(rt2x00dev, &ant);
-}
-
-static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
-{
-       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
-        * also should be done when the RSSI was actually better
-        * then the previous sample.
-        * When the difference exceeds the threshold we should
-        * sample the rssi from the other antenna to make a valid
-        * comparison between the 2 antennas.
-        */
-       if (abs(rssi_curr - rssi_old) < 5)
-               return;
-
-       rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE;
-
-       if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
-               ant.rx = (ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
-
-       if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
-               ant.tx = (ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
-
-       rt2x00lib_config_antenna(rt2x00dev, &ant);
-}
-
-static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Determine if software diversity is enabled for
-        * either the TX or RX antenna (or both).
-        * Always perform this check since within the link
-        * tuner interval the configuration might have changed.
-        */
-       rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY;
-       rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY;
-
-       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY;
-       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY;
-
-       if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) &&
-           !(rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)) {
-               rt2x00dev->link.ant.flags = 0;
-               return;
-       }
-
-       /*
-        * If we have only sampled the data over the last period
-        * we should now harvest the data. Otherwise just evaluate
-        * the data. The latter should only be performed once
-        * every 2 seconds.
-        */
-       if (rt2x00dev->link.ant.flags & ANTENNA_MODE_SAMPLE)
-               rt2x00lib_evaluate_antenna_sample(rt2x00dev);
-       else if (rt2x00dev->link.count & 1)
-               rt2x00lib_evaluate_antenna_eval(rt2x00dev);
-}
-
-static void rt2x00lib_update_link_stats(struct link *link, int rssi)
-{
-       int avg_rssi = rssi;
-
-       /*
-        * Update global RSSI
-        */
-       if (link->qual.avg_rssi)
-               avg_rssi = MOVING_AVERAGE(link->qual.avg_rssi, rssi, 8);
-       link->qual.avg_rssi = avg_rssi;
-
-       /*
-        * Update antenna RSSI
-        */
-       if (link->ant.rssi_ant)
-               rssi = MOVING_AVERAGE(link->ant.rssi_ant, rssi, 8);
-       link->ant.rssi_ant = rssi;
-}
-
-static void rt2x00lib_precalculate_link_signal(struct link_qual *qual)
-{
-       if (qual->rx_failed || qual->rx_success)
-               qual->rx_percentage =
-                   (qual->rx_success * 100) /
-                   (qual->rx_failed + qual->rx_success);
-       else
-               qual->rx_percentage = 50;
-
-       if (qual->tx_failed || qual->tx_success)
-               qual->tx_percentage =
-                   (qual->tx_success * 100) /
-                   (qual->tx_failed + qual->tx_success);
-       else
-               qual->tx_percentage = 50;
-
-       qual->rx_success = 0;
-       qual->rx_failed = 0;
-       qual->tx_success = 0;
-       qual->tx_failed = 0;
-}
-
-static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev,
-                                          int rssi)
-{
-       int rssi_percentage = 0;
-       int signal;
-
-       /*
-        * We need a positive value for the RSSI.
-        */
-       if (rssi < 0)
-               rssi += rt2x00dev->rssi_offset;
-
-       /*
-        * Calculate the different percentages,
-        * which will be used for the signal.
-        */
-       if (rt2x00dev->rssi_offset)
-               rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset;
-
-       /*
-        * Add the individual percentages and use the WEIGHT
-        * defines to calculate the current link signal.
-        */
-       signal = ((WEIGHT_RSSI * rssi_percentage) +
-                 (WEIGHT_TX * rt2x00dev->link.qual.tx_percentage) +
-                 (WEIGHT_RX * rt2x00dev->link.qual.rx_percentage)) / 100;
-
-       return (signal > 100) ? 100 : signal;
-}
-
-static void rt2x00lib_link_tuner(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, link.work.work);
-
-       /*
-        * When the radio is shutting down we should
-        * immediately cease all link tuning.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Update statistics.
-        */
-       rt2x00dev->ops->lib->link_stats(rt2x00dev, &rt2x00dev->link.qual);
-       rt2x00dev->low_level_stats.dot11FCSErrorCount +=
-           rt2x00dev->link.qual.rx_failed;
-
-       /*
-        * Only perform the link tuning when Link tuning
-        * has been enabled (This could have been disabled from the EEPROM).
-        */
-       if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
-               rt2x00dev->ops->lib->link_tuner(rt2x00dev);
-
-       /*
-        * Precalculate a portion of the link signal which is
-        * in based on the tx/rx success/failure counters.
-        */
-       rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
-
-       /*
-        * Send a signal to the led to update the led signal strength.
-        */
-       rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
-
-       /*
-        * Evaluate antenna setup, make this the last step since this could
-        * possibly reset some statistics.
-        */
-       rt2x00lib_evaluate_antenna(rt2x00dev);
-
-       /*
-        * Increase tuner counter, and reschedule the next link tuner run.
-        */
-       rt2x00dev->link.count++;
-       queue_delayed_work(rt2x00dev->hw->workqueue,
-                          &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
+       if (state == STATE_RADIO_RX_ON)
+               rt2x00link_start_tuner(rt2x00dev);
 }
 
 static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
@@ -467,7 +190,9 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
        struct rt2x00_intf *intf = vif_to_intf(vif);
 
        if (vif->type != NL80211_IFTYPE_AP &&
-           vif->type != NL80211_IFTYPE_ADHOC)
+           vif->type != NL80211_IFTYPE_ADHOC &&
+           vif->type != NL80211_IFTYPE_MESH_POINT &&
+           vif->type != NL80211_IFTYPE_WDS)
                return;
 
        /*
@@ -597,7 +322,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
        struct sk_buff *skb;
        struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
        struct ieee80211_supported_band *sband;
-       struct ieee80211_hdr *hdr;
        const struct rt2x00_rate *rate;
        unsigned int header_length;
        unsigned int align;
@@ -668,30 +392,22 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 
        if (idx < 0) {
                WARNING(rt2x00dev, "Frame received with unrecognized signal,"
-                       "signal=0x%.2x, plcp=%d.\n", rxdesc.signal,
-                       !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP));
+                       "signal=0x%.2x, type=%d.\n", rxdesc.signal,
+                       (rxdesc.dev_flags & RXDONE_SIGNAL_MASK));
                idx = 0;
        }
 
        /*
-        * Only update link status if this is a beacon frame carrying our bssid.
+        * Update extra components
         */
-       hdr = (struct ieee80211_hdr *)entry->skb->data;
-       if (ieee80211_is_beacon(hdr->frame_control) &&
-           (rxdesc.dev_flags & RXDONE_MY_BSS))
-               rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi);
-
-       rt2x00debug_update_crypto(rt2x00dev,
-                                 rxdesc.cipher,
-                                 rxdesc.cipher_status);
-
-       rt2x00dev->link.qual.rx_success++;
+       rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
+       rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
 
        rx_status->mactime = rxdesc.timestamp;
        rx_status->rate_idx = idx;
-       rx_status->qual =
-           rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi);
+       rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi);
        rx_status->signal = rxdesc.rssi;
+       rx_status->noise = rxdesc.noise;
        rx_status->flag = rxdesc.flags;
        rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
@@ -1067,7 +783,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
        if (rt2x00dev->ops->bcn->entry_num > 0)
                rt2x00dev->hw->wiphy->interface_modes |=
                    BIT(NL80211_IFTYPE_ADHOC) |
-                   BIT(NL80211_IFTYPE_AP);
+                   BIT(NL80211_IFTYPE_AP) |
+                   BIT(NL80211_IFTYPE_MESH_POINT) |
+                   BIT(NL80211_IFTYPE_WDS);
 
        /*
         * Let the driver probe the device to detect the capabilities.
@@ -1083,7 +801,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
         */
        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
        INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
-       INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
 
        /*
         * Allocate queue array.
@@ -1104,6 +821,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
        /*
         * Register extra components.
         */
+       rt2x00link_register(rt2x00dev);
        rt2x00leds_register(rt2x00dev);
        rt2x00rfkill_allocate(rt2x00dev);
        rt2x00debug_register(rt2x00dev);
@@ -1163,23 +881,17 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
 #ifdef CONFIG_PM
 int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
 {
-       int retval;
-
        NOTICE(rt2x00dev, "Going to sleep.\n");
 
        /*
-        * Only continue if mac80211 has open interfaces.
+        * Prevent mac80211 from accessing driver while suspended.
         */
-       if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
-           !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-               goto exit;
-
-       set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags);
+       if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
 
        /*
-        * Disable radio.
+        * Cleanup as much as possible.
         */
-       rt2x00lib_stop(rt2x00dev);
        rt2x00lib_uninitialize(rt2x00dev);
 
        /*
@@ -1188,7 +900,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
        rt2x00leds_suspend(rt2x00dev);
        rt2x00debug_deregister(rt2x00dev);
 
-exit:
        /*
         * Set device mode to sleep for power management,
         * on some hardware this call seems to consistently fail.
@@ -1200,8 +911,7 @@ exit:
         * the radio and the other components already disabled the
         * device is as good as disabled.
         */
-       retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP);
-       if (retval)
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP))
                WARNING(rt2x00dev, "Device failed to enter sleep state, "
                        "continue suspending.\n");
 
@@ -1209,32 +919,8 @@ exit:
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
 
-static void rt2x00lib_resume_intf(void *data, u8 *mac,
-                                 struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = data;
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       spin_lock(&intf->lock);
-
-       rt2x00lib_config_intf(rt2x00dev, intf,
-                             vif->type, intf->mac, intf->bssid);
-
-
-       /*
-        * Master or Ad-hoc mode require a new beacon update.
-        */
-       if (vif->type == NL80211_IFTYPE_AP ||
-           vif->type == NL80211_IFTYPE_ADHOC)
-               intf->delayed_flags |= DELAYED_UPDATE_BEACON;
-
-       spin_unlock(&intf->lock);
-}
-
 int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
 {
-       int retval;
-
        NOTICE(rt2x00dev, "Waking up.\n");
 
        /*
@@ -1243,61 +929,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
        rt2x00debug_register(rt2x00dev);
        rt2x00leds_resume(rt2x00dev);
 
-       /*
-        * Only continue if mac80211 had open interfaces.
-        */
-       if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Reinitialize device and all active interfaces.
-        */
-       retval = rt2x00lib_start(rt2x00dev);
-       if (retval)
-               goto exit;
-
-       /*
-        * Reconfigure device.
-        */
-       retval = rt2x00mac_config(rt2x00dev->hw, ~0);
-       if (retval)
-               goto exit;
-
-       /*
-        * Iterator over each active interface to
-        * reconfigure the hardware.
-        */
-       ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-                                           rt2x00lib_resume_intf, rt2x00dev);
-
        /*
         * We are ready again to receive requests from mac80211.
         */
        set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
 
-       /*
-        * It is possible that during that mac80211 has attempted
-        * to send frames while we were suspending or resuming.
-        * In that case we have disabled the TX queue and should
-        * now enable it again
-        */
-       ieee80211_wake_queues(rt2x00dev->hw);
-
-       /*
-        * During interface iteration we might have changed the
-        * delayed_flags, time to handles the event by calling
-        * the work handler directly.
-        */
-       rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
-
        return 0;
-
-exit:
-       rt2x00lib_stop(rt2x00dev);
-       rt2x00lib_uninitialize(rt2x00dev);
-       rt2x00debug_deregister(rt2x00dev);
-
-       return retval;
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_resume);
 #endif /* CONFIG_PM */
index 7169c222a4860b94fc5657a2e544870fd991f9e6..fdedb512292814bd8d6ac3b5c479ffc7b1f980a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index bab05a56e7a0f2f9f2679cb220a72b2fca771775..2a7e8bc0016b77066820d71b3f003a18843aff66 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index a0cd35b6beb5a5f1a1865dff5e89456a4f435d17..9b531e0ca0cd15f530d796ffe14a3b3904e05c36 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 9df4a49bdcad22660adf0f16feb13192e0b97a35..1046977e6a124833ecf4231bb63cbfa07b6b9f21 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 86cd26fbf76922a429ad5b0424e80504ec92d776..34efe46535491ca1515473a6a6f92d11e8eb11b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
  * Both the link tuner as the rfkill will be called once per second.
  */
 #define LINK_TUNE_INTERVAL     ( round_jiffies_relative(HZ) )
-#define RFKILL_POLL_INTERVAL   ( round_jiffies_relative(HZ) )
+#define RFKILL_POLL_INTERVAL   ( 1000 )
 
 /*
  * rt2x00_rate: Per rate device information
@@ -63,7 +63,6 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
 int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
-void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
 
 /*
  * Initialization handlers.
@@ -77,7 +76,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
                           struct rt2x00_intf *intf,
                           enum nl80211_iftype type,
-                          u8 *mac, u8 *bssid);
+                          const u8 *mac, const u8 *bssid);
 void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
                          struct rt2x00_intf *intf,
                          struct ieee80211_bss_conf *conf);
@@ -154,6 +153,81 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
 int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
 void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
 
+/**
+ * rt2x00link_update_stats - Update link statistics from RX frame
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @skb: Received frame
+ * @rxdesc: Received frame descriptor
+ *
+ * Update link statistics based on the information from the
+ * received frame descriptor.
+ */
+void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
+                            struct sk_buff *skb,
+                            struct rxdone_entry_desc *rxdesc);
+
+/**
+ * rt2x00link_calculate_signal - Calculate signal quality
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @rssi: RX Frame RSSI
+ *
+ * Calculate the signal quality of a frame based on the rssi
+ * measured during the receiving of the frame and the global
+ * link quality statistics measured since the start of the
+ * link tuning. The result is a value between 0 and 100 which
+ * is an indication of the signal quality.
+ */
+int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi);
+
+/**
+ * rt2x00link_start_tuner - Start periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This start the link tuner periodic work, this work will
+ * be executed periodically until &rt2x00link_stop_tuner has
+ * been called.
+ */
+void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_tuner - Stop periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * After this function completed the link tuner will not
+ * be running until &rt2x00link_start_tuner is called.
+ */
+void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_reset_tuner - Reset periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @antenna: Should the antenna tuning also be reset
+ *
+ * The VGC limit configured in the hardware will be reset to 0
+ * which forces the driver to rediscover the correct value for
+ * the current association. This is needed when configuration
+ * options have changed which could drastically change the
+ * SNR level or link quality (i.e. changing the antenna setting).
+ *
+ * Resetting the link tuner will also cause the periodic work counter
+ * to be reset. Any driver which has a fixed limit on the number
+ * of rounds the link tuner is supposed to work will accept the
+ * tuner actions again if this limit was previously reached.
+ *
+ * If @antenna is set to true a the software antenna diversity
+ * tuning will also be reset.
+ */
+void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
+
+/**
+ * rt2x00link_register - Initialize link tuning functionality
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * Initialize work structure and all link tuning related
+ * paramters. This will not start the link tuning process itself.
+ */
+void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
+
 /*
  * Firmware handlers.
  */
@@ -179,7 +253,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
 void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
                            enum rt2x00_dump_type type, struct sk_buff *skb);
 void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                              enum cipher cipher, enum rx_crypto status);
+                              struct rxdone_entry_desc *rxdesc);
 #else
 static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 {
@@ -196,8 +270,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
 }
 
 static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                                            enum cipher cipher,
-                                            enum rx_crypto status)
+                                            struct rxdone_entry_desc *rxdesc)
 {
 }
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
@@ -209,7 +282,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
 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);
+unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb);
 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);
@@ -227,7 +301,8 @@ static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
 {
 }
 
-static inline unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
+static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                                   struct sk_buff *skb)
 {
        return 0;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
new file mode 100644 (file)
index 0000000..9223a6d
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the
+       Free Software Foundation, Inc.,
+       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 generic link tuning routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+/*
+ * When we lack RSSI information return something less then -80 to
+ * tell the driver to tune the device to maximum sensitivity.
+ */
+#define DEFAULT_RSSI           -128
+
+/*
+ * When no TX/RX percentage could be calculated due to lack of
+ * frames on the air, we fallback to a percentage of 50%.
+ * This will assure we will get at least get some decent value
+ * when the link tuner starts.
+ * The value will be dropped and overwritten with the correct (measured)
+ * value anyway during the first run of the link tuner.
+ */
+#define DEFAULT_PERCENTAGE     50
+
+/*
+ * Small helper macro to work with moving/walking averages.
+ * When adding a value to the average value the following calculation
+ * is needed:
+ *
+ *        avg_rssi = ((avg_rssi * 7) + rssi) / 8;
+ *
+ * The advantage of this approach is that we only need 1 variable
+ * to store the average in (No need for a count and a total).
+ * But more importantly, normal average values will over time
+ * move less and less towards newly added values this results
+ * that with link tuning, the device can have a very good RSSI
+ * for a few minutes but when the device is moved away from the AP
+ * the average will not decrease fast enough to compensate.
+ * The walking average compensates this and will move towards
+ * the new values correctly allowing a effective link tuning.
+ */
+#define MOVING_AVERAGE(__avg, __val, __samples) \
+       ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
+
+/*
+ * Small helper macro for percentage calculation
+ * This is a very simple macro with the only catch that it will
+ * produce a default value in case no total value was provided.
+ */
+#define PERCENTAGE(__value, __total) \
+       ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
+
+/*
+ * For calculating the Signal quality we have determined
+ * the total number of success and failed RX and TX frames.
+ * With the addition of the average RSSI value we can determine
+ * the link quality using the following algorithm:
+ *
+ *         rssi_percentage = (avg_rssi * 100) / rssi_offset
+ *         rx_percentage = (rx_success * 100) / rx_total
+ *         tx_percentage = (tx_success * 100) / tx_total
+ *         avg_signal = ((WEIGHT_RSSI * avg_rssi) +
+ *                       (WEIGHT_TX * tx_percentage) +
+ *                       (WEIGHT_RX * rx_percentage)) / 100
+ *
+ * This value should then be checked to not be greater then 100.
+ * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must
+ * sum up to 100 as well.
+ */
+#define WEIGHT_RSSI    20
+#define WEIGHT_RX      40
+#define WEIGHT_TX      40
+
+static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       if (ant->rssi_ant && rt2x00dev->link.qual.rx_success)
+               return ant->rssi_ant;
+       return DEFAULT_RSSI;
+}
+
+static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev,
+                                              enum antenna antenna)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       if (ant->rssi_history[antenna - ANTENNA_A])
+               return ant->rssi_history[antenna - ANTENNA_A];
+       return DEFAULT_RSSI;
+}
+/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
+#define rt2x00link_antenna_get_rssi_rx_history(__dev) \
+       rt2x00link_antenna_get_rssi_history((__dev), \
+                                           (__dev)->link.ant.active.rx)
+#define rt2x00link_antenna_get_rssi_tx_history(__dev) \
+       rt2x00link_antenna_get_rssi_history((__dev), \
+                                           (__dev)->link.ant.active.tx)
+
+static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
+                                                  enum antenna antenna,
+                                                  int rssi)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       ant->rssi_history[ant->active.rx - ANTENNA_A] = rssi;
+}
+/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
+#define rt2x00link_antenna_update_rssi_rx_history(__dev, __rssi) \
+       rt2x00link_antenna_update_rssi_history((__dev), \
+                                              (__dev)->link.ant.active.rx, \
+                                              (__rssi))
+#define rt2x00link_antenna_update_rssi_tx_history(__dev, __rssi) \
+       rt2x00link_antenna_update_rssi_history((__dev), \
+                                              (__dev)->link.ant.active.tx, \
+                                              (__rssi))
+
+static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
+{
+       rt2x00dev->link.ant.rssi_ant = 0;
+}
+
+static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup new_ant;
+       int sample_a = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_A);
+       int sample_b = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_B);
+
+       memcpy(&new_ant, &ant->active, sizeof(new_ant));
+
+       /*
+        * We are done sampling. Now we should evaluate the results.
+        */
+       ant->flags &= ~ANTENNA_MODE_SAMPLE;
+
+       /*
+        * During the last period we have sampled the RSSI
+        * from both antenna's. It now is time to determine
+        * which antenna demonstrated the best performance.
+        * When we are already on the antenna with the best
+        * performance, then there really is nothing for us
+        * left to do.
+        */
+       if (sample_a == sample_b)
+               return;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               new_ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               new_ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+
+       rt2x00lib_config_antenna(rt2x00dev, &new_ant);
+}
+
+static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup new_ant;
+       int rssi_curr;
+       int rssi_old;
+
+       memcpy(&new_ant, &ant->active, sizeof(new_ant));
+
+       /*
+        * Get current RSSI value along with the historical value,
+        * after that update the history with the current value.
+        */
+       rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
+       rssi_old = rt2x00link_antenna_get_rssi_rx_history(rt2x00dev);
+       rt2x00link_antenna_update_rssi_rx_history(rt2x00dev, rssi_curr);
+
+       /*
+        * Legacy driver indicates that we should swap antenna's
+        * when the difference in RSSI is greater that 5. This
+        * also should be done when the RSSI was actually better
+        * then the previous sample.
+        * When the difference exceeds the threshold we should
+        * sample the rssi from the other antenna to make a valid
+        * comparison between the 2 antennas.
+        */
+       if (abs(rssi_curr - rssi_old) < 5)
+               return;
+
+       ant->flags |= ANTENNA_MODE_SAMPLE;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+       rt2x00lib_config_antenna(rt2x00dev, &new_ant);
+}
+
+static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       /*
+        * Determine if software diversity is enabled for
+        * either the TX or RX antenna (or both).
+        * Always perform this check since within the link
+        * tuner interval the configuration might have changed.
+        */
+       ant->flags &= ~ANTENNA_RX_DIVERSITY;
+       ant->flags &= ~ANTENNA_TX_DIVERSITY;
+
+       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+               ant->flags |= ANTENNA_RX_DIVERSITY;
+       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+               ant->flags |= ANTENNA_TX_DIVERSITY;
+
+       if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
+           !(ant->flags & ANTENNA_TX_DIVERSITY)) {
+               ant->flags = 0;
+               return;
+       }
+
+       /*
+        * If we have only sampled the data over the last period
+        * we should now harvest the data. Otherwise just evaluate
+        * the data. The latter should only be performed once
+        * every 2 seconds.
+        */
+       if (ant->flags & ANTENNA_MODE_SAMPLE)
+               rt2x00lib_antenna_diversity_sample(rt2x00dev);
+       else if (rt2x00dev->link.count & 1)
+               rt2x00lib_antenna_diversity_eval(rt2x00dev);
+}
+
+void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
+                            struct sk_buff *skb,
+                            struct rxdone_entry_desc *rxdesc)
+{
+       struct link *link = &rt2x00dev->link;
+       struct link_qual *qual = &rt2x00dev->link.qual;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       int avg_rssi = rxdesc->rssi;
+       int ant_rssi = rxdesc->rssi;
+
+       /*
+        * Frame was received successfully since non-succesfull
+        * frames would have been dropped by the hardware.
+        */
+       qual->rx_success++;
+
+       /*
+        * We are only interested in quality statistics from
+        * beacons which came from the BSS which we are
+        * associated with.
+        */
+       if (!ieee80211_is_beacon(hdr->frame_control) ||
+           !(rxdesc->dev_flags & RXDONE_MY_BSS))
+               return;
+
+       /*
+        * Update global RSSI
+        */
+       if (link->avg_rssi)
+               avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8);
+       link->avg_rssi = avg_rssi;
+
+       /*
+        * Update antenna RSSI
+        */
+       if (ant->rssi_ant)
+               ant_rssi = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi, 8);
+       ant->rssi_ant = ant_rssi;
+}
+
+static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+       struct link_qual *qual = &rt2x00dev->link.qual;
+
+       link->rx_percentage =
+           PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success);
+       link->tx_percentage =
+           PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success);
+
+       qual->rx_success = 0;
+       qual->rx_failed = 0;
+       qual->tx_success = 0;
+       qual->tx_failed = 0;
+}
+
+int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
+{
+       struct link *link = &rt2x00dev->link;
+       int rssi_percentage = 0;
+       int signal;
+
+       /*
+        * We need a positive value for the RSSI.
+        */
+       if (rssi < 0)
+               rssi += rt2x00dev->rssi_offset;
+
+       /*
+        * Calculate the different percentages,
+        * which will be used for the signal.
+        */
+       rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset);
+
+       /*
+        * Add the individual percentages and use the WEIGHT
+        * defines to calculate the current link signal.
+        */
+       signal = ((WEIGHT_RSSI * rssi_percentage) +
+                 (WEIGHT_TX * link->tx_percentage) +
+                 (WEIGHT_RX * link->rx_percentage)) / 100;
+
+       return max_t(int, signal, 100);
+}
+
+void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * Link tuning should only be performed when
+        * an active sta or master interface exists.
+        * Single monitor mode interfaces should never have
+        * work with link tuners.
+        */
+       if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
+               return;
+
+       link->rx_percentage = DEFAULT_PERCENTAGE;
+       link->tx_percentage = DEFAULT_PERCENTAGE;
+
+       rt2x00link_reset_tuner(rt2x00dev, false);
+
+       queue_delayed_work(rt2x00dev->hw->workqueue,
+                          &link->work, LINK_TUNE_INTERVAL);
+}
+
+void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.work);
+}
+
+void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
+{
+       struct link_qual *qual = &rt2x00dev->link.qual;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Reset link information.
+        * Both the currently active vgc level as well as
+        * the link tuner counter should be reset. Resetting
+        * the counter is important for devices where the
+        * device should only perform link tuning during the
+        * first minute after being enabled.
+        */
+       rt2x00dev->link.count = 0;
+       memset(qual, 0, sizeof(*qual));
+
+       /*
+        * Reset the link tuner.
+        */
+       rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
+
+       if (antenna)
+               rt2x00link_antenna_reset(rt2x00dev);
+}
+
+static void rt2x00link_tuner(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.work.work);
+       struct link *link = &rt2x00dev->link;
+       struct link_qual *qual = &rt2x00dev->link.qual;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease all link tuning.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Update statistics.
+        */
+       rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
+       rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
+
+       /*
+        * Update quality RSSI for link tuning,
+        * when we have received some frames and we managed to
+        * collect the RSSI data we could use this. Otherwise we
+        * must fallback to the default RSSI value.
+        */
+       if (!link->avg_rssi || !qual->rx_success)
+               qual->rssi = DEFAULT_RSSI;
+       else
+               qual->rssi = link->avg_rssi;
+
+       /*
+        * Only perform the link tuning when Link tuning
+        * has been enabled (This could have been disabled from the EEPROM).
+        */
+       if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
+               rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
+
+       /*
+        * Precalculate a portion of the link signal which is
+        * in based on the tx/rx success/failure counters.
+        */
+       rt2x00link_precalculate_signal(rt2x00dev);
+
+       /*
+        * Send a signal to the led to update the led signal strength.
+        */
+       rt2x00leds_led_quality(rt2x00dev, link->avg_rssi);
+
+       /*
+        * Evaluate antenna setup, make this the last step since this could
+        * possibly reset some statistics.
+        */
+       rt2x00lib_antenna_diversity(rt2x00dev);
+
+       /*
+        * Increase tuner counter, and reschedule the next link tuner run.
+        */
+       link->count++;
+       queue_delayed_work(rt2x00dev->hw->workqueue,
+                          &link->work, LINK_TUNE_INTERVAL);
+}
+
+void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
+{
+       INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
+}
index 38edee5fe1683c1022e3739efa808e0292f61eea..71de8a7144f9c1106abc7eeeb35712e95a158c87 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -79,8 +79,7 @@ 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.
         */
-       if (!frag_skb->do_not_encrypt)
-               data_length += rt2x00crypto_tx_overhead(tx_info);
+       data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
 
        if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
                ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
@@ -226,6 +225,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
                break;
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_WDS:
                /*
                 * We don't support mixed combinations of
                 * sta and ap interfaces.
@@ -482,16 +483,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
+static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
+{
+       if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
+               memcpy(&crypto->key,
+                      &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
+                      sizeof(crypto->key));
+
+       if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+               memcpy(&crypto->tx_mic,
+                      &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
+                      sizeof(crypto->tx_mic));
+
+       if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
+               memcpy(&crypto->rx_mic,
+                      &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
+                      sizeof(crypto->rx_mic));
+}
+
 int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                     const u8 *local_address, const u8 *address,
+                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                      struct ieee80211_key_conf *key)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_sta *sta;
+       struct rt2x00_intf *intf = vif_to_intf(vif);
        int (*set_key) (struct rt2x00_dev *rt2x00dev,
                        struct rt2x00lib_crypto *crypto,
                        struct ieee80211_key_conf *key);
        struct rt2x00lib_crypto crypto;
+       static const u8 bcast_addr[ETH_ALEN] =
+               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
 
        if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
                return 0;
@@ -509,45 +530,25 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        if (rt2x00dev->intf_sta_count)
                crypto.bssidx = 0;
        else
-               crypto.bssidx =
-                   local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
+               crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1);
 
        crypto.cipher = rt2x00crypto_key_to_cipher(key);
        if (crypto.cipher == CIPHER_NONE)
                return -EOPNOTSUPP;
 
        crypto.cmd = cmd;
-       crypto.address = address;
-
-       if (crypto.cipher == CIPHER_TKIP) {
-               if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
-                       memcpy(&crypto.key,
-                              &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
-                              sizeof(crypto.key));
-
-               if (key->keylen > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
-                       memcpy(&crypto.tx_mic,
-                              &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
-                              sizeof(crypto.tx_mic));
-
-               if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
-                       memcpy(&crypto.rx_mic,
-                              &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
-                              sizeof(crypto.rx_mic));
-       } else
-               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)
+       if (sta) {
+               /* some drivers need the AID */
                crypto.aid = sta->aid;
-       rcu_read_unlock();
+               crypto.address = sta->addr;
+       } else
+               crypto.address = bcast_addr;
 
+       if (crypto.cipher == CIPHER_TKIP)
+               memcpy_tkip(&crypto, &key->key[0], key->keylen);
+       else
+               memcpy(&crypto.key, &key->key[0], key->keylen);
        /*
         * Each BSS has a maximum of 4 shared keys.
         * Shared key index values:
index d52b22b82d1fb4662184b653efe50f99b43fec13..e616c20d4a782c4dd014927057342e779396548a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 9c0a4d77bc1be1e16ab79940c3c2cb0aa65859c2..15a12487e04b024cfde0400d407d11b67fa95a27 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 0709decec9c237aa93dcb79052a0b8f5d3d61e3a..c86fb64717542c9e8a4f0f61773b25f549bf1c16 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -148,20 +148,105 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
        dev_kfree_skb_any(skb);
 }
 
+static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
+                                                struct txentry_desc *txdesc)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
+       unsigned long irqflags;
+
+       if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ||
+           unlikely(!tx_info->control.vif))
+               return;
+
+       /*
+        * Hardware should insert sequence counter.
+        * FIXME: We insert a software sequence counter first for
+        * hardware that doesn't support hardware sequence counting.
+        *
+        * This is wrong because beacons are not getting sequence
+        * numbers assigned properly.
+        *
+        * A secondary problem exists for drivers that cannot toggle
+        * sequence counting per-frame, since those will override the
+        * sequence counter given by mac80211.
+        */
+       spin_lock_irqsave(&intf->seqlock, irqflags);
+
+       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+               intf->seqno += 0x10;
+       hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+       hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
+
+       spin_unlock_irqrestore(&intf->seqlock, irqflags);
+
+       __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+}
+
+static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
+                                                 struct txentry_desc *txdesc,
+                                                 const struct rt2x00_rate *hwrate)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+       unsigned int data_length;
+       unsigned int duration;
+       unsigned int residual;
+
+       /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
+       data_length = entry->skb->len + 4;
+       data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
+
+       /*
+        * PLCP setup
+        * Length calculation depends on OFDM/CCK rate.
+        */
+       txdesc->signal = hwrate->plcp;
+       txdesc->service = 0x04;
+
+       if (hwrate->flags & DEV_RATE_OFDM) {
+               txdesc->length_high = (data_length >> 6) & 0x3f;
+               txdesc->length_low = data_length & 0x3f;
+       } else {
+               /*
+                * Convert length to microseconds.
+                */
+               residual = GET_DURATION_RES(data_length, hwrate->bitrate);
+               duration = GET_DURATION(data_length, hwrate->bitrate);
+
+               if (residual != 0) {
+                       duration++;
+
+                       /*
+                        * Check if we need to set the Length Extension
+                        */
+                       if (hwrate->bitrate == 110 && residual <= 30)
+                               txdesc->service |= 0x80;
+               }
+
+               txdesc->length_high = (duration >> 8) & 0xff;
+               txdesc->length_low = duration & 0xff;
+
+               /*
+                * When preamble is enabled we should set the
+                * preamble bit for the signal.
+                */
+               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       txdesc->signal |= 0x08;
+       }
+}
+
 static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
                                             struct txentry_desc *txdesc)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
        struct ieee80211_rate *rate =
            ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
        const struct rt2x00_rate *hwrate;
-       unsigned int data_length;
-       unsigned int duration;
-       unsigned int residual;
-       unsigned long irqflags;
 
        memset(txdesc, 0, sizeof(*txdesc));
 
@@ -173,27 +258,12 @@ 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 */
-       data_length = entry->skb->len + 4;
-
        /*
         * Check whether this frame is to be acked.
         */
        if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
                __set_bit(ENTRY_TXD_ACK, &txdesc->flags);
 
-       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) &&
-           !entry->skb->do_not_encrypt) {
-               /* 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);
-       }
-
        /*
         * Check if this is a RTS/CTS frame
         */
@@ -237,86 +307,27 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
         * Set ifs to IFS_SIFS when the this is not the first fragment,
         * or this fragment came after RTS/CTS.
         */
-       if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) {
-               txdesc->ifs = IFS_SIFS;
-       } else if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
+       if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) &&
+           !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) {
                __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
                txdesc->ifs = IFS_BACKOFF;
-       } else {
+       } else
                txdesc->ifs = IFS_SIFS;
-       }
 
        /*
-        * Hardware should insert sequence counter.
-        * FIXME: We insert a software sequence counter first for
-        * hardware that doesn't support hardware sequence counting.
-        *
-        * This is wrong because beacons are not getting sequence
-        * numbers assigned properly.
-        *
-        * A secondary problem exists for drivers that cannot toggle
-        * sequence counting per-frame, since those will override the
-        * sequence counter given by mac80211.
+        * Determine rate modulation.
         */
-       if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-               if (likely(tx_info->control.vif)) {
-                       struct rt2x00_intf *intf;
-
-                       intf = vif_to_intf(tx_info->control.vif);
-
-                       spin_lock_irqsave(&intf->seqlock, irqflags);
-
-                       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
-                               intf->seqno += 0x10;
-                       hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-                       hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
-
-                       spin_unlock_irqrestore(&intf->seqlock, irqflags);
-
-                       __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
-               }
-       }
+       hwrate = rt2x00_get_rate(rate->hw_value);
+       txdesc->rate_mode = RATE_MODE_CCK;
+       if (hwrate->flags & DEV_RATE_OFDM)
+               txdesc->rate_mode = RATE_MODE_OFDM;
 
        /*
-        * PLCP setup
-        * Length calculation depends on OFDM/CCK rate.
+        * Apply TX descriptor handling by components
         */
-       hwrate = rt2x00_get_rate(rate->hw_value);
-       txdesc->signal = hwrate->plcp;
-       txdesc->service = 0x04;
-
-       if (hwrate->flags & DEV_RATE_OFDM) {
-               __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags);
-
-               txdesc->length_high = (data_length >> 6) & 0x3f;
-               txdesc->length_low = data_length & 0x3f;
-       } else {
-               /*
-                * Convert length to microseconds.
-                */
-               residual = GET_DURATION_RES(data_length, hwrate->bitrate);
-               duration = GET_DURATION(data_length, hwrate->bitrate);
-
-               if (residual != 0) {
-                       duration++;
-
-                       /*
-                        * Check if we need to set the Length Extension
-                        */
-                       if (hwrate->bitrate == 110 && residual <= 30)
-                               txdesc->service |= 0x80;
-               }
-
-               txdesc->length_high = (duration >> 8) & 0xff;
-               txdesc->length_low = duration & 0xff;
-
-               /*
-                * When preamble is enabled we should set the
-                * preamble bit for the signal.
-                */
-               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->signal |= 0x08;
-       }
+       rt2x00crypto_create_tx_descriptor(entry, txdesc);
+       rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
+       rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
 
 static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
@@ -403,7 +414,7 @@ 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)) {
-               if (test_bit(CONFIG_CRYPTO_COPY_IV, &queue->rt2x00dev->flags))
+               if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
                        rt2x00crypto_tx_copy_iv(skb, iv_len);
                else
                        rt2x00crypto_tx_remove_iv(skb, iv_len);
index 28293715340849363aa98eeb480f18f593fae7ec..97e2ab08f080153bf1576d14701d4b18e1650437 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -157,6 +157,14 @@ enum rxdone_entry_desc_flags {
        RXDONE_CRYPTO_ICV = 1 << 4,
 };
 
+/**
+ * RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags
+ * except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags
+ * from &rxdone_entry_desc to a signal value type.
+ */
+#define RXDONE_SIGNAL_MASK \
+       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE )
+
 /**
  * struct rxdone_entry_desc: RX Entry descriptor
  *
@@ -165,6 +173,7 @@ enum rxdone_entry_desc_flags {
  * @timestamp: RX Timestamp
  * @signal: Signal of the received frame.
  * @rssi: RSSI of the received frame.
+ * @noise: Measured noise during frame reception.
  * @size: Data size of the received frame.
  * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
  * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
@@ -177,6 +186,7 @@ struct rxdone_entry_desc {
        u64 timestamp;
        int signal;
        int rssi;
+       int noise;
        int size;
        int flags;
        int dev_flags;
@@ -222,7 +232,6 @@ struct txdone_entry_desc {
  *
  * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
  * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame.
- * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
  * @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter.
  * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame.
  * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
@@ -238,7 +247,6 @@ struct txdone_entry_desc {
 enum txentry_desc_flags {
        ENTRY_TXD_RTS_FRAME,
        ENTRY_TXD_CTS_FRAME,
-       ENTRY_TXD_OFDM_RATE,
        ENTRY_TXD_GENERATE_SEQ,
        ENTRY_TXD_FIRST_FRAGMENT,
        ENTRY_TXD_MORE_FRAG,
@@ -263,6 +271,7 @@ enum txentry_desc_flags {
  * @length_low: PLCP length low word.
  * @signal: PLCP signal.
  * @service: PLCP service.
+ * @rate_mode: Rate mode (See @enum rate_modulation).
  * @retry_limit: Max number of retries.
  * @aifs: AIFS value.
  * @ifs: IFS value.
@@ -282,6 +291,8 @@ struct txentry_desc {
        u16 signal;
        u16 service;
 
+       u16 rate_mode;
+
        short retry_limit;
        short aifs;
        short ifs;
index c2fba7c9f05cc86c6fccc2dfadb8a23daa1beb93..9ddc2d07eef8ad6413c9ca42c4e3caf2c51fb789 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -124,6 +124,16 @@ enum cipher {
        CIPHER_MAX = 4,
 };
 
+/*
+ * Rate modulations
+ */
+enum rate_modulation {
+       RATE_MODE_CCK = 0,
+       RATE_MODE_OFDM = 1,
+       RATE_MODE_HT_MIX = 2,
+       RATE_MODE_HT_GREENFIELD = 3,
+};
+
 /*
  * Register handlers.
  * We store the position of a register field inside a field structure,
index 3298cae1e12d50056aa2b22896dea537a9ab9e67..b6d4c6700bf3f8c7342354805287333462f46c9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/rfkill.h>
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
 
-static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
+static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
 {
-       struct rt2x00_dev *rt2x00dev = data;
-       int retval = 0;
-
-       if (unlikely(!rt2x00dev))
-               return 0;
-
-       /*
-        * Only continue if there are enabled interfaces.
-        */
-       if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-               return 0;
-
-       if (state == RFKILL_STATE_UNBLOCKED) {
-               INFO(rt2x00dev, "RFKILL event: enabling radio.\n");
-               clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
-               retval = rt2x00lib_enable_radio(rt2x00dev);
-       } else if (state == RFKILL_STATE_SOFT_BLOCKED) {
-               INFO(rt2x00dev, "RFKILL event: disabling radio.\n");
-               set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
-               rt2x00lib_disable_radio(rt2x00dev);
-       } else {
-               WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state);
-       }
-
-       return retval;
-}
-
-static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state)
-{
-       struct rt2x00_dev *rt2x00dev = data;
-
-       /*
-        * rfkill_poll reports 1 when the key has been pressed and the
-        * radio should be blocked.
-        */
-       *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ?
-           RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
-
-       return 0;
-}
-
-static void rt2x00rfkill_poll(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, rfkill_work.work);
-       enum rfkill_state state;
+       struct rt2x00_dev *rt2x00dev = poll_dev->private;
+       int state, old_state;
 
        if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) ||
            !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
                return;
 
        /*
-        * Poll latest state and report it to rfkill who should sort
-        * out if the state should be toggled or not.
+        * Poll latest state, if the state is different then the previous state,
+        * we should generate an input event.
         */
-       if (!rt2x00rfkill_get_state(rt2x00dev, &state))
-               rfkill_force_state(rt2x00dev->rfkill, state);
+       state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
+       old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state);
 
-       queue_delayed_work(rt2x00dev->hw->workqueue,
-                          &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL);
+       if (old_state != state) {
+               input_report_switch(poll_dev->input, SW_RFKILL_ALL, state);
+               change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state);
+       }
 }
 
 void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
@@ -100,8 +57,8 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
            test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
                return;
 
-       if (rfkill_register(rt2x00dev->rfkill)) {
-               ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
+       if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) {
+               ERROR(rt2x00dev, "Failed to register polled device.\n");
                return;
        }
 
@@ -109,10 +66,10 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
 
        /*
         * Force initial poll which will detect the initial device state,
-        * and correctly sends the signal to the rfkill layer about this
+        * and correctly sends the signal to the input layer about this
         * state.
         */
-       rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work);
+       rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev);
 }
 
 void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
@@ -121,52 +78,50 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
            !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
                return;
 
-       cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
-
-       rfkill_unregister(rt2x00dev->rfkill);
+       input_unregister_polled_device(rt2x00dev->rfkill_poll_dev);
 
        __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
 }
 
 void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
 {
-       struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy);
+       struct input_polled_dev *poll_dev;
 
-       if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+       if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
+           !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
                return;
 
-       rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN);
-       if (!rt2x00dev->rfkill) {
-               ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
+       poll_dev = input_allocate_polled_device();
+       if (!poll_dev) {
+               ERROR(rt2x00dev, "Failed to allocate polled device.\n");
                return;
        }
 
-       __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state);
+       poll_dev->private = rt2x00dev;
+       poll_dev->poll = rt2x00rfkill_poll;
+       poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
 
-       rt2x00dev->rfkill->name = rt2x00dev->ops->name;
-       rt2x00dev->rfkill->data = rt2x00dev;
-       rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
-       if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) {
-               rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state;
-               rt2x00dev->rfkill->state =
-                       rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ?
-                           RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
-       } else {
-               rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED;
-       }
+       poll_dev->input->name = rt2x00dev->ops->name;
+       poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
+       poll_dev->input->id.bustype = BUS_HOST;
+       poll_dev->input->id.vendor = 0x1814;
+       poll_dev->input->id.product = rt2x00dev->chip.rt;
+       poll_dev->input->id.version = rt2x00dev->chip.rev;
+       poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy);
+       poll_dev->input->evbit[0] = BIT(EV_SW);
+       poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL);
 
-       INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll);
+       rt2x00dev->rfkill_poll_dev = poll_dev;
 
-       return;
+       __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state);
 }
 
 void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
 {
-       if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+       if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED,
+                                 &rt2x00dev->rfkill_state))
                return;
 
-       cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
-
-       rfkill_free(rt2x00dev->rfkill);
-       rt2x00dev->rfkill = NULL;
+       input_free_polled_device(rt2x00dev->rfkill_poll_dev);
+       rt2x00dev->rfkill_poll_dev = NULL;
 }
index 0b29d767a2582296d0e7d22ea22b24fb02dae543..c89d1520838c6f9677d0822e424052b46d94100b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 2bd4ac855f528db67f60879ee2166a7b280b037f..fe4523887bdfcf699331b9aa16ef90bc89ab6d9e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
index 987e89009f74ed36debc32498783d57812b68916..d81a8de9dc176fb11e674c70a9c688cb91bce07b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -146,12 +146,6 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-#ifdef CONFIG_RT2X00_LIB_LEDS
-/*
- * This function is only called from rt61pci_led_brightness()
- * make gcc happy by placing this function inside the
- * same ifdef statement as the caller.
- */
 static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
                                const u8 command, const u8 token,
                                const u8 arg0, const u8 arg1)
@@ -180,7 +174,6 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 
 }
-#endif /* CONFIG_RT2X00_LIB_LEDS */
 
 static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
 {
@@ -967,6 +960,50 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 }
 
+static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
+                                  libconf->conf->beacon_int - 10);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
+               rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005);
+               rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
+               rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
+
+               rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
+       } else {
+               rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
+               rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
+               rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
+               rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
+
+               rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+       }
+}
+
 static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
                           struct rt2x00lib_conf *libconf,
                           const unsigned int flags)
@@ -984,6 +1021,8 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
                rt61pci_config_retry_limit(rt2x00dev, libconf);
        if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
                rt61pci_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt61pci_config_ps(rt2x00dev, libconf);
 }
 
 /*
@@ -1007,21 +1046,28 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
        qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
-static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                  struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level != vgc_level) {
+               rt61pci_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                               struct link_qual *qual)
 {
-       rt61pci_bbp_write(rt2x00dev, 17, 0x20);
-       rt2x00dev->link.vgc_level = 0x20;
+       rt61pci_set_vgc(rt2x00dev, qual, 0x20);
 }
 
-static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
 {
-       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-       u8 r17;
        u8 up_bound;
        u8 low_bound;
 
-       rt61pci_bbp_read(rt2x00dev, 17, &r17);
-
        /*
         * Determine r17 bounds.
         */
@@ -1051,38 +1097,32 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
        /*
         * Special big-R17 for very short distance
         */
-       if (rssi >= -35) {
-               if (r17 != 0x60)
-                       rt61pci_bbp_write(rt2x00dev, 17, 0x60);
+       if (qual->rssi >= -35) {
+               rt61pci_set_vgc(rt2x00dev, qual, 0x60);
                return;
        }
 
        /*
         * Special big-R17 for short distance
         */
-       if (rssi >= -58) {
-               if (r17 != up_bound)
-                       rt61pci_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->rssi >= -58) {
+               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
        /*
         * Special big-R17 for middle-short distance
         */
-       if (rssi >= -66) {
-               low_bound += 0x10;
-               if (r17 != low_bound)
-                       rt61pci_bbp_write(rt2x00dev, 17, low_bound);
+       if (qual->rssi >= -66) {
+               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10);
                return;
        }
 
        /*
         * Special mid-R17 for middle distance
         */
-       if (rssi >= -74) {
-               low_bound += 0x08;
-               if (r17 != low_bound)
-                       rt61pci_bbp_write(rt2x00dev, 17, low_bound);
+       if (qual->rssi >= -74) {
+               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08);
                return;
        }
 
@@ -1090,12 +1130,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
         * Special case: Change up_bound based on the rssi.
         * Lower up_bound when rssi is weaker then -74 dBm.
         */
-       up_bound -= 2 * (-74 - rssi);
+       up_bound -= 2 * (-74 - qual->rssi);
        if (low_bound > up_bound)
                up_bound = low_bound;
 
-       if (r17 > up_bound) {
-               rt61pci_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->vgc_level > up_bound) {
+               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
@@ -1105,15 +1145,10 @@ dynamic_cca_tune:
         * r17 does not yet exceed upper limit, continue and base
         * the r17 tuning on the false CCA count.
         */
-       if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-               if (++r17 > up_bound)
-                       r17 = up_bound;
-               rt61pci_bbp_write(rt2x00dev, 17, r17);
-       } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-               if (--r17 < low_bound)
-                       r17 = low_bound;
-               rt61pci_bbp_write(rt2x00dev, 17, r17);
-       }
+       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+               rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+               rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
 }
 
 /*
@@ -1164,6 +1199,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
        int i;
        u32 reg;
 
+       if (len != 8192) {
+               ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len);
+               return -ENOENT;
+       }
+
        /*
         * Wait for stable hardware.
         */
@@ -1812,7 +1852,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                           test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
@@ -2195,7 +2235,8 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_TX_RX_FIXED, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_RX_FIXED, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_TX_FIXED, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
@@ -2339,24 +2380,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         */
        if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
            !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
-               switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
-               case 0:
-                       rt2x00dev->default_ant.tx = ANTENNA_B;
-                       rt2x00dev->default_ant.rx = ANTENNA_A;
-                       break;
-               case 1:
-                       rt2x00dev->default_ant.tx = ANTENNA_B;
-                       rt2x00dev->default_ant.rx = ANTENNA_B;
-                       break;
-               case 2:
-                       rt2x00dev->default_ant.tx = ANTENNA_A;
-                       rt2x00dev->default_ant.rx = ANTENNA_A;
-                       break;
-               case 3:
-                       rt2x00dev->default_ant.tx = ANTENNA_A;
-                       rt2x00dev->default_ant.rx = ANTENNA_B;
-                       break;
-               }
+               rt2x00dev->default_ant.rx =
+                   ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
+               rt2x00dev->default_ant.tx =
+                   ANTENNA_B - rt2x00_get_field16(eeprom, EEPROM_NIC_TX_FIXED);
 
                if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
                        rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
@@ -2534,7 +2561,9 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-           IEEE80211_HW_SIGNAL_DBM;
+           IEEE80211_HW_SIGNAL_DBM |
+           IEEE80211_HW_SUPPORTS_PS |
+           IEEE80211_HW_PS_NULLFUNC_STACK;
        rt2x00dev->hw->extra_tx_headroom = 0;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
@@ -2633,6 +2662,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
        struct rt2x00_field32 field;
        int retval;
        u32 reg;
+       u32 offset;
 
        /*
         * First pass the configuration through rt2x00lib, that will
@@ -2644,24 +2674,23 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
        if (retval)
                return retval;
 
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues/
+        */
+       if (queue_idx >= 4)
+               return 0;
+
        queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
 
        /* Update WMM TXOP register */
-       if (queue_idx < 2) {
-               field.bit_offset = queue_idx * 16;
-               field.bit_mask = 0xffff << field.bit_offset;
-
-               rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
-               rt2x00_set_field32(&reg, field, queue->txop);
-               rt2x00pci_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;
-
-               rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
-               rt2x00_set_field32(&reg, field, queue->txop);
-               rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-       }
+       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
+       field.bit_offset = (queue_idx & 1) * 16;
+       field.bit_mask = 0xffff << field.bit_offset;
+
+       rt2x00pci_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field, queue->txop);
+       rt2x00pci_register_write(rt2x00dev, offset, reg);
 
        /* Update WMM registers */
        field.bit_offset = queue_idx * 4;
index 65fe3332364aa8cb414793ec0f0a057e40038252..2f97fee7a8de84b4cbae8231452ac7220a8a5f44 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
 
 /*
  * SOFT_RESET_CSR
+ * FORCE_CLOCK_ON: Host force MAC clock ON
  */
 #define SOFT_RESET_CSR                 0x0010
+#define SOFT_RESET_CSR_FORCE_CLOCK_ON  FIELD32(0x00000002)
 
 /*
  * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register.
@@ -1054,8 +1056,10 @@ struct hw_pairwise_ta_entry {
 
 /*
  * IO_CNTL_CSR
+ * RF_PS: Set RF interface value to power save
  */
 #define IO_CNTL_CSR                    0x3498
+#define IO_CNTL_CSR_RF_PS              FIELD32(0x00000004)
 
 /*
  * UART_INT_SOURCE_CSR
@@ -1186,7 +1190,8 @@ struct hw_pairwise_ta_entry {
 #define EEPROM_NIC                     0x0011
 #define EEPROM_NIC_ENABLE_DIVERSITY    FIELD16(0x0001)
 #define EEPROM_NIC_TX_DIVERSITY                FIELD16(0x0002)
-#define EEPROM_NIC_TX_RX_FIXED         FIELD16(0x000c)
+#define EEPROM_NIC_RX_FIXED            FIELD16(0x0004)
+#define EEPROM_NIC_TX_FIXED            FIELD16(0x0008)
 #define EEPROM_NIC_EXTERNAL_LNA_BG     FIELD16(0x0010)
 #define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0020)
 #define EEPROM_NIC_EXTERNAL_LNA_A      FIELD16(0x0040)
index 96a8d69f8790480b8fee654beebf60b4e5efbda2..f854551be75d2d5b329fa67158bb42b0ff7397f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -186,6 +186,18 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
 };
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       return rt2x00_get_field32(reg, MAC_CSR13_BIT7);
+}
+#else
+#define rt73usb_rfkill_poll    NULL
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
 #ifdef CONFIG_RT2X00_LIB_LEDS
 static void rt73usb_brightness_set(struct led_classdev *led_cdev,
                                   enum led_brightness brightness)
@@ -844,6 +856,44 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 }
 
+static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
+                                  libconf->conf->beacon_int - 10);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_SLEEP, REGISTER_TIMEOUT);
+       } else {
+               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
+
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+       }
+}
+
 static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
                           struct rt2x00lib_conf *libconf,
                           const unsigned int flags)
@@ -861,6 +911,8 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
                rt73usb_config_retry_limit(rt2x00dev, libconf);
        if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
                rt73usb_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt73usb_config_ps(rt2x00dev, libconf);
 }
 
 /*
@@ -884,21 +936,28 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
        qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
-static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                  struct link_qual *qual, u8 vgc_level)
 {
-       rt73usb_bbp_write(rt2x00dev, 17, 0x20);
-       rt2x00dev->link.vgc_level = 0x20;
+       if (qual->vgc_level != vgc_level) {
+               rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
 }
 
-static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                               struct link_qual *qual)
+{
+       rt73usb_set_vgc(rt2x00dev, qual, 0x20);
+}
+
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
 {
-       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-       u8 r17;
        u8 up_bound;
        u8 low_bound;
 
-       rt73usb_bbp_read(rt2x00dev, 17, &r17);
-
        /*
         * Determine r17 bounds.
         */
@@ -911,10 +970,10 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
                        up_bound += 0x10;
                }
        } else {
-               if (rssi > -82) {
+               if (qual->rssi > -82) {
                        low_bound = 0x1c;
                        up_bound = 0x40;
-               } else if (rssi > -84) {
+               } else if (qual->rssi > -84) {
                        low_bound = 0x1c;
                        up_bound = 0x20;
                } else {
@@ -938,37 +997,32 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
        /*
         * Special big-R17 for very short distance
         */
-       if (rssi > -35) {
-               if (r17 != 0x60)
-                       rt73usb_bbp_write(rt2x00dev, 17, 0x60);
+       if (qual->rssi > -35) {
+               rt73usb_set_vgc(rt2x00dev, qual, 0x60);
                return;
        }
 
        /*
         * Special big-R17 for short distance
         */
-       if (rssi >= -58) {
-               if (r17 != up_bound)
-                       rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->rssi >= -58) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
        /*
         * Special big-R17 for middle-short distance
         */
-       if (rssi >= -66) {
-               low_bound += 0x10;
-               if (r17 != low_bound)
-                       rt73usb_bbp_write(rt2x00dev, 17, low_bound);
+       if (qual->rssi >= -66) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
                return;
        }
 
        /*
         * Special mid-R17 for middle distance
         */
-       if (rssi >= -74) {
-               if (r17 != (low_bound + 0x10))
-                       rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08);
+       if (qual->rssi >= -74) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
                return;
        }
 
@@ -976,12 +1030,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
         * Special case: Change up_bound based on the rssi.
         * Lower up_bound when rssi is weaker then -74 dBm.
         */
-       up_bound -= 2 * (-74 - rssi);
+       up_bound -= 2 * (-74 - qual->rssi);
        if (low_bound > up_bound)
                up_bound = low_bound;
 
-       if (r17 > up_bound) {
-               rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->vgc_level > up_bound) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
@@ -991,17 +1045,12 @@ dynamic_cca_tune:
         * r17 does not yet exceed upper limit, continue and base
         * the r17 tuning on the false CCA count.
         */
-       if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-               r17 += 4;
-               if (r17 > up_bound)
-                       r17 = up_bound;
-               rt73usb_bbp_write(rt2x00dev, 17, r17);
-       } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-               r17 -= 4;
-               if (r17 < low_bound)
-                       r17 = low_bound;
-               rt73usb_bbp_write(rt2x00dev, 17, r17);
-       }
+       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+               rt73usb_set_vgc(rt2x00dev, qual,
+                               min_t(u8, qual->vgc_level + 4, up_bound));
+       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+               rt73usb_set_vgc(rt2x00dev, qual,
+                               max_t(u8, qual->vgc_level - 4, low_bound));
 }
 
 /*
@@ -1036,6 +1085,11 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
        int status;
        u32 reg;
 
+       if (len != 2048) {
+               ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len);
+               return -ENOENT;
+       }
+
        /*
         * Wait for stable hardware.
         */
@@ -1449,7 +1503,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                           test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
@@ -1815,6 +1869,14 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
                __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
 
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
        /*
         * Read frequency offset.
         */
@@ -2020,7 +2082,9 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-           IEEE80211_HW_SIGNAL_DBM;
+           IEEE80211_HW_SIGNAL_DBM |
+           IEEE80211_HW_SUPPORTS_PS |
+           IEEE80211_HW_PS_NULLFUNC_STACK;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
@@ -2121,6 +2185,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
        struct rt2x00_field32 field;
        int retval;
        u32 reg;
+       u32 offset;
 
        /*
         * First pass the configuration through rt2x00lib, that will
@@ -2132,24 +2197,23 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
        if (retval)
                return retval;
 
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues/
+        */
+       if (queue_idx >= 4)
+               return 0;
+
        queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
 
        /* Update WMM TXOP register */
-       if (queue_idx < 2) {
-               field.bit_offset = queue_idx * 16;
-               field.bit_mask = 0xffff << field.bit_offset;
-
-               rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
-               rt2x00_set_field32(&reg, field, queue->txop);
-               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;
-
-               rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
-               rt2x00_set_field32(&reg, field, queue->txop);
-               rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-       }
+       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
+       field.bit_offset = (queue_idx & 1) * 16;
+       field.bit_mask = 0xffff << field.bit_offset;
+
+       rt2x00usb_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field, queue->txop);
+       rt2x00usb_register_write(rt2x00dev, offset, reg);
 
        /* Update WMM registers */
        field.bit_offset = queue_idx * 4;
@@ -2220,6 +2284,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .uninitialize           = rt2x00usb_uninitialize,
        .clear_entry            = rt2x00usb_clear_entry,
        .set_device_state       = rt73usb_set_device_state,
+       .rfkill_poll            = rt73usb_rfkill_poll,
        .link_stats             = rt73usb_link_stats,
        .reset_tuner            = rt73usb_reset_tuner,
        .link_tuner             = rt73usb_link_tuner,
index 46e1405eb0e21ae7d643e5b6d17a011101199d30..834b28ce6cde569b8c93f7140b2a27e9ef7127d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
        <http://rt2x00.serialmonkey.com>
 
        This program is free software; you can redistribute it and/or modify
@@ -267,6 +267,19 @@ struct hw_pairwise_ta_entry {
  * MAC_CSR13: GPIO.
  */
 #define MAC_CSR13                      0x3034
+#define MAC_CSR13_BIT0                 FIELD32(0x00000001)
+#define MAC_CSR13_BIT1                 FIELD32(0x00000002)
+#define MAC_CSR13_BIT2                 FIELD32(0x00000004)
+#define MAC_CSR13_BIT3                 FIELD32(0x00000008)
+#define MAC_CSR13_BIT4                 FIELD32(0x00000010)
+#define MAC_CSR13_BIT5                 FIELD32(0x00000020)
+#define MAC_CSR13_BIT6                 FIELD32(0x00000040)
+#define MAC_CSR13_BIT7                 FIELD32(0x00000080)
+#define MAC_CSR13_BIT8                 FIELD32(0x00000100)
+#define MAC_CSR13_BIT9                 FIELD32(0x00000200)
+#define MAC_CSR13_BIT10                        FIELD32(0x00000400)
+#define MAC_CSR13_BIT11                        FIELD32(0x00000800)
+#define MAC_CSR13_BIT12                        FIELD32(0x00001000)
 
 /*
  * MAC_CSR14: LED control register.
index 3b1e1c2aad26cb35e18167eb7da16e5e354b98b4..9718f61809cfd9b343be23063fb2a6345426b8b3 100644 (file)
@@ -100,6 +100,8 @@ struct rtl8187_priv {
        struct usb_device *udev;
        u32 rx_conf;
        struct usb_anchor anchored;
+       struct delayed_work work;
+       struct ieee80211_hw *dev;
        u16 txpwr_base;
        u8 asic_rev;
        u8 is_rtl8187b;
@@ -117,7 +119,7 @@ struct rtl8187_priv {
        struct {
                __le64 buf;
                struct sk_buff_head queue;
-       } b_tx_status;
+       } b_tx_status; /* This queue is used by both -b and non-b devices */
 };
 
 void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
index 22bc07ef2f3784f70d3588d0a481993dde08a9b8..82bd47e7c617795045a6d3f0b9d9c4590b2d7a53 100644 (file)
@@ -177,25 +177,33 @@ static void rtl8187_tx_cb(struct urb *urb)
                                          sizeof(struct rtl8187_tx_hdr));
        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);
+       if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+               if (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;
+                       /* 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");
+                               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)
+                               old_skb = skb_dequeue(&priv->b_tx_status.queue);
+                               ieee80211_tx_status_irqsafe(hw, old_skb);
+                       }
+                       return;
+               } else {
                        info->flags |= IEEE80211_TX_STAT_ACK;
+               }
+       }
+       if (priv->is_rtl8187b)
                ieee80211_tx_status_irqsafe(hw, skb);
+       else {
+               /* Retry information for the RTI8187 is only available by
+                * reading a register in the device. We are in interrupt mode
+                * here, thus queue the skb and finish on a work queue. */
+               skb_queue_tail(&priv->b_tx_status.queue, skb);
+               queue_delayed_work(hw->workqueue, &priv->work, 0);
        }
 }
 
@@ -391,7 +399,7 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
        struct rtl8187_rx_info *info;
        int ret = 0;
 
-       while (skb_queue_len(&priv->rx_queue) < 8) {
+       while (skb_queue_len(&priv->rx_queue) < 16) {
                skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
                if (!skb) {
                        ret = -ENOMEM;
@@ -645,7 +653,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
 
        rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
        rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
-       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0);
 
        // TODO: set RESP_RATE and BRSR properly
        rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
@@ -765,9 +773,6 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
        rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1);
-       reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK);
-       reg |= RTL818X_RATE_FALLBACK_ENABLE;
-       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg);
 
        rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
        rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
@@ -855,6 +860,34 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        return 0;
 }
 
+static void rtl8187_work(struct work_struct *work)
+{
+       /* The RTL8187 returns the retry count through register 0xFFFA. In
+        * addition, it appears to be a cumulative retry count, not the
+        * value for the current TX packet. When multiple TX entries are
+        * queued, the retry count will be valid for the last one in the queue.
+        * The "error" should not matter for purposes of rate setting. */
+       struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+                                   work.work);
+       struct ieee80211_tx_info *info;
+       struct ieee80211_hw *dev = priv->dev;
+       static u16 retry;
+       u16 tmp;
+
+       mutex_lock(&priv->conf_mutex);
+       tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA);
+       while (skb_queue_len(&priv->b_tx_status.queue) > 0) {
+               struct sk_buff *old_skb;
+
+               old_skb = skb_dequeue(&priv->b_tx_status.queue);
+               info = IEEE80211_SKB_CB(old_skb);
+               info->status.rates[0].count = tmp - retry + 1;
+               ieee80211_tx_status_irqsafe(dev, old_skb);
+       }
+       retry = tmp;
+       mutex_unlock(&priv->conf_mutex);
+}
+
 static int rtl8187_start(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
@@ -869,6 +902,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
        mutex_lock(&priv->conf_mutex);
 
        init_usb_anchor(&priv->anchored);
+       priv->dev = dev;
 
        if (priv->is_rtl8187b) {
                reg = RTL818X_RX_CONF_MGMT |
@@ -936,6 +970,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
        reg |= RTL818X_CMD_TX_ENABLE;
        reg |= RTL818X_CMD_RX_ENABLE;
        rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+       INIT_DELAYED_WORK(&priv->work, rtl8187_work);
        mutex_unlock(&priv->conf_mutex);
 
        return 0;
@@ -966,6 +1001,8 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
                dev_kfree_skb_any(skb);
 
        usb_kill_anchored_urbs(&priv->anchored);
+       if (!priv->is_rtl8187b)
+               cancel_delayed_work_sync(&priv->work);
        mutex_unlock(&priv->conf_mutex);
 }
 
@@ -974,19 +1011,21 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
 {
        struct rtl8187_priv *priv = dev->priv;
        int i;
+       int ret = -EOPNOTSUPP;
 
+       mutex_lock(&priv->conf_mutex);
        if (priv->mode != NL80211_IFTYPE_MONITOR)
-               return -EOPNOTSUPP;
+               goto exit;
 
        switch (conf->type) {
        case NL80211_IFTYPE_STATION:
                priv->mode = conf->type;
                break;
        default:
-               return -EOPNOTSUPP;
+               goto exit;
        }
 
-       mutex_lock(&priv->conf_mutex);
+       ret = 0;
        priv->vif = conf->vif;
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
@@ -995,8 +1034,9 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
                                 ((u8 *)conf->mac_addr)[i]);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
+exit:
        mutex_unlock(&priv->conf_mutex);
-       return 0;
+       return ret;
 }
 
 static void rtl8187_remove_interface(struct ieee80211_hw *dev,
index 7015f2480550faf6145cb175780217538e6a5a88..d6bf8d2ef8eaff8bc29897c9b87ab0604d8dd414 100644 (file)
@@ -1125,7 +1125,7 @@ static int strip_seq_show(struct seq_file *seq, void *v)
 }
 
 
-static struct seq_operations strip_seq_ops = {
+static const struct seq_operations strip_seq_ops = {
        .start = strip_seq_start,
        .next  = strip_seq_next,
        .stop  = strip_seq_stop,
index c99a1b6b948fca668dfbf31b82ace895bb005de7..c8d5c34e8ddffb6943120423040e2d669a85cce7 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 
 #include <net/iw_handler.h>
 
@@ -111,12 +112,6 @@ static void wl3501_release(struct pcmcia_device *link);
  */
 static dev_info_t wl3501_dev_info = "wl3501_cs";
 
-static int wl3501_chan2freq[] = {
-       [0]  = 2412, [1]  = 2417, [2]  = 2422, [3]  = 2427, [4] = 2432,
-       [5]  = 2437, [6]  = 2442, [7]  = 2447, [8]  = 2452, [9] = 2457,
-       [10] = 2462, [11] = 2467, [12] = 2472, [13] = 2477,
-};
-
 static const struct {
        int reg_domain;
        int min, max, deflt;
@@ -1510,7 +1505,7 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info,
 {
        struct wl3501_card *this = netdev_priv(dev);
 
-       wrqu->freq.m = wl3501_chan2freq[this->chan - 1] * 100000;
+       wrqu->freq.m = ieee80211_dsss_chan_to_freq(this->chan) * 100000;
        wrqu->freq.e = 1;
        return 0;
 }
index b45c27d42fd83f98ac6a5f3479b0251f40443e7b..6226ac2357f82a308c6efa7d42daab08d4122a91 100644 (file)
@@ -919,10 +919,9 @@ static int zd1201_set_freq(struct net_device *dev,
        if (freq->e == 0)
                channel = freq->m;
        else {
-               if (freq->m >= 2482)
-                       channel = 14;
-               if (freq->m >= 2407)
-                       channel = (freq->m-2407)/5;
+               channel = ieee80211_freq_to_dsss_chan(freq->m);
+               if (channel < 0)
+                       channel = 0;
        }
 
        err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
index cd6184ee08ee473b01631a5b50dbb30dae521e89..9f102a6535c4976b6a7451a75bcdb19386d5d718 100644 (file)
@@ -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(&np->napi);
+       napi_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(&np->napi);
+                       napi_schedule(&np->napi);
        }
        spin_unlock_bh(&np->rx_lock);
 
@@ -979,7 +979,7 @@ err:
 
                RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
                if (!more_to_do)
-                       __netif_rx_complete(napi);
+                       __napi_complete(napi);
 
                local_irq_restore(flags);
        }
@@ -1317,7 +1317,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(&np->napi);
+                       napi_schedule(&np->napi);
        }
 
        spin_unlock_irqrestore(&np->tx_lock, flags);
index 03a3f34e90393c43202db9731caac53cd25ed40a..a12a7211c982fc7284b8cb2a01b0c52c966a2718 100644 (file)
@@ -183,7 +183,7 @@ static int __init sonic_probe1(struct net_device *dev)
 
        if (lp->descriptors == NULL) {
                printk(KERN_ERR "%s: couldn't alloc DMA memory for "
-                               " descriptors.\n", lp->device->bus_id);
+                               " descriptors.\n", dev_name(lp->device));
                goto out;
        }
 
index f0b15c9347d0dae517497544ef629b9e0f8d80c1..0a6992d8611b6178cbc1a29b94914fd57148d3a4 100644 (file)
@@ -358,6 +358,17 @@ static void znet_set_multicast_list (struct net_device *dev)
         * multicast address configured isn't equal to IFF_ALLMULTI */
 }
 
+static const struct net_device_ops znet_netdev_ops = {
+       .ndo_open               = znet_open,
+       .ndo_stop               = znet_close,
+       .ndo_start_xmit         = znet_send_packet,
+       .ndo_set_multicast_list = znet_set_multicast_list,
+       .ndo_tx_timeout         = znet_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 /* The Z-Note probe is pretty easy.  The NETIDBLK exists in the safe-to-probe
    BIOS area.  We just scan for the signature, and pull the vital parameters
    out of the structure. */
@@ -440,11 +451,7 @@ static int __init znet_probe (void)
        znet->tx_end = znet->tx_start + znet->tx_buf_len;
 
        /* The ZNET-specific entries in the device structure. */
-       dev->open = &znet_open;
-       dev->hard_start_xmit = &znet_send_packet;
-       dev->stop = &znet_close;
-       dev->set_multicast_list = &znet_set_multicast_list;
-       dev->tx_timeout = znet_tx_timeout;
+       dev->netdev_ops = &znet_netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
        err = register_netdev(dev);
        if (err)
index f5e618562c5ff9b1be02d014a022ca13e98e10ef..6669adf355befa399496f26bcd15f12018a82eee 100644 (file)
@@ -60,6 +60,9 @@
  *    1.25  Added Packing support
  *    1.5
  */
+
+#define KMSG_COMPONENT "claw"
+
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 #include <asm/debug.h>
@@ -94,7 +97,7 @@
    CLAW uses the s390dbf file system  see claw_trace and claw_setup
 */
 
-
+static char version[] __initdata = "CLAW driver";
 static char debug_buffer[255];
 /**
  * Debug Facility Stuff
@@ -206,20 +209,30 @@ static struct net_device_stats *claw_stats(struct net_device *dev);
 static int pages_to_order_of_mag(int num_of_pages);
 static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
 /* sysfs Functions */
-static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
+static ssize_t claw_hname_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t claw_hname_write(struct device *dev,
+       struct device_attribute *attr,
        const char *buf, size_t count);
-static ssize_t claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t claw_adname_write(struct device *dev, struct device_attribute *attr,
+static ssize_t claw_adname_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t claw_adname_write(struct device *dev,
+       struct device_attribute *attr,
        const char *buf, size_t count);
-static ssize_t claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t claw_apname_write(struct device *dev, struct device_attribute *attr,
+static ssize_t claw_apname_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t claw_apname_write(struct device *dev,
+       struct device_attribute *attr,
        const char *buf, size_t count);
-static ssize_t claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t claw_wbuff_write(struct device *dev, struct device_attribute *attr,
+static ssize_t claw_wbuff_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t claw_wbuff_write(struct device *dev,
+       struct device_attribute *attr,
        const char *buf, size_t count);
-static ssize_t claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t claw_rbuff_write(struct device *dev, struct device_attribute *attr,
+static ssize_t claw_rbuff_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t claw_rbuff_write(struct device *dev,
+       struct device_attribute *attr,
        const char *buf, size_t count);
 static int claw_add_files(struct device *dev);
 static void claw_remove_files(struct device *dev);
@@ -298,8 +311,8 @@ claw_probe(struct ccwgroup_device *cgdev)
        if (rc) {
                probe_error(cgdev);
                put_device(&cgdev->dev);
-               printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
-                       dev_name(&cgdev->cdev[0]->dev), __func__, __LINE__);
+               dev_err(&cgdev->dev, "Creating the /proc files for a new"
+               " CLAW device failed\n");
                CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
                return rc;
        }
@@ -496,7 +509,8 @@ claw_open(struct net_device *dev)
            ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
            (((privptr->channel[READ].flag |
                privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
-                printk(KERN_INFO "%s: remote side is not ready\n", dev->name);
+               dev_info(&privptr->channel[READ].cdev->dev,
+                       "%s: remote side is not ready\n", dev->name);
                CLAW_DBF_TEXT(2, trace, "notrdy");
 
                 for ( i = 0; i < 2;  i++) {
@@ -582,10 +596,9 @@ claw_irq_handler(struct ccw_device *cdev,
        CLAW_DBF_TEXT(4, trace, "clawirq");
         /* Bypass all 'unsolicited interrupts' */
        if (!cdev->dev.driver_data) {
-                printk(KERN_WARNING "claw: unsolicited interrupt for device:"
-                       "%s received c-%02x d-%02x\n",
-                      dev_name(&cdev->dev), irb->scsw.cmd.cstat,
-                      irb->scsw.cmd.dstat);
+               dev_warn(&cdev->dev, "An uninitialized CLAW device received an"
+                       " IRQ, c-%02x d-%02x\n",
+                       irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
                CLAW_DBF_TEXT(2, trace, "badirq");
                 return;
         }
@@ -597,8 +610,7 @@ claw_irq_handler(struct ccw_device *cdev,
        else if (privptr->channel[WRITE].cdev == cdev)
                p_ch = &privptr->channel[WRITE];
        else {
-               printk(KERN_WARNING "claw: Can't determine channel for "
-                       "interrupt, device %s\n", dev_name(&cdev->dev));
+               dev_warn(&cdev->dev, "The device is not a CLAW device\n");
                CLAW_DBF_TEXT(2, trace, "badchan");
                return;
        }
@@ -612,7 +624,8 @@ claw_irq_handler(struct ccw_device *cdev,
 
        /* Check for good subchannel return code, otherwise info message */
        if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) {
-                printk(KERN_INFO "%s: subchannel check for device: %04x -"
+               dev_info(&cdev->dev,
+                       "%s: subchannel check for device: %04x -"
                        " Sch Stat %02x  Dev Stat %02x CPA - %04x\n",
                         dev->name, p_ch->devno,
                        irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
@@ -651,7 +664,7 @@ claw_irq_handler(struct ccw_device *cdev,
                        wake_up(&p_ch->wait); /* wake claw_open (READ)*/
                } else if (p_ch->flag == CLAW_WRITE) {
                        p_ch->claw_state = CLAW_START_WRITE;
-                       /*      send SYSTEM_VALIDATE                    */
+                       /*      send SYSTEM_VALIDATE                    */
                        claw_strt_read(dev, LOCK_NO);
                        claw_send_control(dev,
                                SYSTEM_VALIDATE_REQUEST,
@@ -659,10 +672,9 @@ claw_irq_handler(struct ccw_device *cdev,
                                p_env->host_name,
                                p_env->adapter_name);
                } else {
-                       printk(KERN_WARNING "claw: unsolicited "
-                               "interrupt for device:"
-                               "%s received c-%02x d-%02x\n",
-                               dev_name(&cdev->dev),
+                       dev_warn(&cdev->dev, "The CLAW device received"
+                               " an unexpected IRQ, "
+                               "c-%02x d-%02x\n",
                                irb->scsw.cmd.cstat,
                                irb->scsw.cmd.dstat);
                        return;
@@ -677,8 +689,8 @@ claw_irq_handler(struct ccw_device *cdev,
                            (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
                            (p_ch->irb->ecw[0])        == 0) {
                                privptr->stats.rx_errors++;
-                               printk(KERN_INFO "%s: Restart is "
-                                       "required after remote "
+                               dev_info(&cdev->dev,
+                                       "%s: Restart is required after remote "
                                        "side recovers \n",
                                        dev->name);
                        }
@@ -713,11 +725,13 @@ claw_irq_handler(struct ccw_device *cdev,
                return;
        case CLAW_START_WRITE:
                if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
-                       printk(KERN_INFO "%s: Unit Check Occured in "
+                       dev_info(&cdev->dev,
+                               "%s: Unit Check Occured in "
                                "write channel\n", dev->name);
                        clear_bit(0, (void *)&p_ch->IO_active);
                        if (p_ch->irb->ecw[0] & 0x80) {
-                               printk(KERN_INFO "%s: Resetting Event "
+                               dev_info(&cdev->dev,
+                                       "%s: Resetting Event "
                                        "occurred:\n", dev->name);
                                init_timer(&p_ch->timer);
                                p_ch->timer.function =
@@ -725,7 +739,8 @@ claw_irq_handler(struct ccw_device *cdev,
                                p_ch->timer.data = (unsigned long)p_ch;
                                p_ch->timer.expires = jiffies + 10*HZ;
                                add_timer(&p_ch->timer);
-                               printk(KERN_INFO "%s: write connection "
+                               dev_info(&cdev->dev,
+                                       "%s: write connection "
                                        "restarting\n", dev->name);
                        }
                        CLAW_DBF_TEXT(4, trace, "rstrtwrt");
@@ -733,9 +748,10 @@ claw_irq_handler(struct ccw_device *cdev,
                }
                if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
                        clear_bit(0, (void *)&p_ch->IO_active);
-                       printk(KERN_INFO "%s: Unit Exception "
-                              "Occured in write channel\n",
-                              dev->name);
+                       dev_info(&cdev->dev,
+                               "%s: Unit Exception "
+                               "occurred in write channel\n",
+                               dev->name);
                }
                if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
                (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
@@ -757,8 +773,9 @@ claw_irq_handler(struct ccw_device *cdev,
                CLAW_DBF_TEXT(4, trace, "StWtExit");
                return;
        default:
-               printk(KERN_WARNING "%s: wrong selection code - irq "
-                       "state=%d\n", dev->name, p_ch->claw_state);
+               dev_warn(&cdev->dev,
+                       "The CLAW device for %s received an unexpected IRQ\n",
+                        dev->name);
                CLAW_DBF_TEXT(2, trace, "badIRQ");
                return;
         }
@@ -910,8 +927,10 @@ claw_release(struct net_device *dev)
         if (((privptr->channel[READ].last_dstat |
                privptr->channel[WRITE].last_dstat) &
                ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) {
-                printk(KERN_WARNING "%s: channel problems during close - "
-                       "read: %02x -  write: %02x\n",
+               dev_warn(&privptr->channel[READ].cdev->dev,
+                       "Deactivating %s completed with incorrect"
+                       " subchannel status "
+                       "(read %02x, write %02x)\n",
                 dev->name,
                privptr->channel[READ].last_dstat,
                privptr->channel[WRITE].last_dstat);
@@ -1076,8 +1095,8 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
         }
 
         if ( privptr-> p_read_active_first ==NULL ) {
-                privptr-> p_read_active_first= p_first;  /*    set new first */
-                privptr-> p_read_active_last = p_last;   /*    set new last  */
+               privptr->p_read_active_first = p_first;  /*  set new first */
+               privptr->p_read_active_last  = p_last;   /*  set new last  */
         }
         else {
 
@@ -1113,7 +1132,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
                         privptr->p_read_active_last->r_TIC_2.cda=
                                (__u32)__pa(&p_first->read);
                 }
-                /*      chain in new set of blocks                              */
+               /*      chain in new set of blocks                         */
                 privptr->p_read_active_last->next = p_first;
                 privptr->p_read_active_last=p_last;
         } /* end of if ( privptr-> p_read_active_first ==NULL)  */
@@ -1135,21 +1154,18 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
                case -EBUSY: /* BUSY is a transient state no action needed */
                        break;
                case -ENODEV:
-                       printk(KERN_EMERG "%s: Missing device called "
-                               "for IO ENODEV\n", dev_name(&cdev->dev));
-                       break;
-               case -EIO:
-                       printk(KERN_EMERG "%s: Status pending... EIO \n",
-                               dev_name(&cdev->dev));
+                       dev_err(&cdev->dev, "The remote channel adapter is not"
+                               " available\n");
                        break;
                case -EINVAL:
-                       printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
-                               dev_name(&cdev->dev));
+                       dev_err(&cdev->dev,
+                               "The status of the remote channel adapter"
+                               " is not valid\n");
                        break;
                default:
-                       printk(KERN_EMERG "%s: Unknown error in "
-                                "Do_IO %d\n", dev_name(&cdev->dev),
-                              return_code);
+                       dev_err(&cdev->dev, "The common device layer"
+                               " returned error code %d\n",
+                                 return_code);
                }
        }
        CLAW_DBF_TEXT(4, trace, "ccwret");
@@ -1163,40 +1179,41 @@ static void
 ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
 {
        struct net_device *ndev = p_ch->ndev;
+       struct device *dev = &p_ch->cdev->dev;
 
        CLAW_DBF_TEXT(4, trace, "unitchek");
-        printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n",
-              ndev->name, sense);
+       dev_warn(dev, "The communication peer of %s disconnected\n",
+               ndev->name);
 
         if (sense & 0x40) {
                 if (sense & 0x01) {
-                        printk(KERN_WARNING "%s: Interface disconnect or "
-                               "Selective reset "
-                               "occurred (remote side)\n", ndev->name);
-                }
-                else {
-                        printk(KERN_WARNING "%s: System reset occured"
-                               " (remote side)\n", ndev->name);
+                       dev_warn(dev, "The remote channel adapter for"
+                               " %s has been reset\n",
+                               ndev->name);
                 }
         }
         else if (sense & 0x20) {
                 if (sense & 0x04) {
-                        printk(KERN_WARNING "%s: Data-streaming "
-                               "timeout)\n", ndev->name);
+                       dev_warn(dev, "A data streaming timeout occurred"
+                               " for %s\n",
+                               ndev->name);
                 }
                 else  {
-                        printk(KERN_WARNING "%s: Data-transfer parity"
-                               " error\n", ndev->name);
+                       dev_warn(dev, "A data transfer parity error occurred"
+                               " for %s\n",
+                               ndev->name);
                 }
         }
         else if (sense & 0x10) {
                 if (sense & 0x20) {
-                        printk(KERN_WARNING "%s: Hardware malfunction "
-                               "(remote side)\n", ndev->name);
+                       dev_warn(dev, "The remote channel adapter for %s"
+                               " is faulty\n",
+                               ndev->name);
                 }
                 else {
-                        printk(KERN_WARNING "%s: read-data parity error "
-                               "(remote side)\n", ndev->name);
+                       dev_warn(dev, "A read data parity error occurred"
+                               " for %s\n",
+                               ndev->name);
                 }
         }
 
@@ -1375,7 +1392,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
         */
 
         if (p_first_ccw!=NULL) {
-                /*      setup ending ccw sequence for this segment              */
+               /*      setup ending ccw sequence for this segment           */
                 pEnd=privptr->p_end_ccw;
                 if (pEnd->write1) {
                         pEnd->write1=0x00;   /* second end ccw is now active */
@@ -1697,10 +1714,11 @@ init_ccw_bk(struct net_device *dev)
                         p_buf-> w_TIC_1.flags      = 0;
                         p_buf-> w_TIC_1.count      = 0;
 
-                        if (((unsigned long)p_buff+privptr->p_env->write_size) >=
+                       if (((unsigned long)p_buff +
+                                           privptr->p_env->write_size) >=
                           ((unsigned long)(p_buff+2*
-                               (privptr->p_env->write_size) -1) & PAGE_MASK)) {
-                        p_buff= p_buff+privptr->p_env->write_size;
+                           (privptr->p_env->write_size) - 1) & PAGE_MASK)) {
+                               p_buff = p_buff+privptr->p_env->write_size;
                         }
                 }
            }
@@ -1840,15 +1858,16 @@ init_ccw_bk(struct net_device *dev)
                         p_buf->header.opcode=0xff;
                         p_buf->header.flag=CLAW_PENDING;
 
-                        if (((unsigned long)p_buff+privptr->p_env->read_size) >=
-                               ((unsigned long)(p_buff+2*(privptr->p_env->read_size) -1)
-                                & PAGE_MASK) ) {
+                       if (((unsigned long)p_buff+privptr->p_env->read_size) >=
+                         ((unsigned long)(p_buff+2*(privptr->p_env->read_size)
+                                -1)
+                          & PAGE_MASK)) {
                                 p_buff= p_buff+privptr->p_env->read_size;
                         }
                         else {
                                 p_buff=
                                (void *)((unsigned long)
-                                       (p_buff+2*(privptr->p_env->read_size) -1)
+                                       (p_buff+2*(privptr->p_env->read_size)-1)
                                         & PAGE_MASK) ;
                         }
                 }   /* for read_buffers   */
@@ -1856,24 +1875,28 @@ init_ccw_bk(struct net_device *dev)
           else {  /* read Size >= PAGE_SIZE  */
                 for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
                         p_buff = (void *)__get_free_pages(__GFP_DMA,
-                               (int)pages_to_order_of_mag(privptr->p_buff_pages_perread) );
+                               (int)pages_to_order_of_mag(
+                                       privptr->p_buff_pages_perread));
                         if (p_buff==NULL) {
                                 free_pages((unsigned long)privptr->p_buff_ccw,
-                                       (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+                                       (int)pages_to_order_of_mag(privptr->
+                                       p_buff_ccw_num));
                                /* free the write pages  */
                                p_buf=privptr->p_buff_write;
                                 while (p_buf!=NULL) {
-                                        free_pages((unsigned long)p_buf->p_buffer,
-                                               (int)pages_to_order_of_mag(
-                                               privptr->p_buff_pages_perwrite ));
+                                       free_pages(
+                                           (unsigned long)p_buf->p_buffer,
+                                           (int)pages_to_order_of_mag(
+                                           privptr->p_buff_pages_perwrite));
                                         p_buf=p_buf->next;
                                 }
                                /* free any read pages already alloc  */
                                p_buf=privptr->p_buff_read;
                                 while (p_buf!=NULL) {
-                                        free_pages((unsigned long)p_buf->p_buffer,
-                                               (int)pages_to_order_of_mag(
-                                               privptr->p_buff_pages_perread ));
+                                       free_pages(
+                                           (unsigned long)p_buf->p_buffer,
+                                           (int)pages_to_order_of_mag(
+                                            privptr->p_buff_pages_perread));
                                         p_buf=p_buf->next;
                                 }
                                 privptr->p_buff_ccw=NULL;
@@ -2003,7 +2026,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
        tdev = &privptr->channel[READ].cdev->dev;
        memcpy( &temp_host_name, p_env->host_name, 8);
         memcpy( &temp_ws_name, p_env->adapter_name , 8);
-        printk(KERN_INFO "%s: CLAW device %.8s: "
+       dev_info(tdev, "%s: CLAW device %.8s: "
                "Received Control Packet\n",
                dev->name, temp_ws_name);
         if (privptr->release_pend==1) {
@@ -2022,32 +2045,30 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                if (p_ctlbk->version != CLAW_VERSION_ID) {
                        claw_snd_sys_validate_rsp(dev, p_ctlbk,
                                CLAW_RC_WRONG_VERSION);
-                       printk("%s: %d is wrong version id. "
-                              "Expected %d\n",
-                              dev->name, p_ctlbk->version,
-                              CLAW_VERSION_ID);
+                       dev_warn(tdev, "The communication peer of %s"
+                               " uses an incorrect API version %d\n",
+                               dev->name, p_ctlbk->version);
                }
                p_sysval = (struct sysval *)&(p_ctlbk->data);
-               printk("%s: Recv Sys Validate Request: "
-                      "Vers=%d,link_id=%d,Corr=%d,WS name=%."
-                      "8s,Host name=%.8s\n",
-                      dev->name, p_ctlbk->version,
-                      p_ctlbk->linkid,
-                      p_ctlbk->correlator,
-                      p_sysval->WS_name,
-                      p_sysval->host_name);
+               dev_info(tdev, "%s: Recv Sys Validate Request: "
+                       "Vers=%d,link_id=%d,Corr=%d,WS name=%.8s,"
+                       "Host name=%.8s\n",
+                       dev->name, p_ctlbk->version,
+                       p_ctlbk->linkid,
+                       p_ctlbk->correlator,
+                       p_sysval->WS_name,
+                       p_sysval->host_name);
                if (memcmp(temp_host_name, p_sysval->host_name, 8)) {
                        claw_snd_sys_validate_rsp(dev, p_ctlbk,
                                CLAW_RC_NAME_MISMATCH);
                        CLAW_DBF_TEXT(2, setup, "HSTBAD");
                        CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->host_name);
                        CLAW_DBF_TEXT_(2, setup, "%s", temp_host_name);
-                       printk(KERN_INFO "%s:  Host name mismatch\n",
-                               dev->name);
-                       printk(KERN_INFO "%s: Received :%s: "
-                               "expected :%s: \n",
-                               dev->name,
+                       dev_warn(tdev,
+                               "Host name %s for %s does not match the"
+                               " remote adapter name %s\n",
                                p_sysval->host_name,
+                               dev->name,
                                temp_host_name);
                }
                if (memcmp(temp_ws_name, p_sysval->WS_name, 8)) {
@@ -2056,35 +2077,38 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        CLAW_DBF_TEXT(2, setup, "WSNBAD");
                        CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->WS_name);
                        CLAW_DBF_TEXT_(2, setup, "%s", temp_ws_name);
-                       printk(KERN_INFO "%s: WS name mismatch\n",
-                               dev->name);
-                       printk(KERN_INFO "%s: Received :%s: "
-                              "expected :%s: \n",
-                              dev->name,
-                              p_sysval->WS_name,
-                              temp_ws_name);
+                       dev_warn(tdev, "Adapter name %s for %s does not match"
+                               " the remote host name %s\n",
+                               p_sysval->WS_name,
+                               dev->name,
+                               temp_ws_name);
                }
                if ((p_sysval->write_frame_size < p_env->write_size) &&
                    (p_env->packing == 0)) {
                        claw_snd_sys_validate_rsp(dev, p_ctlbk,
                                CLAW_RC_HOST_RCV_TOO_SMALL);
-                       printk(KERN_INFO "%s: host write size is too "
-                               "small\n", dev->name);
+                       dev_warn(tdev,
+                               "The local write buffer is smaller than the"
+                               " remote read buffer\n");
                        CLAW_DBF_TEXT(2, setup, "wrtszbad");
                }
                if ((p_sysval->read_frame_size < p_env->read_size) &&
                    (p_env->packing == 0)) {
                        claw_snd_sys_validate_rsp(dev, p_ctlbk,
                                CLAW_RC_HOST_RCV_TOO_SMALL);
-                       printk(KERN_INFO "%s: host read size is too "
-                               "small\n", dev->name);
+                       dev_warn(tdev,
+                               "The local read buffer is smaller than the"
+                               " remote write buffer\n");
                        CLAW_DBF_TEXT(2, setup, "rdsizbad");
                }
                claw_snd_sys_validate_rsp(dev, p_ctlbk, 0);
-               printk(KERN_INFO "%s: CLAW device %.8s: System validate "
-                       "completed.\n", dev->name, temp_ws_name);
-               printk("%s: sys Validate Rsize:%d Wsize:%d\n", dev->name,
-                       p_sysval->read_frame_size, p_sysval->write_frame_size);
+               dev_info(tdev,
+                       "CLAW device %.8s: System validate"
+                       " completed.\n", temp_ws_name);
+               dev_info(tdev,
+                       "%s: sys Validate Rsize:%d Wsize:%d\n",
+                       dev->name, p_sysval->read_frame_size,
+                       p_sysval->write_frame_size);
                privptr->system_validate_comp = 1;
                if (strncmp(p_env->api_type, WS_APPL_NAME_PACKED, 6) == 0)
                        p_env->packing = PACKING_ASK;
@@ -2092,8 +2116,10 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                break;
        case SYSTEM_VALIDATE_RESPONSE:
                p_sysval = (struct sysval *)&(p_ctlbk->data);
-               printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
-                       "WS name=%.8s,Host name=%.8s\n",
+               dev_info(tdev,
+                       "Settings for %s validated (version=%d, "
+                       "remote device=%d, rc=%d, adapter name=%.8s, "
+                       "host name=%.8s)\n",
                        dev->name,
                        p_ctlbk->version,
                        p_ctlbk->correlator,
@@ -2102,41 +2128,39 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        p_sysval->host_name);
                switch (p_ctlbk->rc) {
                case 0:
-                       printk(KERN_INFO "%s: CLAW device "
-                               "%.8s: System validate "
-                               "completed.\n",
-                              dev->name, temp_ws_name);
+                       dev_info(tdev, "%s: CLAW device "
+                               "%.8s: System validate completed.\n",
+                               dev->name, temp_ws_name);
                        if (privptr->system_validate_comp == 0)
                                claw_strt_conn_req(dev);
                        privptr->system_validate_comp = 1;
                        break;
                case CLAW_RC_NAME_MISMATCH:
-                       printk(KERN_INFO "%s: Sys Validate "
-                               "Resp : Host, WS name is "
-                               "mismatch\n",
-                              dev->name);
+                       dev_warn(tdev, "Validating %s failed because of"
+                               " a host or adapter name mismatch\n",
+                               dev->name);
                        break;
                case CLAW_RC_WRONG_VERSION:
-                       printk(KERN_INFO "%s: Sys Validate "
-                               "Resp : Wrong version\n",
+                       dev_warn(tdev, "Validating %s failed because of a"
+                               " version conflict\n",
                                dev->name);
                        break;
                case CLAW_RC_HOST_RCV_TOO_SMALL:
-                       printk(KERN_INFO "%s: Sys Validate "
-                               "Resp : bad frame size\n",
+                       dev_warn(tdev, "Validating %s failed because of a"
+                               " frame size conflict\n",
                                dev->name);
                        break;
                default:
-                       printk(KERN_INFO "%s: Sys Validate "
-                               "error code=%d \n",
-                                dev->name, p_ctlbk->rc);
+                       dev_warn(tdev, "The communication peer of %s rejected"
+                               " the connection\n",
+                                dev->name);
                        break;
                }
                break;
 
        case CONNECTION_REQUEST:
                p_connect = (struct conncmd *)&(p_ctlbk->data);
-               printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
+               dev_info(tdev, "%s: Recv Conn Req: Vers=%d,link_id=%d,"
                        "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
                        dev->name,
                        p_ctlbk->version,
@@ -2146,21 +2170,21 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        p_connect->WS_name);
                if (privptr->active_link_ID != 0) {
                        claw_snd_disc(dev, p_ctlbk);
-                       printk(KERN_INFO "%s: Conn Req error : "
-                               "already logical link is active \n",
+                       dev_info(tdev, "%s rejected a connection request"
+                               " because it is already active\n",
                                dev->name);
                }
                if (p_ctlbk->linkid != 1) {
                        claw_snd_disc(dev, p_ctlbk);
-                       printk(KERN_INFO "%s: Conn Req error : "
-                               "req logical link id is not 1\n",
+                       dev_info(tdev, "%s rejected a request to open multiple"
+                               " connections\n",
                                dev->name);
                }
                rc = find_link(dev, p_connect->host_name, p_connect->WS_name);
                if (rc != 0) {
                        claw_snd_disc(dev, p_ctlbk);
-                       printk(KERN_INFO "%s: Conn Resp error: "
-                               "req appl name does not match\n",
+                       dev_info(tdev, "%s rejected a connection request"
+                               " because of a type mismatch\n",
                                dev->name);
                }
                claw_send_control(dev,
@@ -2172,7 +2196,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        p_env->packing = PACK_SEND;
                        claw_snd_conn_req(dev, 0);
                }
-               printk(KERN_INFO "%s: CLAW device %.8s: Connection "
+               dev_info(tdev, "%s: CLAW device %.8s: Connection "
                        "completed link_id=%d.\n",
                        dev->name, temp_ws_name,
                        p_ctlbk->linkid);
@@ -2182,7 +2206,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                break;
        case CONNECTION_RESPONSE:
                p_connect = (struct conncmd *)&(p_ctlbk->data);
-               printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
+               dev_info(tdev, "%s: Recv Conn Resp: Vers=%d,link_id=%d,"
                        "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
                        dev->name,
                        p_ctlbk->version,
@@ -2193,16 +2217,18 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        p_connect->WS_name);
 
                if (p_ctlbk->rc != 0) {
-                       printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
-                               dev->name, p_ctlbk->rc);
+                       dev_warn(tdev, "The communication peer of %s rejected"
+                               " a connection request\n",
+                               dev->name);
                        return 1;
                }
                rc = find_link(dev,
                        p_connect->host_name, p_connect->WS_name);
                if (rc != 0) {
                        claw_snd_disc(dev, p_ctlbk);
-                       printk(KERN_INFO "%s: Conn Resp error: "
-                               "req appl name does not match\n",
+                       dev_warn(tdev, "The communication peer of %s"
+                               " rejected a connection "
+                               "request because of a type mismatch\n",
                                 dev->name);
                }
                /* should be until CONNECTION_CONFIRM */
@@ -2210,7 +2236,8 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                break;
        case CONNECTION_CONFIRM:
                p_connect = (struct conncmd *)&(p_ctlbk->data);
-               printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
+               dev_info(tdev,
+                       "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
                        "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
                        dev->name,
                        p_ctlbk->version,
@@ -2221,21 +2248,21 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                if (p_ctlbk->linkid == -(privptr->active_link_ID)) {
                        privptr->active_link_ID = p_ctlbk->linkid;
                        if (p_env->packing > PACKING_ASK) {
-                               printk(KERN_INFO "%s: Confirmed Now packing\n",
-                                       dev->name);
+                               dev_info(tdev,
+                               "%s: Confirmed Now packing\n", dev->name);
                                p_env->packing = DO_PACKED;
                        }
                        p_ch = &privptr->channel[WRITE];
                        wake_up(&p_ch->wait);
                } else {
-                      printk(KERN_INFO "%s: Conn confirm: "
-                               "unexpected linkid=%d \n",
+                       dev_warn(tdev, "Activating %s failed because of"
+                               " an incorrect link ID=%d\n",
                                dev->name, p_ctlbk->linkid);
                        claw_snd_disc(dev, p_ctlbk);
                }
                break;
        case DISCONNECT:
-               printk(KERN_INFO "%s: Disconnect: "
+               dev_info(tdev, "%s: Disconnect: "
                        "Vers=%d,link_id=%d,Corr=%d\n",
                        dev->name, p_ctlbk->version,
                        p_ctlbk->linkid, p_ctlbk->correlator);
@@ -2247,12 +2274,13 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
                        privptr->active_link_ID = 0;
                break;
        case CLAW_ERROR:
-               printk(KERN_INFO "%s: CLAW ERROR detected\n",
+               dev_warn(tdev, "The communication peer of %s failed\n",
                        dev->name);
                break;
        default:
-               printk(KERN_INFO "%s:  Unexpected command code=%d \n",
-                       dev->name,  p_ctlbk->command);
+               dev_warn(tdev, "The communication peer of %s sent"
+                       " an unknown command code\n",
+                       dev->name);
                break;
         }
 
@@ -2294,12 +2322,14 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
                         memcpy(&p_sysval->host_name, local_name, 8);
                         memcpy(&p_sysval->WS_name, remote_name, 8);
                        if (privptr->p_env->packing > 0) {
-                               p_sysval->read_frame_size=DEF_PACK_BUFSIZE;
-                               p_sysval->write_frame_size=DEF_PACK_BUFSIZE;
+                               p_sysval->read_frame_size = DEF_PACK_BUFSIZE;
+                               p_sysval->write_frame_size = DEF_PACK_BUFSIZE;
                        } else {
                                /* how big is the biggest group of packets */
-                               p_sysval->read_frame_size=privptr->p_env->read_size;
-                               p_sysval->write_frame_size=privptr->p_env->write_size;
+                          p_sysval->read_frame_size =
+                               privptr->p_env->read_size;
+                          p_sysval->write_frame_size =
+                               privptr->p_env->write_size;
                        }
                         memset(&p_sysval->reserved, 0x00, 4);
                         break;
@@ -2511,8 +2541,10 @@ unpack_read(struct net_device *dev )
                         mtc_this_frm=1;
                         if (p_this_ccw->header.length!=
                                privptr->p_env->read_size ) {
-                                printk(KERN_INFO " %s: Invalid frame detected "
-                                       "length is %02x\n" ,
+                               dev_warn(p_dev,
+                                       "The communication peer of %s"
+                                       " sent a faulty"
+                                       " frame of length %02x\n",
                                         dev->name, p_this_ccw->header.length);
                         }
                 }
@@ -2544,7 +2576,7 @@ unpack_next:
                                goto NextFrame;
                        p_packd = p_this_ccw->p_buffer+pack_off;
                        p_packh = (struct clawph *) p_packd;
-                       if ((p_packh->len == 0) || /* all done with this frame? */
+                       if ((p_packh->len == 0) || /* done with this frame? */
                            (p_packh->flag != 0))
                                goto NextFrame;
                        bytes_to_mov = p_packh->len;
@@ -2594,9 +2626,9 @@ unpack_next:
                                 netif_rx(skb);
                         }
                         else {
+                               dev_info(p_dev, "Allocating a buffer for"
+                                       " incoming data failed\n");
                                 privptr->stats.rx_dropped++;
-                                printk(KERN_WARNING "%s: %s() low on memory\n",
-                               dev->name,__func__);
                         }
                         privptr->mtc_offset=0;
                         privptr->mtc_logical_link=-1;
@@ -2720,8 +2752,8 @@ claw_strt_out_IO( struct net_device *dev )
         if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
                 parm = (unsigned long) p_ch;
                CLAW_DBF_TEXT(2, trace, "StWrtIO");
-                rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm,
-                                      0xff, 0);
+               rc = ccw_device_start(p_ch->cdev, &p_first_ccw->write, parm,
+                                     0xff, 0);
                 if (rc != 0) {
                         ccw_check_return_code(p_ch->cdev, rc);
                 }
@@ -2816,22 +2848,26 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
  * Initialize everything of the net device except the name and the
  * channel structs.
  */
+static const struct net_device_ops claw_netdev_ops = {
+       .ndo_open               = claw_open,
+       .ndo_stop               = claw_release,
+       .ndo_get_stats          = claw_stats,
+       .ndo_start_xmit         = claw_tx,
+       .ndo_change_mtu         = claw_change_mtu,
+};
+
 static void
 claw_init_netdevice(struct net_device * dev)
 {
        CLAW_DBF_TEXT(2, setup, "init_dev");
        CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
        dev->mtu = CLAW_DEFAULT_MTU_SIZE;
-       dev->hard_start_xmit = claw_tx;
-       dev->open = claw_open;
-       dev->stop = claw_release;
-       dev->get_stats = claw_stats;
-       dev->change_mtu = claw_change_mtu;
        dev->hard_header_len = 0;
        dev->addr_len = 0;
        dev->type = ARPHRD_SLIP;
        dev->tx_queue_len = 1300;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+       dev->netdev_ops = &claw_netdev_ops;
        CLAW_DBF_TEXT(2, setup, "initok");
        return;
 }
@@ -2880,8 +2916,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
        int ret;
        struct ccw_dev_id dev_id;
 
-       printk(KERN_INFO "claw: add for %s\n",
-              dev_name(&cgdev->cdev[READ]->dev));
+       dev_info(&cgdev->dev, "add for %s\n",
+                dev_name(&cgdev->cdev[READ]->dev));
        CLAW_DBF_TEXT(2, setup, "new_dev");
        privptr = cgdev->dev.driver_data;
        cgdev->cdev[READ]->dev.driver_data = privptr;
@@ -2897,29 +2933,28 @@ claw_new_device(struct ccwgroup_device *cgdev)
        if (ret == 0)
                ret = add_channel(cgdev->cdev[1],1,privptr);
        if (ret != 0) {
-               printk(KERN_WARNING
-                       "add channel failed with ret = %d\n", ret);
+               dev_warn(&cgdev->dev, "Creating a CLAW group device"
+                       " failed with error code %d\n", ret);
                goto out;
        }
        ret = ccw_device_set_online(cgdev->cdev[READ]);
        if (ret != 0) {
-               printk(KERN_WARNING
-                       "claw: ccw_device_set_online %s READ failed "
-                      "with ret = %d\n", dev_name(&cgdev->cdev[READ]->dev),
-                      ret);
+               dev_warn(&cgdev->dev,
+                       "Setting the read subchannel online"
+                       " failed with error code %d\n", ret);
                goto out;
        }
        ret = ccw_device_set_online(cgdev->cdev[WRITE]);
        if (ret != 0) {
-               printk(KERN_WARNING
-                       "claw: ccw_device_set_online %s WRITE failed "
-                      "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev),
-                      ret);
+               dev_warn(&cgdev->dev,
+                       "Setting the write subchannel online "
+                       "failed with error code %d\n", ret);
                goto out;
        }
        dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
        if (!dev) {
-               printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__);
+               dev_warn(&cgdev->dev,
+                       "Activating the CLAW device failed\n");
                goto out;
        }
        dev->ml_priv = privptr;
@@ -2947,13 +2982,13 @@ claw_new_device(struct ccwgroup_device *cgdev)
        privptr->channel[WRITE].ndev = dev;
        privptr->p_env->ndev = dev;
 
-       printk(KERN_INFO "%s:readsize=%d  writesize=%d "
+       dev_info(&cgdev->dev, "%s:readsize=%d  writesize=%d "
                "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n",
                 dev->name, p_env->read_size,
                p_env->write_size, p_env->read_buffers,
                 p_env->write_buffers, p_env->devno[READ],
                p_env->devno[WRITE]);
-        printk(KERN_INFO "%s:host_name:%.8s, adapter_name "
+       dev_info(&cgdev->dev, "%s:host_name:%.8s, adapter_name "
                ":%.8s api_type: %.8s\n",
                 dev->name, p_env->host_name,
                p_env->adapter_name , p_env->api_type);
@@ -2997,8 +3032,8 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
        ndev = priv->channel[READ].ndev;
        if (ndev) {
                /* Close the device */
-               printk(KERN_INFO
-                       "%s: shuting down \n",ndev->name);
+               dev_info(&cgdev->dev, "%s: shutting down \n",
+                       ndev->name);
                if (ndev->flags & IFF_RUNNING)
                        ret = claw_release(ndev);
                ndev->flags &=~IFF_RUNNING;
@@ -3023,8 +3058,7 @@ claw_remove_device(struct ccwgroup_device *cgdev)
        CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
        priv = cgdev->dev.driver_data;
        BUG_ON(!priv);
-       printk(KERN_INFO "claw: %s() called %s will be removed.\n",
-                       __func__, dev_name(&cgdev->cdev[0]->dev));
+       dev_info(&cgdev->dev, " will be removed.\n");
        if (cgdev->state == CCWGROUP_ONLINE)
                claw_shutdown_device(cgdev);
        claw_remove_files(&cgdev->dev);
@@ -3063,7 +3097,8 @@ claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-claw_hname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+claw_hname_write(struct device *dev, struct device_attribute *attr,
+        const char *buf, size_t count)
 {
        struct claw_privbk *priv;
        struct claw_env *  p_env;
@@ -3100,7 +3135,8 @@ claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-claw_adname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+claw_adname_write(struct device *dev, struct device_attribute *attr,
+        const char *buf, size_t count)
 {
        struct claw_privbk *priv;
        struct claw_env *  p_env;
@@ -3138,7 +3174,8 @@ claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-claw_apname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+claw_apname_write(struct device *dev, struct device_attribute *attr,
+       const char *buf, size_t count)
 {
        struct claw_privbk *priv;
        struct claw_env *  p_env;
@@ -3185,7 +3222,8 @@ claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+claw_wbuff_write(struct device *dev, struct device_attribute *attr,
+       const char *buf, size_t count)
 {
        struct claw_privbk *priv;
        struct claw_env *  p_env;
@@ -3226,7 +3264,8 @@ claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+claw_rbuff_write(struct device *dev, struct device_attribute *attr,
+       const char *buf, size_t count)
 {
        struct claw_privbk *priv;
        struct claw_env *p_env;
@@ -3289,7 +3328,7 @@ claw_cleanup(void)
 {
        unregister_cu3088_discipline(&claw_group_driver);
        claw_unregister_debug_facility();
-       printk(KERN_INFO "claw: Driver unloaded\n");
+       pr_info("Driver unloaded\n");
 
 }
 
@@ -3303,12 +3342,12 @@ static int __init
 claw_init(void)
 {
        int ret = 0;
-       printk(KERN_INFO "claw: starting driver\n");
 
+       pr_info("Loading %s\n", version);
        ret = claw_register_debug_facility();
        if (ret) {
-               printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
-                       __func__,ret);
+               pr_err("Registering with the S/390 debug feature"
+                       " failed with error code %d\n", ret);
                return ret;
        }
        CLAW_DBF_TEXT(2, setup, "init_mod");
@@ -3316,8 +3355,8 @@ claw_init(void)
        if (ret) {
                CLAW_DBF_TEXT(2, setup, "init_bad");
                claw_unregister_debug_facility();
-               printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
-                       __func__,ret);
+               pr_err("Registering with the cu3088 device driver failed "
+                          "with error code %d\n", ret);
        }
        return ret;
 }
index 2678573becec0f625cf58ea92ba904a1128a22d7..8f2a888d0a0ac7226ec61f06ac7da2893c1f876e 100644 (file)
@@ -1099,12 +1099,24 @@ static void ctcm_free_netdevice(struct net_device *dev)
 
 struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
 
+static const struct net_device_ops ctcm_netdev_ops = {
+       .ndo_open               = ctcm_open,
+       .ndo_stop               = ctcm_close,
+       .ndo_get_stats          = ctcm_stats,
+       .ndo_change_mtu         = ctcm_change_mtu,
+       .ndo_start_xmit         = ctcm_tx,
+};
+
+static const struct net_device_ops ctcm_mpc_netdev_ops = {
+       .ndo_open               = ctcm_open,
+       .ndo_stop               = ctcm_close,
+       .ndo_get_stats          = ctcm_stats,
+       .ndo_change_mtu         = ctcm_change_mtu,
+       .ndo_start_xmit         = ctcmpc_tx,
+};
+
 void static ctcm_dev_setup(struct net_device *dev)
 {
-       dev->open = ctcm_open;
-       dev->stop = ctcm_close;
-       dev->get_stats = ctcm_stats;
-       dev->change_mtu = ctcm_change_mtu;
        dev->type = ARPHRD_SLIP;
        dev->tx_queue_len = 100;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
@@ -1157,12 +1169,12 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
                dev->mtu = MPC_BUFSIZE_DEFAULT -
                                TH_HEADER_LENGTH - PDU_HEADER_LENGTH;
 
-               dev->hard_start_xmit = ctcmpc_tx;
+               dev->netdev_ops = &ctcm_mpc_netdev_ops;
                dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
                priv->buffer_size = MPC_BUFSIZE_DEFAULT;
        } else {
                dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
-               dev->hard_start_xmit = ctcm_tx;
+               dev->netdev_ops = &ctcm_netdev_ops;
                dev->hard_header_len = LL_HEADER_LENGTH + 2;
        }
 
index 49c3bfa1afd7c364eea57e017f0e35be84ccf8e7..083f787d260d6f51d2ab807f5a9b9f1fb5a003f0 100644 (file)
@@ -2101,6 +2101,20 @@ lcs_register_netdev(struct ccwgroup_device *ccwgdev)
 /**
  * lcs_new_device will be called by setting the group device online.
  */
+static const struct net_device_ops lcs_netdev_ops = {
+       .ndo_open               = lcs_open_device,
+       .ndo_stop               = lcs_stop_device,
+       .ndo_get_stats          = lcs_getstats,
+       .ndo_start_xmit         = lcs_start_xmit,
+};
+
+static const struct net_device_ops lcs_mc_netdev_ops = {
+       .ndo_open               = lcs_open_device,
+       .ndo_stop               = lcs_stop_device,
+       .ndo_get_stats          = lcs_getstats,
+       .ndo_start_xmit         = lcs_start_xmit,
+       .ndo_set_multicast_list = lcs_set_multicast_list,
+};
 
 static int
 lcs_new_device(struct ccwgroup_device *ccwgdev)
@@ -2168,14 +2182,11 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
                goto out;
        card->dev = dev;
        card->dev->ml_priv = card;
-       card->dev->open = lcs_open_device;
-       card->dev->stop = lcs_stop_device;
-       card->dev->hard_start_xmit = lcs_start_xmit;
-       card->dev->get_stats = lcs_getstats;
+       card->dev->netdev_ops = &lcs_netdev_ops;
        memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
 #ifdef CONFIG_IP_MULTICAST
        if (!lcs_check_multicast_support(card))
-               card->dev->set_multicast_list = lcs_set_multicast_list;
+               card->dev->netdev_ops = &lcs_mc_netdev_ops;
 #endif
 netdev_out:
        lcs_set_allowed_threads(card,0xffffffff);
index 930e2fc2a011a39fea837fa8435d3b1622e31fac..1ba4509435f8fbfc2f021eea0575956ae1068906 100644 (file)
@@ -1876,20 +1876,24 @@ static void netiucv_free_netdevice(struct net_device *dev)
 /**
  * Initialize a net device. (Called from kernel in alloc_netdev())
  */
+static const struct net_device_ops netiucv_netdev_ops = {
+       .ndo_open               = netiucv_open,
+       .ndo_stop               = netiucv_close,
+       .ndo_get_stats          = netiucv_stats,
+       .ndo_start_xmit         = netiucv_tx,
+       .ndo_change_mtu         = netiucv_change_mtu,
+};
+
 static void netiucv_setup_netdevice(struct net_device *dev)
 {
        dev->mtu                 = NETIUCV_MTU_DEFAULT;
-       dev->hard_start_xmit     = netiucv_tx;
-       dev->open                = netiucv_open;
-       dev->stop                = netiucv_close;
-       dev->get_stats           = netiucv_stats;
-       dev->change_mtu          = netiucv_change_mtu;
        dev->destructor          = netiucv_free_netdevice;
        dev->hard_header_len     = NETIUCV_HDRLEN;
        dev->addr_len            = 0;
        dev->type                = ARPHRD_SLIP;
        dev->tx_queue_len        = NETIUCV_QUEUELEN_DEFAULT;
        dev->flags               = IFF_POINTOPOINT | IFF_NOARP;
+       dev->netdev_ops          = &netiucv_netdev_ops;
 }
 
 /**
index 5c7c4d95c493c044141a38281e3a06b98f09464f..f675807cc48f1391413023eedd707727fbe64cea 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __CXGB3I_ULP2_DDP_H__
 #define __CXGB3I_ULP2_DDP_H__
 
+#include <linux/vmalloc.h>
+
 /**
  * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
  *
index 2d27d6d6d08ebe40fdf4b02e4c4a66b601307e11..27a677584a4cb50f6be679628303c17a700defb0 100644 (file)
@@ -21,6 +21,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
@@ -29,6 +30,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
index d5cde051806b1d5c1669c7295e734ed886b2443a..c958ac16423ce68232ebf7069629cde645cb9736 100644 (file)
@@ -467,6 +467,51 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
        /* TODO - get remaining rev 4 stuff needed */
 }
 
+static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
+{
+       int i;
+       u16 v;
+
+       /* extract the MAC address */
+       for (i = 0; i < 3; i++) {
+               v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
+               *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+       }
+       SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
+       SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+       SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+       SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
+            SSB_SPROM8_ANTAVAIL_A_SHIFT);
+       SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
+            SSB_SPROM8_ANTAVAIL_BG_SHIFT);
+       SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
+       SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
+            SSB_SPROM8_ITSSI_BG_SHIFT);
+       SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
+       SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
+            SSB_SPROM8_ITSSI_A_SHIFT);
+       SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
+       SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
+            SSB_SPROM8_GPIOA_P1_SHIFT);
+       SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
+       SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
+            SSB_SPROM8_GPIOB_P3_SHIFT);
+
+       /* Extract the antenna gain values. */
+       SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
+            SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
+       SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
+            SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
+       SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
+            SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
+       SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
+            SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+       memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
+              sizeof(out->antenna_gain.ghz5));
+
+       /* TODO - get remaining rev 8 stuff needed */
+}
+
 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
                         const u16 *in, u16 size)
 {
@@ -487,15 +532,25 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
                out->revision = 4;
                sprom_extract_r45(out, in);
        } else {
-               if (out->revision == 0)
-                       goto unsupported;
-               if (out->revision >= 1 && out->revision <= 3) {
+               switch (out->revision) {
+               case 1:
+               case 2:
+               case 3:
                        sprom_extract_r123(out, in);
-               }
-               if (out->revision == 4 || out->revision == 5)
+                       break;
+               case 4:
+               case 5:
                        sprom_extract_r45(out, in);
-               if (out->revision > 5)
-                       goto unsupported;
+                       break;
+               case 8:
+                       sprom_extract_r8(out, in);
+                       break;
+               default:
+                       ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
+                                  "  revision %d detected. Will extract"
+                                  " v1\n", out->revision);
+                       sprom_extract_r123(out, in);
+               }
        }
 
        if (out->boardflags_lo == 0xFFFF)
@@ -504,11 +559,6 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
                out->boardflags_hi = 0;  /* per specs */
 
        return 0;
-unsupported:
-       ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
-                  "detected. Will extract v1\n", out->revision);
-       sprom_extract_r123(out, in);
-       return 0;
 }
 
 static int ssb_pci_sprom_get(struct ssb_bus *bus,
index a1916078fd080a3d5ce02728c82d529febb69d23..cd4bcb6989ce0e888d7e62f1e771c18e9b2f404e 100644 (file)
@@ -235,8 +235,6 @@ struct Outgoing {
 
 
 struct arcnet_local {
-       struct net_device_stats stats;
-
        uint8_t config,         /* current value of CONFIG register */
                timeout,        /* Extended timeout for COM20020 */
                backplane,      /* Backplane flag for COM20020 */
@@ -335,7 +333,12 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
 
 void arcnet_unregister_proto(struct ArcProto *proto);
 irqreturn_t arcnet_interrupt(int irq, void *dev_id);
-struct net_device *alloc_arcdev(char *name);
+struct net_device *alloc_arcdev(const char *name);
+
+int arcnet_open(struct net_device *dev);
+int arcnet_close(struct net_device *dev);
+int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev);
+void arcnet_timeout(struct net_device *dev);
 
 #endif                         /* __KERNEL__ */
 #endif                         /* _LINUX_ARCDEVICE_H */
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
new file mode 100644 (file)
index 0000000..b847fc7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_ATH9K_PLATFORM_H
+#define _LINUX_ATH9K_PLATFORM_H
+
+#define ATH9K_PLAT_EEP_MAX_WORDS       2048
+
+struct ath9k_platform_data {
+       u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
+};
+
+#endif /* _LINUX_ATH9K_PLATFORM_H */
index ac6d9a43e0853b672aed7b34ea46a6a2eeea9e19..5dcfb944b6ce11591f0623543ff48bb9e03be60d 100644 (file)
@@ -29,6 +29,7 @@
 
 int com20020_check(struct net_device *dev);
 int com20020_found(struct net_device *dev, int shared);
+extern const struct net_device_ops com20020_netdev_ops;
 
 /* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 8
index 34f2789d9b9b0e5208e8a2eeeb085b94573efb8d..fc65d219d88c55759d734f6c6fbfb50fff9a7805 100644 (file)
@@ -109,6 +109,12 @@ struct cn_queue_dev {
        unsigned char name[CN_CBQ_NAMELEN];
 
        struct workqueue_struct *cn_queue;
+       /* Sent to kevent to create cn_queue only when needed */
+       struct work_struct wq_creation;
+       /* Tell if the wq_creation job is pending/completed */
+       atomic_t wq_requested;
+       /* Wait for cn_queue to be created */
+       wait_queue_head_t wq_created;
 
        struct list_head queue_list;
        spinlock_t queue_lock;
@@ -164,6 +170,8 @@ int cn_netlink_send(struct cn_msg *, u32, gfp_t);
 int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
 void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
 
+int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work);
+
 struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
 void cn_queue_free_dev(struct cn_queue_dev *dev);
 
index 61734e27abb7b6fc5e0c54d018c8969381a23c86..7434a8353e2301dcb548ad94965ef0e73390335f 100644 (file)
@@ -355,46 +355,6 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
        return __dccp_hdr_len(dccp_hdr(skb));
 }
 
-
-/* initial values for each feature */
-#define DCCPF_INITIAL_SEQUENCE_WINDOW          100
-#define DCCPF_INITIAL_ACK_RATIO                        2
-#define DCCPF_INITIAL_CCID                     DCCPC_CCID2
-/* FIXME: for now we're default to 1 but it should really be 0 */
-#define DCCPF_INITIAL_SEND_NDP_COUNT           1
-
-/**
-  * struct dccp_minisock - Minimal DCCP connection representation
-  *
-  * Will be used to pass the state from dccp_request_sock to dccp_sock.
-  *
-  * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2)
-  * @dccpms_pending - List of features being negotiated
-  * @dccpms_conf -
-  */
-struct dccp_minisock {
-       __u64                   dccpms_sequence_window;
-       struct list_head        dccpms_pending;
-       struct list_head        dccpms_conf;
-};
-
-struct dccp_opt_conf {
-       __u8                    *dccpoc_val;
-       __u8                    dccpoc_len;
-};
-
-struct dccp_opt_pend {
-       struct list_head        dccpop_node;
-       __u8                    dccpop_type;
-       __u8                    dccpop_feat;
-       __u8                    *dccpop_val;
-       __u8                    dccpop_len;
-       int                     dccpop_conf;
-       struct dccp_opt_conf    *dccpop_sc;
-};
-
-extern void dccp_minisock_init(struct dccp_minisock *dmsk);
-
 /**
  * struct dccp_request_sock  -  represent DCCP-specific connection request
  * @dreq_inet_rsk: structure inherited from
@@ -483,13 +443,14 @@ struct dccp_ackvec;
  * @dccps_timestamp_time - time of receiving latest @dccps_timestamp_echo
  * @dccps_l_ack_ratio - feature-local Ack Ratio
  * @dccps_r_ack_ratio - feature-remote Ack Ratio
+ * @dccps_l_seq_win - local Sequence Window (influences ack number validity)
+ * @dccps_r_seq_win - remote Sequence Window (influences seq number validity)
  * @dccps_pcslen - sender   partial checksum coverage (via sockopt)
  * @dccps_pcrlen - receiver partial checksum coverage (via sockopt)
  * @dccps_send_ndp_count - local Send NDP Count feature (7.7.2)
  * @dccps_ndp_count - number of Non Data Packets since last data packet
  * @dccps_mss_cache - current value of MSS (path MTU minus header sizes)
  * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4)
- * @dccps_minisock - associated minisock (accessed via dccp_msk)
  * @dccps_featneg - tracks feature-negotiation state (mostly during handshake)
  * @dccps_hc_rx_ackvec - rx half connection ack vector
  * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection)
@@ -523,12 +484,13 @@ struct dccp_sock {
        __u32                           dccps_timestamp_time;
        __u16                           dccps_l_ack_ratio;
        __u16                           dccps_r_ack_ratio;
+       __u64                           dccps_l_seq_win:48;
+       __u64                           dccps_r_seq_win:48;
        __u8                            dccps_pcslen:4;
        __u8                            dccps_pcrlen:4;
        __u8                            dccps_send_ndp_count:1;
        __u64                           dccps_ndp_count:48;
        unsigned long                   dccps_rate_last;
-       struct dccp_minisock            dccps_minisock;
        struct list_head                dccps_featneg;
        struct dccp_ackvec              *dccps_hc_rx_ackvec;
        struct ccid                     *dccps_hc_rx_ccid;
@@ -546,11 +508,6 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk)
        return (struct dccp_sock *)sk;
 }
 
-static inline struct dccp_minisock *dccp_msk(const struct sock *sk)
-{
-       return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock;
-}
-
 static inline const char *dccp_role(const struct sock *sk)
 {
        switch (dccp_sk(sk)->dccps_role) {
index fd47a151665e363a5d9cdb63f33810ccd55f9a1d..6a6e701f1631622c950a0dc25174184036ce18b5 100644 (file)
@@ -38,6 +38,7 @@ struct hdlc_proto {
        int (*ioctl)(struct net_device *dev, struct ifreq *ifr);
        __be16 (*type_trans)(struct sk_buff *skb, struct net_device *dev);
        int (*netif_rx)(struct sk_buff *skb);
+       int (*xmit)(struct sk_buff *skb, struct net_device *dev);
        struct module *module;
        struct hdlc_proto *next; /* next protocol in the list */
 };
@@ -102,6 +103,10 @@ static __inline__ void debug_frame(const struct sk_buff *skb)
 int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
 void hdlc_close(struct net_device *dev);
+/* May be used by hardware driver */
+int hdlc_change_mtu(struct net_device *dev, int new_mtu);
+/* Must be pointed to by hw driver's dev->netdev_ops->ndo_start_xmit */
+int hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
                         size_t size);
index bf6302f6b5f88d44c2acdafa7f17022630d84cba..0821bac62b83449bfad09dad77eab8b7e244499a 100644 (file)
@@ -241,7 +241,6 @@ struct hdlcdrv_state {
        struct hdlcdrv_bitbuffer bitbuf_hdlc;
 #endif /* HDLCDRV_DEBUG */
 
-       struct net_device_stats stats;
        int ptt_keyed;
 
        /* queued skb for transmission */
index 1c7a0dd5536aca7e8d2a1527ec60e48b0d26736c..06695b74d40585e5ef8428372c6327682745807b 100644 (file)
@@ -207,7 +207,7 @@ struct tok_info {
        unsigned short exsap_station_id;
        unsigned short global_int_enable;
        struct sk_buff *current_skb;
-       struct net_device_stats tr_stats;
+
        unsigned char auto_speedsave;
        open_state                      open_status, sap_status;
        enum {MANUAL, AUTOMATIC}        open_mode;
index c4e6ca1a630668755ce78903e55e6510b6991487..b1bb817d1427875a4ddc2923084fb9dfebc65b57 100644 (file)
@@ -527,6 +527,8 @@ struct ieee80211_tim_ie {
        u8 virtual_map[0];
 } __attribute__ ((packed));
 
+#define WLAN_SA_QUERY_TR_ID_LEN 16
+
 struct ieee80211_mgmt {
        __le16 frame_control;
        __le16 duration;
@@ -646,6 +648,10 @@ struct ieee80211_mgmt {
                                        u8 action_code;
                                        u8 variable[0];
                                } __attribute__((packed)) mesh_action;
+                               struct {
+                                       u8 action;
+                                       u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+                               } __attribute__ ((packed)) sa_query;
                        } u;
                } __attribute__ ((packed)) action;
        } u;
@@ -655,6 +661,15 @@ struct ieee80211_mgmt {
 #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
 
 
+/* Management MIC information element (IEEE 802.11w) */
+struct ieee80211_mmie {
+       u8 element_id;
+       u8 length;
+       __le16 key_id;
+       u8 sequence_number[6];
+       u8 mic[8];
+} __attribute__ ((packed));
+
 /* Control frames */
 struct ieee80211_rts {
        __le16 frame_control;
@@ -899,6 +914,9 @@ enum ieee80211_statuscode {
        /* 802.11g */
        WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
        WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+       /* 802.11w */
+       WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30,
+       WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
        /* 802.11i */
        WLAN_STATUS_INVALID_IE = 40,
        WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
@@ -1018,6 +1036,8 @@ enum ieee80211_eid {
        WLAN_EID_HT_INFORMATION = 61,
        /* 802.11i */
        WLAN_EID_RSN = 48,
+       WLAN_EID_TIMEOUT_INTERVAL = 56,
+       WLAN_EID_MMIE = 76 /* 802.11w */,
        WLAN_EID_WPA = 221,
        WLAN_EID_GENERIC = 221,
        WLAN_EID_VENDOR_SPECIFIC = 221,
@@ -1030,6 +1050,8 @@ enum ieee80211_category {
        WLAN_CATEGORY_QOS = 1,
        WLAN_CATEGORY_DLS = 2,
        WLAN_CATEGORY_BACK = 3,
+       WLAN_CATEGORY_PUBLIC = 4,
+       WLAN_CATEGORY_SA_QUERY = 8,
        WLAN_CATEGORY_WMM = 17,
 };
 
@@ -1104,6 +1126,12 @@ struct ieee80211_country_ie_triplet {
        };
 } __attribute__ ((packed));
 
+enum ieee80211_timeout_interval_type {
+       WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */,
+       WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */,
+       WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */,
+};
+
 /* BACK action code */
 enum ieee80211_back_actioncode {
        WLAN_ACTION_ADDBA_REQ = 0,
@@ -1118,6 +1146,13 @@ enum ieee80211_back_parties {
        WLAN_BACK_TIMER = 2,
 };
 
+/* SA Query action */
+enum ieee80211_sa_query_action {
+       WLAN_ACTION_SA_QUERY_REQUEST = 0,
+       WLAN_ACTION_SA_QUERY_RESPONSE = 1,
+};
+
+
 /* A-MSDU 802.11n */
 #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080
 
@@ -1128,6 +1163,7 @@ enum ieee80211_back_parties {
 /* reserved:                           0x000FAC03 */
 #define WLAN_CIPHER_SUITE_CCMP         0x000FAC04
 #define WLAN_CIPHER_SUITE_WEP104       0x000FAC05
+#define WLAN_CIPHER_SUITE_AES_CMAC     0x000FAC06
 
 #define WLAN_MAX_KEY_LEN               32
 
@@ -1185,4 +1221,149 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
                return hdr->addr1;
 }
 
+/**
+ * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
+ * @hdr: the frame (buffer must include at least the first octet of payload)
+ */
+static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
+{
+       if (ieee80211_is_disassoc(hdr->frame_control) ||
+           ieee80211_is_deauth(hdr->frame_control))
+               return true;
+
+       if (ieee80211_is_action(hdr->frame_control)) {
+               u8 *category;
+
+               /*
+                * Action frames, excluding Public Action frames, are Robust
+                * Management Frames. However, if we are looking at a Protected
+                * frame, skip the check since the data may be encrypted and
+                * the frame has already been found to be a Robust Management
+                * Frame (by the other end).
+                */
+               if (ieee80211_has_protected(hdr->frame_control))
+                       return true;
+               category = ((u8 *) hdr) + 24;
+               return *category != WLAN_CATEGORY_PUBLIC;
+       }
+
+       return false;
+}
+
+/**
+ * ieee80211_fhss_chan_to_freq - get channel frequency
+ * @channel: the FHSS channel
+ *
+ * Convert IEEE802.11 FHSS channel to frequency (MHz)
+ * Ref IEEE 802.11-2007 section 14.6
+ */
+static inline int ieee80211_fhss_chan_to_freq(int channel)
+{
+       if ((channel > 1) && (channel < 96))
+               return channel + 2400;
+       else
+               return -1;
+}
+
+/**
+ * ieee80211_freq_to_fhss_chan - get channel
+ * @freq: the channels frequency
+ *
+ * Convert frequency (MHz) to IEEE802.11 FHSS channel
+ * Ref IEEE 802.11-2007 section 14.6
+ */
+static inline int ieee80211_freq_to_fhss_chan(int freq)
+{
+       if ((freq > 2401) && (freq < 2496))
+               return freq - 2400;
+       else
+               return -1;
+}
+
+/**
+ * ieee80211_dsss_chan_to_freq - get channel center frequency
+ * @channel: the DSSS channel
+ *
+ * Convert IEEE802.11 DSSS channel to the center frequency (MHz).
+ * Ref IEEE 802.11-2007 section 15.6
+ */
+static inline int ieee80211_dsss_chan_to_freq(int channel)
+{
+       if ((channel > 0) && (channel < 14))
+               return 2407 + (channel * 5);
+       else if (channel == 14)
+               return 2484;
+       else
+               return -1;
+}
+
+/**
+ * ieee80211_freq_to_dsss_chan - get channel
+ * @freq: the frequency
+ *
+ * Convert frequency (MHz) to IEEE802.11 DSSS channel
+ * Ref IEEE 802.11-2007 section 15.6
+ *
+ * This routine selects the channel with the closest center frequency.
+ */
+static inline int ieee80211_freq_to_dsss_chan(int freq)
+{
+       if ((freq >= 2410) && (freq < 2475))
+               return (freq - 2405) / 5;
+       else if ((freq >= 2482) && (freq < 2487))
+               return 14;
+       else
+               return -1;
+}
+
+/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back
+ * Ref IEEE 802.11-2007 section 18.4.6.2
+ *
+ * The channels and frequencies are the same as those defined for DSSS
+ */
+#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan)
+#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq)
+
+/* Convert IEEE802.11 ERP channel to frequency (MHz) and back
+ * Ref IEEE 802.11-2007 section 19.4.2
+ */
+#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan)
+#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq)
+
+/**
+ * ieee80211_ofdm_chan_to_freq - get channel center frequency
+ * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
+ * @channel: the OFDM channel
+ *
+ * Convert IEEE802.11 OFDM channel to center frequency (MHz)
+ * Ref IEEE 802.11-2007 section 17.3.8.3.2
+ */
+static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel)
+{
+       if ((channel > 0) && (channel <= 200) &&
+           (s_freq >= 4000))
+               return s_freq + (channel * 5);
+       else
+               return -1;
+}
+
+/**
+ * ieee80211_freq_to_ofdm_channel - get channel
+ * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
+ * @freq: the frequency
+ *
+ * Convert frequency (MHz) to IEEE802.11 OFDM channel
+ * Ref IEEE 802.11-2007 section 17.3.8.3.2
+ *
+ * This routine selects the channel with the closest center frequency.
+ */
+static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq)
+{
+       if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) &&
+           (s_freq >= 4000))
+               return (freq + 2 - s_freq) / 5;
+       else
+               return -1;
+}
+
 #endif /* LINUX_IEEE80211_H */
index 2a6e29620a963bcbfbd9195859fbab7c07f84266..1108f3e099e3bcb7a80b89c9ee2f43fa5dcefa88 100644 (file)
@@ -66,6 +66,7 @@
 #define IFF_SLAVE_NEEDARP 0x40         /* need ARPs for validation     */
 #define IFF_ISATAP     0x80            /* ISATAP interface (RFC4214)   */
 #define IFF_MASTER_ARPMON 0x100                /* bonding master, ARP mon in use */
+#define IFF_WAN_HDLC   0x200           /* WAN HDLC device              */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index 06fcdb45106bb1a39c5c7606345cd3c0d8487743..acef2a770b6bce589b2cf6e84680e892b235a351 100644 (file)
@@ -108,6 +108,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 #define IN_DEV_ARPFILTER(in_dev)       IN_DEV_ORCONF((in_dev), ARPFILTER)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)    IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)      IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
+#define IN_DEV_ARP_NOTIFY(in_dev)      IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
 
 struct in_ifaddr
 {
index 8a455694d6826c84b3f606c7ea9c81a888094354..0d45b4e8d367e0ec6219f2a98a2b642d9f7e85f4 100644 (file)
@@ -193,6 +193,9 @@ struct vif_device
 struct mfc_cache 
 {
        struct mfc_cache *next;                 /* Next entry on cache line     */
+#ifdef CONFIG_NET_NS
+       struct net *mfc_net;
+#endif
        __be32 mfc_mcastgrp;                    /* Group the entry belongs to   */
        __be32 mfc_origin;                      /* Source of packet             */
        vifi_t mfc_parent;                      /* Source interface             */
@@ -215,6 +218,18 @@ struct mfc_cache
        } mfc_un;
 };
 
+static inline
+struct net *mfc_net(const struct mfc_cache *mfc)
+{
+       return read_pnet(&mfc->mfc_net);
+}
+
+static inline
+void mfc_net_set(struct mfc_cache *mfc, struct net *net)
+{
+       write_pnet(&mfc->mfc_net, hold_net(net));
+}
+
 #define MFC_STATIC             1
 #define MFC_NOTIFY             2
 
@@ -241,7 +256,8 @@ struct mfc_cache
 
 #ifdef __KERNEL__
 struct rtmsg;
-extern int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
+extern int ipmr_get_route(struct net *net, struct sk_buff *skb,
+                         struct rtmsg *rtm, int nowait);
 #endif
 
 #endif
index ec54785d34f90904224afe17a2713a8f32ed05ba..7a5057fbb7cda79323996439848005a86a284606 100644 (file)
@@ -984,6 +984,9 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
 void netif_napi_del(struct napi_struct *napi);
 
 struct napi_gro_cb {
+       /* This indicates where we are processing relative to skb->data. */
+       int data_offset;
+
        /* This is non-zero if the packet may be of the same flow. */
        int same_flow;
 
@@ -1087,6 +1090,29 @@ extern int               dev_restart(struct net_device *dev);
 #ifdef CONFIG_NETPOLL_TRAP
 extern int             netpoll_trap(void);
 #endif
+extern void          *skb_gro_header(struct sk_buff *skb, unsigned int hlen);
+extern int            skb_gro_receive(struct sk_buff **head,
+                                      struct sk_buff *skb);
+
+static inline unsigned int skb_gro_offset(const struct sk_buff *skb)
+{
+       return NAPI_GRO_CB(skb)->data_offset;
+}
+
+static inline unsigned int skb_gro_len(const struct sk_buff *skb)
+{
+       return skb->len - NAPI_GRO_CB(skb)->data_offset;
+}
+
+static inline void skb_gro_pull(struct sk_buff *skb, unsigned int len)
+{
+       NAPI_GRO_CB(skb)->data_offset += len;
+}
+
+static inline void skb_gro_reset_offset(struct sk_buff *skb)
+{
+       NAPI_GRO_CB(skb)->data_offset = 0;
+}
 
 static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                                  unsigned short type,
@@ -1375,12 +1401,15 @@ extern int              netif_receive_skb(struct sk_buff *skb);
 extern void            napi_gro_flush(struct napi_struct *napi);
 extern int             dev_gro_receive(struct napi_struct *napi,
                                        struct sk_buff *skb);
+extern int             napi_skb_finish(int ret, struct sk_buff *skb);
 extern int             napi_gro_receive(struct napi_struct *napi,
                                         struct sk_buff *skb);
 extern void            napi_reuse_skb(struct napi_struct *napi,
                                       struct sk_buff *skb);
 extern struct sk_buff *        napi_fraginfo_skb(struct napi_struct *napi,
                                          struct napi_gro_fraginfo *info);
+extern int             napi_frags_finish(struct napi_struct *napi,
+                                         struct sk_buff *skb, int ret);
 extern int             napi_gro_frags(struct napi_struct *napi,
                                       struct napi_gro_fraginfo *info);
 extern void            netif_nit_deliver(struct sk_buff *skb);
@@ -1574,56 +1603,6 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits)
        return (1 << debug_value) - 1;
 }
 
-/* Test if receive needs to be scheduled but only if up */
-static inline int netif_rx_schedule_prep(struct napi_struct *napi)
-{
-       return napi_schedule_prep(napi);
-}
-
-/* Add interface to tail of rx poll list. This assumes that _prep has
- * already been called and returned 1.
- */
-static inline void __netif_rx_schedule(struct napi_struct *napi)
-{
-       __napi_schedule(napi);
-}
-
-/* Try to reschedule poll. Called by irq handler. */
-
-static inline void netif_rx_schedule(struct napi_struct *napi)
-{
-       if (netif_rx_schedule_prep(napi))
-               __netif_rx_schedule(napi);
-}
-
-/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().  */
-static inline int netif_rx_reschedule(struct napi_struct *napi)
-{
-       if (napi_schedule_prep(napi)) {
-               __netif_rx_schedule(napi);
-               return 1;
-       }
-       return 0;
-}
-
-/* same as netif_rx_complete, except that local_irq_save(flags)
- * has already been issued
- */
-static inline void __netif_rx_complete(struct napi_struct *napi)
-{
-       __napi_complete(napi);
-}
-
-/* Remove interface from poll list: it must be in the poll list
- * on current cpu. This primitive is called by dev->poll(), when
- * it completes the work. The device cannot be out of poll list at this
- * moment, it is BUG().
- */
-static inline void netif_rx_complete(struct napi_struct *napi)
-{
-       napi_complete(napi);
-}
-
 static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
 {
        spin_lock(&txq->_xmit_lock);
index e86ed59f9ad59b25317ce2be2f084a73063704c5..76aae3d8e97e9c636190498055489f88ea025768 100644 (file)
@@ -47,7 +47,7 @@
  * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
  *     %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
  *     %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or
- *     %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET.
+ *     %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
  * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
  *     or rename notification. Has attributes %NL80211_ATTR_WIPHY and
  *     %NL80211_ATTR_WIPHY_NAME.
@@ -72,8 +72,8 @@
  *
  * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
  *     by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
- * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT or
- *     %NL80211_ATTR_KEY_THRESHOLD.
+ * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
+ *     %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
  * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
  *     %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
  *     attributes.
@@ -84,7 +84,7 @@
  *     %NL80222_CMD_NEW_BEACON message)
  * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
  *     using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
- *     %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes.
+ *     %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes.
  * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
  *     parameters are like for %NL80211_CMD_SET_BEACON.
  * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
  * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
  *      interface identified by %NL80211_ATTR_IFINDEX
  *
+ * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The
+ *     interface is identified with %NL80211_ATTR_IFINDEX and the management
+ *     frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be
+ *     added to the end of the specified management frame is specified with
+ *     %NL80211_ATTR_IE. If the command succeeds, the requested data will be
+ *     added to all specified management frames generated by
+ *     kernel/firmware/driver.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -178,6 +186,8 @@ enum nl80211_commands {
        NL80211_CMD_GET_MESH_PARAMS,
        NL80211_CMD_SET_MESH_PARAMS,
 
+       NL80211_CMD_SET_MGMT_EXTRA_IE,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -190,6 +200,7 @@ enum nl80211_commands {
  * here
  */
 #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
+#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE
 
 /**
  * enum nl80211_attrs - nl80211 netlink attributes
@@ -284,6 +295,12 @@ enum nl80211_commands {
  *     supported interface types, each a flag attribute with the number
  *     of the interface mode.
  *
+ * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for
+ *     %NL80211_CMD_SET_MGMT_EXTRA_IE.
+ *
+ * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with
+ *     %NL80211_CMD_SET_MGMT_EXTRA_IE).
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -346,6 +363,11 @@ enum nl80211_attrs {
        NL80211_ATTR_WIPHY_FREQ,
        NL80211_ATTR_WIPHY_CHANNEL_TYPE,
 
+       NL80211_ATTR_KEY_DEFAULT_MGMT,
+
+       NL80211_ATTR_MGMT_SUBTYPE,
+       NL80211_ATTR_IE,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -360,7 +382,9 @@ enum nl80211_attrs {
 #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
 #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
 #define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
-#define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET
+#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE
+#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE
+#define NL80211_ATTR_IE NL80211_ATTR_IE
 
 #define NL80211_MAX_SUPP_RATES                 32
 #define NL80211_MAX_SUPP_REG_RULES             32
@@ -412,12 +436,14 @@ enum nl80211_iftype {
  * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
  *     with short barker preamble
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
+ * @NL80211_STA_FLAG_MFP: station uses management frame protection
  */
 enum nl80211_sta_flags {
        __NL80211_STA_FLAG_INVALID,
        NL80211_STA_FLAG_AUTHORIZED,
        NL80211_STA_FLAG_SHORT_PREAMBLE,
        NL80211_STA_FLAG_WME,
+       NL80211_STA_FLAG_MFP,
 
        /* keep last */
        __NL80211_STA_FLAG_AFTER_LAST,
index 52a9fe08451cfa105c733099350355a8b89dc028..966e02332990443c3f8f010ca9db7cffc730dace 100644 (file)
 #define PCI_DEVICE_ID_PROMISE_20276    0x5275
 #define PCI_DEVICE_ID_PROMISE_20277    0x7275
 
+#define PCI_VENDOR_ID_FOXCONN          0x105b
+
 #define PCI_VENDOR_ID_UMC              0x1060
 #define PCI_DEVICE_ID_UMC_UM8673F      0x0101
 #define PCI_DEVICE_ID_UMC_UM8886BF     0x673a
 
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 
+#define PCI_VENDOR_ID_AMBIT            0x1468
+
 #define PCI_VENDOR_ID_MYRICOM          0x14c1
 
 #define PCI_VENDOR_ID_TITAN            0x14D2
 
 #define PCI_VENDOR_ID_TOPSPIN          0x1867
 
+#define PCI_VENDOR_ID_SILAN            0x1904
+
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
index a942892d6dfe714ca552544a02dd830781fe7eab..9d64bdf147703560d3065cac35b0853b95e7f75b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/skbuff.h>
 #include <linux/poll.h>
+#include <net/net_namespace.h>
 
 struct ppp_channel;
 
@@ -56,6 +57,9 @@ extern void ppp_input(struct ppp_channel *, struct sk_buff *);
    that we may have missed a packet. */
 extern void ppp_input_error(struct ppp_channel *, int code);
 
+/* Attach a channel to a given PPP unit in specified net. */
+extern int ppp_register_net_channel(struct net *, struct ppp_channel *);
+
 /* Attach a channel to a given PPP unit. */
 extern int ppp_register_channel(struct ppp_channel *);
 
index cf2cb50f77d1fe5f19e9894b78f4532789054ce7..08670d017479d88df2e9a6d121a3e0f960dd56cb 100644 (file)
@@ -1687,8 +1687,6 @@ extern int               skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
                                 int shiftlen);
 
 extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
-extern int            skb_gro_receive(struct sk_buff **head,
-                                      struct sk_buff *skb);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
                                       int len, void *buffer)
@@ -1904,6 +1902,21 @@ static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_bu
        to->queue_mapping = from->queue_mapping;
 }
 
+static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue)
+{
+       skb->queue_mapping = rx_queue + 1;
+}
+
+static inline u16 skb_get_rx_queue(struct sk_buff *skb)
+{
+       return skb->queue_mapping - 1;
+}
+
+static inline bool skb_rx_queue_recorded(struct sk_buff *skb)
+{
+       return (skb->queue_mapping != 0);
+}
+
 #ifdef CONFIG_XFRM
 static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
 {
index 1cbf0313adde93f0971e56a89a7a907a08fcb8d6..b32725075d7183a58bbf192fef069f26b8ef2735 100644 (file)
@@ -43,5 +43,8 @@ struct smsc911x_platform_config {
 /* Constants for flags */
 #define SMSC911X_USE_16BIT                     (BIT(0))
 #define SMSC911X_USE_32BIT                     (BIT(1))
+#define SMSC911X_FORCE_INTERNAL_PHY            (BIT(2))
+#define SMSC911X_FORCE_EXTERNAL_PHY            (BIT(3))
+#define SMSC911X_SAVE_MAC_ADDRESS              (BIT(4))
 
 #endif /* __LINUX_SMSC911X_H__ */
diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h
new file mode 100644 (file)
index 0000000..ada71b4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * board-specific data for the libertas_spi driver.
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#ifndef _LIBERTAS_SPI_H_
+#define _LIBERTAS_SPI_H_
+struct libertas_spi_platform_data {
+       /* There are two ways to read data from the WLAN module's SPI
+        * interface. Setting 0 or 1 here controls which one is used.
+        *
+        * Usually you want to set use_dummy_writes = 1.
+        * However, if that doesn't work or if you are using a slow SPI clock
+        * speed, you may want to use 0 here. */
+       u16 use_dummy_writes;
+
+       /* GPIO number to use as chip select */
+       u16 gpio_cs;
+};
+#endif
index 99a0f991e85000431e300758472e7f053dc430ff..a01b982b578356b6798b1f6115d7f3907fbc7b99 100644 (file)
 #define  SSB_SPROM5_GPIOB_P3           0xFF00  /* Pin 3 */
 #define  SSB_SPROM5_GPIOB_P3_SHIFT     8
 
+/* SPROM Revision 8 */
+#define SSB_SPROM8_BFLLO               0x1084  /* Boardflags (low 16 bits) */
+#define SSB_SPROM8_BFLHI               0x1086  /* Boardflags Hi */
+#define SSB_SPROM8_IL0MAC              0x108C  /* 6 byte MAC address */
+#define SSB_SPROM8_CCODE               0x1092  /* 2 byte country code */
+#define SSB_SPROM8_ANTAVAIL            0x109C  /* Antenna available bitfields*/
+#define SSB_SPROM8_ANTAVAIL_A          0xFF00  /* A-PHY bitfield */
+#define SSB_SPROM8_ANTAVAIL_A_SHIFT    8
+#define SSB_SPROM8_ANTAVAIL_BG         0x00FF  /* B-PHY and G-PHY bitfield */
+#define SSB_SPROM8_ANTAVAIL_BG_SHIFT   0
+#define SSB_SPROM8_AGAIN01             0x109E  /* Antenna Gain (in dBm Q5.2) */
+#define  SSB_SPROM8_AGAIN0             0x00FF  /* Antenna 0 */
+#define  SSB_SPROM8_AGAIN0_SHIFT       0
+#define  SSB_SPROM8_AGAIN1             0xFF00  /* Antenna 1 */
+#define  SSB_SPROM8_AGAIN1_SHIFT       8
+#define SSB_SPROM8_AGAIN23             0x10A0
+#define  SSB_SPROM8_AGAIN2             0x00FF  /* Antenna 2 */
+#define  SSB_SPROM8_AGAIN2_SHIFT       0
+#define  SSB_SPROM8_AGAIN3             0xFF00  /* Antenna 3 */
+#define  SSB_SPROM8_AGAIN3_SHIFT       8
+#define SSB_SPROM8_GPIOA               0x1096  /*Gen. Purpose IO # 0 and 1 */
+#define  SSB_SPROM8_GPIOA_P0           0x00FF  /* Pin 0 */
+#define  SSB_SPROM8_GPIOA_P1           0xFF00  /* Pin 1 */
+#define  SSB_SPROM8_GPIOA_P1_SHIFT     8
+#define SSB_SPROM8_GPIOB               0x1098  /* Gen. Purpose IO # 2 and 3 */
+#define  SSB_SPROM8_GPIOB_P2           0x00FF  /* Pin 2 */
+#define  SSB_SPROM8_GPIOB_P3           0xFF00  /* Pin 3 */
+#define  SSB_SPROM8_GPIOB_P3_SHIFT     8
+#define SSB_SPROM8_MAXP_BG             0x10C0  /* Max Power BG in path 1 */
+#define  SSB_SPROM8_MAXP_BG_MASK       0x00FF  /* Mask for Max Power BG */
+#define  SSB_SPROM8_ITSSI_BG           0xFF00  /* Mask for path 1 itssi_bg */
+#define  SSB_SPROM8_ITSSI_BG_SHIFT     8
+#define SSB_SPROM8_MAXP_A              0x10C8  /* Max Power A in path 1 */
+#define  SSB_SPROM8_MAXP_A_MASK                0x00FF  /* Mask for Max Power A */
+#define  SSB_SPROM8_ITSSI_A            0xFF00  /* Mask for path 1 itssi_a */
+#define  SSB_SPROM8_ITSSI_A_SHIFT      8
 
 /* Values for SSB_SPROM1_BINF_CCODE */
 enum {
index 39d471d1163b4e8a54a95f56584f04e8a65a2d61..e76d3b22a46645b503283138b317ced96a0fbbef 100644 (file)
@@ -490,6 +490,7 @@ enum
        NET_IPV4_CONF_ARP_IGNORE=19,
        NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
        NET_IPV4_CONF_ARP_ACCEPT=21,
+       NET_IPV4_CONF_ARP_NOTIFY=22,
        __NET_IPV4_CONF_MAX
 };
 
index 3efa86c3ecb30ca4f7ce50d4319989373d4fbc2c..242348bb3766a69e45d0255575bf108a7eb4a744 100644 (file)
 #define VIRTIO_NET_F_HOST_ECN  13      /* Host can handle TSO[6] w/ ECN in. */
 #define VIRTIO_NET_F_HOST_UFO  14      /* Host can handle UFO in. */
 #define VIRTIO_NET_F_MRG_RXBUF 15      /* Host can merge receive buffers. */
+#define VIRTIO_NET_F_STATUS    16      /* virtio_net_config.status available */
+#define VIRTIO_NET_F_CTRL_VQ   17      /* Control channel available */
+#define VIRTIO_NET_F_CTRL_RX   18      /* Control channel RX mode support */
+#define VIRTIO_NET_F_CTRL_VLAN 19      /* Control channel VLAN filtering */
+
+#define VIRTIO_NET_S_LINK_UP   1       /* Link is up */
 
 struct virtio_net_config
 {
        /* The config defining mac address (if VIRTIO_NET_F_MAC) */
        __u8 mac[6];
+       /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
+       __u16 status;
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't
@@ -54,4 +62,67 @@ struct virtio_net_hdr_mrg_rxbuf {
        __u16 num_buffers;      /* Number of merged rx buffers */
 };
 
+/*
+ * Control virtqueue data structures
+ *
+ * The control virtqueue expects a header in the first sg entry
+ * and an ack/status response in the last entry.  Data for the
+ * command goes in between.
+ */
+struct virtio_net_ctrl_hdr {
+       __u8 class;
+       __u8 cmd;
+} __attribute__((packed));
+
+typedef __u8 virtio_net_ctrl_ack;
+
+#define VIRTIO_NET_OK     0
+#define VIRTIO_NET_ERR    1
+
+/*
+ * Control the RX mode, ie. promisucous and allmulti.  PROMISC and
+ * ALLMULTI commands require an "out" sg entry containing a 1 byte
+ * state value, zero = disable, non-zero = enable.  These commands
+ * are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ */
+#define VIRTIO_NET_CTRL_RX    0
+ #define VIRTIO_NET_CTRL_RX_PROMISC      0
+ #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+
+/*
+ * Control the MAC filter table.
+ *
+ * The MAC filter table is managed by the hypervisor, the guest should
+ * assume the size is infinite.  Filtering should be considered
+ * non-perfect, ie. based on hypervisor resources, the guest may
+ * received packets from sources not specified in the filter list.
+ *
+ * In addition to the class/cmd header, the TABLE_SET command requires
+ * two out scatterlists.  Each contains a 4 byte count of entries followed
+ * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The
+ * first sg list contains unicast addresses, the second is for multicast.
+ * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
+ * is available.
+ */
+struct virtio_net_ctrl_mac {
+       __u32 entries;
+       __u8 macs[][ETH_ALEN];
+} __attribute__((packed));
+
+#define VIRTIO_NET_CTRL_MAC    1
+ #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
+
+/*
+ * Control VLAN filtering
+ *
+ * The VLAN filter table is controlled via a simple ADD/DEL interface.
+ * VLAN IDs not added may be filterd by the hypervisor.  Del is the
+ * opposite of add.  Both commands expect an out entry containing a 2
+ * byte VLAN ID.  VLAN filterting is available with the
+ * VIRTIO_NET_F_CTRL_VLAN feature bit.
+ */
+#define VIRTIO_NET_CTRL_VLAN       2
+ #define VIRTIO_NET_CTRL_VLAN_ADD             0
+ #define VIRTIO_NET_CTRL_VLAN_DEL             1
+
 #endif /* _LINUX_VIRTIO_NET_H */
index d7958f9b52cba59e15dfb8a26e4ce5b04ea1309a..cb24204851f7e7118a25c8db99d60030c03b1c3a 100644 (file)
 #define IW_AUTH_RX_UNENCRYPTED_EAPOL   8
 #define IW_AUTH_ROAMING_CONTROL                9
 #define IW_AUTH_PRIVACY_INVOKED                10
+#define IW_AUTH_CIPHER_GROUP_MGMT      11
+#define IW_AUTH_MFP                    12
 
 /* IW_AUTH_WPA_VERSION values (bit field) */
 #define IW_AUTH_WPA_VERSION_DISABLED   0x00000001
 #define IW_AUTH_WPA_VERSION_WPA                0x00000002
 #define IW_AUTH_WPA_VERSION_WPA2       0x00000004
 
-/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT
+ * values (bit field) */
 #define IW_AUTH_CIPHER_NONE    0x00000001
 #define IW_AUTH_CIPHER_WEP40   0x00000002
 #define IW_AUTH_CIPHER_TKIP    0x00000004
 #define IW_AUTH_CIPHER_CCMP    0x00000008
 #define IW_AUTH_CIPHER_WEP104  0x00000010
+#define IW_AUTH_CIPHER_AES_CMAC        0x00000020
 
 /* IW_AUTH_KEY_MGMT values (bit field) */
 #define IW_AUTH_KEY_MGMT_802_1X        1
 #define IW_AUTH_ROAMING_DISABLE        1       /* user space program used for roaming
                                         * control */
 
+/* IW_AUTH_MFP (management frame protection) values */
+#define IW_AUTH_MFP_DISABLED   0       /* MFP disabled */
+#define IW_AUTH_MFP_OPTIONAL   1       /* MFP optional */
+#define IW_AUTH_MFP_REQUIRED   2       /* MFP required */
+
 /* SIOCSIWENCODEEXT definitions */
 #define IW_ENCODE_SEQ_MAX_SIZE 8
 /* struct iw_encode_ext ->alg */
 #define IW_ENCODE_ALG_TKIP     2
 #define IW_ENCODE_ALG_CCMP     3
 #define IW_ENCODE_ALG_PMK      4
+#define IW_ENCODE_ALG_AES_CMAC 5
 /* struct iw_encode_ext ->ext_flags */
 #define IW_ENCODE_EXT_TX_SEQ_VALID     0x00000001
 #define IW_ENCODE_EXT_RX_SEQ_VALID     0x00000002
index b5a51a7bb36476ce7be0a4f3ed0130742e354276..467c531b8a7ef84cc2610eb78ebb137799135ec2 100644 (file)
@@ -50,7 +50,6 @@ struct atmarp_entry {
 struct clip_priv {
        int number;                     /* for convenience ... */
        spinlock_t xoff_lock;           /* ensures that pop is atomic (SMP) */
-       struct net_device_stats stats;
        struct net_device *next;        /* next CLIP interface */
 };
 
index 23c0ab74ded63bfbc9f57a36751872be3e195f77..dd1fd51638fcd02a67d2cad8b8f9cb89f7d78987 100644 (file)
@@ -112,12 +112,14 @@ struct beacon_parameters {
  * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
  *     with short preambles
  * @STATION_FLAG_WME: station is WME/QoS capable
+ * @STATION_FLAG_MFP: station uses management frame protection
  */
 enum station_flags {
        STATION_FLAG_CHANGED            = 1<<0,
        STATION_FLAG_AUTHORIZED         = 1<<NL80211_STA_FLAG_AUTHORIZED,
        STATION_FLAG_SHORT_PREAMBLE     = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE,
        STATION_FLAG_WME                = 1<<NL80211_STA_FLAG_WME,
+       STATION_FLAG_MFP                = 1<<NL80211_STA_FLAG_MFP,
 };
 
 /**
@@ -355,6 +357,51 @@ enum reg_set_by {
        REGDOM_SET_BY_COUNTRY_IE,
 };
 
+/**
+ * enum environment_cap - Environment parsed from country IE
+ * @ENVIRON_ANY: indicates country IE applies to both indoor and
+ *     outdoor operation.
+ * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation
+ * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation
+ */
+enum environment_cap {
+       ENVIRON_ANY,
+       ENVIRON_INDOOR,
+       ENVIRON_OUTDOOR,
+};
+
+/**
+ * struct regulatory_request - receipt of last regulatory request
+ *
+ * @wiphy: this is set if this request's initiator is
+ *     %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
+ *     can be used by the wireless core to deal with conflicts
+ *     and potentially inform users of which devices specifically
+ *     cased the conflicts.
+ * @initiator: indicates who sent this request, could be any of
+ *     of those set in reg_set_by, %REGDOM_SET_BY_*
+ * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
+ *     regulatory domain. We have a few special codes:
+ *     00 - World regulatory domain
+ *     99 - built by driver but a specific alpha2 cannot be determined
+ *     98 - result of an intersection between two regulatory domains
+ * @intersect: indicates whether the wireless core should intersect
+ *     the requested regulatory domain with the presently set regulatory
+ *     domain.
+ * @country_ie_checksum: checksum of the last processed and accepted
+ *     country IE
+ * @country_ie_env: lets us know if the AP is telling us we are outdoor,
+ *     indoor, or if it doesn't matter
+ */
+struct regulatory_request {
+       struct wiphy *wiphy;
+       enum reg_set_by initiator;
+       char alpha2[2];
+       bool intersect;
+       u32 country_ie_checksum;
+       enum environment_cap country_ie_env;
+};
+
 struct ieee80211_freq_range {
        u32 start_freq_khz;
        u32 end_freq_khz;
@@ -431,6 +478,26 @@ struct ieee80211_txq_params {
        u8 aifs;
 };
 
+/**
+ * struct mgmt_extra_ie_params - Extra management frame IE parameters
+ *
+ * Used to add extra IE(s) into management frames. If the driver cannot add the
+ * requested data into all management frames of the specified subtype that are
+ * generated in kernel or firmware/hardware, it must reject the configuration
+ * call. The IE data buffer is added to the end of the specified management
+ * frame body after all other IEs. This addition is not applied to frames that
+ * are injected through a monitor interface.
+ *
+ * @subtype: Management frame subtype
+ * @ies: IE data buffer or %NULL to remove previous data
+ * @ies_len: Length of @ies in octets
+ */
+struct mgmt_extra_ie_params {
+       u8 subtype;
+       u8 *ies;
+       int ies_len;
+};
+
 /* from net/wireless.h */
 struct wiphy;
 
@@ -450,6 +517,9 @@ struct ieee80211_channel;
  * wireless extensions but this is subject to reevaluation as soon as this
  * code is used more widely and we have a first user without wext.
  *
+ * @suspend: wiphy device needs to be suspended
+ * @resume: wiphy device needs to be resumed
+ *
  * @add_virtual_intf: create a new virtual interface with the given name,
  *     must set the struct wireless_dev's iftype.
  *
@@ -471,6 +541,8 @@ struct ieee80211_channel;
  *
  * @set_default_key: set the default key on an interface
  *
+ * @set_default_mgmt_key: set the default management frame key on an interface
+ *
  * @add_beacon: Add a beacon with given parameters, @head, @interval
  *     and @dtim_period will be valid, @tail is optional.
  * @set_beacon: Change the beacon parameters for an access point mode
@@ -497,8 +569,13 @@ struct ieee80211_channel;
  * @set_txq_params: Set TX queue parameters
  *
  * @set_channel: Set channel
+ *
+ * @set_mgmt_extra_ie: Set extra IE data for management frames
  */
 struct cfg80211_ops {
+       int     (*suspend)(struct wiphy *wiphy);
+       int     (*resume)(struct wiphy *wiphy);
+
        int     (*add_virtual_intf)(struct wiphy *wiphy, char *name,
                                    enum nl80211_iftype type, u32 *flags,
                                    struct vif_params *params);
@@ -518,6 +595,9 @@ struct cfg80211_ops {
        int     (*set_default_key)(struct wiphy *wiphy,
                                   struct net_device *netdev,
                                   u8 key_index);
+       int     (*set_default_mgmt_key)(struct wiphy *wiphy,
+                                       struct net_device *netdev,
+                                       u8 key_index);
 
        int     (*add_beacon)(struct wiphy *wiphy, struct net_device *dev,
                              struct beacon_parameters *info);
@@ -564,6 +644,10 @@ struct cfg80211_ops {
        int     (*set_channel)(struct wiphy *wiphy,
                               struct ieee80211_channel *chan,
                               enum nl80211_channel_type channel_type);
+
+       int     (*set_mgmt_extra_ie)(struct wiphy *wiphy,
+                                    struct net_device *dev,
+                                    struct mgmt_extra_ie_params *params);
 };
 
 /* temporary wext handlers */
index d0a043153cc6741de298c53f18773f05adc0b0ba..a44e2248b2ef108f1bff42062449bac760ec9899 100644 (file)
@@ -82,6 +82,7 @@ struct inet_bind_bucket {
 #endif
        unsigned short          port;
        signed short            fastreuse;
+       int                     num_owners;
        struct hlist_node       node;
        struct hlist_head       owners;
 };
@@ -133,7 +134,7 @@ struct inet_hashinfo {
        struct inet_bind_hashbucket     *bhash;
 
        unsigned int                    bhash_size;
-       /* Note : 4 bytes padding on 64 bit arches */
+       /* 4 bytes hole on 64 bit */
 
        struct kmem_cache               *bind_bucket_cachep;
 
@@ -150,6 +151,7 @@ struct inet_hashinfo {
        struct inet_listen_hashbucket   listening_hash[INET_LHTABLE_SIZE]
                                        ____cacheline_aligned_in_smp;
 
+       atomic_t                        bsockets;
 };
 
 static inline struct inet_ehash_bucket *inet_ehash_bucket(
index 559422fc0943837d35563677a25a35ecbe1b5a10..e2144f0e8728f8b872ed2c87c1f866671eb4d1b2 100644 (file)
@@ -207,7 +207,7 @@ struct ieee80211_bss_conf {
        u16 beacon_int;
        u16 assoc_capability;
        u64 timestamp;
-       u64 basic_rates;
+       u32 basic_rates;
        struct ieee80211_bss_ht_conf ht;
 };
 
@@ -262,6 +262,26 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTL_RATE_CTRL_PROBE        = BIT(12),
 };
 
+/**
+ * enum mac80211_rate_control_flags - per-rate flags set by the
+ *     Rate Control algorithm.
+ *
+ * These flags are set by the Rate control algorithm for each rate during tx,
+ * in the @flags member of struct ieee80211_tx_rate.
+ *
+ * @IEEE80211_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.
+ * @IEEE80211_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.
+ *     This is set if the current BSS requires ERP protection.
+ * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
+ * @IEEE80211_TX_RC_MCS: HT rate.
+ * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
+ *     Greenfield mode.
+ * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
+ *     adjacent 20 MHz channels, if the current channel type is
+ *     NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
+ * @IEEE80211_TX_RC_SHORT_GI: Short Guard interval should be used for this rate.
+ */
 enum mac80211_rate_control_flags {
        IEEE80211_TX_RC_USE_RTS_CTS             = BIT(0),
        IEEE80211_TX_RC_USE_CTS_PROTECT         = BIT(1),
@@ -507,11 +527,6 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void)
 }
 #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME())
 
-struct ieee80211_ht_conf {
-       bool enabled;
-       enum nl80211_channel_type channel_type;
-};
-
 /**
  * enum ieee80211_conf_changed - denotes which configuration changed
  *
@@ -520,10 +535,10 @@ struct ieee80211_ht_conf {
  * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
  * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
  * @IEEE80211_CONF_CHANGE_PS: the PS flag changed
+ * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed
  * @IEEE80211_CONF_CHANGE_POWER: the TX power changed
- * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed
+ * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed
  * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
- * @IEEE80211_CONF_CHANGE_HT: HT configuration changed
  */
 enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_RADIO_ENABLED     = BIT(0),
@@ -531,10 +546,10 @@ enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_LISTEN_INTERVAL   = BIT(2),
        IEEE80211_CONF_CHANGE_RADIOTAP          = BIT(3),
        IEEE80211_CONF_CHANGE_PS                = BIT(4),
-       IEEE80211_CONF_CHANGE_POWER             = BIT(5),
-       IEEE80211_CONF_CHANGE_CHANNEL           = BIT(6),
-       IEEE80211_CONF_CHANGE_RETRY_LIMITS      = BIT(7),
-       IEEE80211_CONF_CHANGE_HT                = BIT(8),
+       IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT     = BIT(5),
+       IEEE80211_CONF_CHANGE_POWER             = BIT(6),
+       IEEE80211_CONF_CHANGE_CHANNEL           = BIT(7),
+       IEEE80211_CONF_CHANGE_RETRY_LIMITS      = BIT(8),
 };
 
 /**
@@ -547,8 +562,9 @@ enum ieee80211_conf_changed {
  * @listen_interval: listen interval in units of beacon interval
  * @flags: configuration flags defined above
  * @power_level: requested transmit power (in dBm)
+ * @dynamic_ps_timeout: dynamic powersave timeout (in ms)
  * @channel: the channel to tune to
- * @ht: the HT configuration for the device
+ * @channel_type: the channel (HT) type
  * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
  *    (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
  *    but actually means the number of transmissions not the number of retries
@@ -559,7 +575,7 @@ enum ieee80211_conf_changed {
 struct ieee80211_conf {
        int beacon_int;
        u32 flags;
-       int power_level;
+       int power_level, dynamic_ps_timeout;
 
        u16 listen_interval;
        bool radio_enabled;
@@ -567,7 +583,7 @@ struct ieee80211_conf {
        u8 long_frame_max_tx_count, short_frame_max_tx_count;
 
        struct ieee80211_channel *channel;
-       struct ieee80211_ht_conf ht;
+       enum nl80211_channel_type channel_type;
 };
 
 /**
@@ -630,10 +646,12 @@ struct ieee80211_if_init_conf {
  * @IEEE80211_IFCC_BSSID: The BSSID changed.
  * @IEEE80211_IFCC_BEACON: The beacon for this interface changed
  *     (currently AP and MESH only), use ieee80211_beacon_get().
+ * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed.
  */
 enum ieee80211_if_conf_change {
-       IEEE80211_IFCC_BSSID    = BIT(0),
-       IEEE80211_IFCC_BEACON   = BIT(1),
+       IEEE80211_IFCC_BSSID            = BIT(0),
+       IEEE80211_IFCC_BEACON           = BIT(1),
+       IEEE80211_IFCC_BEACON_ENABLED   = BIT(2),
 };
 
 /**
@@ -641,13 +659,16 @@ enum ieee80211_if_conf_change {
  *
  * @changed: parameters that have changed, see &enum ieee80211_if_conf_change.
  * @bssid: BSSID of the network we are associated to/creating.
+ * @enable_beacon: Indicates whether beacons can be sent.
+ *     This is valid only for AP/IBSS/MESH modes.
  *
  * This structure is passed to the config_interface() callback of
  * &struct ieee80211_hw.
  */
 struct ieee80211_if_conf {
        u32 changed;
-       u8 *bssid;
+       const u8 *bssid;
+       bool enable_beacon;
 };
 
 /**
@@ -655,11 +676,13 @@ struct ieee80211_if_conf {
  * @ALG_WEP: WEP40 or WEP104
  * @ALG_TKIP: TKIP
  * @ALG_CCMP: CCMP (AES)
+ * @ALG_AES_CMAC: AES-128-CMAC
  */
 enum ieee80211_key_alg {
        ALG_WEP,
        ALG_TKIP,
        ALG_CCMP,
+       ALG_AES_CMAC,
 };
 
 /**
@@ -688,12 +711,16 @@ enum ieee80211_key_len {
  *     generation in software.
  * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
  *     that the key is pairwise rather then a shared key.
+ * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
+ *     CCMP key if it requires CCMP encryption of management frames (MFP) to
+ *     be done in software.
  */
 enum ieee80211_key_flags {
        IEEE80211_KEY_FLAG_WMM_STA      = 1<<0,
        IEEE80211_KEY_FLAG_GENERATE_IV  = 1<<1,
        IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
        IEEE80211_KEY_FLAG_PAIRWISE     = 1<<3,
+       IEEE80211_KEY_FLAG_SW_MGMT      = 1<<4,
 };
 
 /**
@@ -714,8 +741,8 @@ enum ieee80211_key_flags {
  *     - Temporal Encryption Key (128 bits)
  *     - Temporal Authenticator Tx MIC Key (64 bits)
  *     - Temporal Authenticator Rx MIC Key (64 bits)
- * @icv_len: FIXME
- * @iv_len: FIXME
+ * @icv_len: The ICV length for this key type
+ * @iv_len: The IV length for this key type
  */
 struct ieee80211_key_conf {
        enum ieee80211_key_alg alg;
@@ -759,7 +786,7 @@ enum set_key_cmd {
  *     sizeof(void *), size is determined in hw information.
  */
 struct ieee80211_sta {
-       u64 supp_rates[IEEE80211_NUM_BANDS];
+       u32 supp_rates[IEEE80211_NUM_BANDS];
        u8 addr[ETH_ALEN];
        u16 aid;
        struct ieee80211_sta_ht_cap ht_cap;
@@ -854,10 +881,18 @@ enum ieee80211_tkip_key_type {
  * @IEEE80211_HW_AMPDU_AGGREGATION:
  *     Hardware supports 11n A-MPDU aggregation.
  *
- * @IEEE80211_HW_NO_STACK_DYNAMIC_PS:
- *     Hardware which has dynamic power save support, meaning
- *     that power save is enabled in idle periods, and don't need support
- *     from stack.
+ * @IEEE80211_HW_SUPPORTS_PS:
+ *     Hardware has power save support (i.e. can go to sleep).
+ *
+ * @IEEE80211_HW_PS_NULLFUNC_STACK:
+ *     Hardware requires nullfunc frame handling in stack, implies
+ *     stack support for dynamic PS.
+ *
+ * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS:
+ *     Hardware has support for dynamic PS.
+ *
+ * @IEEE80211_HW_MFP_CAPABLE:
+ *     Hardware supports management frame protection (MFP, IEEE 802.11w).
  */
 enum ieee80211_hw_flags {
        IEEE80211_HW_RX_INCLUDES_FCS                    = 1<<1,
@@ -870,7 +905,10 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_NOISE_DBM                          = 1<<8,
        IEEE80211_HW_SPECTRUM_MGMT                      = 1<<9,
        IEEE80211_HW_AMPDU_AGGREGATION                  = 1<<10,
-       IEEE80211_HW_NO_STACK_DYNAMIC_PS                = 1<<11,
+       IEEE80211_HW_SUPPORTS_PS                        = 1<<11,
+       IEEE80211_HW_PS_NULLFUNC_STACK                  = 1<<12,
+       IEEE80211_HW_SUPPORTS_DYNAMIC_PS                = 1<<13,
+       IEEE80211_HW_MFP_CAPABLE                        = 1<<14,
 };
 
 /**
@@ -890,9 +928,8 @@ enum ieee80211_hw_flags {
  * @workqueue: single threaded workqueue available for driver use,
  *     allocated by mac80211 on registration and flushed when an
  *     interface is removed.
- *     NOTICE: All work performed on this workqueue should NEVER
- *     acquire the RTNL lock (i.e. Don't use the function
- *     ieee80211_iterate_active_interfaces())
+ *     NOTICE: All work performed on this workqueue must not
+ *     acquire the RTNL lock.
  *
  * @priv: pointer to private area that was allocated for driver use
  *     along with this structure.
@@ -951,6 +988,19 @@ struct ieee80211_hw {
        u8 max_rate_tries;
 };
 
+/**
+ * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy
+ *
+ * @wiphy: the &struct wiphy which we want to query
+ *
+ * mac80211 drivers can use this to get to their respective
+ * &struct ieee80211_hw. Drivers wishing to get to their own private
+ * structure can then access it via hw->priv. Note that mac802111 drivers should
+ * not use wiphy_priv() to try to get their private driver structure as this
+ * is already used internally by mac80211.
+ */
+struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy);
+
 /**
  * SET_IEEE80211_DEV - set device for 802.11 hardware
  *
@@ -1018,16 +1068,12 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  *
  * The set_key() callback in the &struct ieee80211_ops for a given
  * device is called to enable hardware acceleration of encryption and
- * decryption. The callback takes an @address parameter that will be
- * the broadcast address for default keys, the other station's hardware
- * address for individual keys or the zero address for keys that will
- * be used only for transmission.
+ * decryption. The callback takes a @sta parameter that will be NULL
+ * for default keys or keys used for transmission only, or point to
+ * the station information for the peer for individual keys.
  * Multiple transmission keys with the same key index may be used when
  * VLANs are configured for an access point.
  *
- * The @local_address parameter will always be set to our own address,
- * this is only relevant if you support multiple local addresses.
- *
  * When transmitting, the TX control data will use the @hw_key_idx
  * selected by the driver by modifying the &struct ieee80211_key_conf
  * pointed to by the @key parameter to the set_key() function.
@@ -1060,6 +1106,42 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  * handler is software decryption with wrap around of iv16.
  */
 
+/**
+ * DOC: Powersave support
+ *
+ * mac80211 has support for various powersave implementations.
+ *
+ * First, it can support hardware that handles all powersaving by
+ * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS
+ * hardware flag. In that case, it will be told about the desired
+ * powersave mode depending on the association status, and the driver
+ * must take care of sending nullfunc frames when necessary, i.e. when
+ * entering and leaving powersave mode. The driver is required to look at
+ * the AID in beacons and signal to the AP that it woke up when it finds
+ * traffic directed to it. This mode supports dynamic PS by simply
+ * enabling/disabling PS.
+ *
+ * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS
+ * flag to indicate that it can support dynamic PS mode itself (see below).
+ *
+ * Other hardware designs cannot send nullfunc frames by themselves and also
+ * need software support for parsing the TIM bitmap. This is also supported
+ * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and
+ * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still
+ * required to pass up beacons. Additionally, in this case, mac80211 will
+ * wake up the hardware when multicast traffic is announced in the beacon.
+ *
+ * FIXME: I don't think we can be fast enough in software when we want to
+ *       receive multicast traffic?
+ *
+ * Dynamic powersave mode is an extension to normal powersave mode in which
+ * the hardware stays awake for a user-specified period of time after sending
+ * a frame so that reply frames need not be buffered and therefore delayed
+ * to the next wakeup. This can either be supported by hardware, in which case
+ * the driver needs to look at the @dynamic_ps_timeout hardware configuration
+ * value, or by the stack if all nullfunc handling is in the stack.
+ */
+
 /**
  * DOC: Frame filtering
  *
@@ -1172,6 +1254,8 @@ enum ieee80211_ampdu_mlme_action {
  *     configuration in the TX control data. This handler should,
  *     preferably, never fail and stop queues appropriately, more
  *     importantly, however, it must never fail for A-MPDU-queues.
+ *     This function should return NETDEV_TX_OK except in very
+ *     limited cases.
  *     Must be implemented and atomic.
  *
  * @start: Called before the first netdevice attached to the hardware
@@ -1212,9 +1296,12 @@ enum ieee80211_ampdu_mlme_action {
  *
  * @config: Handler for configuration requests. IEEE 802.11 code calls this
  *     function to change hardware configuration, e.g., channel.
+ *     This function should never fail but returns a negative error code
+ *     if it does.
  *
  * @config_interface: Handler for configuration requests related to interfaces
  *     (e.g. BSSID changes.)
+ *     Returns a negative error code which will be seen in userspace.
  *
  * @bss_info_changed: Handler for configuration requests related to BSS
  *     parameters that may vary during BSS's lifespan, and may affect low
@@ -1232,8 +1319,9 @@ enum ieee80211_ampdu_mlme_action {
  *
  * @set_key: See the section "Hardware crypto acceleration"
  *     This callback can sleep, and is only called between add_interface
- *     and remove_interface calls, i.e. while the interface with the
- *     given local_address is enabled.
+ *     and remove_interface calls, i.e. while the given virtual interface
+ *     is enabled.
+ *     Returns a negative error code if the key can't be added.
  *
  * @update_tkip_key: See the section "Hardware crypto acceleration"
  *     This callback will be called in the context of Rx. Called for drivers
@@ -1245,8 +1333,10 @@ enum ieee80211_ampdu_mlme_action {
  *     bands. When the scan finishes, ieee80211_scan_completed() must be
  *     called; note that it also must be called when the scan cannot finish
  *     because the hardware is turned off! Anything else is a bug!
+ *     Returns a negative error code which will be seen in userspace.
  *
- * @get_stats: return low-level statistics
+ * @get_stats: Return low-level statistics.
+ *     Returns zero if statistics are available.
  *
  * @get_tkip_seq: If your device implements TKIP encryption in hardware this
  *     callback should be provided to read the TKIP transmit IVs (both IV32
@@ -1260,6 +1350,7 @@ enum ieee80211_ampdu_mlme_action {
  *
  * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
  *     bursting) for a hardware TX queue.
+ *     Returns a negative error code on failure.
  *
  * @get_tx_stats: Get statistics of the current TX queue status. This is used
  *     to get number of currently queued packets (queue length), maximum queue
@@ -1268,7 +1359,11 @@ enum ieee80211_ampdu_mlme_action {
  *     hw->ampdu_queues items.
  *
  * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
- *     this is only used for IBSS mode debugging and, as such, is not a
+ *     this is only used for IBSS mode BSSID merging and debugging. Is not a
+ *     required function. Must be atomic.
+ *
+ * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
+ *      Currently, this is only used for IBSS mode debugging. Is not a
  *     required function. Must be atomic.
  *
  * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
@@ -1279,13 +1374,15 @@ enum ieee80211_ampdu_mlme_action {
  * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
  *     This is needed only for IBSS mode and the result of this function is
  *     used to determine whether to reply to Probe Requests.
+ *     Returns non-zero if this device sent the last beacon.
  *
  * @ampdu_action: Perform a certain A-MPDU action
  *     The RA/TID combination determines the destination and TID we want
  *     the ampdu action to be performed for. The action is defined through
  *     ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
- *     is the first frame we expect to perform the action on. notice
+ *     is the first frame we expect to perform the action on. Notice
  *     that TX/RX_STOP can pass NULL for this parameter.
+ *     Returns a negative error code on failure.
  */
 struct ieee80211_ops {
        int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1310,7 +1407,7 @@ struct ieee80211_ops {
        int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                       bool set);
        int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                      const u8 *local_address, const u8 *address,
+                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                       struct ieee80211_key_conf *key);
        void (*update_tkip_key)(struct ieee80211_hw *hw,
                        struct ieee80211_key_conf *conf, const u8 *address,
@@ -1328,6 +1425,7 @@ struct ieee80211_ops {
        int (*get_tx_stats)(struct ieee80211_hw *hw,
                            struct ieee80211_tx_queue_stats *stats);
        u64 (*get_tsf)(struct ieee80211_hw *hw);
+       void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf);
        void (*reset_tsf)(struct ieee80211_hw *hw);
        int (*tx_last_beacon)(struct ieee80211_hw *hw);
        int (*ampdu_action)(struct ieee80211_hw *hw,
@@ -1962,4 +2060,34 @@ rate_lowest_index(struct ieee80211_supported_band *sband,
 int ieee80211_rate_control_register(struct rate_control_ops *ops);
 void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
 
+static inline bool
+conf_is_ht20(struct ieee80211_conf *conf)
+{
+       return conf->channel_type == NL80211_CHAN_HT20;
+}
+
+static inline bool
+conf_is_ht40_minus(struct ieee80211_conf *conf)
+{
+       return conf->channel_type == NL80211_CHAN_HT40MINUS;
+}
+
+static inline bool
+conf_is_ht40_plus(struct ieee80211_conf *conf)
+{
+       return conf->channel_type == NL80211_CHAN_HT40PLUS;
+}
+
+static inline bool
+conf_is_ht40(struct ieee80211_conf *conf)
+{
+       return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf);
+}
+
+static inline bool
+conf_is_ht(struct ieee80211_conf *conf)
+{
+       return conf->channel_type != NL80211_CHAN_NO_HT;
+}
+
 #endif /* MAC80211_H */
index 977f482d97a95144f0f777df1b0bbbacb7f1b11e..2eb3814d6258e8d0f9da0be8c81560b20af5b9cf 100644 (file)
@@ -54,5 +54,18 @@ struct netns_ipv4 {
 
        struct timer_list rt_secret_timer;
        atomic_t rt_genid;
+
+#ifdef CONFIG_IP_MROUTE
+       struct sock             *mroute_sk;
+       struct mfc_cache        **mfc_cache_array;
+       struct vif_device       *vif_table;
+       int                     maxvif;
+       atomic_t                cache_resolve_queue_len;
+       int                     mroute_do_assert;
+       int                     mroute_do_pim;
+#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
+       int                     mroute_reg_vif_num;
+#endif
+#endif
 };
 #endif
index f06852bba62afb8a1cd42d1c3af51ee7efcc6c49..15696b1fd30fbe85c248ad95fba4a4e7db4f4454 100644 (file)
@@ -59,10 +59,6 @@ enum {
 #define NR_MAX_WINDOW_SIZE             127                     /* Maximum Window Allowable - 127 */
 #define        NR_MAX_PACKET_SIZE              236                     /* Maximum Packet Length - 236 */
 
-struct nr_private {
-       struct net_device_stats stats;
-};
-
 struct nr_sock {
        struct sock             sock;
        ax25_address            user_addr, source_addr, dest_addr;
index 057b0a8a28859f519a6fc85694de0ee69913b8bf..d43f71b5ec004218f5eb969d15b8bd82ce143f9c 100644 (file)
@@ -105,7 +105,6 @@ void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
 
 int phonet_sysctl_init(void);
 void phonet_sysctl_exit(void);
-void phonet_netlink_register(void);
 int isi_register(void);
 void isi_unregister(void);
 
index aa1c59a1d33f6f5245b330b6e0f3e9fe9988420b..5054dc5ea2c260439277a6c252f51df68cd72a39 100644 (file)
@@ -28,7 +28,7 @@ struct phonet_device_list {
        spinlock_t lock;
 };
 
-extern struct phonet_device_list pndevs;
+struct phonet_device_list *phonet_device_list(struct net *net);
 
 struct phonet_device {
        struct list_head list;
@@ -36,8 +36,9 @@ struct phonet_device {
        DECLARE_BITMAP(addrs, 64);
 };
 
-void phonet_device_init(void);
+int phonet_device_init(void);
 void phonet_device_exit(void);
+int phonet_netlink_register(void);
 struct net_device *phonet_device_get(struct net *net);
 
 int phonet_address_add(struct net_device *dev, u8 addr);
index 4082f39f507916c5002d7677831da8aff0e9013f..e37fe3129c17ddbf192de69ed3984f2ee5fbc93b 100644 (file)
@@ -85,6 +85,7 @@ extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
                struct nlattr *tab);
 extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 extern void qdisc_put_stab(struct qdisc_size_table *tab);
+extern void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
 
 extern void __qdisc_run(struct Qdisc *q);
 
index f8c47429044aee1db7ddf54a14e405305be51b0a..3d78a4d224601f5003aef260f4363bc88707d3be 100644 (file)
@@ -42,9 +42,10 @@ struct Qdisc
        int                     (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
        struct sk_buff *        (*dequeue)(struct Qdisc *dev);
        unsigned                flags;
-#define TCQ_F_BUILTIN  1
-#define TCQ_F_THROTTLED        2
-#define TCQ_F_INGRESS  4
+#define TCQ_F_BUILTIN          1
+#define TCQ_F_THROTTLED                2
+#define TCQ_F_INGRESS          4
+#define TCQ_F_WARN_NONWC       (1 << 16)
        int                     padded;
        struct Qdisc_ops        *ops;
        struct qdisc_size_table *stab;
index 21c5d966142d9cc3b5964364c482068a03f25c0b..a42c1562d52bd61ea377a7253bbaec6ab790e269 100644 (file)
@@ -181,12 +181,25 @@ struct ieee80211_supported_band {
  * struct wiphy - wireless hardware description
  * @idx: the wiphy index assigned to this item
  * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
- * @fw_handles_regulatory: tells us the firmware for this device
- *     has its own regulatory solution and cannot identify the
+ * @custom_regulatory: tells us the driver for this device
+ *     has its own custom regulatory domain and cannot identify the
  *     ISO / IEC 3166 alpha2 it belongs to. When this is enabled
  *     we will disregard the first regulatory hint (when the
  *     initiator is %REGDOM_SET_BY_CORE).
+ * @strict_regulatory: tells us the driver for this device will ignore
+ *     regulatory domain settings until it gets its own regulatory domain
+ *     via its regulatory_hint(). After its gets its own regulatory domain
+ *     it will only allow further regulatory domain settings to further
+ *     enhance compliance. For example if channel 13 and 14 are disabled
+ *     by this regulatory domain no user regulatory domain can enable these
+ *     channels at a later time. This can be used for devices which do not
+ *     have calibration information gauranteed for frequencies or settings
+ *     outside of its regulatory domain.
  * @reg_notifier: the driver's regulatory notification callback
+ * @regd: the driver's regulatory domain, if one was requested via
+ *     the regulatory_hint() API. This can be used by the driver
+ *     on the reg_notifier() if it chooses to ignore future
+ *     regulatory domain changes caused by other drivers.
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -197,7 +210,8 @@ struct wiphy {
        /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
        u16 interface_modes;
 
-       bool fw_handles_regulatory;
+       bool custom_regulatory;
+       bool strict_regulatory;
 
        /* If multiple wiphys are registered and you're handed e.g.
         * a regular netdev with assigned ieee80211_ptr, you won't
@@ -209,10 +223,13 @@ struct wiphy {
        struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
 
        /* Lets us get back the wiphy on the callback */
-       int (*reg_notifier)(struct wiphy *wiphy, enum reg_set_by setby);
+       int (*reg_notifier)(struct wiphy *wiphy,
+                           struct regulatory_request *request);
 
        /* fields below are read-only, assigned by cfg80211 */
 
+       const struct ieee80211_regdomain *regd;
+
        /* the item in /sys/class/ieee80211/ points to this,
         * you need use set_wiphy_dev() (see below) */
        struct device dev;
@@ -361,7 +378,7 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq)
  */
 struct ieee80211_rate *
 ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
-                           u64 basic_rates, int bitrate);
+                           u32 basic_rates, int bitrate);
 
 /**
  * regulatory_hint - driver hint to the wireless core a regulatory domain
@@ -395,4 +412,45 @@ extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2);
 extern void regulatory_hint_11d(struct wiphy *wiphy,
                                u8 *country_ie,
                                u8 country_ie_len);
+
+/**
+ * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
+ * @wiphy: the wireless device we want to process the regulatory domain on
+ * @regd: the custom regulatory domain to use for this wiphy
+ *
+ * Drivers can sometimes have custom regulatory domains which do not apply
+ * to a specific country. Drivers can use this to apply such custom regulatory
+ * domains. This routine must be called prior to wiphy registration. The
+ * custom regulatory domain will be trusted completely and as such previous
+ * default channel settings will be disregarded. If no rule is found for a
+ * channel on the regulatory domain the channel will be disabled.
+ */
+extern void wiphy_apply_custom_regulatory(
+       struct wiphy *wiphy,
+       const struct ieee80211_regdomain *regd);
+
+/**
+ * freq_reg_info - get regulatory information for the given frequency
+ * @wiphy: the wiphy for which we want to process this rule for
+ * @center_freq: Frequency in KHz for which we want regulatory information for
+ * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one
+ *     you can set this to 0. If this frequency is allowed we then set
+ *     this value to the maximum allowed bandwidth.
+ * @reg_rule: the regulatory rule which we have for this frequency
+ *
+ * Use this function to get the regulatory rule for a specific frequency on
+ * a given wireless device. If the device has a specific regulatory domain
+ * it wants to follow we respect that unless a country IE has been received
+ * and processed already.
+ *
+ * Returns 0 if it was able to find a valid regulatory rule which does
+ * apply to the given center_freq otherwise it returns non-zero. It will
+ * also return -ERANGE if we determine the given center_freq does not even have
+ * a regulatory rule for a frequency range in the center_freq's band. See
+ * freq_in_rule_band() for our current definition of a band -- this is purely
+ * subjective and right now its 802.11 specific.
+ */
+extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth,
+                        const struct ieee80211_reg_rule **reg_rule);
+
 #endif /* __NET_WIRELESS_H */
index fafeb48f27c046d0b6586e2797b40397a6a76f19..b38423ca711ad5ef191db6b74205c6cc945cc463 100644 (file)
@@ -219,6 +219,7 @@ static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = {
        { NET_IPV4_CONF_ARP_IGNORE,             "arp_ignore" },
        { NET_IPV4_CONF_PROMOTE_SECONDARIES,    "promote_secondaries" },
        { NET_IPV4_CONF_ARP_ACCEPT,             "arp_accept" },
+       { NET_IPV4_CONF_ARP_NOTIFY,             "arp_notify" },
        {}
 };
 
index 70980baeb68297bdc629b27f8ea63f68b0a9e04a..6ed711748f26a55d49e2073fb7f061c438e2ccd8 100644 (file)
@@ -51,7 +51,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
        int rc = 1;
        struct datalink_proto *proto;
        static struct packet_type snap_packet_type = {
-               .type = __constant_htons(ETH_P_SNAP),
+               .type = cpu_to_be16(ETH_P_SNAP),
        };
 
        if (unlikely(!pskb_may_pull(skb, 5)))
index 41e8f65bd3f0f6ea0a121ad4bc48f68ffd569a61..4163ea65bf4152c40d29f978f4e75f7fbe6e10dc 100644 (file)
@@ -52,7 +52,7 @@ static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
 static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
 
 static struct packet_type vlan_packet_type = {
-       .type = __constant_htons(ETH_P_8021Q),
+       .type = cpu_to_be16(ETH_P_8021Q),
        .func = vlan_skb_recv, /* VLAN receive method */
 };
 
index e9db889d6222c466e6ad2a896dcdcdfd8d7d2d94..378fa69d625ae19b0bae9d70d0f9aeb5d66b2ebd 100644 (file)
@@ -98,22 +98,9 @@ drop:
 int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
                     unsigned int vlan_tci, struct sk_buff *skb)
 {
-       int err = NET_RX_SUCCESS;
+       skb_gro_reset_offset(skb);
 
-       switch (vlan_gro_common(napi, grp, vlan_tci, skb)) {
-       case -1:
-               return netif_receive_skb(skb);
-
-       case 2:
-               err = NET_RX_DROP;
-               /* fall through */
-
-       case 1:
-               kfree_skb(skb);
-               break;
-       }
-
-       return err;
+       return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb);
 }
 EXPORT_SYMBOL(vlan_gro_receive);
 
@@ -121,27 +108,11 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
                   unsigned int vlan_tci, struct napi_gro_fraginfo *info)
 {
        struct sk_buff *skb = napi_fraginfo_skb(napi, info);
-       int err = NET_RX_DROP;
 
        if (!skb)
-               goto out;
-
-       err = NET_RX_SUCCESS;
-
-       switch (vlan_gro_common(napi, grp, vlan_tci, skb)) {
-       case -1:
-               return netif_receive_skb(skb);
-
-       case 2:
-               err = NET_RX_DROP;
-               /* fall through */
-
-       case 1:
-               napi_reuse_skb(napi, skb);
-               break;
-       }
+               return NET_RX_DROP;
 
-out:
-       return err;
+       return napi_frags_finish(napi, skb,
+                                vlan_gro_common(napi, grp, vlan_tci, skb));
 }
 EXPORT_SYMBOL(vlan_gro_frags);
index cdb8fdef6c4aaac30b1ba6cf5ace134ea6bfcb89..a12bae0e3fe9b59f5df801b7e0bc417a2f0847c7 100644 (file)
@@ -185,6 +185,7 @@ source "net/x25/Kconfig"
 source "net/lapb/Kconfig"
 source "net/econet/Kconfig"
 source "net/wanrouter/Kconfig"
+source "net/phonet/Kconfig"
 source "net/sched/Kconfig"
 source "net/dcb/Kconfig"
 
@@ -229,7 +230,6 @@ source "net/can/Kconfig"
 source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 source "net/rxrpc/Kconfig"
-source "net/phonet/Kconfig"
 
 config FIB_RULES
        bool
index 5abce07fb50a195b1f280af8dbe588e2fefc2d6c..510a6782da8f83e70a324c21cb0d47b976e2f952 100644 (file)
@@ -1861,12 +1861,12 @@ static struct notifier_block ddp_notifier = {
 };
 
 static struct packet_type ltalk_packet_type = {
-       .type           = __constant_htons(ETH_P_LOCALTALK),
+       .type           = cpu_to_be16(ETH_P_LOCALTALK),
        .func           = ltalk_rcv,
 };
 
 static struct packet_type ppptalk_packet_type = {
-       .type           = __constant_htons(ETH_P_PPPTALK),
+       .type           = cpu_to_be16(ETH_P_PPPTALK),
        .func           = atalk_rcv,
 };
 
index d856a62ab50fda448896689ff210e235dc8d0e6d..72277d70c980be38035f11bc7aae0a1be46b8398 100644 (file)
@@ -9,22 +9,20 @@
 #include <linux/if_arp.h>
 #include <linux/if_ltalk.h>
 
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
 static int ltalk_change_mtu(struct net_device *dev, int mtu)
 {
        return -EINVAL;
 }
-
-static int ltalk_mac_addr(struct net_device *dev, void *addr)
-{
-       return -EINVAL;
-}
+#endif
 
 static void ltalk_setup(struct net_device *dev)
 {
        /* Fill in the fields of the device structure with localtalk-generic values. */
 
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
        dev->change_mtu         = ltalk_change_mtu;
-       dev->set_mac_address    = ltalk_mac_addr;
+#endif
 
        dev->type               = ARPHRD_LOCALTLK;
        dev->hard_header_len    = LTALK_HLEN;
index ea9438fc6855fb3a569e7e25a2064d5191a14989..334fcd4a4ea469c26ecdc958b40ffa5b74d35f1e 100644 (file)
@@ -83,7 +83,6 @@ struct br2684_dev {
        struct list_head br2684_devs;
        int number;
        struct list_head brvccs;        /* one device <=> one vcc (before xmas) */
-       struct net_device_stats stats;
        int mac_was_set;
        enum br2684_payload payload;
 };
@@ -148,9 +147,10 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
  * the way for multiple vcc's per itf.  Returns true if we can send,
  * otherwise false
  */
-static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
+static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
                           struct br2684_vcc *brvcc)
 {
+       struct br2684_dev *brdev = BRPRIV(dev);
        struct atm_vcc *atmvcc;
        int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
 
@@ -211,8 +211,8 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
        }
        atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
        ATM_SKB(skb)->atm_options = atmvcc->atm_options;
-       brdev->stats.tx_packets++;
-       brdev->stats.tx_bytes += skb->len;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
        atmvcc->send(atmvcc, skb);
        return 1;
 }
@@ -233,14 +233,14 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
        brvcc = pick_outgoing_vcc(skb, brdev);
        if (brvcc == NULL) {
                pr_debug("no vcc attached to dev %s\n", dev->name);
-               brdev->stats.tx_errors++;
-               brdev->stats.tx_carrier_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_carrier_errors++;
                /* netif_stop_queue(dev); */
                dev_kfree_skb(skb);
                read_unlock(&devs_lock);
                return 0;
        }
-       if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
+       if (!br2684_xmit_vcc(skb, dev, brvcc)) {
                /*
                 * We should probably use netif_*_queue() here, but that
                 * involves added complication.  We need to walk before
@@ -248,27 +248,20 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
                 *
                 * Don't free here! this pointer might be no longer valid!
                 */
-               brdev->stats.tx_errors++;
-               brdev->stats.tx_fifo_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_fifo_errors++;
        }
        read_unlock(&devs_lock);
        return 0;
 }
 
-static struct net_device_stats *br2684_get_stats(struct net_device *dev)
-{
-       pr_debug("br2684_get_stats\n");
-       return &BRPRIV(dev)->stats;
-}
-
 /*
  * We remember when the MAC gets set, so we don't override it later with
  * the ESI of the ATM card of the first VC
  */
-static int (*my_eth_mac_addr) (struct net_device *, void *);
 static int br2684_mac_addr(struct net_device *dev, void *p)
 {
-       int err = my_eth_mac_addr(dev, p);
+       int err = eth_mac_addr(dev, p);
        if (!err)
                BRPRIV(dev)->mac_was_set = 1;
        return err;
@@ -430,17 +423,17 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
        /* sigh, interface is down? */
        if (unlikely(!(net_dev->flags & IFF_UP)))
                goto dropped;
-       brdev->stats.rx_packets++;
-       brdev->stats.rx_bytes += skb->len;
+       net_dev->stats.rx_packets++;
+       net_dev->stats.rx_bytes += skb->len;
        memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
        netif_rx(skb);
        return;
 
 dropped:
-       brdev->stats.rx_dropped++;
+       net_dev->stats.rx_dropped++;
        goto free_skb;
 error:
-       brdev->stats.rx_errors++;
+       net_dev->stats.rx_errors++;
 free_skb:
        dev_kfree_skb(skb);
        return;
@@ -531,8 +524,8 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 
                skb->next = skb->prev = NULL;
                br2684_push(atmvcc, skb);
-               BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
-               BRPRIV(skb->dev)->stats.rx_packets--;
+               skb->dev->stats.rx_bytes -= skb->len;
+               skb->dev->stats.rx_packets--;
 
                skb = next;
        }
@@ -544,17 +537,20 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        return err;
 }
 
+static const struct net_device_ops br2684_netdev_ops = {
+       .ndo_start_xmit         = br2684_start_xmit,
+       .ndo_set_mac_address    = br2684_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 static void br2684_setup(struct net_device *netdev)
 {
        struct br2684_dev *brdev = BRPRIV(netdev);
 
        ether_setup(netdev);
-       brdev->net_dev = netdev;
 
-       my_eth_mac_addr = netdev->set_mac_address;
-       netdev->set_mac_address = br2684_mac_addr;
-       netdev->hard_start_xmit = br2684_start_xmit;
-       netdev->get_stats = br2684_get_stats;
+       netdev->netdev_ops = &br2684_netdev_ops;
 
        INIT_LIST_HEAD(&brdev->brvccs);
 }
@@ -565,10 +561,8 @@ static void br2684_setup_routed(struct net_device *netdev)
        brdev->net_dev = netdev;
 
        netdev->hard_header_len = 0;
-       my_eth_mac_addr = netdev->set_mac_address;
-       netdev->set_mac_address = br2684_mac_addr;
-       netdev->hard_start_xmit = br2684_start_xmit;
-       netdev->get_stats = br2684_get_stats;
+
+       netdev->netdev_ops = &br2684_netdev_ops;
        netdev->addr_len = 0;
        netdev->mtu = 1500;
        netdev->type = ARPHRD_PPP;
index 2d33a83be799c36dec054340553610d64e61070c..da42fd06b61fc6c6c93a47b7336d15bca2438373 100644 (file)
@@ -214,15 +214,15 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
                skb->protocol = ((__be16 *) skb->data)[3];
                skb_pull(skb, RFC1483LLC_LEN);
                if (skb->protocol == htons(ETH_P_ARP)) {
-                       PRIV(skb->dev)->stats.rx_packets++;
-                       PRIV(skb->dev)->stats.rx_bytes += skb->len;
+                       skb->dev->stats.rx_packets++;
+                       skb->dev->stats.rx_bytes += skb->len;
                        clip_arp_rcv(skb);
                        return;
                }
        }
        clip_vcc->last_use = jiffies;
-       PRIV(skb->dev)->stats.rx_packets++;
-       PRIV(skb->dev)->stats.rx_bytes += skb->len;
+       skb->dev->stats.rx_packets++;
+       skb->dev->stats.rx_bytes += skb->len;
        memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
        netif_rx(skb);
 }
@@ -372,7 +372,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (!skb->dst) {
                printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
                dev_kfree_skb(skb);
-               clip_priv->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                return 0;
        }
        if (!skb->dst->neighbour) {
@@ -380,13 +380,13 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
                skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
                if (!skb->dst->neighbour) {
                        dev_kfree_skb(skb);     /* lost that one */
-                       clip_priv->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                        return 0;
                }
 #endif
                printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
                dev_kfree_skb(skb);
-               clip_priv->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                return 0;
        }
        entry = NEIGH2ENTRY(skb->dst->neighbour);
@@ -400,7 +400,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_queue_tail(&entry->neigh->arp_queue, skb);
                else {
                        dev_kfree_skb(skb);
-                       clip_priv->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                }
                return 0;
        }
@@ -423,8 +423,8 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
                printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
                return 0;
        }
-       clip_priv->stats.tx_packets++;
-       clip_priv->stats.tx_bytes += skb->len;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
        vcc->send(vcc, skb);
        if (atm_may_send(vcc, 0)) {
                entry->vccs->xoff = 0;
@@ -443,11 +443,6 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *clip_get_stats(struct net_device *dev)
-{
-       return &PRIV(dev)->stats;
-}
-
 static int clip_mkip(struct atm_vcc *vcc, int timeout)
 {
        struct clip_vcc *clip_vcc;
@@ -501,8 +496,8 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout)
 
                        skb_get(skb);
                        clip_push(vcc, skb);
-                       PRIV(skb->dev)->stats.rx_packets--;
-                       PRIV(skb->dev)->stats.rx_bytes -= len;
+                       skb->dev->stats.rx_packets--;
+                       skb->dev->stats.rx_bytes -= len;
                        kfree_skb(skb);
                }
 
@@ -561,7 +556,6 @@ static void clip_setup(struct net_device *dev)
 {
        dev->hard_start_xmit = clip_start_xmit;
        /* sg_xmit ... */
-       dev->get_stats = clip_get_stats;
        dev->type = ARPHRD_ATM;
        dev->hard_header_len = RFC1483LLC_LEN;
        dev->mtu = RFC1626_MTU;
index e5e301550e8a72ce7897fce6729bd2a82f844ea0..c0cba9a037e842d92ac7116907b21c950b001b2d 100644 (file)
@@ -62,7 +62,6 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
 static int lec_open(struct net_device *dev);
 static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lec_close(struct net_device *dev);
-static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
 static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
                                          const unsigned char *mac_addr);
@@ -218,28 +217,28 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
 
 static int lec_open(struct net_device *dev)
 {
-       struct lec_priv *priv = netdev_priv(dev);
-
        netif_start_queue(dev);
-       memset(&priv->stats, 0, sizeof(struct net_device_stats));
+       memset(&dev->stats, 0, sizeof(struct net_device_stats));
 
        return 0;
 }
 
-static __inline__ void
-lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
+static void
+lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
+       struct net_device *dev = skb->dev;
+
        ATM_SKB(skb)->vcc = vcc;
        ATM_SKB(skb)->atm_options = vcc->atm_options;
 
        atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
        if (vcc->send(vcc, skb) < 0) {
-               priv->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                return;
        }
 
-       priv->stats.tx_packets++;
-       priv->stats.tx_bytes += skb->len;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
 }
 
 static void lec_tx_timeout(struct net_device *dev)
@@ -270,7 +269,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
        pr_debug("lec_start_xmit called\n");
        if (!priv->lecd) {
                printk("%s:No lecd attached\n", dev->name);
-               priv->stats.tx_errors++;
+               dev->stats.tx_errors++;
                netif_stop_queue(dev);
                return -EUNATCH;
        }
@@ -345,7 +344,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                               GFP_ATOMIC);
                        dev_kfree_skb(skb);
                        if (skb2 == NULL) {
-                               priv->stats.tx_dropped++;
+                               dev->stats.tx_dropped++;
                                return 0;
                        }
                        skb = skb2;
@@ -380,7 +379,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
                            ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
                             dev->name);
                        pr_debug("MAC address %pM\n", lec_h->h_dest);
-                       priv->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                        dev_kfree_skb(skb);
                }
                goto out;
@@ -392,10 +391,10 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
        while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
                pr_debug("lec.c: emptying tx queue, ");
                pr_debug("MAC address %pM\n", lec_h->h_dest);
-               lec_send(vcc, skb2, priv);
+               lec_send(vcc, skb2);
        }
 
-       lec_send(vcc, skb, priv);
+       lec_send(vcc, skb);
 
        if (!atm_may_send(vcc, 0)) {
                struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
@@ -427,15 +426,6 @@ static int lec_close(struct net_device *dev)
        return 0;
 }
 
-/*
- * Get the current statistics.
- * This may be called with the card open or closed.
- */
-static struct net_device_stats *lec_get_stats(struct net_device *dev)
-{
-       return &((struct lec_priv *)netdev_priv(dev))->stats;
-}
-
 static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
        unsigned long flags;
@@ -677,17 +667,19 @@ static void lec_set_multicast_list(struct net_device *dev)
        return;
 }
 
+static const struct net_device_ops lec_netdev_ops = {
+       .ndo_open               = lec_open,
+       .ndo_stop               = lec_close,
+       .ndo_start_xmit         = lec_start_xmit,
+       .ndo_change_mtu         = lec_change_mtu,
+       .ndo_tx_timeout         = lec_tx_timeout,
+       .ndo_set_multicast_list = lec_set_multicast_list,
+};
+
+
 static void lec_init(struct net_device *dev)
 {
-       dev->change_mtu = lec_change_mtu;
-       dev->open = lec_open;
-       dev->stop = lec_close;
-       dev->hard_start_xmit = lec_start_xmit;
-       dev->tx_timeout = lec_tx_timeout;
-
-       dev->get_stats = lec_get_stats;
-       dev->set_multicast_list = lec_set_multicast_list;
-       dev->do_ioctl = NULL;
+       dev->netdev_ops = &lec_netdev_ops;
        printk("%s: Initialized!\n", dev->name);
 }
 
@@ -810,8 +802,8 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                else
 #endif
                        skb->protocol = eth_type_trans(skb, dev);
-               priv->stats.rx_packets++;
-               priv->stats.rx_bytes += skb->len;
+               dev->stats.rx_packets++;
+               dev->stats.rx_bytes += skb->len;
                memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
                netif_rx(skb);
        }
@@ -1887,7 +1879,7 @@ restart:
                                        lec_arp_hold(entry);
                                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                                        while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
-                                               lec_send(vcc, skb, entry->priv);
+                                               lec_send(vcc, skb);
                                        entry->last_used = jiffies;
                                        entry->status = ESI_FORWARD_DIRECT;
                                        lec_arp_put(entry);
@@ -2305,7 +2297,7 @@ restart:
                                lec_arp_hold(entry);
                                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                                while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
-                                       lec_send(vcc, skb, entry->priv);
+                                       lec_send(vcc, skb);
                                entry->last_used = jiffies;
                                entry->status = ESI_FORWARD_DIRECT;
                                lec_arp_put(entry);
index 0d376682c1a321ba7837f3721555ab2dcd6ca8a0..9d14d196cc1d74aa9ea06baec24ba5772cc2c24b 100644 (file)
@@ -69,7 +69,6 @@ struct lane2_ops {
 #define LEC_ARP_TABLE_SIZE 16
 
 struct lec_priv {
-       struct net_device_stats stats;
        unsigned short lecid;                   /* Lecid of this client */
        struct hlist_head lec_arp_empty_ones;
                                                /* Used for storing VCC's that don't have a MAC address attached yet */
index 00d9e5e131582669cab51f01b91b43c204ea0da8..d127fd3ba5c6acd8a7c3ce0f6b4ea5ee8b25f47b 100644 (file)
@@ -1986,7 +1986,7 @@ static const struct proto_ops ax25_proto_ops = {
  *     Called by socket.c on kernel start up
  */
 static struct packet_type ax25_packet_type = {
-       .type   =       __constant_htons(ETH_P_AX25),
+       .type   =       cpu_to_be16(ETH_P_AX25),
        .dev    =       NULL,                           /* All devices */
        .func   =       ax25_kiss_rcv,
 };
index cf754ace0b75ba8c57e35e9420cfd97137ff88f9..3953ac4214c818e27a2a19d39c3e71bdd531f17a 100644 (file)
@@ -107,7 +107,7 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 static struct dst_ops fake_dst_ops = {
        .family =               AF_INET,
-       .protocol =             __constant_htons(ETH_P_IP),
+       .protocol =             cpu_to_be16(ETH_P_IP),
        .update_pmtu =          fake_update_pmtu,
        .entries =              ATOMIC_INIT(0),
 };
index fa417ca6cbe6c88cf97c305ed399681125acdc03..d90e8dd975fcf05d842be52fd41ef8e1f369d411 100644 (file)
@@ -828,7 +828,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
  */
 
 static struct packet_type can_packet __read_mostly = {
-       .type = __constant_htons(ETH_P_CAN),
+       .type = cpu_to_be16(ETH_P_CAN),
        .dev  = NULL,
        .func = can_rcv,
 };
index 5379b0c1190a86aa10ab8afd0ae4da9597af1611..220f52a1001e1a211d7096488860a9c1191b37af 100644 (file)
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
 
+enum {
+       GRO_MERGED,
+       GRO_MERGED_FREE,
+       GRO_HELD,
+       GRO_NORMAL,
+       GRO_DROP,
+};
+
 /*
  *     The list of packet types we will receive (as opposed to discard)
  *     and the routines to invoke.
@@ -207,6 +215,13 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
        return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
 }
 
+static inline void *skb_gro_mac_header(struct sk_buff *skb)
+{
+       return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) :
+              page_address(skb_shinfo(skb)->frags[0].page) +
+              skb_shinfo(skb)->frags[0].page_offset;
+}
+
 /* Device list insertion */
 static int list_netdevice(struct net_device *dev)
 {
@@ -1708,56 +1723,26 @@ out_kfree_skb:
        return 0;
 }
 
-static u32 simple_tx_hashrnd;
-static int simple_tx_hashrnd_initialized = 0;
+static u32 skb_tx_hashrnd;
+static int skb_tx_hashrnd_initialized = 0;
 
-static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
+static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
 {
-       u32 addr1, addr2, ports;
-       u32 hash, ihl;
-       u8 ip_proto = 0;
+       u32 hash;
 
-       if (unlikely(!simple_tx_hashrnd_initialized)) {
-               get_random_bytes(&simple_tx_hashrnd, 4);
-               simple_tx_hashrnd_initialized = 1;
+       if (unlikely(!skb_tx_hashrnd_initialized)) {
+               get_random_bytes(&skb_tx_hashrnd, 4);
+               skb_tx_hashrnd_initialized = 1;
        }
 
-       switch (skb->protocol) {
-       case htons(ETH_P_IP):
-               if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
-                       ip_proto = ip_hdr(skb)->protocol;
-               addr1 = ip_hdr(skb)->saddr;
-               addr2 = ip_hdr(skb)->daddr;
-               ihl = ip_hdr(skb)->ihl;
-               break;
-       case htons(ETH_P_IPV6):
-               ip_proto = ipv6_hdr(skb)->nexthdr;
-               addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
-               addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
-               ihl = (40 >> 2);
-               break;
-       default:
-               return 0;
-       }
-
-
-       switch (ip_proto) {
-       case IPPROTO_TCP:
-       case IPPROTO_UDP:
-       case IPPROTO_DCCP:
-       case IPPROTO_ESP:
-       case IPPROTO_AH:
-       case IPPROTO_SCTP:
-       case IPPROTO_UDPLITE:
-               ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
-               break;
-
-       default:
-               ports = 0;
-               break;
-       }
+       if (skb_rx_queue_recorded(skb)) {
+               hash = skb_get_rx_queue(skb);
+       } else if (skb->sk && skb->sk->sk_hash) {
+               hash = skb->sk->sk_hash;
+       } else
+               hash = skb->protocol;
 
-       hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd);
+       hash = jhash_1word(hash, skb_tx_hashrnd);
 
        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
 }
@@ -1771,7 +1756,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
        if (ops->ndo_select_queue)
                queue_index = ops->ndo_select_queue(dev, skb);
        else if (dev->real_num_tx_queues > 1)
-               queue_index = simple_tx_hash(dev, skb);
+               queue_index = skb_tx_hash(dev, skb);
 
        skb_set_queue_mapping(skb, queue_index);
        return netdev_get_tx_queue(dev, queue_index);
@@ -2372,7 +2357,6 @@ static int napi_gro_complete(struct sk_buff *skb)
 
 out:
        skb_shinfo(skb)->gso_size = 0;
-       __skb_push(skb, -skb_network_offset(skb));
        return netif_receive_skb(skb);
 }
 
@@ -2390,6 +2374,25 @@ void napi_gro_flush(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_gro_flush);
 
+void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
+{
+       unsigned int offset = skb_gro_offset(skb);
+
+       hlen += offset;
+       if (hlen <= skb_headlen(skb))
+               return skb->data + offset;
+
+       if (unlikely(!skb_shinfo(skb)->nr_frags ||
+                    skb_shinfo(skb)->frags[0].size <=
+                    hlen - skb_headlen(skb) ||
+                    PageHighMem(skb_shinfo(skb)->frags[0].page)))
+               return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
+
+       return page_address(skb_shinfo(skb)->frags[0].page) +
+              skb_shinfo(skb)->frags[0].page_offset + offset;
+}
+EXPORT_SYMBOL(skb_gro_header);
+
 int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff **pp = NULL;
@@ -2399,7 +2402,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        int count = 0;
        int same_flow;
        int mac_len;
-       int free;
+       int ret;
 
        if (!(skb->dev->features & NETIF_F_GRO))
                goto normal;
@@ -2410,11 +2413,13 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
                struct sk_buff *p;
+               void *mac;
 
                if (ptype->type != type || ptype->dev || !ptype->gro_receive)
                        continue;
 
-               skb_reset_network_header(skb);
+               skb_set_network_header(skb, skb_gro_offset(skb));
+               mac = skb_gro_mac_header(skb);
                mac_len = skb->network_header - skb->mac_header;
                skb->mac_len = mac_len;
                NAPI_GRO_CB(skb)->same_flow = 0;
@@ -2428,8 +2433,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                                continue;
 
                        if (p->mac_len != mac_len ||
-                           memcmp(skb_mac_header(p), skb_mac_header(skb),
-                                  mac_len))
+                           memcmp(skb_mac_header(p), mac, mac_len))
                                NAPI_GRO_CB(p)->same_flow = 0;
                }
 
@@ -2442,7 +2446,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                goto normal;
 
        same_flow = NAPI_GRO_CB(skb)->same_flow;
-       free = NAPI_GRO_CB(skb)->free;
+       ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED;
 
        if (pp) {
                struct sk_buff *nskb = *pp;
@@ -2456,21 +2460,28 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        if (same_flow)
                goto ok;
 
-       if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) {
-               __skb_push(skb, -skb_network_offset(skb));
+       if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS)
                goto normal;
-       }
 
        NAPI_GRO_CB(skb)->count = 1;
-       skb_shinfo(skb)->gso_size = skb->len;
+       skb_shinfo(skb)->gso_size = skb_gro_len(skb);
        skb->next = napi->gro_list;
        napi->gro_list = skb;
+       ret = GRO_HELD;
+
+pull:
+       if (unlikely(!pskb_may_pull(skb, skb_gro_offset(skb)))) {
+               if (napi->gro_list == skb)
+                       napi->gro_list = skb->next;
+               ret = GRO_DROP;
+       }
 
 ok:
-       return free;
+       return ret;
 
 normal:
-       return -1;
+       ret = GRO_NORMAL;
+       goto pull;
 }
 EXPORT_SYMBOL(dev_gro_receive);
 
@@ -2486,18 +2497,32 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        return dev_gro_receive(napi, skb);
 }
 
-int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+int napi_skb_finish(int ret, struct sk_buff *skb)
 {
-       switch (__napi_gro_receive(napi, skb)) {
-       case -1:
+       int err = NET_RX_SUCCESS;
+
+       switch (ret) {
+       case GRO_NORMAL:
                return netif_receive_skb(skb);
 
-       case 1:
+       case GRO_DROP:
+               err = NET_RX_DROP;
+               /* fall through */
+
+       case GRO_MERGED_FREE:
                kfree_skb(skb);
                break;
        }
 
-       return NET_RX_SUCCESS;
+       return err;
+}
+EXPORT_SYMBOL(napi_skb_finish);
+
+int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+{
+       skb_gro_reset_offset(skb);
+
+       return napi_skb_finish(__napi_gro_receive(napi, skb), skb);
 }
 EXPORT_SYMBOL(napi_gro_receive);
 
@@ -2515,6 +2540,9 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi,
 {
        struct net_device *dev = napi->dev;
        struct sk_buff *skb = napi->skb;
+       struct ethhdr *eth;
+       skb_frag_t *frag;
+       int i;
 
        napi->skb = NULL;
 
@@ -2527,20 +2555,36 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi,
        }
 
        BUG_ON(info->nr_frags > MAX_SKB_FRAGS);
+       frag = &info->frags[info->nr_frags - 1];
+
+       for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) {
+               skb_fill_page_desc(skb, i, frag->page, frag->page_offset,
+                                  frag->size);
+               frag++;
+       }
        skb_shinfo(skb)->nr_frags = info->nr_frags;
-       memcpy(skb_shinfo(skb)->frags, info->frags, sizeof(info->frags));
 
        skb->data_len = info->len;
        skb->len += info->len;
        skb->truesize += info->len;
 
-       if (!pskb_may_pull(skb, ETH_HLEN)) {
+       skb_reset_mac_header(skb);
+       skb_gro_reset_offset(skb);
+
+       eth = skb_gro_header(skb, sizeof(*eth));
+       if (!eth) {
                napi_reuse_skb(napi, skb);
                skb = NULL;
                goto out;
        }
 
-       skb->protocol = eth_type_trans(skb, dev);
+       skb_gro_pull(skb, sizeof(*eth));
+
+       /*
+        * This works because the only protocols we care about don't require
+        * special handling.  We'll fix it up properly at the end.
+        */
+       skb->protocol = eth->h_proto;
 
        skb->ip_summed = info->ip_summed;
        skb->csum = info->csum;
@@ -2550,29 +2594,43 @@ out:
 }
 EXPORT_SYMBOL(napi_fraginfo_skb);
 
-int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info)
+int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret)
 {
-       struct sk_buff *skb = napi_fraginfo_skb(napi, info);
-       int err = NET_RX_DROP;
+       int err = NET_RX_SUCCESS;
 
-       if (!skb)
-               goto out;
+       switch (ret) {
+       case GRO_NORMAL:
+       case GRO_HELD:
+               skb->protocol = eth_type_trans(skb, napi->dev);
 
-       err = NET_RX_SUCCESS;
+               if (ret == GRO_NORMAL)
+                       return netif_receive_skb(skb);
 
-       switch (__napi_gro_receive(napi, skb)) {
-       case -1:
-               return netif_receive_skb(skb);
+               skb_gro_pull(skb, -ETH_HLEN);
+               break;
 
-       case 0:
-               goto out;
-       }
+       case GRO_DROP:
+               err = NET_RX_DROP;
+               /* fall through */
 
-       napi_reuse_skb(napi, skb);
+       case GRO_MERGED_FREE:
+               napi_reuse_skb(napi, skb);
+               break;
+       }
 
-out:
        return err;
 }
+EXPORT_SYMBOL(napi_frags_finish);
+
+int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info)
+{
+       struct sk_buff *skb = napi_fraginfo_skb(napi, info);
+
+       if (!skb)
+               return NET_RX_DROP;
+
+       return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb));
+}
 EXPORT_SYMBOL(napi_gro_frags);
 
 static int process_backlog(struct napi_struct *napi, int quota)
index da74b844f4eab0464374a1a667cea8aa40a7bf26..e55d1ef5690dc4d024454bc2142b53a1c357a148 100644 (file)
@@ -1333,14 +1333,39 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
        put_page(spd->pages[i]);
 }
 
-static inline struct page *linear_to_page(struct page *page, unsigned int len,
-                                         unsigned int offset)
-{
-       struct page *p = alloc_pages(GFP_KERNEL, 0);
+static inline struct page *linear_to_page(struct page *page, unsigned int *len,
+                                         unsigned int *offset,
+                                         struct sk_buff *skb)
+{
+       struct sock *sk = skb->sk;
+       struct page *p = sk->sk_sndmsg_page;
+       unsigned int off;
+
+       if (!p) {
+new_page:
+               p = sk->sk_sndmsg_page = alloc_pages(sk->sk_allocation, 0);
+               if (!p)
+                       return NULL;
 
-       if (!p)
-               return NULL;
-       memcpy(page_address(p) + offset, page_address(page) + offset, len);
+               off = sk->sk_sndmsg_off = 0;
+               /* hold one ref to this page until it's full */
+       } else {
+               unsigned int mlen;
+
+               off = sk->sk_sndmsg_off;
+               mlen = PAGE_SIZE - off;
+               if (mlen < 64 && mlen < *len) {
+                       put_page(p);
+                       goto new_page;
+               }
+
+               *len = min_t(unsigned int, *len, mlen);
+       }
+
+       memcpy(page_address(p) + off, page_address(page) + *offset, *len);
+       sk->sk_sndmsg_off += *len;
+       *offset = off;
+       get_page(p);
 
        return p;
 }
@@ -1349,21 +1374,21 @@ static inline struct page *linear_to_page(struct page *page, unsigned int len,
  * Fill page/offset/length into spd, if it can hold more pages.
  */
 static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
-                               unsigned int len, unsigned int offset,
+                               unsigned int *len, unsigned int offset,
                                struct sk_buff *skb, int linear)
 {
        if (unlikely(spd->nr_pages == PIPE_BUFFERS))
                return 1;
 
        if (linear) {
-               page = linear_to_page(page, len, offset);
+               page = linear_to_page(page, len, &offset, skb);
                if (!page)
                        return 1;
        } else
                get_page(page);
 
        spd->pages[spd->nr_pages] = page;
-       spd->partial[spd->nr_pages].len = len;
+       spd->partial[spd->nr_pages].len = *len;
        spd->partial[spd->nr_pages].offset = offset;
        spd->nr_pages++;
 
@@ -1405,7 +1430,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff,
                /* the linear region may spread across several pages  */
                flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
 
-               if (spd_fill_page(spd, page, flen, poff, skb, linear))
+               if (spd_fill_page(spd, page, &flen, poff, skb, linear))
                        return 1;
 
                __segment_seek(&page, &poff, &plen, flen);
@@ -2585,17 +2610,23 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        struct sk_buff *p = *head;
        struct sk_buff *nskb;
        unsigned int headroom;
-       unsigned int hlen = p->data - skb_mac_header(p);
-       unsigned int len = skb->len;
+       unsigned int len = skb_gro_len(skb);
 
-       if (hlen + p->len + len >= 65536)
+       if (p->len + len >= 65536)
                return -E2BIG;
 
        if (skb_shinfo(p)->frag_list)
                goto merge;
-       else if (!skb_headlen(p) && !skb_headlen(skb) &&
-                skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <
-                MAX_SKB_FRAGS) {
+       else if (skb_headlen(skb) <= skb_gro_offset(skb)) {
+               if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags >
+                   MAX_SKB_FRAGS)
+                       return -E2BIG;
+
+               skb_shinfo(skb)->frags[0].page_offset +=
+                       skb_gro_offset(skb) - skb_headlen(skb);
+               skb_shinfo(skb)->frags[0].size -=
+                       skb_gro_offset(skb) - skb_headlen(skb);
+
                memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags,
                       skb_shinfo(skb)->frags,
                       skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
@@ -2612,7 +2643,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        }
 
        headroom = skb_headroom(p);
-       nskb = netdev_alloc_skb(p->dev, headroom);
+       nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p));
        if (unlikely(!nskb))
                return -ENOMEM;
 
@@ -2620,12 +2651,15 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        nskb->mac_len = p->mac_len;
 
        skb_reserve(nskb, headroom);
+       __skb_put(nskb, skb_gro_offset(p));
 
-       skb_set_mac_header(nskb, -hlen);
+       skb_set_mac_header(nskb, skb_mac_header(p) - p->data);
        skb_set_network_header(nskb, skb_network_offset(p));
        skb_set_transport_header(nskb, skb_transport_offset(p));
 
-       memcpy(skb_mac_header(nskb), skb_mac_header(p), hlen);
+       __skb_pull(p, skb_gro_offset(p));
+       memcpy(skb_mac_header(nskb), skb_mac_header(p),
+              p->data - skb_mac_header(p));
 
        *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
        skb_shinfo(nskb)->frag_list = p;
index f2230fc168e14b257028378c49d5227397ae52b7..08a569ff02d1283816a7f11818cb06dd5dd7da87 100644 (file)
 extern int dccp_debug;
 #define dccp_pr_debug(format, a...)      DCCP_PR_DEBUG(dccp_debug, format, ##a)
 #define dccp_pr_debug_cat(format, a...)   DCCP_PRINTK(dccp_debug, format, ##a)
+#define dccp_debug(fmt, a...)            dccp_pr_debug_cat(KERN_DEBUG fmt, ##a)
 #else
 #define dccp_pr_debug(format, a...)
 #define dccp_pr_debug_cat(format, a...)
+#define dccp_debug(format, a...)
 #endif
 
 extern struct inet_hashinfo dccp_hashinfo;
@@ -95,9 +97,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
 extern int  sysctl_dccp_request_retries;
 extern int  sysctl_dccp_retries1;
 extern int  sysctl_dccp_retries2;
-extern int  sysctl_dccp_feat_sequence_window;
-extern int  sysctl_dccp_feat_rx_ccid;
-extern int  sysctl_dccp_feat_tx_ccid;
 extern int  sysctl_dccp_tx_qlen;
 extern int  sysctl_dccp_sync_ratelimit;
 
@@ -409,23 +408,21 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack,
 static inline void dccp_update_gsr(struct sock *sk, u64 seq)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       const struct dccp_minisock *dmsk = dccp_msk(sk);
 
        dp->dccps_gsr = seq;
-       dccp_set_seqno(&dp->dccps_swl,
-                      dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4));
-       dccp_set_seqno(&dp->dccps_swh,
-                      dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4);
+       /* Sequence validity window depends on remote Sequence Window (7.5.1) */
+       dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
+       dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);
 }
 
 static inline void dccp_update_gss(struct sock *sk, u64 seq)
 {
        struct dccp_sock *dp = dccp_sk(sk);
 
-       dp->dccps_awh = dp->dccps_gss = seq;
-       dccp_set_seqno(&dp->dccps_awl,
-                      (dp->dccps_gss -
-                       dccp_msk(sk)->dccpms_sequence_window + 1));
+       dp->dccps_gss = seq;
+       /* Ack validity window depends on local Sequence Window value (7.5.1) */
+       dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);
+       dp->dccps_awh = dp->dccps_gss;
 }
 
 static inline int dccp_ack_pending(const struct sock *sk)
index 4152308958ab0b3a10a70b729e32e8d988816e3b..b04160a2eea551e0ddb3d18b89f60674328f105b 100644 (file)
 #include "ccid.h"
 #include "feat.h"
 
+/* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */
+unsigned long  sysctl_dccp_sequence_window __read_mostly = 100;
+int            sysctl_dccp_rx_ccid         __read_mostly = 2,
+               sysctl_dccp_tx_ccid         __read_mostly = 2;
+
 /*
  * Feature activation handlers.
  *
@@ -51,8 +56,17 @@ static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
 
 static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)
 {
-       if (!rx)
-               dccp_msk(sk)->dccpms_sequence_window = seq_win;
+       struct dccp_sock *dp = dccp_sk(sk);
+
+       if (rx) {
+               dp->dccps_r_seq_win = seq_win;
+               /* propagate changes to update SWL/SWH */
+               dccp_update_gsr(sk, dp->dccps_gsr);
+       } else {
+               dp->dccps_l_seq_win = seq_win;
+               /* propagate changes to update AWL */
+               dccp_update_gss(sk, dp->dccps_gss);
+       }
        return 0;
 }
 
@@ -194,6 +208,100 @@ static int dccp_feat_default_value(u8 feat_num)
        return idx < 0 ? 0 : dccp_feat_table[idx].default_value;
 }
 
+/*
+ *     Debugging and verbose-printing section
+ */
+static const char *dccp_feat_fname(const u8 feat)
+{
+       static const char *feature_names[] = {
+               [DCCPF_RESERVED]        = "Reserved",
+               [DCCPF_CCID]            = "CCID",
+               [DCCPF_SHORT_SEQNOS]    = "Allow Short Seqnos",
+               [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
+               [DCCPF_ECN_INCAPABLE]   = "ECN Incapable",
+               [DCCPF_ACK_RATIO]       = "Ack Ratio",
+               [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
+               [DCCPF_SEND_NDP_COUNT]  = "Send NDP Count",
+               [DCCPF_MIN_CSUM_COVER]  = "Min. Csum Coverage",
+               [DCCPF_DATA_CHECKSUM]   = "Send Data Checksum",
+       };
+       if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
+               return feature_names[DCCPF_RESERVED];
+
+       if (feat ==  DCCPF_SEND_LEV_RATE)
+               return "Send Loss Event Rate";
+       if (feat >= DCCPF_MIN_CCID_SPECIFIC)
+               return "CCID-specific";
+
+       return feature_names[feat];
+}
+
+static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING",
+                                        "UNSTABLE", "STABLE" };
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+static const char *dccp_feat_oname(const u8 opt)
+{
+       switch (opt) {
+       case DCCPO_CHANGE_L:  return "Change_L";
+       case DCCPO_CONFIRM_L: return "Confirm_L";
+       case DCCPO_CHANGE_R:  return "Change_R";
+       case DCCPO_CONFIRM_R: return "Confirm_R";
+       }
+       return NULL;
+}
+
+static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val)
+{
+       u8 i, type = dccp_feat_type(feat_num);
+
+       if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL))
+               dccp_pr_debug_cat("(NULL)");
+       else if (type == FEAT_SP)
+               for (i = 0; i < val->sp.len; i++)
+                       dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]);
+       else if (type == FEAT_NN)
+               dccp_pr_debug_cat("%llu", (unsigned long long)val->nn);
+       else
+               dccp_pr_debug_cat("unknown type %u", type);
+}
+
+static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len)
+{
+       u8 type = dccp_feat_type(feat_num);
+       dccp_feat_val fval = { .sp.vec = list, .sp.len = len };
+
+       if (type == FEAT_NN)
+               fval.nn = dccp_decode_value_var(list, len);
+       dccp_feat_printval(feat_num, &fval);
+}
+
+static void dccp_feat_print_entry(struct dccp_feat_entry const *entry)
+{
+       dccp_debug("   * %s %s = ", entry->is_local ? "local" : "remote",
+                                   dccp_feat_fname(entry->feat_num));
+       dccp_feat_printval(entry->feat_num, &entry->val);
+       dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state],
+                         entry->needs_confirm ? "(Confirm pending)" : "");
+}
+
+#define dccp_feat_print_opt(opt, feat, val, len, mandatory)    do {          \
+       dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\
+       dccp_feat_printvals(feat, val, len);                                  \
+       dccp_pr_debug_cat(") %s\n", mandatory ? "!" : "");      } while (0)
+
+#define dccp_feat_print_fnlist(fn_list)  {             \
+       const struct dccp_feat_entry *___entry;         \
+                                                       \
+       dccp_pr_debug("List Dump:\n");                  \
+       list_for_each_entry(___entry, fn_list, node)    \
+               dccp_feat_print_entry(___entry);        \
+}
+#else  /* ! CONFIG_IP_DCCP_DEBUG */
+#define dccp_feat_print_opt(opt, feat, val, len, mandatory)
+#define dccp_feat_print_fnlist(fn_list)
+#endif
+
 static int __dccp_feat_activate(struct sock *sk, const int idx,
                                const bool is_local, dccp_feat_val const *fval)
 {
@@ -226,6 +334,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx,
        /* Location is RX if this is a local-RX or remote-TX feature */
        rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX));
 
+       dccp_debug("   -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX",
+                  dccp_feat_fname(dccp_feat_table[idx].feat_num),
+                  fval ? "" : "default ",  (unsigned long long)val);
+
        return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
 }
 
@@ -530,6 +642,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
                                return -1;
                        }
                }
+               dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0);
 
                if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt))
                        return -1;
@@ -783,6 +896,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp)
        while (i--)
                if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i))
                        return -1;
+       dccp_feat_print_fnlist(fn);
        return 0;
 }
 
@@ -901,6 +1015,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
        if (len == 0 || type == FEAT_UNKNOWN)           /* 6.1 and 6.6.8 */
                goto unknown_feature_or_value;
 
+       dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
+
        /*
         *      Negotiation of NN features: Change R is invalid, so there is no
         *      simultaneous negotiation; hence we do not look up in the list.
@@ -1006,6 +1122,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
        const bool local = (opt == DCCPO_CONFIRM_R);
        struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local);
 
+       dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
+
        if (entry == NULL) {    /* nothing queued: ignore or handle error */
                if (is_mandatory && type == FEAT_UNKNOWN)
                        return DCCP_RESET_CODE_MANDATORY_ERROR;
@@ -1115,23 +1233,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
        return 0;       /* ignore FN options in all other states */
 }
 
+/**
+ * dccp_feat_init  -  Seed feature negotiation with host-specific defaults
+ * This initialises global defaults, depending on the value of the sysctls.
+ * These can later be overridden by registering changes via setsockopt calls.
+ * The last link in the chain is finalise_settings, to make sure that between
+ * here and the start of actual feature negotiation no inconsistencies enter.
+ *
+ * All features not appearing below use either defaults or are otherwise
+ * later adjusted through dccp_feat_finalise_settings().
+ */
 int dccp_feat_init(struct sock *sk)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct dccp_minisock *dmsk = dccp_msk(sk);
+       struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
+       u8 on = 1, off = 0;
        int rc;
+       struct {
+               u8 *val;
+               u8 len;
+       } tx, rx;
+
+       /* Non-negotiable (NN) features */
+       rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
+                                   sysctl_dccp_sequence_window);
+       if (rc)
+               return rc;
+
+       /* Server-priority (SP) features */
+
+       /* Advertise that short seqnos are not supported (7.6.1) */
+       rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
+       if (rc)
+               return rc;
 
-       INIT_LIST_HEAD(&dmsk->dccpms_pending);  /* XXX no longer used */
-       INIT_LIST_HEAD(&dmsk->dccpms_conf);     /* XXX no longer used */
+       /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
+       rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
+       if (rc)
+               return rc;
+
+       /*
+        * We advertise the available list of CCIDs and reorder according to
+        * preferences, to avoid failure resulting from negotiating different
+        * singleton values (which always leads to failure).
+        * These settings can still (later) be overridden via sockopts.
+        */
+       if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||
+           ccid_get_builtin_ccids(&rx.val, &rx.len))
+               return -ENOBUFS;
+
+       if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) ||
+           !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len))
+               goto free_ccid_lists;
+
+       rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
+       if (rc)
+               goto free_ccid_lists;
+
+       rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
 
-       /* Ack ratio */
-       rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0,
-                               dp->dccps_l_ack_ratio);
+free_ccid_lists:
+       kfree(tx.val);
+       kfree(rx.val);
        return rc;
 }
 
-EXPORT_SYMBOL_GPL(dccp_feat_init);
-
 int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
 {
        struct dccp_sock *dp = dccp_sk(sk);
@@ -1156,9 +1321,10 @@ int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
                        goto activation_failed;
                }
                if (cur->state != FEAT_STABLE) {
-                       DCCP_CRIT("Negotiation of %s %u failed in state %u",
+                       DCCP_CRIT("Negotiation of %s %s failed in state %s",
                                  cur->is_local ? "local" : "remote",
-                                 cur->feat_num, cur->state);
+                                 dccp_feat_fname(cur->feat_num),
+                                 dccp_feat_sname[cur->state]);
                        goto activation_failed;
                }
                fvals[idx][cur->is_local] = &cur->val;
@@ -1199,43 +1365,3 @@ activation_failed:
        dp->dccps_hc_rx_ackvec = NULL;
        return -1;
 }
-
-#ifdef CONFIG_IP_DCCP_DEBUG
-const char *dccp_feat_typename(const u8 type)
-{
-       switch(type) {
-       case DCCPO_CHANGE_L:  return("ChangeL");
-       case DCCPO_CONFIRM_L: return("ConfirmL");
-       case DCCPO_CHANGE_R:  return("ChangeR");
-       case DCCPO_CONFIRM_R: return("ConfirmR");
-       /* the following case must not appear in feature negotation  */
-       default:              dccp_pr_debug("unknown type %d [BUG!]\n", type);
-       }
-       return NULL;
-}
-
-const char *dccp_feat_name(const u8 feat)
-{
-       static const char *feature_names[] = {
-               [DCCPF_RESERVED]        = "Reserved",
-               [DCCPF_CCID]            = "CCID",
-               [DCCPF_SHORT_SEQNOS]    = "Allow Short Seqnos",
-               [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
-               [DCCPF_ECN_INCAPABLE]   = "ECN Incapable",
-               [DCCPF_ACK_RATIO]       = "Ack Ratio",
-               [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
-               [DCCPF_SEND_NDP_COUNT]  = "Send NDP Count",
-               [DCCPF_MIN_CSUM_COVER]  = "Min. Csum Coverage",
-               [DCCPF_DATA_CHECKSUM]   = "Send Data Checksum",
-       };
-       if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
-               return feature_names[DCCPF_RESERVED];
-
-       if (feat ==  DCCPF_SEND_LEV_RATE)
-               return "Send Loss Event Rate";
-       if (feat >= DCCPF_MIN_CCID_SPECIFIC)
-               return "CCID-specific";
-
-       return feature_names[feat];
-}
-#endif /* CONFIG_IP_DCCP_DEBUG */
index 9b46e2a7866e675db04857d21b0b58899af70b8f..f96721619defecb9d844fd56e5e9f3e9d65f6eb6 100644 (file)
@@ -100,26 +100,21 @@ struct ccid_dependency {
        u8      val;
 };
 
-#ifdef CONFIG_IP_DCCP_DEBUG
-extern const char *dccp_feat_typename(const u8 type);
-extern const char *dccp_feat_name(const u8 feat);
-
-static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)
-{
-       dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type),
-                                          dccp_feat_name(feat), feat, val);
-}
-#else
-#define dccp_feat_debug(type, feat, val)
-#endif /* CONFIG_IP_DCCP_DEBUG */
+/*
+ * Sysctls to seed defaults for feature negotiation
+ */
+extern unsigned long sysctl_dccp_sequence_window;
+extern int          sysctl_dccp_rx_ccid;
+extern int          sysctl_dccp_tx_ccid;
 
+extern int  dccp_feat_init(struct sock *sk);
+extern void dccp_feat_initialise_sysctls(void);
 extern int  dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
                                  u8 const *list, u8 len);
 extern int  dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
 extern int  dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,
                                    u8 mand, u8 opt, u8 feat, u8 *val, u8 len);
 extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
-extern int  dccp_feat_init(struct sock *sk);
 
 /*
  * Encoding variable-length options and their maximum length.
index 6821ae33dd37a02600dc80b4ba7f8f8452c6185a..5ca49cec95f5aedf3d45406567c5f22bdf65d9af 100644 (file)
@@ -42,11 +42,6 @@ struct inet_timewait_death_row dccp_death_row = {
 
 EXPORT_SYMBOL_GPL(dccp_death_row);
 
-void dccp_minisock_init(struct dccp_minisock *dmsk)
-{
-       dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;
-}
-
 void dccp_time_wait(struct sock *sk, int state, int timeo)
 {
        struct inet_timewait_sock *tw = NULL;
@@ -110,7 +105,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
                struct dccp_request_sock *dreq = dccp_rsk(req);
                struct inet_connection_sock *newicsk = inet_csk(newsk);
                struct dccp_sock *newdp = dccp_sk(newsk);
-               struct dccp_minisock *newdmsk = dccp_msk(newsk);
 
                newdp->dccps_role           = DCCP_ROLE_SERVER;
                newdp->dccps_hc_rx_ackvec   = NULL;
@@ -128,10 +122,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
                 *    Initialize S.GAR := S.ISS
                 *    Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
                 */
-
-               /* See dccp_v4_conn_request */
-               newdmsk->dccpms_sequence_window = req->rcv_wnd;
-
                newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss;
                dccp_update_gss(newsk, dreq->dreq_iss);
 
@@ -290,7 +280,6 @@ int dccp_reqsk_init(struct request_sock *req,
        inet_rsk(req)->rmt_port   = dccp_hdr(skb)->dccph_sport;
        inet_rsk(req)->loc_port   = dccp_hdr(skb)->dccph_dport;
        inet_rsk(req)->acked      = 0;
-       req->rcv_wnd              = sysctl_dccp_feat_sequence_window;
        dreq->dreq_timestamp_echo = 0;
 
        /* inherit feature negotiation options from listening socket */
index 7b1165c21f5173a40c9511f934ccc5dcc02cc896..1b08cae9c65ba21fb1a28c255b810e868acc044a 100644 (file)
 #include "dccp.h"
 #include "feat.h"
 
-int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
-int sysctl_dccp_feat_rx_ccid         = DCCPF_INITIAL_CCID;
-int sysctl_dccp_feat_tx_ccid         = DCCPF_INITIAL_CCID;
-
 u64 dccp_decode_value_var(const u8 *bf, const u8 len)
 {
        u64 value = 0;
@@ -502,10 +498,6 @@ int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
                *to++ = *val;
        if (len)
                memcpy(to, val, len);
-
-       dccp_pr_debug("%s(%s (%d), ...), length %d\n",
-                     dccp_feat_typename(type),
-                     dccp_feat_name(feat), feat, len);
        return 0;
 }
 
index 945b4d5d23b3153fce6efd1fb0b3e04dee04b501..314a1b5c033c88950ddf73eccf30a34bcaf60191 100644 (file)
@@ -174,8 +174,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
        struct dccp_sock *dp = dccp_sk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
 
-       dccp_minisock_init(&dp->dccps_minisock);
-
        icsk->icsk_rto          = DCCP_TIMEOUT_INIT;
        icsk->icsk_syn_retries  = sysctl_dccp_request_retries;
        sk->sk_state            = DCCP_CLOSED;
index 018e210875e168141a2aca941ab11ca7daaca9ef..a5a1856234e76bd32368b799c49ab43520092532 100644 (file)
 #error This file should not be compiled without CONFIG_SYSCTL defined
 #endif
 
+/* Boundary values */
+static int             zero     = 0,
+                       u8_max   = 0xFF;
+static unsigned long   seqw_min = 32;
+
 static struct ctl_table dccp_default_table[] = {
        {
                .procname       = "seq_window",
-               .data           = &sysctl_dccp_feat_sequence_window,
-               .maxlen         = sizeof(sysctl_dccp_feat_sequence_window),
+               .data           = &sysctl_dccp_sequence_window,
+               .maxlen         = sizeof(sysctl_dccp_sequence_window),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &seqw_min,            /* RFC 4340, 7.5.2 */
        },
        {
                .procname       = "rx_ccid",
-               .data           = &sysctl_dccp_feat_rx_ccid,
-               .maxlen         = sizeof(sysctl_dccp_feat_rx_ccid),
+               .data           = &sysctl_dccp_rx_ccid,
+               .maxlen         = sizeof(sysctl_dccp_rx_ccid),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &u8_max,              /* RFC 4340, 10. */
        },
        {
                .procname       = "tx_ccid",
-               .data           = &sysctl_dccp_feat_tx_ccid,
-               .maxlen         = sizeof(sysctl_dccp_feat_tx_ccid),
+               .data           = &sysctl_dccp_tx_ccid,
+               .maxlen         = sizeof(sysctl_dccp_tx_ccid),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &u8_max,              /* RFC 4340, 10. */
        },
        {
                .procname       = "request_retries",
                .data           = &sysctl_dccp_request_retries,
                .maxlen         = sizeof(sysctl_dccp_request_retries),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &u8_max,
        },
        {
                .procname       = "retries1",
                .data           = &sysctl_dccp_retries1,
                .maxlen         = sizeof(sysctl_dccp_retries1),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &u8_max,
        },
        {
                .procname       = "retries2",
                .data           = &sysctl_dccp_retries2,
                .maxlen         = sizeof(sysctl_dccp_retries2),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &u8_max,
        },
        {
                .procname       = "tx_qlen",
                .data           = &sysctl_dccp_tx_qlen,
                .maxlen         = sizeof(sysctl_dccp_tx_qlen),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
        },
        {
                .procname       = "sync_ratelimit",
index cf0e18499297080bac82f4b020409dd2dbb0f5fa..12bf7d4c16c641dd31a33904331b43d0069a666f 100644 (file)
@@ -2113,7 +2113,7 @@ static struct notifier_block dn_dev_notifier = {
 extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
 
 static struct packet_type dn_dix_packet_type = {
-       .type =         __constant_htons(ETH_P_DNA_RT),
+       .type =         cpu_to_be16(ETH_P_DNA_RT),
        .dev =          NULL,           /* All devices */
        .func =         dn_route_rcv,
 };
index c754670b7fca4e98376fdb22657efb5e3e5613d6..5130dee0b384023911306aaf29da23aab1a1dc30 100644 (file)
@@ -124,7 +124,7 @@ int decnet_dst_gc_interval = 2;
 
 static struct dst_ops dn_dst_ops = {
        .family =               PF_DECnet,
-       .protocol =             __constant_htons(ETH_P_DNA_RT),
+       .protocol =             cpu_to_be16(ETH_P_DNA_RT),
        .gc_thresh =            128,
        .gc =                   dn_dst_gc,
        .check =                dn_dst_check,
index ec8c6a0482d3dde28385c498fbad59707da6ede3..1003187222146c2a7708258369c7a30d15243762 100644 (file)
@@ -394,7 +394,7 @@ static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds)
 }
 
 static struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
-       .tag_protocol           = __constant_htons(ETH_P_EDSA),
+       .tag_protocol           = cpu_to_be16(ETH_P_EDSA),
        .priv_size              = sizeof(struct mv88e6xxx_priv_state),
        .probe                  = mv88e6123_61_65_probe,
        .setup                  = mv88e6123_61_65_setup,
index 374d46a01265a334901bc652c57b939a419ddfaf..70fae2444cb65e64828e07bcbd9aef5bf35f2b65 100644 (file)
@@ -353,7 +353,7 @@ static int mv88e6131_get_sset_count(struct dsa_switch *ds)
 }
 
 static struct dsa_switch_driver mv88e6131_switch_driver = {
-       .tag_protocol           = __constant_htons(ETH_P_DSA),
+       .tag_protocol           = cpu_to_be16(ETH_P_DSA),
        .priv_size              = sizeof(struct mv88e6xxx_priv_state),
        .probe                  = mv88e6131_probe,
        .setup                  = mv88e6131_setup,
index f99a019b939ed7e2b15e90bcfa5be1716accd1b9..63e532a69fdb1186077d0cc6dd658f276ec59565 100644 (file)
@@ -176,7 +176,7 @@ out:
 }
 
 static struct packet_type dsa_packet_type = {
-       .type   = __constant_htons(ETH_P_DSA),
+       .type   = cpu_to_be16(ETH_P_DSA),
        .func   = dsa_rcv,
 };
 
index 328ec957f7864a670ce7ad841ae43010fa2d2e35..6197f9a7ef421f7eec701f8a61defdbb11bcbbdb 100644 (file)
@@ -195,7 +195,7 @@ out:
 }
 
 static struct packet_type edsa_packet_type = {
-       .type   = __constant_htons(ETH_P_EDSA),
+       .type   = cpu_to_be16(ETH_P_EDSA),
        .func   = edsa_rcv,
 };
 
index b59132878ad1c45ce54271213d5b4909d5113809..d7e7f424ff0c4a09c6bccb8cdff5fbbe556e687e 100644 (file)
@@ -112,7 +112,7 @@ out:
 }
 
 static struct packet_type trailer_packet_type = {
-       .type   = __constant_htons(ETH_P_TRAILER),
+       .type   = cpu_to_be16(ETH_P_TRAILER),
        .func   = trailer_rcv,
 };
 
index 8789d2bb1b067fd59515a286610971a67dfebf37..7bf35582f65643f97e959b290a77bc66f2b88538 100644 (file)
@@ -1103,7 +1103,7 @@ drop:
 }
 
 static struct packet_type econet_packet_type = {
-       .type =         __constant_htons(ETH_P_ECONET),
+       .type =         cpu_to_be16(ETH_P_ECONET),
        .func =         econet_rcv,
 };
 
index 743f5542d65a6385c7ae423ddb49d4c69daaeaee..c79087719df0e4f8242eca4c25a6df37dd94b5a2 100644 (file)
@@ -369,7 +369,6 @@ lookup_protocol:
        sock_init_data(sock, sk);
 
        sk->sk_destruct    = inet_sock_destruct;
-       sk->sk_family      = PF_INET;
        sk->sk_protocol    = protocol;
        sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
 
@@ -1253,10 +1252,10 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
        int proto;
        int id;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
+       iph = skb_gro_header(skb, sizeof(*iph));
+       if (unlikely(!iph))
                goto out;
 
-       iph = ip_hdr(skb);
        proto = iph->protocol & (MAX_INET_PROTOS - 1);
 
        rcu_read_lock();
@@ -1270,7 +1269,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
        if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
                goto out_unlock;
 
-       flush = ntohs(iph->tot_len) != skb->len ||
+       flush = ntohs(iph->tot_len) != skb_gro_len(skb) ||
                iph->frag_off != htons(IP_DF);
        id = ntohs(iph->id);
 
@@ -1298,8 +1297,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
        }
 
        NAPI_GRO_CB(skb)->flush |= flush;
-       __skb_pull(skb, sizeof(*iph));
-       skb_reset_transport_header(skb);
+       skb_gro_pull(skb, sizeof(*iph));
+       skb_set_transport_header(skb, skb_gro_offset(skb));
 
        pp = ops->gro_receive(head, skb);
 
@@ -1501,7 +1500,7 @@ static int ipv4_proc_init(void);
  */
 
 static struct packet_type ip_packet_type = {
-       .type = __constant_htons(ETH_P_IP),
+       .type = cpu_to_be16(ETH_P_IP),
        .func = ip_rcv,
        .gso_send_check = inet_gso_send_check,
        .gso_segment = inet_gso_segment,
index 29a74c01d8de54857fa3ef4a82184dc8a03b91cd..3f6b7354699bb8fe8df7cb47a1ced87e9816cf06 100644 (file)
@@ -1226,7 +1226,7 @@ void arp_ifdown(struct net_device *dev)
  */
 
 static struct packet_type arp_packet_type = {
-       .type = __constant_htons(ETH_P_ARP),
+       .type = cpu_to_be16(ETH_P_ARP),
        .func = arp_rcv,
 };
 
index 309997edc8a5169546e87ed2a51e51214e4bea6f..d519a6a6672634902f93459e0581e92a2af51f0b 100644 (file)
@@ -1075,6 +1075,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                        }
                }
                ip_mc_up(in_dev);
+               /* fall through */
+       case NETDEV_CHANGEADDR:
+               if (IN_DEV_ARP_NOTIFY(in_dev))
+                       arp_send(ARPOP_REQUEST, ETH_P_ARP,
+                                in_dev->ifa_list->ifa_address,
+                                dev,
+                                in_dev->ifa_list->ifa_address,
+                                NULL, dev->dev_addr, NULL);
                break;
        case NETDEV_DOWN:
                ip_mc_down(in_dev);
@@ -1439,6 +1447,7 @@ static struct devinet_sysctl_table {
                DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
                DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
                DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
+               DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
 
                DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
                DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
index f26ab38680de00a5b77c303e34774a078022d499..22cd19ee44e52f5b94788e37dd6b5dc02f018eae 100644 (file)
@@ -93,24 +93,40 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
        struct inet_bind_hashbucket *head;
        struct hlist_node *node;
        struct inet_bind_bucket *tb;
-       int ret;
+       int ret, attempts = 5;
        struct net *net = sock_net(sk);
+       int smallest_size = -1, smallest_rover;
 
        local_bh_disable();
        if (!snum) {
                int remaining, rover, low, high;
 
+again:
                inet_get_local_port_range(&low, &high);
                remaining = (high - low) + 1;
-               rover = net_random() % remaining + low;
+               smallest_rover = rover = net_random() % remaining + low;
 
+               smallest_size = -1;
                do {
                        head = &hashinfo->bhash[inet_bhashfn(net, rover,
                                        hashinfo->bhash_size)];
                        spin_lock(&head->lock);
                        inet_bind_bucket_for_each(tb, node, &head->chain)
-                               if (ib_net(tb) == net && tb->port == rover)
+                               if (ib_net(tb) == net && tb->port == rover) {
+                                       if (tb->fastreuse > 0 &&
+                                           sk->sk_reuse &&
+                                           sk->sk_state != TCP_LISTEN &&
+                                           (tb->num_owners < smallest_size || smallest_size == -1)) {
+                                               smallest_size = tb->num_owners;
+                                               smallest_rover = rover;
+                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
+                                                       spin_unlock(&head->lock);
+                                                       snum = smallest_rover;
+                                                       goto have_snum;
+                                               }
+                                       }
                                        goto next;
+                               }
                        break;
                next:
                        spin_unlock(&head->lock);
@@ -125,14 +141,19 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
                 * the top level, not from the 'break;' statement.
                 */
                ret = 1;
-               if (remaining <= 0)
+               if (remaining <= 0) {
+                       if (smallest_size != -1) {
+                               snum = smallest_rover;
+                               goto have_snum;
+                       }
                        goto fail;
-
+               }
                /* OK, here is the one we will use.  HEAD is
                 * non-NULL and we hold it's mutex.
                 */
                snum = rover;
        } else {
+have_snum:
                head = &hashinfo->bhash[inet_bhashfn(net, snum,
                                hashinfo->bhash_size)];
                spin_lock(&head->lock);
@@ -145,12 +166,19 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
 tb_found:
        if (!hlist_empty(&tb->owners)) {
                if (tb->fastreuse > 0 &&
-                   sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
+                   sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+                   smallest_size == -1) {
                        goto success;
                } else {
                        ret = 1;
-                       if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
+                       if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+                               if (sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+                                   smallest_size != -1 && --attempts >= 0) {
+                                       spin_unlock(&head->lock);
+                                       goto again;
+                               }
                                goto fail_unlock;
+                       }
                }
        }
 tb_not_found:
index 6a1045da48d21774a78f0466deefed4539005306..625cc5f64c949fb2483c18e82d398ba6c2b0236d 100644 (file)
@@ -38,6 +38,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
                write_pnet(&tb->ib_net, hold_net(net));
                tb->port      = snum;
                tb->fastreuse = 0;
+               tb->num_owners = 0;
                INIT_HLIST_HEAD(&tb->owners);
                hlist_add_head(&tb->node, &head->chain);
        }
@@ -59,8 +60,13 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
 void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
                    const unsigned short snum)
 {
+       struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+
+       atomic_inc(&hashinfo->bsockets);
+
        inet_sk(sk)->num = snum;
        sk_add_bind_node(sk, &tb->owners);
+       tb->num_owners++;
        inet_csk(sk)->icsk_bind_hash = tb;
 }
 
@@ -75,9 +81,12 @@ static void __inet_put_port(struct sock *sk)
        struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
        struct inet_bind_bucket *tb;
 
+       atomic_dec(&hashinfo->bsockets);
+
        spin_lock(&head->lock);
        tb = inet_csk(sk)->icsk_bind_hash;
        __sk_del_bind_node(sk);
+       tb->num_owners--;
        inet_csk(sk)->icsk_bind_hash = NULL;
        inet_sk(sk)->num = 0;
        inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
@@ -444,9 +453,9 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
                         */
                        inet_bind_bucket_for_each(tb, node, &head->chain) {
                                if (ib_net(tb) == net && tb->port == port) {
-                                       WARN_ON(hlist_empty(&tb->owners));
                                        if (tb->fastreuse >= 0)
                                                goto next_port;
+                                       WARN_ON(hlist_empty(&tb->owners));
                                        if (!check_established(death_row, sk,
                                                                port, &tw))
                                                goto ok;
@@ -523,6 +532,7 @@ void inet_hashinfo_init(struct inet_hashinfo *h)
 {
        int i;
 
+       atomic_set(&h->bsockets, 0);
        for (i = 0; i < INET_LHTABLE_SIZE; i++) {
                spin_lock_init(&h->listening_hash[i].lock);
                INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].head,
index 0101521f366b74546cbb90f60e7e6faac597b430..07a188afb3ac7af64650d8eb7f641f27b8eb09b6 100644 (file)
@@ -164,67 +164,124 @@ static DEFINE_RWLOCK(ipgre_lock);
 
 /* Given src, dst and key, find appropriate for input tunnel. */
 
-static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
+static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
                                              __be32 remote, __be32 local,
                                              __be32 key, __be16 gre_proto)
 {
+       struct net *net = dev_net(dev);
+       int link = dev->ifindex;
        unsigned h0 = HASH(remote);
        unsigned h1 = HASH(key);
-       struct ip_tunnel *t;
-       struct ip_tunnel *t2 = NULL;
+       struct ip_tunnel *t, *cand = NULL;
        struct ipgre_net *ign = net_generic(net, ipgre_net_id);
        int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
                       ARPHRD_ETHER : ARPHRD_IPGRE;
+       int score, cand_score = 4;
 
        for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
-               if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
-                       if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
-                               if (t->dev->type == dev_type)
-                                       return t;
-                               if (t->dev->type == ARPHRD_IPGRE && !t2)
-                                       t2 = t;
-                       }
+               if (local != t->parms.iph.saddr ||
+                   remote != t->parms.iph.daddr ||
+                   key != t->parms.i_key ||
+                   !(t->dev->flags & IFF_UP))
+                       continue;
+
+               if (t->dev->type != ARPHRD_IPGRE &&
+                   t->dev->type != dev_type)
+                       continue;
+
+               score = 0;
+               if (t->parms.link != link)
+                       score |= 1;
+               if (t->dev->type != dev_type)
+                       score |= 2;
+               if (score == 0)
+                       return t;
+
+               if (score < cand_score) {
+                       cand = t;
+                       cand_score = score;
                }
        }
 
        for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
-               if (remote == t->parms.iph.daddr) {
-                       if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
-                               if (t->dev->type == dev_type)
-                                       return t;
-                               if (t->dev->type == ARPHRD_IPGRE && !t2)
-                                       t2 = t;
-                       }
+               if (remote != t->parms.iph.daddr ||
+                   key != t->parms.i_key ||
+                   !(t->dev->flags & IFF_UP))
+                       continue;
+
+               if (t->dev->type != ARPHRD_IPGRE &&
+                   t->dev->type != dev_type)
+                       continue;
+
+               score = 0;
+               if (t->parms.link != link)
+                       score |= 1;
+               if (t->dev->type != dev_type)
+                       score |= 2;
+               if (score == 0)
+                       return t;
+
+               if (score < cand_score) {
+                       cand = t;
+                       cand_score = score;
                }
        }
 
        for (t = ign->tunnels_l[h1]; t; t = t->next) {
-               if (local == t->parms.iph.saddr ||
-                    (local == t->parms.iph.daddr &&
-                     ipv4_is_multicast(local))) {
-                       if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
-                               if (t->dev->type == dev_type)
-                                       return t;
-                               if (t->dev->type == ARPHRD_IPGRE && !t2)
-                                       t2 = t;
-                       }
+               if ((local != t->parms.iph.saddr &&
+                    (local != t->parms.iph.daddr ||
+                     !ipv4_is_multicast(local))) ||
+                   key != t->parms.i_key ||
+                   !(t->dev->flags & IFF_UP))
+                       continue;
+
+               if (t->dev->type != ARPHRD_IPGRE &&
+                   t->dev->type != dev_type)
+                       continue;
+
+               score = 0;
+               if (t->parms.link != link)
+                       score |= 1;
+               if (t->dev->type != dev_type)
+                       score |= 2;
+               if (score == 0)
+                       return t;
+
+               if (score < cand_score) {
+                       cand = t;
+                       cand_score = score;
                }
        }
 
        for (t = ign->tunnels_wc[h1]; t; t = t->next) {
-               if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
-                       if (t->dev->type == dev_type)
-                               return t;
-                       if (t->dev->type == ARPHRD_IPGRE && !t2)
-                               t2 = t;
+               if (t->parms.i_key != key ||
+                   !(t->dev->flags & IFF_UP))
+                       continue;
+
+               if (t->dev->type != ARPHRD_IPGRE &&
+                   t->dev->type != dev_type)
+                       continue;
+
+               score = 0;
+               if (t->parms.link != link)
+                       score |= 1;
+               if (t->dev->type != dev_type)
+                       score |= 2;
+               if (score == 0)
+                       return t;
+
+               if (score < cand_score) {
+                       cand = t;
+                       cand_score = score;
                }
        }
 
-       if (t2)
-               return t2;
+       if (cand != NULL)
+               return cand;
 
-       if (ign->fb_tunnel_dev->flags&IFF_UP)
+       if (ign->fb_tunnel_dev->flags & IFF_UP)
                return netdev_priv(ign->fb_tunnel_dev);
+
        return NULL;
 }
 
@@ -284,6 +341,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
        __be32 remote = parms->iph.daddr;
        __be32 local = parms->iph.saddr;
        __be32 key = parms->i_key;
+       int link = parms->link;
        struct ip_tunnel *t, **tp;
        struct ipgre_net *ign = net_generic(net, ipgre_net_id);
 
@@ -291,6 +349,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
                if (local == t->parms.iph.saddr &&
                    remote == t->parms.iph.daddr &&
                    key == t->parms.i_key &&
+                   link == t->parms.link &&
                    type == t->dev->type)
                        break;
 
@@ -421,7 +480,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
        }
 
        read_lock(&ipgre_lock);
-       t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
+       t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
                                flags & GRE_KEY ?
                                *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
                                p[1]);
@@ -518,7 +577,7 @@ static int ipgre_rcv(struct sk_buff *skb)
        gre_proto = *(__be16 *)(h + 2);
 
        read_lock(&ipgre_lock);
-       if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
+       if ((tunnel = ipgre_tunnel_lookup(skb->dev,
                                          iph->saddr, iph->daddr, key,
                                          gre_proto))) {
                struct net_device_stats *stats = &tunnel->dev->stats;
index d722013c1cae2a620c70282e39a767662bf608c5..90d22ae0a419e95f4a34c26a40673b03ed1840b1 100644 (file)
 #define CONF_NAMESERVERS_MAX   3       /* Maximum number of nameservers
                                           - '3' from resolv.h */
 
-#define NONE __constant_htonl(INADDR_NONE)
-#define ANY __constant_htonl(INADDR_ANY)
+#define NONE cpu_to_be32(INADDR_NONE)
+#define ANY cpu_to_be32(INADDR_ANY)
 
 /*
  * Public IP configuration
@@ -406,7 +406,7 @@ static int __init ic_defaults(void)
 static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
 
 static struct packet_type rarp_packet_type __initdata = {
-       .type = __constant_htons(ETH_P_RARP),
+       .type = cpu_to_be16(ETH_P_RARP),
        .func = ic_rarp_recv,
 };
 
@@ -568,7 +568,7 @@ struct bootp_pkt {          /* BOOTP packet format */
 static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
 
 static struct packet_type bootp_packet_type __initdata = {
-       .type = __constant_htons(ETH_P_IP),
+       .type = cpu_to_be16(ETH_P_IP),
        .func = ic_bootp_recv,
 };
 
index 14666449dc1c2f140da8b64162d2dcfa789d3a78..21a6dc710f20a5d08866f30ecb8e1f0298c204b3 100644 (file)
@@ -67,9 +67,6 @@
 #define CONFIG_IP_PIMSM        1
 #endif
 
-static struct sock *mroute_socket;
-
-
 /* Big lock, protecting vif table, mrt cache and mroute socket state.
    Note that the changes are semaphored via rtnl_lock.
  */
@@ -80,18 +77,9 @@ static DEFINE_RWLOCK(mrt_lock);
  *     Multicast router control variables
  */
 
-static struct vif_device vif_table[MAXVIFS];           /* Devices              */
-static int maxvif;
-
-#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL)
-
-static int mroute_do_assert;                           /* Set in PIM assert    */
-static int mroute_do_pim;
-
-static struct mfc_cache *mfc_cache_array[MFC_LINES];   /* Forwarding cache     */
+#define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL)
 
 static struct mfc_cache *mfc_unres_queue;              /* Queue of unresolved entries */
-static atomic_t cache_resolve_queue_len;               /* Size of unresolved   */
 
 /* Special spinlock for queue of unresolved entries */
 static DEFINE_SPINLOCK(mfc_unres_lock);
@@ -107,7 +95,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
 static struct kmem_cache *mrt_cachep __read_mostly;
 
 static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local);
-static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert);
+static int ipmr_cache_report(struct net *net,
+                            struct sk_buff *pkt, vifi_t vifi, int assert);
 static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm);
 
 #ifdef CONFIG_IP_PIMSM_V2
@@ -120,9 +109,11 @@ static struct timer_list ipmr_expire_timer;
 
 static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
 {
+       struct net *net = dev_net(dev);
+
        dev_close(dev);
 
-       dev = __dev_get_by_name(&init_net, "tunl0");
+       dev = __dev_get_by_name(net, "tunl0");
        if (dev) {
                const struct net_device_ops *ops = dev->netdev_ops;
                struct ifreq ifr;
@@ -148,11 +139,11 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
 }
 
 static
-struct net_device *ipmr_new_tunnel(struct vifctl *v)
+struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
 {
        struct net_device  *dev;
 
-       dev = __dev_get_by_name(&init_net, "tunl0");
+       dev = __dev_get_by_name(net, "tunl0");
 
        if (dev) {
                const struct net_device_ops *ops = dev->netdev_ops;
@@ -181,7 +172,8 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
 
                dev = NULL;
 
-               if (err == 0 && (dev = __dev_get_by_name(&init_net, p.name)) != NULL) {
+               if (err == 0 &&
+                   (dev = __dev_get_by_name(net, p.name)) != NULL) {
                        dev->flags |= IFF_MULTICAST;
 
                        in_dev = __in_dev_get_rtnl(dev);
@@ -209,14 +201,15 @@ failure:
 
 #ifdef CONFIG_IP_PIMSM
 
-static int reg_vif_num = -1;
-
 static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       struct net *net = dev_net(dev);
+
        read_lock(&mrt_lock);
        dev->stats.tx_bytes += skb->len;
        dev->stats.tx_packets++;
-       ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT);
+       ipmr_cache_report(net, skb, net->ipv4.mroute_reg_vif_num,
+                         IGMPMSG_WHOLEPKT);
        read_unlock(&mrt_lock);
        kfree_skb(skb);
        return 0;
@@ -283,16 +276,16 @@ failure:
  *     @notify: Set to 1, if the caller is a notifier_call
  */
 
-static int vif_delete(int vifi, int notify)
+static int vif_delete(struct net *net, int vifi, int notify)
 {
        struct vif_device *v;
        struct net_device *dev;
        struct in_device *in_dev;
 
-       if (vifi < 0 || vifi >= maxvif)
+       if (vifi < 0 || vifi >= net->ipv4.maxvif)
                return -EADDRNOTAVAIL;
 
-       v = &vif_table[vifi];
+       v = &net->ipv4.vif_table[vifi];
 
        write_lock_bh(&mrt_lock);
        dev = v->dev;
@@ -304,17 +297,17 @@ static int vif_delete(int vifi, int notify)
        }
 
 #ifdef CONFIG_IP_PIMSM
-       if (vifi == reg_vif_num)
-               reg_vif_num = -1;
+       if (vifi == net->ipv4.mroute_reg_vif_num)
+               net->ipv4.mroute_reg_vif_num = -1;
 #endif
 
-       if (vifi+1 == maxvif) {
+       if (vifi+1 == net->ipv4.maxvif) {
                int tmp;
                for (tmp=vifi-1; tmp>=0; tmp--) {
-                       if (VIF_EXISTS(tmp))
+                       if (VIF_EXISTS(net, tmp))
                                break;
                }
-               maxvif = tmp+1;
+               net->ipv4.maxvif = tmp+1;
        }
 
        write_unlock_bh(&mrt_lock);
@@ -333,6 +326,12 @@ static int vif_delete(int vifi, int notify)
        return 0;
 }
 
+static inline void ipmr_cache_free(struct mfc_cache *c)
+{
+       release_net(mfc_net(c));
+       kmem_cache_free(mrt_cachep, c);
+}
+
 /* Destroy an unresolved cache entry, killing queued skbs
    and reporting error to netlink readers.
  */
@@ -341,8 +340,9 @@ static void ipmr_destroy_unres(struct mfc_cache *c)
 {
        struct sk_buff *skb;
        struct nlmsgerr *e;
+       struct net *net = mfc_net(c);
 
-       atomic_dec(&cache_resolve_queue_len);
+       atomic_dec(&net->ipv4.cache_resolve_queue_len);
 
        while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) {
                if (ip_hdr(skb)->version == 0) {
@@ -354,12 +354,12 @@ static void ipmr_destroy_unres(struct mfc_cache *c)
                        e->error = -ETIMEDOUT;
                        memset(&e->msg, 0, sizeof(e->msg));
 
-                       rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
+                       rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
                } else
                        kfree_skb(skb);
        }
 
-       kmem_cache_free(mrt_cachep, c);
+       ipmr_cache_free(c);
 }
 
 
@@ -376,7 +376,7 @@ static void ipmr_expire_process(unsigned long dummy)
                return;
        }
 
-       if (atomic_read(&cache_resolve_queue_len) == 0)
+       if (mfc_unres_queue == NULL)
                goto out;
 
        now = jiffies;
@@ -397,7 +397,7 @@ static void ipmr_expire_process(unsigned long dummy)
                ipmr_destroy_unres(c);
        }
 
-       if (atomic_read(&cache_resolve_queue_len))
+       if (mfc_unres_queue != NULL)
                mod_timer(&ipmr_expire_timer, jiffies + expires);
 
 out:
@@ -409,13 +409,15 @@ out:
 static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
 {
        int vifi;
+       struct net *net = mfc_net(cache);
 
        cache->mfc_un.res.minvif = MAXVIFS;
        cache->mfc_un.res.maxvif = 0;
        memset(cache->mfc_un.res.ttls, 255, MAXVIFS);
 
-       for (vifi=0; vifi<maxvif; vifi++) {
-               if (VIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
+       for (vifi = 0; vifi < net->ipv4.maxvif; vifi++) {
+               if (VIF_EXISTS(net, vifi) &&
+                   ttls[vifi] && ttls[vifi] < 255) {
                        cache->mfc_un.res.ttls[vifi] = ttls[vifi];
                        if (cache->mfc_un.res.minvif > vifi)
                                cache->mfc_un.res.minvif = vifi;
@@ -425,16 +427,16 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
        }
 }
 
-static int vif_add(struct vifctl *vifc, int mrtsock)
+static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock)
 {
        int vifi = vifc->vifc_vifi;
-       struct vif_device *v = &vif_table[vifi];
+       struct vif_device *v = &net->ipv4.vif_table[vifi];
        struct net_device *dev;
        struct in_device *in_dev;
        int err;
 
        /* Is vif busy ? */
-       if (VIF_EXISTS(vifi))
+       if (VIF_EXISTS(net, vifi))
                return -EADDRINUSE;
 
        switch (vifc->vifc_flags) {
@@ -444,7 +446,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
                 * Special Purpose VIF in PIM
                 * All the packets will be sent to the daemon
                 */
-               if (reg_vif_num >= 0)
+               if (net->ipv4.mroute_reg_vif_num >= 0)
                        return -EADDRINUSE;
                dev = ipmr_reg_vif();
                if (!dev)
@@ -458,7 +460,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
                break;
 #endif
        case VIFF_TUNNEL:
-               dev = ipmr_new_tunnel(vifc);
+               dev = ipmr_new_tunnel(net, vifc);
                if (!dev)
                        return -ENOBUFS;
                err = dev_set_allmulti(dev, 1);
@@ -469,7 +471,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
                }
                break;
        case 0:
-               dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr);
+               dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr);
                if (!dev)
                        return -EADDRNOTAVAIL;
                err = dev_set_allmulti(dev, 1);
@@ -510,20 +512,22 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
        v->dev = dev;
 #ifdef CONFIG_IP_PIMSM
        if (v->flags&VIFF_REGISTER)
-               reg_vif_num = vifi;
+               net->ipv4.mroute_reg_vif_num = vifi;
 #endif
-       if (vifi+1 > maxvif)
-               maxvif = vifi+1;
+       if (vifi+1 > net->ipv4.maxvif)
+               net->ipv4.maxvif = vifi+1;
        write_unlock_bh(&mrt_lock);
        return 0;
 }
 
-static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp)
+static struct mfc_cache *ipmr_cache_find(struct net *net,
+                                        __be32 origin,
+                                        __be32 mcastgrp)
 {
        int line = MFC_HASH(mcastgrp, origin);
        struct mfc_cache *c;
 
-       for (c=mfc_cache_array[line]; c; c = c->next) {
+       for (c = net->ipv4.mfc_cache_array[line]; c; c = c->next) {
                if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp)
                        break;
        }
@@ -533,22 +537,24 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp)
 /*
  *     Allocate a multicast cache entry
  */
-static struct mfc_cache *ipmr_cache_alloc(void)
+static struct mfc_cache *ipmr_cache_alloc(struct net *net)
 {
        struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
        if (c == NULL)
                return NULL;
        c->mfc_un.res.minvif = MAXVIFS;
+       mfc_net_set(c, net);
        return c;
 }
 
-static struct mfc_cache *ipmr_cache_alloc_unres(void)
+static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net)
 {
        struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
        if (c == NULL)
                return NULL;
        skb_queue_head_init(&c->mfc_un.unres.unresolved);
        c->mfc_un.unres.expires = jiffies + 10*HZ;
+       mfc_net_set(c, net);
        return c;
 }
 
@@ -581,7 +587,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c)
                                memset(&e->msg, 0, sizeof(e->msg));
                        }
 
-                       rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
+                       rtnl_unicast(skb, mfc_net(c), NETLINK_CB(skb).pid);
                } else
                        ip_mr_forward(skb, c, 0);
        }
@@ -594,7 +600,8 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c)
  *     Called under mrt_lock.
  */
 
-static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
+static int ipmr_cache_report(struct net *net,
+                            struct sk_buff *pkt, vifi_t vifi, int assert)
 {
        struct sk_buff *skb;
        const int ihl = ip_hdrlen(pkt);
@@ -626,7 +633,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
                memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr));
                msg->im_msgtype = IGMPMSG_WHOLEPKT;
                msg->im_mbz = 0;
-               msg->im_vif = reg_vif_num;
+               msg->im_vif = net->ipv4.mroute_reg_vif_num;
                ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
                ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
                                             sizeof(struct iphdr));
@@ -658,7 +665,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
        skb->transport_header = skb->network_header;
        }
 
-       if (mroute_socket == NULL) {
+       if (net->ipv4.mroute_sk == NULL) {
                kfree_skb(skb);
                return -EINVAL;
        }
@@ -666,7 +673,8 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
        /*
         *      Deliver to mrouted
         */
-       if ((ret = sock_queue_rcv_skb(mroute_socket, skb))<0) {
+       ret = sock_queue_rcv_skb(net->ipv4.mroute_sk, skb);
+       if (ret < 0) {
                if (net_ratelimit())
                        printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n");
                kfree_skb(skb);
@@ -680,7 +688,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
  */
 
 static int
-ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
+ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb)
 {
        int err;
        struct mfc_cache *c;
@@ -688,7 +696,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
 
        spin_lock_bh(&mfc_unres_lock);
        for (c=mfc_unres_queue; c; c=c->next) {
-               if (c->mfc_mcastgrp == iph->daddr &&
+               if (net_eq(mfc_net(c), net) &&
+                   c->mfc_mcastgrp == iph->daddr &&
                    c->mfc_origin == iph->saddr)
                        break;
        }
@@ -698,8 +707,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
                 *      Create a new entry if allowable
                 */
 
-               if (atomic_read(&cache_resolve_queue_len) >= 10 ||
-                   (c=ipmr_cache_alloc_unres())==NULL) {
+               if (atomic_read(&net->ipv4.cache_resolve_queue_len) >= 10 ||
+                   (c = ipmr_cache_alloc_unres(net)) == NULL) {
                        spin_unlock_bh(&mfc_unres_lock);
 
                        kfree_skb(skb);
@@ -716,18 +725,19 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
                /*
                 *      Reflect first query at mrouted.
                 */
-               if ((err = ipmr_cache_report(skb, vifi, IGMPMSG_NOCACHE))<0) {
+               err = ipmr_cache_report(net, skb, vifi, IGMPMSG_NOCACHE);
+               if (err < 0) {
                        /* If the report failed throw the cache entry
                           out - Brad Parker
                         */
                        spin_unlock_bh(&mfc_unres_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ipmr_cache_free(c);
                        kfree_skb(skb);
                        return err;
                }
 
-               atomic_inc(&cache_resolve_queue_len);
+               atomic_inc(&net->ipv4.cache_resolve_queue_len);
                c->next = mfc_unres_queue;
                mfc_unres_queue = c;
 
@@ -753,35 +763,37 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
  *     MFC cache manipulation by user space mroute daemon
  */
 
-static int ipmr_mfc_delete(struct mfcctl *mfc)
+static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc)
 {
        int line;
        struct mfc_cache *c, **cp;
 
        line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
 
-       for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) {
+       for (cp = &net->ipv4.mfc_cache_array[line];
+            (c = *cp) != NULL; cp = &c->next) {
                if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
                    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
                        write_lock_bh(&mrt_lock);
                        *cp = c->next;
                        write_unlock_bh(&mrt_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ipmr_cache_free(c);
                        return 0;
                }
        }
        return -ENOENT;
 }
 
-static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
+static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)
 {
        int line;
        struct mfc_cache *uc, *c, **cp;
 
        line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
 
-       for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) {
+       for (cp = &net->ipv4.mfc_cache_array[line];
+            (c = *cp) != NULL; cp = &c->next) {
                if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
                    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr)
                        break;
@@ -800,7 +812,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
        if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
                return -EINVAL;
 
-       c = ipmr_cache_alloc();
+       c = ipmr_cache_alloc(net);
        if (c == NULL)
                return -ENOMEM;
 
@@ -812,8 +824,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
                c->mfc_flags |= MFC_STATIC;
 
        write_lock_bh(&mrt_lock);
-       c->next = mfc_cache_array[line];
-       mfc_cache_array[line] = c;
+       c->next = net->ipv4.mfc_cache_array[line];
+       net->ipv4.mfc_cache_array[line] = c;
        write_unlock_bh(&mrt_lock);
 
        /*
@@ -823,19 +835,21 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
        spin_lock_bh(&mfc_unres_lock);
        for (cp = &mfc_unres_queue; (uc=*cp) != NULL;
             cp = &uc->next) {
-               if (uc->mfc_origin == c->mfc_origin &&
+               if (net_eq(mfc_net(uc), net) &&
+                   uc->mfc_origin == c->mfc_origin &&
                    uc->mfc_mcastgrp == c->mfc_mcastgrp) {
                        *cp = uc->next;
-                       if (atomic_dec_and_test(&cache_resolve_queue_len))
-                               del_timer(&ipmr_expire_timer);
+                       atomic_dec(&net->ipv4.cache_resolve_queue_len);
                        break;
                }
        }
+       if (mfc_unres_queue == NULL)
+               del_timer(&ipmr_expire_timer);
        spin_unlock_bh(&mfc_unres_lock);
 
        if (uc) {
                ipmr_cache_resolve(uc, c);
-               kmem_cache_free(mrt_cachep, uc);
+               ipmr_cache_free(uc);
        }
        return 0;
 }
@@ -844,16 +858,16 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock)
  *     Close the multicast socket, and clear the vif tables etc
  */
 
-static void mroute_clean_tables(struct sock *sk)
+static void mroute_clean_tables(struct net *net)
 {
        int i;
 
        /*
         *      Shut down all active vif entries
         */
-       for (i=0; i<maxvif; i++) {
-               if (!(vif_table[i].flags&VIFF_STATIC))
-                       vif_delete(i, 0);
+       for (i = 0; i < net->ipv4.maxvif; i++) {
+               if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC))
+                       vif_delete(net, i, 0);
        }
 
        /*
@@ -862,7 +876,7 @@ static void mroute_clean_tables(struct sock *sk)
        for (i=0; i<MFC_LINES; i++) {
                struct mfc_cache *c, **cp;
 
-               cp = &mfc_cache_array[i];
+               cp = &net->ipv4.mfc_cache_array[i];
                while ((c = *cp) != NULL) {
                        if (c->mfc_flags&MFC_STATIC) {
                                cp = &c->next;
@@ -872,22 +886,23 @@ static void mroute_clean_tables(struct sock *sk)
                        *cp = c->next;
                        write_unlock_bh(&mrt_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ipmr_cache_free(c);
                }
        }
 
-       if (atomic_read(&cache_resolve_queue_len) != 0) {
-               struct mfc_cache *c;
+       if (atomic_read(&net->ipv4.cache_resolve_queue_len) != 0) {
+               struct mfc_cache *c, **cp;
 
                spin_lock_bh(&mfc_unres_lock);
-               while (mfc_unres_queue != NULL) {
-                       c = mfc_unres_queue;
-                       mfc_unres_queue = c->next;
-                       spin_unlock_bh(&mfc_unres_lock);
+               cp = &mfc_unres_queue;
+               while ((c = *cp) != NULL) {
+                       if (!net_eq(mfc_net(c), net)) {
+                               cp = &c->next;
+                               continue;
+                       }
+                       *cp = c->next;
 
                        ipmr_destroy_unres(c);
-
-                       spin_lock_bh(&mfc_unres_lock);
                }
                spin_unlock_bh(&mfc_unres_lock);
        }
@@ -895,15 +910,17 @@ static void mroute_clean_tables(struct sock *sk)
 
 static void mrtsock_destruct(struct sock *sk)
 {
+       struct net *net = sock_net(sk);
+
        rtnl_lock();
-       if (sk == mroute_socket) {
-               IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--;
+       if (sk == net->ipv4.mroute_sk) {
+               IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
 
                write_lock_bh(&mrt_lock);
-               mroute_socket = NULL;
+               net->ipv4.mroute_sk = NULL;
                write_unlock_bh(&mrt_lock);
 
-               mroute_clean_tables(sk);
+               mroute_clean_tables(net);
        }
        rtnl_unlock();
 }
@@ -920,9 +937,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
        int ret;
        struct vifctl vif;
        struct mfcctl mfc;
+       struct net *net = sock_net(sk);
 
        if (optname != MRT_INIT) {
-               if (sk != mroute_socket && !capable(CAP_NET_ADMIN))
+               if (sk != net->ipv4.mroute_sk && !capable(CAP_NET_ADMIN))
                        return -EACCES;
        }
 
@@ -935,7 +953,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                        return -ENOPROTOOPT;
 
                rtnl_lock();
-               if (mroute_socket) {
+               if (net->ipv4.mroute_sk) {
                        rtnl_unlock();
                        return -EADDRINUSE;
                }
@@ -943,15 +961,15 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                ret = ip_ra_control(sk, 1, mrtsock_destruct);
                if (ret == 0) {
                        write_lock_bh(&mrt_lock);
-                       mroute_socket = sk;
+                       net->ipv4.mroute_sk = sk;
                        write_unlock_bh(&mrt_lock);
 
-                       IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++;
+                       IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
                }
                rtnl_unlock();
                return ret;
        case MRT_DONE:
-               if (sk != mroute_socket)
+               if (sk != net->ipv4.mroute_sk)
                        return -EACCES;
                return ip_ra_control(sk, 0, NULL);
        case MRT_ADD_VIF:
@@ -964,9 +982,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                        return -ENFILE;
                rtnl_lock();
                if (optname == MRT_ADD_VIF) {
-                       ret = vif_add(&vif, sk==mroute_socket);
+                       ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk);
                } else {
-                       ret = vif_delete(vif.vifc_vifi, 0);
+                       ret = vif_delete(net, vif.vifc_vifi, 0);
                }
                rtnl_unlock();
                return ret;
@@ -983,9 +1001,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                        return -EFAULT;
                rtnl_lock();
                if (optname == MRT_DEL_MFC)
-                       ret = ipmr_mfc_delete(&mfc);
+                       ret = ipmr_mfc_delete(net, &mfc);
                else
-                       ret = ipmr_mfc_add(&mfc, sk==mroute_socket);
+                       ret = ipmr_mfc_add(net, &mfc, sk == net->ipv4.mroute_sk);
                rtnl_unlock();
                return ret;
                /*
@@ -996,7 +1014,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                int v;
                if (get_user(v,(int __user *)optval))
                        return -EFAULT;
-               mroute_do_assert=(v)?1:0;
+               net->ipv4.mroute_do_assert = (v) ? 1 : 0;
                return 0;
        }
 #ifdef CONFIG_IP_PIMSM
@@ -1010,11 +1028,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
 
                rtnl_lock();
                ret = 0;
-               if (v != mroute_do_pim) {
-                       mroute_do_pim = v;
-                       mroute_do_assert = v;
+               if (v != net->ipv4.mroute_do_pim) {
+                       net->ipv4.mroute_do_pim = v;
+                       net->ipv4.mroute_do_assert = v;
 #ifdef CONFIG_IP_PIMSM_V2
-                       if (mroute_do_pim)
+                       if (net->ipv4.mroute_do_pim)
                                ret = inet_add_protocol(&pim_protocol,
                                                        IPPROTO_PIM);
                        else
@@ -1045,6 +1063,7 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
 {
        int olr;
        int val;
+       struct net *net = sock_net(sk);
 
        if (optname != MRT_VERSION &&
 #ifdef CONFIG_IP_PIMSM
@@ -1066,10 +1085,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
                val = 0x0305;
 #ifdef CONFIG_IP_PIMSM
        else if (optname == MRT_PIM)
-               val = mroute_do_pim;
+               val = net->ipv4.mroute_do_pim;
 #endif
        else
-               val = mroute_do_assert;
+               val = net->ipv4.mroute_do_assert;
        if (copy_to_user(optval, &val, olr))
                return -EFAULT;
        return 0;
@@ -1085,16 +1104,17 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
        struct sioc_vif_req vr;
        struct vif_device *vif;
        struct mfc_cache *c;
+       struct net *net = sock_net(sk);
 
        switch (cmd) {
        case SIOCGETVIFCNT:
                if (copy_from_user(&vr, arg, sizeof(vr)))
                        return -EFAULT;
-               if (vr.vifi >= maxvif)
+               if (vr.vifi >= net->ipv4.maxvif)
                        return -EINVAL;
                read_lock(&mrt_lock);
-               vif=&vif_table[vr.vifi];
-               if (VIF_EXISTS(vr.vifi))        {
+               vif = &net->ipv4.vif_table[vr.vifi];
+               if (VIF_EXISTS(net, vr.vifi)) {
                        vr.icount = vif->pkt_in;
                        vr.ocount = vif->pkt_out;
                        vr.ibytes = vif->bytes_in;
@@ -1112,7 +1132,7 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
                        return -EFAULT;
 
                read_lock(&mrt_lock);
-               c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr);
+               c = ipmr_cache_find(net, sr.src.s_addr, sr.grp.s_addr);
                if (c) {
                        sr.pktcnt = c->mfc_un.res.pkt;
                        sr.bytecnt = c->mfc_un.res.bytes;
@@ -1134,18 +1154,19 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
 static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
        struct net_device *dev = ptr;
+       struct net *net = dev_net(dev);
        struct vif_device *v;
        int ct;
 
-       if (!net_eq(dev_net(dev), &init_net))
+       if (!net_eq(dev_net(dev), net))
                return NOTIFY_DONE;
 
        if (event != NETDEV_UNREGISTER)
                return NOTIFY_DONE;
-       v=&vif_table[0];
-       for (ct=0; ct<maxvif; ct++,v++) {
+       v = &net->ipv4.vif_table[0];
+       for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) {
                if (v->dev == dev)
-                       vif_delete(ct, 1);
+                       vif_delete(net, ct, 1);
        }
        return NOTIFY_DONE;
 }
@@ -1205,8 +1226,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
 
 static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
 {
+       struct net *net = mfc_net(c);
        const struct iphdr *iph = ip_hdr(skb);
-       struct vif_device *vif = &vif_table[vifi];
+       struct vif_device *vif = &net->ipv4.vif_table[vifi];
        struct net_device *dev;
        struct rtable *rt;
        int    encap = 0;
@@ -1220,7 +1242,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
                vif->bytes_out += skb->len;
                vif->dev->stats.tx_bytes += skb->len;
                vif->dev->stats.tx_packets++;
-               ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT);
+               ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT);
                kfree_skb(skb);
                return;
        }
@@ -1233,7 +1255,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
                                                .saddr = vif->local,
                                                .tos = RT_TOS(iph->tos) } },
                                    .proto = IPPROTO_IPIP };
-               if (ip_route_output_key(&init_net, &rt, &fl))
+               if (ip_route_output_key(net, &rt, &fl))
                        goto out_free;
                encap = sizeof(struct iphdr);
        } else {
@@ -1242,7 +1264,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
                                              { .daddr = iph->daddr,
                                                .tos = RT_TOS(iph->tos) } },
                                    .proto = IPPROTO_IPIP };
-               if (ip_route_output_key(&init_net, &rt, &fl))
+               if (ip_route_output_key(net, &rt, &fl))
                        goto out_free;
        }
 
@@ -1306,9 +1328,10 @@ out_free:
 
 static int ipmr_find_vif(struct net_device *dev)
 {
+       struct net *net = dev_net(dev);
        int ct;
-       for (ct=maxvif-1; ct>=0; ct--) {
-               if (vif_table[ct].dev == dev)
+       for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) {
+               if (net->ipv4.vif_table[ct].dev == dev)
                        break;
        }
        return ct;
@@ -1320,6 +1343,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
 {
        int psend = -1;
        int vif, ct;
+       struct net *net = mfc_net(cache);
 
        vif = cache->mfc_parent;
        cache->mfc_un.res.pkt++;
@@ -1328,7 +1352,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
        /*
         * Wrong interface: drop packet and (maybe) send PIM assert.
         */
-       if (vif_table[vif].dev != skb->dev) {
+       if (net->ipv4.vif_table[vif].dev != skb->dev) {
                int true_vifi;
 
                if (skb->rtable->fl.iif == 0) {
@@ -1349,23 +1373,24 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
                cache->mfc_un.res.wrong_if++;
                true_vifi = ipmr_find_vif(skb->dev);
 
-               if (true_vifi >= 0 && mroute_do_assert &&
+               if (true_vifi >= 0 && net->ipv4.mroute_do_assert &&
                    /* pimsm uses asserts, when switching from RPT to SPT,
                       so that we cannot check that packet arrived on an oif.
                       It is bad, but otherwise we would need to move pretty
                       large chunk of pimd to kernel. Ough... --ANK
                     */
-                   (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) &&
+                   (net->ipv4.mroute_do_pim ||
+                    cache->mfc_un.res.ttls[true_vifi] < 255) &&
                    time_after(jiffies,
                               cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
                        cache->mfc_un.res.last_assert = jiffies;
-                       ipmr_cache_report(skb, true_vifi, IGMPMSG_WRONGVIF);
+                       ipmr_cache_report(net, skb, true_vifi, IGMPMSG_WRONGVIF);
                }
                goto dont_forward;
        }
 
-       vif_table[vif].pkt_in++;
-       vif_table[vif].bytes_in += skb->len;
+       net->ipv4.vif_table[vif].pkt_in++;
+       net->ipv4.vif_table[vif].bytes_in += skb->len;
 
        /*
         *      Forward the frame
@@ -1405,6 +1430,7 @@ dont_forward:
 int ip_mr_input(struct sk_buff *skb)
 {
        struct mfc_cache *cache;
+       struct net *net = dev_net(skb->dev);
        int local = skb->rtable->rt_flags&RTCF_LOCAL;
 
        /* Packet is looped back after forward, it should not be
@@ -1425,9 +1451,9 @@ int ip_mr_input(struct sk_buff *skb)
                               that we can forward NO IGMP messages.
                             */
                            read_lock(&mrt_lock);
-                           if (mroute_socket) {
+                           if (net->ipv4.mroute_sk) {
                                    nf_reset(skb);
-                                   raw_rcv(mroute_socket, skb);
+                                   raw_rcv(net->ipv4.mroute_sk, skb);
                                    read_unlock(&mrt_lock);
                                    return 0;
                            }
@@ -1436,7 +1462,7 @@ int ip_mr_input(struct sk_buff *skb)
        }
 
        read_lock(&mrt_lock);
-       cache = ipmr_cache_find(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
+       cache = ipmr_cache_find(net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
 
        /*
         *      No usable cache entry
@@ -1456,7 +1482,7 @@ int ip_mr_input(struct sk_buff *skb)
 
                vif = ipmr_find_vif(skb->dev);
                if (vif >= 0) {
-                       int err = ipmr_cache_unresolved(vif, skb);
+                       int err = ipmr_cache_unresolved(net, vif, skb);
                        read_unlock(&mrt_lock);
 
                        return err;
@@ -1487,6 +1513,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
 {
        struct net_device *reg_dev = NULL;
        struct iphdr *encap;
+       struct net *net = dev_net(skb->dev);
 
        encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
        /*
@@ -1501,8 +1528,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
                return 1;
 
        read_lock(&mrt_lock);
-       if (reg_vif_num >= 0)
-               reg_dev = vif_table[reg_vif_num].dev;
+       if (net->ipv4.mroute_reg_vif_num >= 0)
+               reg_dev = net->ipv4.vif_table[net->ipv4.mroute_reg_vif_num].dev;
        if (reg_dev)
                dev_hold(reg_dev);
        read_unlock(&mrt_lock);
@@ -1537,13 +1564,14 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
 int pim_rcv_v1(struct sk_buff * skb)
 {
        struct igmphdr *pim;
+       struct net *net = dev_net(skb->dev);
 
        if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
                goto drop;
 
        pim = igmp_hdr(skb);
 
-       if (!mroute_do_pim ||
+       if (!net->ipv4.mroute_do_pim ||
            pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
                goto drop;
 
@@ -1583,7 +1611,8 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
 {
        int ct;
        struct rtnexthop *nhp;
-       struct net_device *dev = vif_table[c->mfc_parent].dev;
+       struct net *net = mfc_net(c);
+       struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev;
        u8 *b = skb_tail_pointer(skb);
        struct rtattr *mp_head;
 
@@ -1599,7 +1628,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
                        nhp->rtnh_flags = 0;
                        nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
-                       nhp->rtnh_ifindex = vif_table[ct].dev->ifindex;
+                       nhp->rtnh_ifindex = net->ipv4.vif_table[ct].dev->ifindex;
                        nhp->rtnh_len = sizeof(*nhp);
                }
        }
@@ -1613,14 +1642,15 @@ rtattr_failure:
        return -EMSGSIZE;
 }
 
-int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+int ipmr_get_route(struct net *net,
+                  struct sk_buff *skb, struct rtmsg *rtm, int nowait)
 {
        int err;
        struct mfc_cache *cache;
        struct rtable *rt = skb->rtable;
 
        read_lock(&mrt_lock);
-       cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
+       cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst);
 
        if (cache == NULL) {
                struct sk_buff *skb2;
@@ -1651,7 +1681,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
                iph->saddr = rt->rt_src;
                iph->daddr = rt->rt_dst;
                iph->version = 0;
-               err = ipmr_cache_unresolved(vif, skb2);
+               err = ipmr_cache_unresolved(net, vif, skb2);
                read_unlock(&mrt_lock);
                return err;
        }
@@ -1668,17 +1698,19 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
  *     The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
  */
 struct ipmr_vif_iter {
+       struct seq_net_private p;
        int ct;
 };
 
-static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter,
+static struct vif_device *ipmr_vif_seq_idx(struct net *net,
+                                          struct ipmr_vif_iter *iter,
                                           loff_t pos)
 {
-       for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
-               if (!VIF_EXISTS(iter->ct))
+       for (iter->ct = 0; iter->ct < net->ipv4.maxvif; ++iter->ct) {
+               if (!VIF_EXISTS(net, iter->ct))
                        continue;
                if (pos-- == 0)
-                       return &vif_table[iter->ct];
+                       return &net->ipv4.vif_table[iter->ct];
        }
        return NULL;
 }
@@ -1686,23 +1718,26 @@ static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter,
 static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
        __acquires(mrt_lock)
 {
+       struct net *net = seq_file_net(seq);
+
        read_lock(&mrt_lock);
-       return *pos ? ipmr_vif_seq_idx(seq->private, *pos - 1)
+       return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1)
                : SEQ_START_TOKEN;
 }
 
 static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct ipmr_vif_iter *iter = seq->private;
+       struct net *net = seq_file_net(seq);
 
        ++*pos;
        if (v == SEQ_START_TOKEN)
-               return ipmr_vif_seq_idx(iter, 0);
+               return ipmr_vif_seq_idx(net, iter, 0);
 
-       while (++iter->ct < maxvif) {
-               if (!VIF_EXISTS(iter->ct))
+       while (++iter->ct < net->ipv4.maxvif) {
+               if (!VIF_EXISTS(net, iter->ct))
                        continue;
-               return &vif_table[iter->ct];
+               return &net->ipv4.vif_table[iter->ct];
        }
        return NULL;
 }
@@ -1715,6 +1750,8 @@ static void ipmr_vif_seq_stop(struct seq_file *seq, void *v)
 
 static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
 {
+       struct net *net = seq_file_net(seq);
+
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq,
                         "Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote\n");
@@ -1724,7 +1761,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
 
                seq_printf(seq,
                           "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X %08X %08X\n",
-                          vif - vif_table,
+                          vif - net->ipv4.vif_table,
                           name, vif->bytes_in, vif->pkt_in,
                           vif->bytes_out, vif->pkt_out,
                           vif->flags, vif->local, vif->remote);
@@ -1741,8 +1778,8 @@ static const struct seq_operations ipmr_vif_seq_ops = {
 
 static int ipmr_vif_open(struct inode *inode, struct file *file)
 {
-       return seq_open_private(file, &ipmr_vif_seq_ops,
-                       sizeof(struct ipmr_vif_iter));
+       return seq_open_net(inode, file, &ipmr_vif_seq_ops,
+                           sizeof(struct ipmr_vif_iter));
 }
 
 static const struct file_operations ipmr_vif_fops = {
@@ -1750,23 +1787,26 @@ static const struct file_operations ipmr_vif_fops = {
        .open    = ipmr_vif_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release_private,
+       .release = seq_release_net,
 };
 
 struct ipmr_mfc_iter {
+       struct seq_net_private p;
        struct mfc_cache **cache;
        int ct;
 };
 
 
-static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
+static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net,
+                                         struct ipmr_mfc_iter *it, loff_t pos)
 {
        struct mfc_cache *mfc;
 
-       it->cache = mfc_cache_array;
+       it->cache = net->ipv4.mfc_cache_array;
        read_lock(&mrt_lock);
        for (it->ct = 0; it->ct < MFC_LINES; it->ct++)
-               for (mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next)
+               for (mfc = net->ipv4.mfc_cache_array[it->ct];
+                    mfc; mfc = mfc->next)
                        if (pos-- == 0)
                                return mfc;
        read_unlock(&mrt_lock);
@@ -1774,7 +1814,8 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
        it->cache = &mfc_unres_queue;
        spin_lock_bh(&mfc_unres_lock);
        for (mfc = mfc_unres_queue; mfc; mfc = mfc->next)
-               if (pos-- == 0)
+               if (net_eq(mfc_net(mfc), net) &&
+                   pos-- == 0)
                        return mfc;
        spin_unlock_bh(&mfc_unres_lock);
 
@@ -1786,9 +1827,11 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
 static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct ipmr_mfc_iter *it = seq->private;
+       struct net *net = seq_file_net(seq);
+
        it->cache = NULL;
        it->ct = 0;
-       return *pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1)
+       return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
                : SEQ_START_TOKEN;
 }
 
@@ -1796,11 +1839,12 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct mfc_cache *mfc = v;
        struct ipmr_mfc_iter *it = seq->private;
+       struct net *net = seq_file_net(seq);
 
        ++*pos;
 
        if (v == SEQ_START_TOKEN)
-               return ipmr_mfc_seq_idx(seq->private, 0);
+               return ipmr_mfc_seq_idx(net, seq->private, 0);
 
        if (mfc->next)
                return mfc->next;
@@ -1808,10 +1852,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        if (it->cache == &mfc_unres_queue)
                goto end_of_list;
 
-       BUG_ON(it->cache != mfc_cache_array);
+       BUG_ON(it->cache != net->ipv4.mfc_cache_array);
 
        while (++it->ct < MFC_LINES) {
-               mfc = mfc_cache_array[it->ct];
+               mfc = net->ipv4.mfc_cache_array[it->ct];
                if (mfc)
                        return mfc;
        }
@@ -1823,6 +1867,8 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
        spin_lock_bh(&mfc_unres_lock);
        mfc = mfc_unres_queue;
+       while (mfc && !net_eq(mfc_net(mfc), net))
+               mfc = mfc->next;
        if (mfc)
                return mfc;
 
@@ -1836,16 +1882,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
 {
        struct ipmr_mfc_iter *it = seq->private;
+       struct net *net = seq_file_net(seq);
 
        if (it->cache == &mfc_unres_queue)
                spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == mfc_cache_array)
+       else if (it->cache == net->ipv4.mfc_cache_array)
                read_unlock(&mrt_lock);
 }
 
 static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
 {
        int n;
+       struct net *net = seq_file_net(seq);
 
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq,
@@ -1866,9 +1914,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
                                   mfc->mfc_un.res.wrong_if);
                        for (n = mfc->mfc_un.res.minvif;
                             n < mfc->mfc_un.res.maxvif; n++ ) {
-                               if (VIF_EXISTS(n)
-                                  && mfc->mfc_un.res.ttls[n] < 255)
-                               seq_printf(seq,
+                               if (VIF_EXISTS(net, n) &&
+                                   mfc->mfc_un.res.ttls[n] < 255)
+                                       seq_printf(seq,
                                           " %2d:%-3d",
                                           n, mfc->mfc_un.res.ttls[n]);
                        }
@@ -1892,8 +1940,8 @@ static const struct seq_operations ipmr_mfc_seq_ops = {
 
 static int ipmr_mfc_open(struct inode *inode, struct file *file)
 {
-       return seq_open_private(file, &ipmr_mfc_seq_ops,
-                       sizeof(struct ipmr_mfc_iter));
+       return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
+                           sizeof(struct ipmr_mfc_iter));
 }
 
 static const struct file_operations ipmr_mfc_fops = {
@@ -1901,7 +1949,7 @@ static const struct file_operations ipmr_mfc_fops = {
        .open    = ipmr_mfc_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release_private,
+       .release = seq_release_net,
 };
 #endif
 
@@ -1915,6 +1963,65 @@ static struct net_protocol pim_protocol = {
 /*
  *     Setup for IP multicast routing
  */
+static int __net_init ipmr_net_init(struct net *net)
+{
+       int err = 0;
+
+       net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device),
+                                     GFP_KERNEL);
+       if (!net->ipv4.vif_table) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       /* Forwarding cache */
+       net->ipv4.mfc_cache_array = kcalloc(MFC_LINES,
+                                           sizeof(struct mfc_cache *),
+                                           GFP_KERNEL);
+       if (!net->ipv4.mfc_cache_array) {
+               err = -ENOMEM;
+               goto fail_mfc_cache;
+       }
+
+#ifdef CONFIG_IP_PIMSM
+       net->ipv4.mroute_reg_vif_num = -1;
+#endif
+
+#ifdef CONFIG_PROC_FS
+       err = -ENOMEM;
+       if (!proc_net_fops_create(net, "ip_mr_vif", 0, &ipmr_vif_fops))
+               goto proc_vif_fail;
+       if (!proc_net_fops_create(net, "ip_mr_cache", 0, &ipmr_mfc_fops))
+               goto proc_cache_fail;
+#endif
+       return 0;
+
+#ifdef CONFIG_PROC_FS
+proc_cache_fail:
+       proc_net_remove(net, "ip_mr_vif");
+proc_vif_fail:
+       kfree(net->ipv4.mfc_cache_array);
+#endif
+fail_mfc_cache:
+       kfree(net->ipv4.vif_table);
+fail:
+       return err;
+}
+
+static void __net_exit ipmr_net_exit(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+       proc_net_remove(net, "ip_mr_cache");
+       proc_net_remove(net, "ip_mr_vif");
+#endif
+       kfree(net->ipv4.mfc_cache_array);
+       kfree(net->ipv4.vif_table);
+}
+
+static struct pernet_operations ipmr_net_ops = {
+       .init = ipmr_net_init,
+       .exit = ipmr_net_exit,
+};
 
 int __init ip_mr_init(void)
 {
@@ -1927,26 +2034,20 @@ int __init ip_mr_init(void)
        if (!mrt_cachep)
                return -ENOMEM;
 
+       err = register_pernet_subsys(&ipmr_net_ops);
+       if (err)
+               goto reg_pernet_fail;
+
        setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
        err = register_netdevice_notifier(&ip_mr_notifier);
        if (err)
                goto reg_notif_fail;
-#ifdef CONFIG_PROC_FS
-       err = -ENOMEM;
-       if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops))
-               goto proc_vif_fail;
-       if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops))
-               goto proc_cache_fail;
-#endif
        return 0;
-#ifdef CONFIG_PROC_FS
-proc_cache_fail:
-       proc_net_remove(&init_net, "ip_mr_vif");
-proc_vif_fail:
-       unregister_netdevice_notifier(&ip_mr_notifier);
-#endif
+
 reg_notif_fail:
        del_timer(&ipmr_expire_timer);
+       unregister_pernet_subsys(&ipmr_net_ops);
+reg_pernet_fail:
        kmem_cache_destroy(mrt_cachep);
        return err;
 }
index 182f845de92f762e76a5bb5546aa417cf81330bf..d9521f6f9ed0f29a9eeabc27710636d7c6393ac9 100644 (file)
@@ -1292,7 +1292,7 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = {
        .expect_policy          = &snmp_exp_policy,
        .name                   = "snmp",
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.udp.port   = __constant_htons(SNMP_PORT),
+       .tuple.src.u.udp.port   = cpu_to_be16(SNMP_PORT),
        .tuple.dst.protonum     = IPPROTO_UDP,
 };
 
@@ -1302,7 +1302,7 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
        .expect_policy          = &snmp_exp_policy,
        .name                   = "snmp_trap",
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.udp.port   = __constant_htons(SNMP_TRAP_PORT),
+       .tuple.src.u.udp.port   = cpu_to_be16(SNMP_TRAP_PORT),
        .tuple.dst.protonum     = IPPROTO_UDP,
 };
 
index 97f71153584faa6bf379235f0db151e17a5ed4e9..5caee609be06bb9f3b205a7a1a8628f655212ec5 100644 (file)
@@ -151,7 +151,7 @@ static void rt_emergency_hash_rebuild(struct net *net);
 
 static struct dst_ops ipv4_dst_ops = {
        .family =               AF_INET,
-       .protocol =             __constant_htons(ETH_P_IP),
+       .protocol =             cpu_to_be16(ETH_P_IP),
        .gc =                   rt_garbage_collect,
        .check =                ipv4_dst_check,
        .destroy =              ipv4_dst_destroy,
@@ -2696,7 +2696,7 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 static struct dst_ops ipv4_dst_blackhole_ops = {
        .family                 =       AF_INET,
-       .protocol               =       __constant_htons(ETH_P_IP),
+       .protocol               =       cpu_to_be16(ETH_P_IP),
        .destroy                =       ipv4_dst_destroy,
        .check                  =       ipv4_dst_check,
        .update_pmtu            =       ipv4_rt_blackhole_update_pmtu,
@@ -2779,7 +2779,8 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp)
        return ip_route_output_flow(net, rp, flp, NULL, 0);
 }
 
-static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+static int rt_fill_info(struct net *net,
+                       struct sk_buff *skb, u32 pid, u32 seq, int event,
                        int nowait, unsigned int flags)
 {
        struct rtable *rt = skb->rtable;
@@ -2844,8 +2845,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                __be32 dst = rt->rt_dst;
 
                if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) &&
-                   IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) {
-                       int err = ipmr_get_route(skb, r, nowait);
+                   IPV4_DEVCONF_ALL(net, MC_FORWARDING)) {
+                       int err = ipmr_get_route(net, skb, r, nowait);
                        if (err <= 0) {
                                if (!nowait) {
                                        if (err == 0)
@@ -2950,7 +2951,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
        if (rtm->rtm_flags & RTM_F_NOTIFY)
                rt->rt_flags |= RTCF_NOTIFY;
 
-       err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+       err = rt_fill_info(net, skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
                           RTM_NEWROUTE, 0, 0);
        if (err <= 0)
                goto errout_free;
@@ -2988,7 +2989,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
                        if (rt_is_expired(rt))
                                continue;
                        skb->dst = dst_clone(&rt->u.dst);
-                       if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
+                       if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid,
                                         cb->nlh->nlmsg_seq, RTM_NEWROUTE,
                                         1, NLM_F_MULTI) <= 0) {
                                dst_release(xchg(&skb->dst, NULL));
index 76b148bcb0dcb9ffcb333aa2b3ab3a2ed68fad33..73266b79c19a8d90643b7239c5e6d9fe1f6a73d5 100644 (file)
@@ -2482,19 +2482,19 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        unsigned int mss = 1;
        int flush = 1;
 
-       if (!pskb_may_pull(skb, sizeof(*th)))
+       th = skb_gro_header(skb, sizeof(*th));
+       if (unlikely(!th))
                goto out;
 
-       th = tcp_hdr(skb);
        thlen = th->doff * 4;
        if (thlen < sizeof(*th))
                goto out;
 
-       if (!pskb_may_pull(skb, thlen))
+       th = skb_gro_header(skb, thlen);
+       if (unlikely(!th))
                goto out;
 
-       th = tcp_hdr(skb);
-       __skb_pull(skb, thlen);
+       skb_gro_pull(skb, thlen);
 
        flags = tcp_flag_word(th);
 
@@ -2522,10 +2522,10 @@ found:
        flush |= th->ack_seq != th2->ack_seq || th->window != th2->window;
        flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th));
 
-       total = p->len;
+       total = skb_gro_len(p);
        mss = skb_shinfo(p)->gso_size;
 
-       flush |= skb->len > mss || skb->len <= 0;
+       flush |= skb_gro_len(skb) > mss || !skb_gro_len(skb);
        flush |= ntohl(th2->seq) + total != ntohl(th->seq);
 
        if (flush || skb_gro_receive(head, skb)) {
@@ -2538,7 +2538,7 @@ found:
        tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH);
 
 out_check_final:
-       flush = skb->len < mss;
+       flush = skb_gro_len(skb) < mss;
        flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST |
                          TCP_FLAG_SYN | TCP_FLAG_FIN);
 
index 19d7b429a2625b8ecc3b7fc35392d3e0af99ffd2..f6b962f56ab425f5bb3480e8433c888e7169a861 100644 (file)
@@ -2355,7 +2355,7 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
-               if (!tcp_v4_check(skb->len, iph->saddr, iph->daddr,
+               if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
                                  skb->csum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
index 2ad24ba31f9de591df4305d7b3d406318ec18976..60d918c96a4fff19c0d4062558ea8c594fa9bef2 100644 (file)
@@ -241,7 +241,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 
 static struct dst_ops xfrm4_dst_ops = {
        .family =               AF_INET,
-       .protocol =             __constant_htons(ETH_P_IP),
+       .protocol =             cpu_to_be16(ETH_P_IP),
        .gc =                   xfrm4_garbage_collect,
        .update_pmtu =          xfrm4_update_pmtu,
        .destroy =              xfrm4_dst_destroy,
index c802bc1658a854bc2599c6821fe6bfb4b5998870..fa2ac7ee662fa3de8bc162ca2a2429b2dcebde28 100644 (file)
@@ -799,24 +799,34 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
        int proto;
        __wsum csum;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
+       iph = skb_gro_header(skb, sizeof(*iph));
+       if (unlikely(!iph))
                goto out;
 
-       iph = ipv6_hdr(skb);
-       __skb_pull(skb, sizeof(*iph));
+       skb_gro_pull(skb, sizeof(*iph));
+       skb_set_transport_header(skb, skb_gro_offset(skb));
 
-       flush += ntohs(iph->payload_len) != skb->len;
+       flush += ntohs(iph->payload_len) != skb_gro_len(skb);
 
        rcu_read_lock();
-       proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr);
-       iph = ipv6_hdr(skb);
-       IPV6_GRO_CB(skb)->proto = proto;
+       proto = iph->nexthdr;
        ops = rcu_dereference(inet6_protos[proto]);
-       if (!ops || !ops->gro_receive)
-               goto out_unlock;
+       if (!ops || !ops->gro_receive) {
+               __pskb_pull(skb, skb_gro_offset(skb));
+               proto = ipv6_gso_pull_exthdrs(skb, proto);
+               skb_gro_pull(skb, -skb_transport_offset(skb));
+               skb_reset_transport_header(skb);
+               __skb_push(skb, skb_gro_offset(skb));
+
+               if (!ops || !ops->gro_receive)
+                       goto out_unlock;
+
+               iph = ipv6_hdr(skb);
+       }
+
+       IPV6_GRO_CB(skb)->proto = proto;
 
        flush--;
-       skb_reset_transport_header(skb);
        nlen = skb_network_header_len(skb);
 
        for (p = *head; p; p = p->next) {
@@ -880,7 +890,7 @@ out_unlock:
 }
 
 static struct packet_type ipv6_packet_type = {
-       .type = __constant_htons(ETH_P_IPV6),
+       .type = cpu_to_be16(ETH_P_IPV6),
        .func = ipv6_rcv,
        .gso_send_check = ipv6_gso_send_check,
        .gso_segment = ipv6_gso_segment,
index 9c574235c9058bb137bcc0f6bc8e8188c7111f63..c3d486a3edad17f4a9125829462863850ced9a65 100644 (file)
@@ -98,7 +98,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
 
 static struct dst_ops ip6_dst_ops_template = {
        .family                 =       AF_INET6,
-       .protocol               =       __constant_htons(ETH_P_IPV6),
+       .protocol               =       cpu_to_be16(ETH_P_IPV6),
        .gc                     =       ip6_dst_gc,
        .gc_thresh              =       1024,
        .check                  =       ip6_dst_check,
@@ -117,7 +117,7 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 static struct dst_ops ip6_dst_blackhole_ops = {
        .family                 =       AF_INET6,
-       .protocol               =       __constant_htons(ETH_P_IPV6),
+       .protocol               =       cpu_to_be16(ETH_P_IPV6),
        .destroy                =       ip6_dst_destroy,
        .check                  =       ip6_dst_check,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
index e5b85d45bee837153cd6c07d94dc4a128ed0cb16..00f1269e11e95e3691a388836592ef905433648b 100644 (file)
@@ -948,7 +948,7 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
-               if (!tcp_v6_check(skb->len, &iph->saddr, &iph->daddr,
+               if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
                                  skb->csum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
index 97ab068e8ccc10be9d1ee27ec3b4a081322bb307..b4b16a43f2771bd62558a2cd8ca3af60b0d99808 100644 (file)
@@ -272,7 +272,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 
 static struct dst_ops xfrm6_dst_ops = {
        .family =               AF_INET6,
-       .protocol =             __constant_htons(ETH_P_IPV6),
+       .protocol =             cpu_to_be16(ETH_P_IPV6),
        .gc =                   xfrm6_garbage_collect,
        .update_pmtu =          xfrm6_update_pmtu,
        .destroy =              xfrm6_dst_destroy,
index b6e70f92e7fb016140aa393fce90fa486cc12e95..43d0ffc6d5655ab2e5b18d77c249e21a2b33e28e 100644 (file)
@@ -1959,12 +1959,12 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
 SOCKOPS_WRAP(ipx_dgram, PF_IPX);
 
 static struct packet_type ipx_8023_packet_type = {
-       .type           = __constant_htons(ETH_P_802_3),
+       .type           = cpu_to_be16(ETH_P_802_3),
        .func           = ipx_rcv,
 };
 
 static struct packet_type ipx_dix_packet_type = {
-       .type           = __constant_htons(ETH_P_IPX),
+       .type           = cpu_to_be16(ETH_P_IPX),
        .func           = ipx_rcv,
 };
 
index 4c487a883725e7f3ad4c98c567a248b16880688c..1bb607f2f5c7715222ed3f3f0108fca3391bff80 100644 (file)
@@ -56,7 +56,7 @@ EXPORT_SYMBOL(irda_debug);
  * Tell the kernel how IrDA packets should be handled.
  */
 static struct packet_type irda_packet_type = {
-       .type   = __constant_htons(ETH_P_IRDA),
+       .type   = cpu_to_be16(ETH_P_IRDA),
        .func   = irlap_driver_rcv,     /* Packet type handler irlap_frame.c */
 };
 
index 50d5b10e23a27e52898a9a65e4f75bc6edd78f18..a7fe1adc378d68834a70f44739c98f927659d927 100644 (file)
@@ -148,12 +148,12 @@ void llc_sap_close(struct llc_sap *sap)
 }
 
 static struct packet_type llc_packet_type = {
-       .type = __constant_htons(ETH_P_802_2),
+       .type = cpu_to_be16(ETH_P_802_2),
        .func = llc_rcv,
 };
 
 static struct packet_type llc_tr_packet_type = {
-       .type = __constant_htons(ETH_P_TR_802_2),
+       .type = cpu_to_be16(ETH_P_TR_802_2),
        .func = llc_rcv,
 };
 
index 7d4971aa443f177a692bd909a9dbef8c50e682d5..58c94bb38e8701a52f69f1109e68406b5bf96b16 100644 (file)
@@ -15,6 +15,7 @@ mac80211-y := \
        michael.o \
        tkip.o \
        aes_ccm.o \
+       aes_cmac.o \
        cfg.o \
        rx.o \
        spectmgmt.o \
@@ -37,6 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
        mesh_plink.o \
        mesh_hwmp.o
 
+mac80211-$(CONFIG_PM) += pm.o
+
 # objects for PID algorithm
 rc80211_pid-y := rc80211_pid_algo.o
 rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
new file mode 100644 (file)
index 0000000..3d097b3
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
+ * Copyright 2008, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+
+#include <net/mac80211.h>
+#include "key.h"
+#include "aes_cmac.h"
+
+#define AES_BLOCK_SIZE 16
+#define AES_CMAC_KEY_LEN 16
+#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
+#define AAD_LEN 20
+
+
+static void gf_mulx(u8 *pad)
+{
+       int i, carry;
+
+       carry = pad[0] & 0x80;
+       for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
+               pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
+       pad[AES_BLOCK_SIZE - 1] <<= 1;
+       if (carry)
+               pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+}
+
+
+static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch,
+                               size_t num_elem,
+                               const u8 *addr[], const size_t *len, u8 *mac)
+{
+       u8 *cbc, *pad;
+       const u8 *pos, *end;
+       size_t i, e, left, total_len;
+
+       cbc = scratch;
+       pad = scratch + AES_BLOCK_SIZE;
+
+       memset(cbc, 0, AES_BLOCK_SIZE);
+
+       total_len = 0;
+       for (e = 0; e < num_elem; e++)
+               total_len += len[e];
+       left = total_len;
+
+       e = 0;
+       pos = addr[0];
+       end = pos + len[0];
+
+       while (left >= AES_BLOCK_SIZE) {
+               for (i = 0; i < AES_BLOCK_SIZE; i++) {
+                       cbc[i] ^= *pos++;
+                       if (pos >= end) {
+                               e++;
+                               pos = addr[e];
+                               end = pos + len[e];
+                       }
+               }
+               if (left > AES_BLOCK_SIZE)
+                       crypto_cipher_encrypt_one(tfm, cbc, cbc);
+               left -= AES_BLOCK_SIZE;
+       }
+
+       memset(pad, 0, AES_BLOCK_SIZE);
+       crypto_cipher_encrypt_one(tfm, pad, pad);
+       gf_mulx(pad);
+
+       if (left || total_len == 0) {
+               for (i = 0; i < left; i++) {
+                       cbc[i] ^= *pos++;
+                       if (pos >= end) {
+                               e++;
+                               pos = addr[e];
+                               end = pos + len[e];
+                       }
+               }
+               cbc[left] ^= 0x80;
+               gf_mulx(pad);
+       }
+
+       for (i = 0; i < AES_BLOCK_SIZE; i++)
+               pad[i] ^= cbc[i];
+       crypto_cipher_encrypt_one(tfm, pad, pad);
+       memcpy(mac, pad, CMAC_TLEN);
+}
+
+
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
+                       const u8 *data, size_t data_len, u8 *mic)
+{
+       const u8 *addr[3];
+       size_t len[3];
+       u8 zero[CMAC_TLEN];
+
+       memset(zero, 0, CMAC_TLEN);
+       addr[0] = aad;
+       len[0] = AAD_LEN;
+       addr[1] = data;
+       len[1] = data_len - CMAC_TLEN;
+       addr[2] = zero;
+       len[2] = CMAC_TLEN;
+
+       aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic);
+}
+
+
+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[])
+{
+       struct crypto_cipher *tfm;
+
+       tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm))
+               return NULL;
+
+       crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN);
+
+       return tfm;
+}
+
+
+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
+{
+       if (tfm)
+               crypto_free_cipher(tfm);
+}
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
new file mode 100644 (file)
index 0000000..0eb9a48
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2008, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ */
+
+#ifndef AES_CMAC_H
+#define AES_CMAC_H
+
+#include <linux/crypto.h>
+
+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]);
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
+                       const u8 *data, size_t data_len, u8 *mic);
+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
+
+#endif /* AES_CMAC_H */
index 9d4e4d846ec16ec978af0c95f1487e2e846f5841..a1a1344c5c4b9193623415ac8634df8f56b581fe 100644 (file)
@@ -133,6 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        case WLAN_CIPHER_SUITE_CCMP:
                alg = ALG_CCMP;
                break;
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+               alg = ALG_AES_CMAC;
+               break;
        default:
                return -EINVAL;
        }
@@ -275,6 +278,17 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                else
                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
                break;
+       case ALG_AES_CMAC:
+               params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+               seq[0] = key->u.aes_cmac.tx_pn[5];
+               seq[1] = key->u.aes_cmac.tx_pn[4];
+               seq[2] = key->u.aes_cmac.tx_pn[3];
+               seq[3] = key->u.aes_cmac.tx_pn[2];
+               seq[4] = key->u.aes_cmac.tx_pn[1];
+               seq[5] = key->u.aes_cmac.tx_pn[0];
+               params.seq = seq;
+               params.seq_len = 6;
+               break;
        }
 
        params.key = key->conf.key;
@@ -304,6 +318,22 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
        return 0;
 }
 
+static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
+                                            struct net_device *dev,
+                                            u8 key_idx)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       rcu_read_lock();
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ieee80211_set_default_mgmt_key(sdata, key_idx);
+
+       rcu_read_unlock();
+
+       return 0;
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -493,7 +523,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
        kfree(old);
 
-       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+                                         IEEE80211_IFCC_BEACON_ENABLED);
 }
 
 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
@@ -553,7 +584,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
        synchronize_rcu();
        kfree(old);
 
-       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
 }
 
 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
@@ -630,6 +661,10 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                sta->flags &= ~WLAN_STA_WME;
                if (params->station_flags & STATION_FLAG_WME)
                        sta->flags |= WLAN_STA_WME;
+
+               sta->flags &= ~WLAN_STA_MFP;
+               if (params->station_flags & STATION_FLAG_MFP)
+                       sta->flags |= WLAN_STA_MFP;
                spin_unlock_bh(&sta->lock);
        }
 
@@ -1141,6 +1176,102 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
        return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 }
 
+static int set_mgmt_extra_ie_sta(struct ieee80211_if_sta *ifsta, u8 subtype,
+                                u8 *ies, size_t ies_len)
+{
+       switch (subtype) {
+       case IEEE80211_STYPE_PROBE_REQ >> 4:
+               kfree(ifsta->ie_probereq);
+               ifsta->ie_probereq = ies;
+               ifsta->ie_probereq_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_PROBE_RESP >> 4:
+               kfree(ifsta->ie_proberesp);
+               ifsta->ie_proberesp = ies;
+               ifsta->ie_proberesp_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_AUTH >> 4:
+               kfree(ifsta->ie_auth);
+               ifsta->ie_auth = ies;
+               ifsta->ie_auth_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_ASSOC_REQ >> 4:
+               kfree(ifsta->ie_assocreq);
+               ifsta->ie_assocreq = ies;
+               ifsta->ie_assocreq_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_REASSOC_REQ >> 4:
+               kfree(ifsta->ie_reassocreq);
+               ifsta->ie_reassocreq = ies;
+               ifsta->ie_reassocreq_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_DEAUTH >> 4:
+               kfree(ifsta->ie_deauth);
+               ifsta->ie_deauth = ies;
+               ifsta->ie_deauth_len = ies_len;
+               return 0;
+       case IEEE80211_STYPE_DISASSOC >> 4:
+               kfree(ifsta->ie_disassoc);
+               ifsta->ie_disassoc = ies;
+               ifsta->ie_disassoc_len = ies_len;
+               return 0;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy,
+                                      struct net_device *dev,
+                                      struct mgmt_extra_ie_params *params)
+{
+       struct ieee80211_sub_if_data *sdata;
+       u8 *ies;
+       size_t ies_len;
+       int ret = -EOPNOTSUPP;
+
+       if (params->ies) {
+               ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL);
+               if (ies == NULL)
+                       return -ENOMEM;
+               ies_len = params->ies_len;
+       } else {
+               ies = NULL;
+               ies_len = 0;
+       }
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+               ret = set_mgmt_extra_ie_sta(&sdata->u.sta, params->subtype,
+                                           ies, ies_len);
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+       if (ret)
+               kfree(ies);
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int ieee80211_suspend(struct wiphy *wiphy)
+{
+       return __ieee80211_suspend(wiphy_priv(wiphy));
+}
+
+static int ieee80211_resume(struct wiphy *wiphy)
+{
+       return __ieee80211_resume(wiphy_priv(wiphy));
+}
+#else
+#define ieee80211_suspend NULL
+#define ieee80211_resume NULL
+#endif
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -1149,6 +1280,7 @@ struct cfg80211_ops mac80211_config_ops = {
        .del_key = ieee80211_del_key,
        .get_key = ieee80211_get_key,
        .set_default_key = ieee80211_config_default_key,
+       .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
        .add_beacon = ieee80211_add_beacon,
        .set_beacon = ieee80211_set_beacon,
        .del_beacon = ieee80211_del_beacon,
@@ -1169,4 +1301,7 @@ struct cfg80211_ops mac80211_config_ops = {
        .change_bss = ieee80211_change_bss,
        .set_txq_params = ieee80211_set_txq_params,
        .set_channel = ieee80211_set_channel,
+       .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie,
+       .suspend = ieee80211_suspend,
+       .resume = ieee80211_resume,
 };
index 2697a2fe608f60978d521acdcb0d90d5ff9ae5b4..e37f557de3f33e5178ccaeb9fdc0f01689b8fc29 100644 (file)
@@ -57,11 +57,62 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
                      local->hw.conf.long_frame_max_tx_count);
 DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
                      local->total_ps_buffered);
-DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
                      local->wep_iv & 0xffffff);
 DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
                      local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
 
+static ssize_t tsf_read(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       u64 tsf = 0;
+       char buf[100];
+
+       if (local->ops->get_tsf)
+               tsf = local->ops->get_tsf(local_to_hw(local));
+
+       snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
+}
+
+static ssize_t tsf_write(struct file *file,
+                         const char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       unsigned long long tsf;
+       char buf[100];
+       size_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+
+       if (strncmp(buf, "reset", 5) == 0) {
+               if (local->ops->reset_tsf) {
+                       local->ops->reset_tsf(local_to_hw(local));
+                       printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy));
+               }
+       } else {
+               tsf = simple_strtoul(buf, NULL, 0);
+               if (local->ops->set_tsf) {
+                       local->ops->set_tsf(local_to_hw(local), tsf);
+                       printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf);
+               }
+       }
+
+       return count;
+}
+
+static const struct file_operations tsf_ops = {
+       .read = tsf_read,
+       .write = tsf_write,
+       .open = mac80211_open_file_generic
+};
+
 /* statistics stuff */
 
 #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)                        \
@@ -136,8 +187,6 @@ DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
                   local->dot11MulticastReceivedFrameCount);
 DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
                   local->dot11TransmittedFrameCount);
-DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u",
-                  local->dot11WEPUndecryptableCount);
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
                   local->tx_handlers_drop);
@@ -204,6 +253,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
        DEBUGFS_ADD(long_retry_limit);
        DEBUGFS_ADD(total_ps_buffered);
        DEBUGFS_ADD(wep_iv);
+       DEBUGFS_ADD(tsf);
 
        statsd = debugfs_create_dir("statistics", phyd);
        local->debugfs.statistics = statsd;
@@ -221,7 +271,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
        DEBUGFS_STATS_ADD(received_fragment_count);
        DEBUGFS_STATS_ADD(multicast_received_frame_count);
        DEBUGFS_STATS_ADD(transmitted_frame_count);
-       DEBUGFS_STATS_ADD(wep_undecryptable_count);
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
        DEBUGFS_STATS_ADD(tx_handlers_drop);
        DEBUGFS_STATS_ADD(tx_handlers_queued);
@@ -258,6 +307,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
        DEBUGFS_DEL(long_retry_limit);
        DEBUGFS_DEL(total_ps_buffered);
        DEBUGFS_DEL(wep_iv);
+       DEBUGFS_DEL(tsf);
 
        DEBUGFS_STATS_DEL(transmitted_fragment_count);
        DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
@@ -268,7 +318,6 @@ void debugfs_hw_del(struct ieee80211_local *local)
        DEBUGFS_STATS_DEL(received_fragment_count);
        DEBUGFS_STATS_DEL(multicast_received_frame_count);
        DEBUGFS_STATS_DEL(transmitted_frame_count);
-       DEBUGFS_STATS_DEL(wep_undecryptable_count);
        DEBUGFS_STATS_DEL(num_scans);
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
        DEBUGFS_STATS_DEL(tx_handlers_drop);
index 6424ac565ae0e1760697e626c2a875c295f472a4..99c752588b30ef58c4d1a18f242c7f9906d230af 100644 (file)
@@ -76,6 +76,9 @@ static ssize_t key_algorithm_read(struct file *file,
        case ALG_CCMP:
                alg = "CCMP\n";
                break;
+       case ALG_AES_CMAC:
+               alg = "AES-128-CMAC\n";
+               break;
        default:
                return 0;
        }
@@ -105,6 +108,12 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
                len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
                                tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
                break;
+       case ALG_AES_CMAC:
+               tpn = key->u.aes_cmac.tx_pn;
+               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+                               tpn[0], tpn[1], tpn[2], tpn[3], tpn[4],
+                               tpn[5]);
+               break;
        default:
                return 0;
        }
@@ -142,6 +151,14 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
                }
                len = p - buf;
                break;
+       case ALG_AES_CMAC:
+               rpn = key->u.aes_cmac.rx_pn;
+               p += scnprintf(p, sizeof(buf)+buf-p,
+                              "%02x%02x%02x%02x%02x%02x\n",
+                              rpn[0], rpn[1], rpn[2],
+                              rpn[3], rpn[4], rpn[5]);
+               len = p - buf;
+               break;
        default:
                return 0;
        }
@@ -156,13 +173,40 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
        char buf[20];
        int len;
 
-       if (key->conf.alg != ALG_CCMP)
+       switch (key->conf.alg) {
+       case ALG_CCMP:
+               len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+               break;
+       case ALG_AES_CMAC:
+               len = scnprintf(buf, sizeof(buf), "%u\n",
+                               key->u.aes_cmac.replays);
+               break;
+       default:
                return 0;
-       len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+       }
        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 }
 KEY_OPS(replays);
 
+static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
+                                 size_t count, loff_t *ppos)
+{
+       struct ieee80211_key *key = file->private_data;
+       char buf[20];
+       int len;
+
+       switch (key->conf.alg) {
+       case ALG_AES_CMAC:
+               len = scnprintf(buf, sizeof(buf), "%u\n",
+                               key->u.aes_cmac.icverrors);
+               break;
+       default:
+               return 0;
+       }
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(icverrors);
+
 static ssize_t key_key_read(struct file *file, char __user *userbuf,
                            size_t count, loff_t *ppos)
 {
@@ -222,6 +266,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
        DEBUGFS_ADD(tx_spec);
        DEBUGFS_ADD(rx_spec);
        DEBUGFS_ADD(replays);
+       DEBUGFS_ADD(icverrors);
        DEBUGFS_ADD(key);
        DEBUGFS_ADD(ifindex);
 };
@@ -243,6 +288,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
        DEBUGFS_DEL(tx_spec);
        DEBUGFS_DEL(rx_spec);
        DEBUGFS_DEL(replays);
+       DEBUGFS_DEL(icverrors);
        DEBUGFS_DEL(key);
        DEBUGFS_DEL(ifindex);
 
@@ -280,6 +326,35 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
        sdata->common_debugfs.default_key = NULL;
 }
 
+void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
+{
+       char buf[50];
+       struct ieee80211_key *key;
+
+       if (!sdata->debugfsdir)
+               return;
+
+       /* this is running under the key lock */
+
+       key = sdata->default_mgmt_key;
+       if (key) {
+               sprintf(buf, "../keys/%d", key->debugfs.cnt);
+               sdata->common_debugfs.default_mgmt_key =
+                       debugfs_create_symlink("default_mgmt_key",
+                                              sdata->debugfsdir, buf);
+       } else
+               ieee80211_debugfs_key_remove_mgmt_default(sdata);
+}
+
+void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
+{
+       if (!sdata)
+               return;
+
+       debugfs_remove(sdata->common_debugfs.default_mgmt_key);
+       sdata->common_debugfs.default_mgmt_key = NULL;
+}
+
 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                   struct sta_info *sta)
 {
index b1a3754ee240525d6301046f73265593436dc0f4..54717b4e1371b352dc1bed514ab3c74954fd7538 100644 (file)
@@ -6,6 +6,10 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key);
 void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_add_mgmt_default(
+       struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_remove_mgmt_default(
+       struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                   struct sta_info *sta);
 #else
@@ -19,6 +23,12 @@ static inline void ieee80211_debugfs_key_add_default(
 static inline void ieee80211_debugfs_key_remove_default(
        struct ieee80211_sub_if_data *sdata)
 {}
+static inline void ieee80211_debugfs_key_add_mgmt_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_remove_mgmt_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
 static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
                                                 struct sta_info *sta)
 {}
index a2fbe0131312dcf23dda4b2ce8600af246f462f7..90230c718b5bb62b77f6b76fa6285e04d3a1a22f 100644 (file)
@@ -67,14 +67,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
        char buf[100];
        struct sta_info *sta = file->private_data;
        u32 staflags = get_sta_flags(sta);
-       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
+       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
                staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
                staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
                staflags & WLAN_STA_PS ? "PS\n" : "",
                staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
                staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
                staflags & WLAN_STA_WME ? "WME\n" : "",
-               staflags & WLAN_STA_WDS ? "WDS\n" : "");
+               staflags & WLAN_STA_WDS ? "WDS\n" : "",
+               staflags & WLAN_STA_MFP ? "MFP\n" : "");
        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 }
 STA_OPS(flags);
index c5c0c5271096ca7ae3369c2d99b0eeafe34bd413..7a38d2e76ca9c6fbf89515fa4a7df5a46fe26360 100644 (file)
@@ -130,14 +130,15 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       ht_changed = local->hw.conf.ht.enabled != enable_ht ||
-                    channel_type != local->hw.conf.ht.channel_type;
+       ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
+                    channel_type != local->hw.conf.channel_type;
 
        local->oper_channel_type = channel_type;
-       local->hw.conf.ht.enabled = enable_ht;
 
-       if (ht_changed)
-               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
+       if (ht_changed) {
+                /* channel_type change automatically detected */
+               ieee80211_hw_config(local, 0);
+        }
 
        /* disable HT */
        if (!enable_ht)
@@ -201,7 +202,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.addba_req.start_seq_num =
                                        cpu_to_le16(start_seq_num << 4);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
 }
 
 static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
@@ -247,7 +248,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
        mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
        mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
 }
 
 static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
@@ -290,7 +291,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.delba.params = cpu_to_le16(params);
        mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
 }
 
 void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
@@ -949,7 +950,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 
        /* prepare reordering buffer */
        tid_agg_rx->reorder_buf =
-               kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC);
+               kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC);
        if (!tid_agg_rx->reorder_buf) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
@@ -959,8 +960,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
                kfree(sta->ampdu_mlme.tid_rx[tid]);
                goto end;
        }
-       memset(tid_agg_rx->reorder_buf, 0,
-               buf_size * sizeof(struct sk_buff *));
 
        if (local->ops->ampdu_action)
                ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
index f3eec989662bebb2523d4df393f608546308cc94..eaf3603862b7f0df8b11ef9fa037c791e07fc964 100644 (file)
@@ -43,7 +43,7 @@ struct ieee80211_local;
 
 /* Required encryption head and tailroom */
 #define IEEE80211_ENCRYPT_HEADROOM 8
-#define IEEE80211_ENCRYPT_TAILROOM 12
+#define IEEE80211_ENCRYPT_TAILROOM 18
 
 /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
  * reception of at least three fragmented frames. This limit can be increased
@@ -258,6 +258,9 @@ struct mesh_preq_queue {
 #define IEEE80211_STA_AUTO_BSSID_SEL   BIT(11)
 #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
 #define IEEE80211_STA_PRIVACY_INVOKED  BIT(13)
+#define IEEE80211_STA_TKIP_WEP_USED    BIT(14)
+#define IEEE80211_STA_CSA_RECEIVED     BIT(15)
+#define IEEE80211_STA_MFP_ENABLED      BIT(16)
 /* flags for MLME request */
 #define IEEE80211_STA_REQ_SCAN 0
 #define IEEE80211_STA_REQ_DIRECT_PROBE 1
@@ -282,7 +285,9 @@ enum ieee80211_sta_mlme_state {
 
 struct ieee80211_if_sta {
        struct timer_list timer;
+       struct timer_list chswitch_timer;
        struct work_struct work;
+       struct work_struct chswitch_work;
        u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
        u8 ssid[IEEE80211_MAX_SSID_LEN];
        enum ieee80211_sta_mlme_state state;
@@ -315,11 +320,33 @@ struct ieee80211_if_sta {
        int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
        int auth_transaction;
 
+       enum {
+               IEEE80211_MFP_DISABLED,
+               IEEE80211_MFP_OPTIONAL,
+               IEEE80211_MFP_REQUIRED
+       } mfp; /* management frame protection */
+
        unsigned long ibss_join_req;
        struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
        u32 supp_rates_bits[IEEE80211_NUM_BANDS];
 
        int wmm_last_param_set;
+
+       /* Extra IE data for management frames */
+       u8 *ie_probereq;
+       size_t ie_probereq_len;
+       u8 *ie_proberesp;
+       size_t ie_proberesp_len;
+       u8 *ie_auth;
+       size_t ie_auth_len;
+       u8 *ie_assocreq;
+       size_t ie_assocreq_len;
+       u8 *ie_reassocreq;
+       size_t ie_reassocreq_len;
+       u8 *ie_deauth;
+       size_t ie_deauth_len;
+       u8 *ie_disassoc;
+       size_t ie_disassoc_len;
 };
 
 struct ieee80211_if_mesh {
@@ -404,8 +431,10 @@ struct ieee80211_sub_if_data {
        unsigned int fragment_next;
 
 #define NUM_DEFAULT_KEYS 4
-       struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
+#define NUM_DEFAULT_MGMT_KEYS 2
+       struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
        struct ieee80211_key *default_key;
+       struct ieee80211_key *default_mgmt_key;
 
        u16 sequence_number;
 
@@ -477,6 +506,7 @@ struct ieee80211_sub_if_data {
        } debugfs;
        struct {
                struct dentry *default_key;
+               struct dentry *default_mgmt_key;
        } common_debugfs;
 
 #ifdef CONFIG_MAC80211_MESH
@@ -541,6 +571,7 @@ enum {
 enum queue_stop_reason {
        IEEE80211_QUEUE_STOP_REASON_DRIVER,
        IEEE80211_QUEUE_STOP_REASON_PS,
+       IEEE80211_QUEUE_STOP_REASON_CSA
 };
 
 /* maximum number of hardware queues we support. */
@@ -612,7 +643,9 @@ struct ieee80211_local {
        struct crypto_blkcipher *wep_rx_tfm;
        u32 wep_iv;
 
+       /* see iface.c */
        struct list_head interfaces;
+       struct mutex iflist_mtx;
 
        /*
         * Key lock, protects sdata's key_list and sta_info's
@@ -630,7 +663,7 @@ struct ieee80211_local {
        unsigned long last_scan_completed;
        struct delayed_work scan_work;
        struct ieee80211_sub_if_data *scan_sdata;
-       struct ieee80211_channel *oper_channel, *scan_channel;
+       struct ieee80211_channel *oper_channel, *scan_channel, *csa_channel;
        enum nl80211_channel_type oper_channel_type;
        u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
        size_t scan_ssid_len;
@@ -649,7 +682,6 @@ struct ieee80211_local {
        u32 dot11ReceivedFragmentCount;
        u32 dot11MulticastReceivedFrameCount;
        u32 dot11TransmittedFrameCount;
-       u32 dot11WEPUndecryptableCount;
 
 #ifdef CONFIG_MAC80211_LEDS
        int tx_led_counter, rx_led_counter;
@@ -696,11 +728,13 @@ struct ieee80211_local {
        unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
        bool powersave;
-       int dynamic_ps_timeout;
        struct work_struct dynamic_ps_enable_work;
        struct work_struct dynamic_ps_disable_work;
        struct timer_list dynamic_ps_timer;
 
+       int user_power_level; /* in dBm */
+       int power_constr_level; /* in dBm */
+
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct local_debugfsdentries {
                struct dentry *rcdir;
@@ -712,6 +746,7 @@ struct ieee80211_local {
                struct dentry *long_retry_limit;
                struct dentry *total_ps_buffered;
                struct dentry *wep_iv;
+               struct dentry *tsf;
                struct dentry *statistics;
                struct local_debugfsdentries_statsdentries {
                        struct dentry *transmitted_fragment_count;
@@ -805,6 +840,7 @@ struct ieee802_11_elems {
        u8 *country_elem;
        u8 *pwr_constr_elem;
        u8 *quiet_elem;         /* first quite element */
+       u8 *timeout_int;
 
        /* length of them, respectively */
        u8 ssid_len;
@@ -832,6 +868,7 @@ struct ieee802_11_elems {
        u8 pwr_constr_elem_len;
        u8 quiet_elem_len;
        u8 num_of_quiet_elem;   /* can be more the one */
+       u8 timeout_int_len;
 };
 
 static inline struct ieee80211_local *hw_to_local(
@@ -875,11 +912,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
 void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
                            struct ieee80211_if_sta *ifsta);
 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-                                       u8 *bssid, u8 *addr, u64 supp_rates);
+                                       u8 *bssid, u8 *addr, u32 supp_rates);
 int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
 int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
-u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
+u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
                            struct ieee802_11_elems *elems,
                            enum ieee80211_band band);
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
@@ -963,6 +1000,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
                                       struct ieee80211_mgmt *mgmt,
                                       size_t len);
+void ieee80211_chswitch_timer(unsigned long data);
+void ieee80211_chswitch_work(struct work_struct *work);
+void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
+                                 struct ieee80211_channel_sw_ie *sw_elem,
+                                 struct ieee80211_bss *bss);
+void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+                                u16 capab_info, u8 *pwr_constr_elem,
+                                u8 pwr_constr_elem_len);
+
+/* Suspend/resume */
+int __ieee80211_suspend(struct ieee80211_hw *hw);
+int __ieee80211_resume(struct ieee80211_hw *hw);
 
 /* utility functions/constants */
 extern void *mac80211_wiphy_privid; /* for wiphy privid */
@@ -980,12 +1029,15 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
 void ieee802_11_parse_elems(u8 *start, size_t len,
                            struct ieee802_11_elems *elems);
 int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
-u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
+u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
                              enum ieee80211_band band);
 
 void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_timer(unsigned long data);
+void ieee80211_send_nullfunc(struct ieee80211_local *local,
+                            struct ieee80211_sub_if_data *sdata,
+                            int powersave);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
                                     enum queue_stop_reason reason);
index b9074824862aee74c9e6555f3d43a0cba51cd4f8..00562a8b99cf250915e2fa62555fac9405eb4b64 100644 (file)
 #include "mesh.h"
 #include "led.h"
 
+/**
+ * DOC: Interface list locking
+ *
+ * The interface list in each struct ieee80211_local is protected
+ * three-fold:
+ *
+ * (1) modifications may only be done under the RTNL
+ * (2) modifications and readers are protected against each other by
+ *     the iflist_mtx.
+ * (3) modifications are done in an RCU manner so atomic readers
+ *     can traverse the list in RCU-safe blocks.
+ *
+ * As a consequence, reads (traversals) of the list can be protected
+ * by either the RTNL, the iflist_mtx or RCU.
+ */
+
+
 static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
 {
        int meshhdrlen;
@@ -383,6 +400,8 @@ static int ieee80211_stop(struct net_device *dev)
                atomic_dec(&local->iff_promiscs);
 
        dev_mc_unsync(local->mdev, dev);
+       del_timer_sync(&local->dynamic_ps_timer);
+       cancel_work_sync(&local->dynamic_ps_enable_work);
 
        /* APs need special treatment */
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
@@ -441,6 +460,7 @@ static int ieee80211_stop(struct net_device *dev)
                                                WLAN_REASON_DEAUTH_LEAVING);
 
                memset(sdata->u.sta.bssid, 0, ETH_ALEN);
+               del_timer_sync(&sdata->u.sta.chswitch_timer);
                del_timer_sync(&sdata->u.sta.timer);
                /*
                 * If the timer fired while we waited for it, it will have
@@ -450,6 +470,7 @@ static int ieee80211_stop(struct net_device *dev)
                 * it no longer is.
                 */
                cancel_work_sync(&sdata->u.sta.work);
+               cancel_work_sync(&sdata->u.sta.chswitch_work);
                /*
                 * When we get here, the interface is marked down.
                 * Call synchronize_rcu() to wait for the RX path
@@ -459,7 +480,8 @@ static int ieee80211_stop(struct net_device *dev)
                synchronize_rcu();
                skb_queue_purge(&sdata->u.sta.skb_queue);
 
-               sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+               sdata->u.sta.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED |
+                                       IEEE80211_STA_TKIP_WEP_USED);
                kfree(sdata->u.sta.extra_ie);
                sdata->u.sta.extra_ie = NULL;
                sdata->u.sta.extra_ie_len = 0;
@@ -627,6 +649,13 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
                kfree(sdata->u.sta.assocreq_ies);
                kfree(sdata->u.sta.assocresp_ies);
                kfree_skb(sdata->u.sta.probe_resp);
+               kfree(sdata->u.sta.ie_probereq);
+               kfree(sdata->u.sta.ie_proberesp);
+               kfree(sdata->u.sta.ie_auth);
+               kfree(sdata->u.sta.ie_assocreq);
+               kfree(sdata->u.sta.ie_reassocreq);
+               kfree(sdata->u.sta.ie_deauth);
+               kfree(sdata->u.sta.ie_disassoc);
                break;
        case NL80211_IFTYPE_WDS:
        case NL80211_IFTYPE_AP_VLAN:
@@ -788,7 +817,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                                            params->mesh_id_len,
                                            params->mesh_id);
 
+       mutex_lock(&local->iflist_mtx);
        list_add_tail_rcu(&sdata->list, &local->interfaces);
+       mutex_unlock(&local->iflist_mtx);
 
        if (new_dev)
                *new_dev = ndev;
@@ -804,7 +835,10 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
 {
        ASSERT_RTNL();
 
+       mutex_lock(&sdata->local->iflist_mtx);
        list_del_rcu(&sdata->list);
+       mutex_unlock(&sdata->local->iflist_mtx);
+
        synchronize_rcu();
        unregister_netdevice(sdata->dev);
 }
@@ -820,7 +854,16 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
        ASSERT_RTNL();
 
        list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+               /*
+                * we cannot hold the iflist_mtx across unregister_netdevice,
+                * but we only need to hold it for list modifications to lock
+                * out readers since we're under the RTNL here as all other
+                * writers.
+                */
+               mutex_lock(&local->iflist_mtx);
                list_del(&sdata->list);
+               mutex_unlock(&local->iflist_mtx);
+
                unregister_netdevice(sdata->dev);
        }
 }
index 999f7aa423267a33c525ee5693244f0c67070a30..19b480de4bbcbfa498f1d520ca9db8f798d26cce 100644 (file)
@@ -18,6 +18,7 @@
 #include "ieee80211_i.h"
 #include "debugfs_key.h"
 #include "aes_ccm.h"
+#include "aes_cmac.h"
 
 
 /**
@@ -47,7 +48,6 @@
  */
 
 static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const u8 zero_addr[ETH_ALEN];
 
 /* key mutex: used to synchronise todo runners */
 static DEFINE_MUTEX(key_mutex);
@@ -108,29 +108,18 @@ static void assert_key_lock(void)
        WARN_ON(!mutex_is_locked(&key_mutex));
 }
 
-static const u8 *get_mac_for_key(struct ieee80211_key *key)
+static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
 {
-       const u8 *addr = bcast_addr;
-
-       /*
-        * If we're an AP we won't ever receive frames with a non-WEP
-        * group key so we tell the driver that by using the zero MAC
-        * address to indicate a transmit-only key.
-        */
-       if (key->conf.alg != ALG_WEP &&
-           (key->sdata->vif.type == NL80211_IFTYPE_AP ||
-            key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
-               addr = zero_addr;
-
        if (key->sta)
-               addr = key->sta->sta.addr;
+               return &key->sta->sta;
 
-       return addr;
+       return NULL;
 }
 
 static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 {
-       const u8 *addr;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sta *sta;
        int ret;
 
        assert_key_lock();
@@ -139,11 +128,16 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
        if (!key->local->ops->set_key)
                return;
 
-       addr = get_mac_for_key(key);
+       sta = get_sta_for_key(key);
+
+       sdata = key->sdata;
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss,
+                                    struct ieee80211_sub_if_data,
+                                    u.ap);
 
        ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
-                                      key->sdata->dev->dev_addr, addr,
-                                      &key->conf);
+                                      &sdata->vif, sta, &key->conf);
 
        if (!ret) {
                spin_lock(&todo_lock);
@@ -155,12 +149,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
                printk(KERN_ERR "mac80211-%s: failed to set key "
                       "(%d, %pM) to hardware (%d)\n",
                       wiphy_name(key->local->hw.wiphy),
-                      key->conf.keyidx, addr, ret);
+                      key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
 }
 
 static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
 {
-       const u8 *addr;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sta *sta;
        int ret;
 
        assert_key_lock();
@@ -176,17 +171,22 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        }
        spin_unlock(&todo_lock);
 
-       addr = get_mac_for_key(key);
+       sta = get_sta_for_key(key);
+       sdata = key->sdata;
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss,
+                                    struct ieee80211_sub_if_data,
+                                    u.ap);
 
        ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY,
-                                      key->sdata->dev->dev_addr, addr,
-                                      &key->conf);
+                                      &sdata->vif, sta, &key->conf);
 
        if (ret)
                printk(KERN_ERR "mac80211-%s: failed to remove key "
                       "(%d, %pM) from hardware (%d)\n",
                       wiphy_name(key->local->hw.wiphy),
-                      key->conf.keyidx, addr, ret);
+                      key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
 
        spin_lock(&todo_lock);
        key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
@@ -216,13 +216,38 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
        spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 }
 
+static void
+__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
+{
+       struct ieee80211_key *key = NULL;
+
+       if (idx >= NUM_DEFAULT_KEYS &&
+           idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
+               key = sdata->keys[idx];
+
+       rcu_assign_pointer(sdata->default_mgmt_key, key);
+
+       if (key)
+               add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY);
+}
+
+void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
+                                   int idx)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdata->local->key_lock, flags);
+       __ieee80211_set_default_mgmt_key(sdata, idx);
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
+}
+
 
 static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                                    struct sta_info *sta,
                                    struct ieee80211_key *old,
                                    struct ieee80211_key *new)
 {
-       int idx, defkey;
+       int idx, defkey, defmgmtkey;
 
        if (new)
                list_add(&new->list, &sdata->key_list);
@@ -238,13 +263,19 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                        idx = new->conf.keyidx;
 
                defkey = old && sdata->default_key == old;
+               defmgmtkey = old && sdata->default_mgmt_key == old;
 
                if (defkey && !new)
                        __ieee80211_set_default_key(sdata, -1);
+               if (defmgmtkey && !new)
+                       __ieee80211_set_default_mgmt_key(sdata, -1);
 
                rcu_assign_pointer(sdata->keys[idx], new);
                if (defkey && new)
                        __ieee80211_set_default_key(sdata, new->conf.keyidx);
+               if (defmgmtkey && new)
+                       __ieee80211_set_default_mgmt_key(sdata,
+                                                        new->conf.keyidx);
        }
 
        if (old) {
@@ -263,7 +294,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
 {
        struct ieee80211_key *key;
 
-       BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS);
+       BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
 
        key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
        if (!key)
@@ -292,6 +323,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
                key->conf.iv_len = CCMP_HDR_LEN;
                key->conf.icv_len = CCMP_MIC_LEN;
                break;
+       case ALG_AES_CMAC:
+               key->conf.iv_len = 0;
+               key->conf.icv_len = sizeof(struct ieee80211_mmie);
+               break;
        }
        memcpy(key->conf.key, key_data, key_len);
        INIT_LIST_HEAD(&key->list);
@@ -309,6 +344,19 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
                }
        }
 
+       if (alg == ALG_AES_CMAC) {
+               /*
+                * Initialize AES key state here as an optimization so that
+                * it does not need to be initialized for every packet.
+                */
+               key->u.aes_cmac.tfm =
+                       ieee80211_aes_cmac_key_setup(key_data);
+               if (!key->u.aes_cmac.tfm) {
+                       kfree(key);
+                       return NULL;
+               }
+       }
+
        return key;
 }
 
@@ -462,6 +510,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
 
        if (key->conf.alg == ALG_CCMP)
                ieee80211_aes_key_free(key->u.ccmp.tfm);
+       if (key->conf.alg == ALG_AES_CMAC)
+               ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
        ieee80211_debugfs_key_remove(key);
 
        kfree(key);
@@ -484,6 +534,7 @@ static void __ieee80211_key_todo(void)
                list_del_init(&key->todo);
                todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
                                          KEY_FLAG_TODO_DEFKEY |
+                                         KEY_FLAG_TODO_DEFMGMTKEY |
                                          KEY_FLAG_TODO_HWACCEL_ADD |
                                          KEY_FLAG_TODO_HWACCEL_REMOVE |
                                          KEY_FLAG_TODO_DELETE);
@@ -501,6 +552,11 @@ static void __ieee80211_key_todo(void)
                        ieee80211_debugfs_key_add_default(key->sdata);
                        work_done = true;
                }
+               if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) {
+                       ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
+                       ieee80211_debugfs_key_add_mgmt_default(key->sdata);
+                       work_done = true;
+               }
                if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
                        ieee80211_key_enable_hw_accel(key);
                        work_done = true;
@@ -536,6 +592,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
        ieee80211_key_lock();
 
        ieee80211_debugfs_key_remove_default(sdata);
+       ieee80211_debugfs_key_remove_mgmt_default(sdata);
 
        spin_lock_irqsave(&sdata->local->key_lock, flags);
        list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
index 425816e0996cb27d292b759915f91eb4ce2d3e4e..215d3ef42a4f3c8a3db8017d9792caca7bddff6f 100644 (file)
@@ -46,6 +46,8 @@ struct sta_info;
  *     acceleration.
  * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
  * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
+ * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs
+ *     to be updated.
  */
 enum ieee80211_internal_key_flags {
        KEY_FLAG_UPLOADED_TO_HARDWARE   = BIT(0),
@@ -54,6 +56,7 @@ enum ieee80211_internal_key_flags {
        KEY_FLAG_TODO_HWACCEL_REMOVE    = BIT(3),
        KEY_FLAG_TODO_DEFKEY            = BIT(4),
        KEY_FLAG_TODO_ADD_DEBUGFS       = BIT(5),
+       KEY_FLAG_TODO_DEFMGMTKEY        = BIT(6),
 };
 
 struct tkip_ctx {
@@ -96,6 +99,16 @@ struct ieee80211_key {
                        u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
                        u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
                } ccmp;
+               struct {
+                       u8 tx_pn[6];
+                       u8 rx_pn[6];
+                       struct crypto_cipher *tfm;
+                       u32 replays; /* dot11RSNAStatsCMACReplays */
+                       u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
+                       /* scratch buffers for virt_to_page() (crypto API) */
+                       u8 tx_crypto_buf[2 * AES_BLOCK_LEN];
+                       u8 rx_crypto_buf[2 * AES_BLOCK_LEN];
+               } aes_cmac;
        } u;
 
        /* number of times this key has been used */
@@ -114,6 +127,7 @@ struct ieee80211_key {
                struct dentry *tx_spec;
                struct dentry *rx_spec;
                struct dentry *replays;
+               struct dentry *icverrors;
                struct dentry *key;
                struct dentry *ifindex;
                int cnt;
@@ -140,6 +154,8 @@ void ieee80211_key_link(struct ieee80211_key *key,
                        struct sta_info *sta);
 void ieee80211_key_free(struct ieee80211_key *key);
 void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
+void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
+                                   int idx);
 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
 void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
index 24b14363d6e70c77766c06946ba5407de122dc89..a109c06e8e4ec46f1951a2f011aa9fd3ecb20554 100644 (file)
@@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
                return 0;
 
        memset(&conf, 0, sizeof(conf));
-       conf.changed = changed;
 
        if (sdata->vif.type == NL80211_IFTYPE_STATION ||
            sdata->vif.type == NL80211_IFTYPE_ADHOC)
@@ -176,16 +175,57 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
        else if (sdata->vif.type == NL80211_IFTYPE_AP)
                conf.bssid = sdata->dev->dev_addr;
        else if (ieee80211_vif_is_mesh(&sdata->vif)) {
-               u8 zero[ETH_ALEN] = { 0 };
+               static const u8 zero[ETH_ALEN] = { 0 };
                conf.bssid = zero;
        } else {
                WARN_ON(1);
                return -EINVAL;
        }
 
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_MESH_POINT:
+               break;
+       default:
+               /* do not warn to simplify caller in scan.c */
+               changed &= ~IEEE80211_IFCC_BEACON_ENABLED;
+               if (WARN_ON(changed & IEEE80211_IFCC_BEACON))
+                       return -EINVAL;
+               changed &= ~IEEE80211_IFCC_BEACON;
+               break;
+       }
+
+       if (changed & IEEE80211_IFCC_BEACON_ENABLED) {
+               if (local->sw_scanning) {
+                       conf.enable_beacon = false;
+               } else {
+                       /*
+                        * Beacon should be enabled, but AP mode must
+                        * check whether there is a beacon configured.
+                        */
+                       switch (sdata->vif.type) {
+                       case NL80211_IFTYPE_AP:
+                               conf.enable_beacon =
+                                       !!rcu_dereference(sdata->u.ap.beacon);
+                               break;
+                       case NL80211_IFTYPE_ADHOC:
+                       case NL80211_IFTYPE_MESH_POINT:
+                               conf.enable_beacon = true;
+                               break;
+                       default:
+                               /* not reached */
+                               WARN_ON(1);
+                               break;
+                       }
+               }
+       }
+
        if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
                return -EINVAL;
 
+       conf.changed = changed;
+
        return local->ops->config_interface(local_to_hw(local),
                                            &sdata->vif, &conf);
 }
@@ -208,26 +248,22 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
        }
 
        if (chan != local->hw.conf.channel ||
-           channel_type != local->hw.conf.ht.channel_type) {
+           channel_type != local->hw.conf.channel_type) {
                local->hw.conf.channel = chan;
-               local->hw.conf.ht.channel_type = channel_type;
-               switch (channel_type) {
-               case NL80211_CHAN_NO_HT:
-                       local->hw.conf.ht.enabled = false;
-                       break;
-               case NL80211_CHAN_HT20:
-               case NL80211_CHAN_HT40MINUS:
-               case NL80211_CHAN_HT40PLUS:
-                       local->hw.conf.ht.enabled = true;
-                       break;
-               }
+               local->hw.conf.channel_type = channel_type;
                changed |= IEEE80211_CONF_CHANGE_CHANNEL;
        }
 
-       if (!local->hw.conf.power_level)
+       if (local->sw_scanning)
                power = chan->max_power;
        else
-               power = min(chan->max_power, local->hw.conf.power_level);
+               power = local->power_constr_level ?
+                       (chan->max_power - local->power_constr_level) :
+                       chan->max_power;
+
+       if (local->user_power_level)
+               power = min(power, local->user_power_level);
+
        if (local->hw.conf.power_level != power) {
                changed |= IEEE80211_CONF_CHANGE_POWER;
                local->hw.conf.power_level = power;
@@ -722,6 +758,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        local->hw.conf.radio_enabled = true;
 
        INIT_LIST_HEAD(&local->interfaces);
+       mutex_init(&local->iflist_mtx);
 
        spin_lock_init(&local->key_lock);
 
@@ -822,7 +859,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        mdev->set_multicast_list = ieee80211_master_set_multicast_list;
 
        local->hw.workqueue =
-               create_freezeable_workqueue(wiphy_name(local->hw.wiphy));
+               create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
        if (!local->hw.workqueue) {
                result = -ENOMEM;
                goto fail_workqueue;
@@ -972,6 +1009,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
 {
        struct ieee80211_local *local = hw_to_local(hw);
 
+       mutex_destroy(&local->iflist_mtx);
+
        wiphy_free(local->hw.wiphy);
 }
 EXPORT_SYMBOL(ieee80211_free_hw);
index 82f568e943657c2c5114ef111f57e53292011edc..8a1fcaeee4f20023e760d9125a2802f06fd2d96f 100644 (file)
@@ -442,7 +442,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 
        ifmsh->housekeeping = true;
        queue_work(local->hw.workqueue, &ifmsh->work);
-       ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+       ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+                                  IEEE80211_IFCC_BEACON_ENABLED);
 }
 
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -476,7 +477,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee802_11_elems elems;
        struct ieee80211_channel *channel;
-       u64 supp_rates = 0;
+       u32 supp_rates = 0;
        size_t baselen;
        int freq;
        enum ieee80211_band band = rx_status->band;
index c197ab545e54a05e56b46f946d1d2bb8e3f5e5e9..9e064ee98ee0040f1a2546361869ada96889e226 100644 (file)
  *
  *
  *
- * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding
- * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path
+ * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding
+ * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path
  * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence
  *     number
  * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
  *     modified
  * @MESH_PATH_RESOLVED: the mesh path can has been resolved
  *
- * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to
+ * MESH_PATH_RESOLVED is used by the mesh path timer to
  * decide when to stop or cancel the mesh path discovery.
  */
 enum mesh_path_flags {
@@ -236,14 +236,13 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_mgmt *mgmt, size_t len);
 int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
 /* Mesh plinks */
-void mesh_neighbour_update(u8 *hw_addr, u64 rates,
+void mesh_neighbour_update(u8 *hw_addr, u32 rates,
                struct ieee80211_sub_if_data *sdata, bool add);
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
 void mesh_plink_broken(struct sta_info *sta);
 void mesh_plink_deactivate(struct sta_info *sta);
 int mesh_plink_open(struct sta_info *sta);
-int mesh_plink_close(struct sta_info *sta);
 void mesh_plink_block(struct sta_info *sta);
 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
                         struct ieee80211_mgmt *mgmt, size_t len,
index 71fe609612303a2d9d6fc11e263845df26438256..4f862b2a0041094af3d6045090a1cc76b1b122f4 100644 (file)
@@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
        pos += ETH_ALEN;
        memcpy(pos, &dst_dsn, 4);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
        return 0;
 }
 
@@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
        pos += ETH_ALEN;
        memcpy(pos, &dst_dsn, 4);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
        return 0;
 }
 
@@ -759,7 +759,7 @@ enddiscovery:
 }
 
 /**
- * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
+ * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame
  *
  * @skb: 802.11 frame to be sent
  * @sdata: network subif the frame will be sent through
index 1159bdb4119c6ecad0167b266b9fa4f8fb7b3b4a..a8bbdeca013a1b3caf8c928226b7877b88a57cf6 100644 (file)
@@ -93,7 +93,7 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
  *       on it in the lifecycle management section!
  */
 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
-                                        u8 *hw_addr, u64 rates)
+                                        u8 *hw_addr, u32 rates)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
@@ -218,11 +218,11 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                memcpy(pos, &reason, 2);
        }
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
        return 0;
 }
 
-void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata,
+void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata,
                           bool peer_accepting_plinks)
 {
        struct ieee80211_local *local = sdata->local;
@@ -361,36 +361,6 @@ void mesh_plink_block(struct sta_info *sta)
        spin_unlock_bh(&sta->lock);
 }
 
-int mesh_plink_close(struct sta_info *sta)
-{
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-       __le16 llid, plid, reason;
-
-       mpl_dbg("Mesh plink: closing link with %pM\n", sta->sta.addr);
-       spin_lock_bh(&sta->lock);
-       sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
-       reason = sta->reason;
-
-       if (sta->plink_state == PLINK_LISTEN ||
-           sta->plink_state == PLINK_BLOCKED) {
-               mesh_plink_fsm_restart(sta);
-               spin_unlock_bh(&sta->lock);
-               return 0;
-       } else if (sta->plink_state == PLINK_ESTAB) {
-               __mesh_plink_deactivate(sta);
-               /* The timer should not be running */
-               mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
-       } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)))
-               sta->ignore_plink_timer = true;
-
-       sta->plink_state = PLINK_HOLDING;
-       llid = sta->llid;
-       plid = sta->plid;
-       spin_unlock_bh(&sta->lock);
-       mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid,
-                           plid, reason);
-       return 0;
-}
 
 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
                         size_t len, struct ieee80211_rx_status *rx_status)
@@ -477,7 +447,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                spin_lock_bh(&sta->lock);
        } else if (!sta) {
                /* ftype == PLINK_OPEN */
-               u64 rates;
+               u32 rates;
                if (!mesh_plink_free_count(sdata)) {
                        mpl_dbg("Mesh plink error: no more free plinks\n");
                        rcu_read_unlock();
index 2b890af01ba47e8dd21134f1c8d849d94bbcfddf..9d51e278c1e5c74baa90c9604059144f069ceed8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * BSS client mode implementation
- * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
  * Copyright 2004, Instant802 Networks, Inc.
  * Copyright 2005, Devicescape Software, Inc.
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
@@ -73,7 +73,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
 
 static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
                                      struct ieee80211_supported_band *sband,
-                                     u64 *rates)
+                                     u32 *rates)
 {
        int i, j, count;
        *rates = 0;
@@ -93,14 +93,14 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
 }
 
 /* also used by mesh code */
-u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
+u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
                            struct ieee802_11_elems *elems,
                            enum ieee80211_band band)
 {
        struct ieee80211_supported_band *sband;
        struct ieee80211_rate *bitrates;
        size_t num_rates;
-       u64 supp_rates;
+       u32 supp_rates;
        int i, j;
        sband = local->hw.wiphy->bands[band];
 
@@ -131,6 +131,12 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
 
 /* frame sending functions */
 
+static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len)
+{
+       if (ies)
+               memcpy(skb_put(skb, ies_len), ies, ies_len);
+}
+
 /* also used by scanning code */
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                              u8 *ssid, size_t ssid_len)
@@ -142,7 +148,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
        u8 *pos, *supp_rates, *esupp_rates = NULL;
        int i;
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
+                           sdata->u.sta.ie_probereq_len);
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
                       "request\n", sdata->dev->name);
@@ -189,6 +196,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                *pos = rate->bitrate / 5;
        }
 
+       add_extra_ies(skb, sdata->u.sta.ie_probereq,
+                     sdata->u.sta.ie_probereq_len);
+
        ieee80211_tx_skb(sdata, skb, 0);
 }
 
@@ -202,7 +212,8 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgmt *mgmt;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-                           sizeof(*mgmt) + 6 + extra_len);
+                           sizeof(*mgmt) + 6 + extra_len +
+                           sdata->u.sta.ie_auth_len);
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
                       "frame\n", sdata->dev->name);
@@ -225,6 +236,7 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
        mgmt->u.auth.status_code = cpu_to_le16(0);
        if (extra)
                memcpy(skb_put(skb, extra_len), extra, extra_len);
+       add_extra_ies(skb, sdata->u.sta.ie_auth, sdata->u.sta.ie_auth_len);
 
        ieee80211_tx_skb(sdata, skb, encrypt);
 }
@@ -235,17 +247,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       u8 *pos, *ies, *ht_ie;
+       u8 *pos, *ies, *ht_ie, *e_ies;
        int i, len, count, rates_len, supp_rates_len;
        u16 capab;
        struct ieee80211_bss *bss;
        int wmm = 0;
        struct ieee80211_supported_band *sband;
-       u64 rates = 0;
+       u32 rates = 0;
+       size_t e_ies_len;
+
+       if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
+               e_ies = sdata->u.sta.ie_reassocreq;
+               e_ies_len = sdata->u.sta.ie_reassocreq_len;
+       } else {
+               e_ies = sdata->u.sta.ie_assocreq;
+               e_ies_len = sdata->u.sta.ie_assocreq_len;
+       }
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
                            sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
-                           ifsta->ssid_len);
+                           ifsta->ssid_len + e_ies_len);
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
                       "frame\n", sdata->dev->name);
@@ -391,10 +412,17 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
        }
 
        /* wmm support is a must to HT */
+       /*
+        * IEEE802.11n does not allow TKIP/WEP as pairwise
+        * ciphers in HT mode. We still associate in non-ht
+        * mode (11a/b/g) if any one of these ciphers is
+        * configured as pairwise.
+        */
        if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
            sband->ht_cap.ht_supported &&
            (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
-           ht_ie[1] >= sizeof(struct ieee80211_ht_info)) {
+           ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
+           (!(ifsta->flags & IEEE80211_STA_TKIP_WEP_USED))) {
                struct ieee80211_ht_info *ht_info =
                        (struct ieee80211_ht_info *)(ht_ie + 2);
                u16 cap = sband->ht_cap.cap;
@@ -429,6 +457,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
                memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
        }
 
+       add_extra_ies(skb, e_ies, e_ies_len);
+
        kfree(ifsta->assocreq_ies);
        ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
        ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
@@ -446,8 +476,19 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_sta *ifsta = &sdata->u.sta;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
+       u8 *ies;
+       size_t ies_len;
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+       if (stype == IEEE80211_STYPE_DEAUTH) {
+               ies = sdata->u.sta.ie_deauth;
+               ies_len = sdata->u.sta.ie_deauth_len;
+       } else {
+               ies = sdata->u.sta.ie_disassoc;
+               ies_len = sdata->u.sta.ie_disassoc_len;
+       }
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) +
+                           ies_len);
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for "
                       "deauth/disassoc frame\n", sdata->dev->name);
@@ -465,7 +506,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
        /* u.deauth.reason_code == u.disassoc.reason_code */
        mgmt->u.deauth.reason_code = cpu_to_le16(reason);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       add_extra_ies(skb, ies, ies_len);
+
+       ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED);
 }
 
 /* MLME */
@@ -568,6 +611,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
        }
 }
 
+static bool check_tim(struct ieee802_11_elems *elems, u16 aid, bool *is_mc)
+{
+       u8 mask;
+       u8 index, indexn1, indexn2;
+       struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim;
+
+       aid &= 0x3fff;
+       index = aid / 8;
+       mask  = 1 << (aid & 7);
+
+       if (tim->bitmap_ctrl & 0x01)
+               *is_mc = true;
+
+       indexn1 = tim->bitmap_ctrl & 0xfe;
+       indexn2 = elems->tim_len + indexn1 - 4;
+
+       if (index < indexn1 || index > indexn2)
+               return false;
+
+       index -= indexn1;
+
+       return !!(tim->virtual_map[index] & mask);
+}
+
 static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
                                           u16 capab, bool erp_valid, u8 erp)
 {
@@ -745,13 +812,16 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
        if (local->powersave) {
-               if (local->dynamic_ps_timeout > 0)
+               if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) &&
+                   local->hw.conf.dynamic_ps_timeout > 0) {
                        mod_timer(&local->dynamic_ps_timer, jiffies +
-                                 msecs_to_jiffies(local->dynamic_ps_timeout));
-               else {
+                                 msecs_to_jiffies(
+                                       local->hw.conf.dynamic_ps_timeout));
+               } else {
+                       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+                               ieee80211_send_nullfunc(local, sdata, 1);
                        conf->flags |= IEEE80211_CONF_PS;
-                       ieee80211_hw_config(local,
-                                           IEEE80211_CONF_CHANGE_PS);
+                       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
                }
        }
 
@@ -868,9 +938,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        rcu_read_unlock();
 
-       local->hw.conf.ht.enabled = false;
+       /* channel(_type) changes are handled by ieee80211_hw_config */
        local->oper_channel_type = NL80211_CHAN_NO_HT;
-       config_changed |= IEEE80211_CONF_CHANGE_HT;
+
+       local->power_constr_level = 0;
 
        del_timer_sync(&local->dynamic_ps_timer);
        cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -1211,7 +1282,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
        struct sta_info *sta;
-       u64 rates, basic_rates;
+       u32 rates, basic_rates;
        u16 capab_info, status_code, aid;
        struct ieee802_11_elems elems;
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
@@ -1242,6 +1313,24 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
               sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
               capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 
+       pos = mgmt->u.assoc_resp.variable;
+       ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+
+       if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
+           elems.timeout_int && elems.timeout_int_len == 5 &&
+           elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
+               u32 tu, ms;
+               tu = get_unaligned_le32(elems.timeout_int + 1);
+               ms = tu * 1024 / 1000;
+               printk(KERN_DEBUG "%s: AP rejected association temporarily; "
+                      "comeback duration %u TU (%u ms)\n",
+                      sdata->dev->name, tu, ms);
+               if (ms > IEEE80211_ASSOC_TIMEOUT)
+                       mod_timer(&ifsta->timer,
+                                 jiffies + msecs_to_jiffies(ms));
+               return;
+       }
+
        if (status_code != WLAN_STATUS_SUCCESS) {
                printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
                       sdata->dev->name, status_code);
@@ -1257,9 +1346,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                       "set\n", sdata->dev->name, aid);
        aid &= ~(BIT(15) | BIT(14));
 
-       pos = mgmt->u.assoc_resp.variable;
-       ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-
        if (!elems.supp_rates) {
                printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
                       sdata->dev->name);
@@ -1375,6 +1461,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 
        rate_control_rate_init(sta);
 
+       if (ifsta->flags & IEEE80211_STA_MFP_ENABLED)
+               set_sta_flags(sta, WLAN_STA_MFP);
+
        if (elems.wmm_param)
                set_sta_flags(sta, WLAN_STA_WME);
 
@@ -1421,7 +1510,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_supported_band *sband;
        union iwreq_data wrqu;
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
+                           sdata->u.sta.ie_proberesp_len);
        if (!skb) {
                printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
                       "response\n", sdata->dev->name);
@@ -1504,9 +1594,13 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                memcpy(pos, &bss->supp_rates[8], rates);
        }
 
+       add_extra_ies(skb, sdata->u.sta.ie_proberesp,
+                     sdata->u.sta.ie_proberesp_len);
+
        ifsta->probe_resp = skb;
 
-       ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+       ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
+                                  IEEE80211_IFCC_BEACON_ENABLED);
 
 
        rates = 0;
@@ -1521,6 +1615,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_sta_def_wmm_params(sdata, bss);
 
+       ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
        ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED;
        mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
 
@@ -1546,7 +1641,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
        struct ieee80211_channel *channel;
        u64 beacon_timestamp, rx_timestamp;
-       u64 supp_rates = 0;
+       u32 supp_rates = 0;
        enum ieee80211_band band = rx_status->band;
 
        if (elems->ds_params && elems->ds_params_len == 1)
@@ -1567,7 +1662,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 
                sta = sta_info_get(local, mgmt->sa);
                if (sta) {
-                       u64 prev_rates;
+                       u32 prev_rates;
 
                        prev_rates = sta->sta.supp_rates[band];
                        /* make sure mandatory rates are always added */
@@ -1597,6 +1692,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        if (!bss)
                return;
 
+       if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
+           (memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0)) {
+               struct ieee80211_channel_sw_ie *sw_elem =
+                       (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
+               ieee80211_process_chanswitch(sdata, sw_elem, bss);
+       }
+
        /* was just updated in ieee80211_bss_info_update */
        beacon_timestamp = bss->timestamp;
 
@@ -1612,6 +1714,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 
        /* check if we need to merge IBSS */
        if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
+           (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
            bss->capability & WLAN_CAPABILITY_IBSS &&
            bss->freq == local->oper_channel->center_freq &&
            elems->ssid_len == sdata->u.sta.ssid_len &&
@@ -1712,7 +1815,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        struct ieee802_11_elems elems;
        struct ieee80211_local *local = sdata->local;
        u32 changed = 0;
-       bool erp_valid;
+       bool erp_valid, directed_tim, is_mc = false;
        u8 erp_value = 0;
 
        /* Process beacon from the current BSS */
@@ -1732,9 +1835,22 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
            memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
                return;
 
+       if (rx_status->freq != local->hw.conf.channel->center_freq)
+               return;
+
        ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
                                 elems.wmm_param_len);
 
+       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK &&
+           local->hw.conf.flags & IEEE80211_CONF_PS) {
+               directed_tim = check_tim(&elems, ifsta->aid, &is_mc);
+
+               if (directed_tim || is_mc) {
+                       local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+                       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+                       ieee80211_send_nullfunc(local, sdata, 0);
+               }
+       }
 
        if (elems.erp_info && elems.erp_info_len >= 1) {
                erp_valid = true;
@@ -1778,6 +1894,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                 * for the BSSID we are associated to */
                regulatory_hint_11d(local->hw.wiphy,
                        elems.country_elem, elems.country_elem_len);
+
+               /* TODO: IBSS also needs this */
+               if (elems.pwr_constr_elem)
+                       ieee80211_handle_pwr_constr(sdata,
+                               le16_to_cpu(mgmt->u.probe_resp.capab_info),
+                               elems.pwr_constr_elem,
+                               elems.pwr_constr_elem_len);
        }
 
        ieee80211_bss_info_change_notify(sdata, changed);
@@ -1787,8 +1910,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
                                        struct ieee80211_if_sta *ifsta,
                                        struct ieee80211_mgmt *mgmt,
-                                       size_t len,
-                                       struct ieee80211_rx_status *rx_status)
+                                       size_t len)
 {
        struct ieee80211_local *local = sdata->local;
        int tx_last_beacon;
@@ -1903,8 +2025,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_PROBE_REQ:
-               ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len,
-                                           rx_status);
+               ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len);
                break;
        case IEEE80211_STYPE_PROBE_RESP:
                ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status);
@@ -1965,6 +2086,10 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
        if (ieee80211_sta_active_ibss(sdata))
                return;
 
+       if ((sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) &&
+           (!(sdata->u.sta.flags & IEEE80211_STA_AUTO_CHANNEL_SEL)))
+               return;
+
        printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
               "IBSS networks with same SSID (merge)\n", sdata->dev->name);
        ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len);
@@ -2054,19 +2179,18 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
        int i;
        int ret;
 
-#if 0
-       /* Easier testing, use fixed BSSID. */
-       memset(bssid, 0xfe, ETH_ALEN);
-#else
-       /* Generate random, not broadcast, locally administered BSSID. Mix in
-        * own MAC address to make sure that devices that do not have proper
-        * random number generator get different BSSID. */
-       get_random_bytes(bssid, ETH_ALEN);
-       for (i = 0; i < ETH_ALEN; i++)
-               bssid[i] ^= sdata->dev->dev_addr[i];
-       bssid[0] &= ~0x01;
-       bssid[0] |= 0x02;
-#endif
+       if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) {
+               memcpy(bssid, ifsta->bssid, ETH_ALEN);
+       } else {
+               /* Generate random, not broadcast, locally administered BSSID. Mix in
+                * own MAC address to make sure that devices that do not have proper
+                * random number generator get different BSSID. */
+               get_random_bytes(bssid, ETH_ALEN);
+               for (i = 0; i < ETH_ALEN; i++)
+                       bssid[i] ^= sdata->dev->dev_addr[i];
+               bssid[0] &= ~0x01;
+               bssid[0] |= 0x02;
+       }
 
        printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
               sdata->dev->name, bssid);
@@ -2127,6 +2251,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
                    memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
                    || !(bss->capability & WLAN_CAPABILITY_IBSS))
                        continue;
+               if ((ifsta->flags & IEEE80211_STA_BSSID_SET) &&
+                   memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) != 0)
+                       continue;
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
                printk(KERN_DEBUG "   bssid=%pM found\n", bss->bssid);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
@@ -2143,7 +2270,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
                       "%pM\n", bssid, ifsta->bssid);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
-       if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+       if (found &&
+           ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
+            memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) {
                int ret;
                int search_freq;
 
@@ -2258,6 +2387,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
                                               selected->ssid_len);
                ieee80211_sta_set_bssid(sdata, selected->bssid);
                ieee80211_sta_def_wmm_params(sdata, selected);
+               if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED)
+                       sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED;
+               else
+                       sdata->u.sta.flags &= ~IEEE80211_STA_MFP_ENABLED;
 
                /* Send out direct probe if no probe resp was received or
                 * the one we have is outdated
@@ -2376,8 +2509,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 
        ifsta = &sdata->u.sta;
        INIT_WORK(&ifsta->work, ieee80211_sta_work);
+       INIT_WORK(&ifsta->chswitch_work, ieee80211_chswitch_work);
        setup_timer(&ifsta->timer, ieee80211_sta_timer,
                    (unsigned long) sdata);
+       setup_timer(&ifsta->chswitch_timer, ieee80211_chswitch_timer,
+                   (unsigned long) sdata);
        skb_queue_head_init(&ifsta->skb_queue);
 
        ifsta->capab = WLAN_CAPABILITY_ESS;
@@ -2396,7 +2532,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
  * must be callable in atomic context.
  */
 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-                                       u8 *bssid,u8 *addr, u64 supp_rates)
+                                       u8 *bssid,u8 *addr, u32 supp_rates)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
@@ -2474,16 +2610,16 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
                memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
                memcpy(ifsta->ssid, ssid, len);
                ifsta->ssid_len = len;
-               ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
        }
 
+       ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+
        if (len)
                ifsta->flags |= IEEE80211_STA_SSID_SET;
        else
                ifsta->flags &= ~IEEE80211_STA_SSID_SET;
 
-       if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-           !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
+       if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
                ifsta->ibss_join_req = jiffies;
                ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
                return ieee80211_sta_find_ibss(sdata, ifsta);
@@ -2503,31 +2639,25 @@ int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
 int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
 {
        struct ieee80211_if_sta *ifsta;
-       int res;
 
        ifsta = &sdata->u.sta;
 
-       if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+       if (is_valid_ether_addr(bssid)) {
                memcpy(ifsta->bssid, bssid, ETH_ALEN);
-               res = 0;
-               /*
-                * Hack! See also ieee80211_sta_set_ssid.
-                */
-               if (netif_running(sdata->dev))
-                       res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
-               if (res) {
+               ifsta->flags |= IEEE80211_STA_BSSID_SET;
+       } else {
+               memset(ifsta->bssid, 0, ETH_ALEN);
+               ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
+       }
+
+       if (netif_running(sdata->dev)) {
+               if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
                        printk(KERN_DEBUG "%s: Failed to config new BSSID to "
                               "the low-level driver\n", sdata->dev->name);
-                       return res;
                }
        }
 
-       if (is_valid_ether_addr(bssid))
-               ifsta->flags |= IEEE80211_STA_BSSID_SET;
-       else
-               ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
-
-       return 0;
+       return ieee80211_sta_set_ssid(sdata, ifsta->ssid, ifsta->ssid_len);
 }
 
 int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
@@ -2623,12 +2753,15 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
        struct ieee80211_local *local =
                container_of(work, struct ieee80211_local,
                             dynamic_ps_enable_work);
+       struct ieee80211_sub_if_data *sdata = local->scan_sdata;
 
        if (local->hw.conf.flags & IEEE80211_CONF_PS)
                return;
 
-       local->hw.conf.flags |= IEEE80211_CONF_PS;
+       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+               ieee80211_send_nullfunc(local, sdata, 1);
 
+       local->hw.conf.flags |= IEEE80211_CONF_PS;
        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 }
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
new file mode 100644 (file)
index 0000000..44525f5
--- /dev/null
@@ -0,0 +1,117 @@
+#include <net/mac80211.h>
+#include <net/rtnetlink.h>
+
+#include "ieee80211_i.h"
+#include "led.h"
+
+int __ieee80211_suspend(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_init_conf conf;
+       struct sta_info *sta;
+
+       flush_workqueue(local->hw.workqueue);
+
+       /* disable keys */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               ieee80211_disable_keys(sdata);
+
+       /* remove STAs */
+       list_for_each_entry(sta, &local->sta_list, list) {
+
+               if (local->ops->sta_notify) {
+                       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                               sdata = container_of(sdata->bss,
+                                            struct ieee80211_sub_if_data,
+                                            u.ap);
+
+                       local->ops->sta_notify(hw, &sdata->vif,
+                               STA_NOTIFY_REMOVE, &sta->sta);
+               }
+       }
+
+       /* remove all interfaces */
+       list_for_each_entry(sdata, &local->interfaces, list) {
+
+               if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+                   netif_running(sdata->dev)) {
+                       conf.vif = &sdata->vif;
+                       conf.type = sdata->vif.type;
+                       conf.mac_addr = sdata->dev->dev_addr;
+                       local->ops->remove_interface(hw, &conf);
+               }
+       }
+
+       /* flush again, in case driver queued work */
+       flush_workqueue(local->hw.workqueue);
+
+       /* stop hardware */
+       if (local->open_count) {
+               ieee80211_led_radio(local, false);
+               local->ops->stop(hw);
+       }
+       return 0;
+}
+
+int __ieee80211_resume(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_init_conf conf;
+       struct sta_info *sta;
+       int res;
+
+       /* restart hardware */
+       if (local->open_count) {
+               res = local->ops->start(hw);
+
+               ieee80211_led_radio(local, hw->conf.radio_enabled);
+       }
+
+       /* add interfaces */
+       list_for_each_entry(sdata, &local->interfaces, list) {
+
+               if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+                   netif_running(sdata->dev)) {
+                       conf.vif = &sdata->vif;
+                       conf.type = sdata->vif.type;
+                       conf.mac_addr = sdata->dev->dev_addr;
+                       res = local->ops->add_interface(hw, &conf);
+               }
+       }
+
+       /* add STAs back */
+       list_for_each_entry(sta, &local->sta_list, list) {
+
+               if (local->ops->sta_notify) {
+                       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                               sdata = container_of(sdata->bss,
+                                            struct ieee80211_sub_if_data,
+                                            u.ap);
+
+                       local->ops->sta_notify(hw, &sdata->vif,
+                               STA_NOTIFY_ADD, &sta->sta);
+               }
+       }
+
+       /* add back keys */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               if (netif_running(sdata->dev))
+                       ieee80211_enable_keys(sdata);
+
+       /* setup RTS threshold */
+       if (local->ops->set_rts_threshold)
+               local->ops->set_rts_threshold(hw, local->rts_threshold);
+
+       /* reconfigure hardware */
+       ieee80211_hw_config(local, ~0);
+
+       netif_addr_lock_bh(local->mdev);
+       ieee80211_configure_filter(local);
+       netif_addr_unlock_bh(local->mdev);
+
+       return 0;
+}
index 7175ae80c36a3b3a513fd1f5040643e595401a5c..19ffc8ef1d1d64b4f5b4464ea2a435719afb3161 100644 (file)
@@ -102,7 +102,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
        return len;
 }
 
-/**
+/*
  * ieee80211_add_rx_radiotap_header - add radiotap header
  *
  * add a radiotap header containing all the fields which the hardware provided.
@@ -158,7 +158,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                 */
                *pos = 0;
        } else {
-               rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);
+               rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
                *pos = rate->bitrate / 5;
        }
        pos++;
@@ -371,39 +371,50 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
        rx->skb->priority = (tid > 7) ? 0 : tid;
 }
 
-static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
+/**
+ * DOC: Packet alignment
+ *
+ * Drivers always need to pass packets that are aligned to two-byte boundaries
+ * to the stack.
+ *
+ * Additionally, should, if possible, align the payload data in a way that
+ * guarantees that the contained IP header is aligned to a four-byte
+ * boundary. In the case of regular frames, this simply means aligning the
+ * payload to a four-byte boundary (because either the IP header is directly
+ * contained, or IV/RFC1042 headers that have a length divisible by four are
+ * in front of it).
+ *
+ * With A-MSDU frames, however, the payload data address must yield two modulo
+ * four because there are 14-byte 802.3 headers within the A-MSDU frames that
+ * push the IP header further back to a multiple of four again. Thankfully, the
+ * specs were sane enough this time around to require padding each A-MSDU
+ * subframe to a length that is a multiple of four.
+ *
+ * Padding like Atheros hardware adds which is inbetween the 802.11 header and
+ * the payload is not supported, the driver is required to move the 802.11
+ * header to be directly in front of the payload in that case.
+ */
+static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
 {
-#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        int hdrlen;
 
+#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+       return;
+#endif
+
+       if (WARN_ONCE((unsigned long)rx->skb->data & 1,
+                     "unaligned packet at 0x%p\n", rx->skb->data))
+               return;
+
        if (!ieee80211_is_data_present(hdr->frame_control))
                return;
 
-       /*
-        * Drivers are required to align the payload data in a way that
-        * guarantees that the contained IP header is aligned to a four-
-        * byte boundary. In the case of regular frames, this simply means
-        * aligning the payload to a four-byte boundary (because either
-        * the IP header is directly contained, or IV/RFC1042 headers that
-        * have a length divisible by four are in front of it.
-        *
-        * With A-MSDU frames, however, the payload data address must
-        * yield two modulo four because there are 14-byte 802.3 headers
-        * within the A-MSDU frames that push the IP header further back
-        * to a multiple of four again. Thankfully, the specs were sane
-        * enough this time around to require padding each A-MSDU subframe
-        * to a length that is a multiple of four.
-        *
-        * Padding like atheros hardware adds which is inbetween the 802.11
-        * header and the payload is not supported, the driver is required
-        * to move the 802.11 header further back in that case.
-        */
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
        if (rx->flags & IEEE80211_RX_AMSDU)
                hdrlen += ETH_HLEN;
-       WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
-#endif
+       WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3,
+                 "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen);
 }
 
 
@@ -435,6 +446,52 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
+
+static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+       if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
+               return 0;
+
+       return ieee80211_is_robust_mgmt_frame(hdr);
+}
+
+
+static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+       if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
+               return 0;
+
+       return ieee80211_is_robust_mgmt_frame(hdr);
+}
+
+
+/* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */
+static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
+{
+       struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
+       struct ieee80211_mmie *mmie;
+
+       if (skb->len < 24 + sizeof(*mmie) ||
+           !is_multicast_ether_addr(hdr->da))
+               return -1;
+
+       if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
+               return -1; /* not a robust management frame */
+
+       mmie = (struct ieee80211_mmie *)
+               (skb->data + skb->len - sizeof(*mmie));
+       if (mmie->element_id != WLAN_EID_MMIE ||
+           mmie->length != sizeof(*mmie) - 2)
+               return -1;
+
+       return le16_to_cpu(mmie->key_id);
+}
+
+
 static ieee80211_rx_result
 ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 {
@@ -550,21 +607,23 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        int hdrlen;
        ieee80211_rx_result result = RX_DROP_UNUSABLE;
        struct ieee80211_key *stakey = NULL;
+       int mmie_keyidx = -1;
 
        /*
         * Key selection 101
         *
-        * There are three types of keys:
+        * There are four types of keys:
         *  - GTK (group keys)
+        *  - IGTK (group keys for management frames)
         *  - PTK (pairwise keys)
         *  - STK (station-to-station pairwise keys)
         *
         * When selecting a key, we have to distinguish between multicast
         * (including broadcast) and unicast frames, the latter can only
-        * use PTKs and STKs while the former always use GTKs. Unless, of
-        * course, actual WEP keys ("pre-RSNA") are used, then unicast
-        * frames can also use key indizes like GTKs. Hence, if we don't
-        * have a PTK/STK we check the key index for a WEP key.
+        * use PTKs and STKs while the former always use GTKs and IGTKs.
+        * Unless, of course, actual WEP keys ("pre-RSNA") are used, then
+        * unicast frames can also use key indices like GTKs. Hence, if we
+        * don't have a PTK/STK we check the key index for a WEP key.
         *
         * Note that in a regular BSS, multicast frames are sent by the
         * AP only, associated stations unicast the frame to the AP first
@@ -577,8 +636,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
         * possible.
         */
 
-       if (!ieee80211_has_protected(hdr->frame_control))
-               return RX_CONTINUE;
+       if (!ieee80211_has_protected(hdr->frame_control)) {
+               if (!ieee80211_is_mgmt(hdr->frame_control) ||
+                   rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP))
+                       return RX_CONTINUE;
+               mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
+               if (mmie_keyidx < 0)
+                       return RX_CONTINUE;
+       }
 
        /*
         * No point in finding a key and decrypting if the frame is neither
@@ -592,6 +657,16 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 
        if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
                rx->key = stakey;
+       } else if (mmie_keyidx >= 0) {
+               /* Broadcast/multicast robust management frame / BIP */
+               if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
+                   (rx->status->flag & RX_FLAG_IV_STRIPPED))
+                       return RX_CONTINUE;
+
+               if (mmie_keyidx < NUM_DEFAULT_KEYS ||
+                   mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
+                       return RX_DROP_MONITOR; /* unexpected BIP keyidx */
+               rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
        } else {
                /*
                 * The device doesn't give us the IV so we won't be
@@ -654,6 +729,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        case ALG_CCMP:
                result = ieee80211_crypto_ccmp_decrypt(rx);
                break;
+       case ALG_AES_CMAC:
+               result = ieee80211_crypto_aes_cmac_decrypt(rx);
+               break;
        }
 
        /* either the frame has been decrypted or will be dropped */
@@ -1101,6 +1179,15 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
        /* Drop unencrypted frames if key is set. */
        if (unlikely(!ieee80211_has_protected(fc) &&
                     !ieee80211_is_nullfunc(fc) &&
+                    (!ieee80211_is_mgmt(fc) ||
+                     (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+                      rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) &&
+                    (rx->key || rx->sdata->drop_unencrypted)))
+               return -EACCES;
+       /* BIP does not use Protected field, so need to check MMIE */
+       if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) &&
+                    ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
+                    ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
                     (rx->key || rx->sdata->drop_unencrypted)))
                return -EACCES;
 
@@ -1267,10 +1354,37 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        }
 
        if (skb) {
-               /* deliver to local stack */
-               skb->protocol = eth_type_trans(skb, dev);
-               memset(skb->cb, 0, sizeof(skb->cb));
-               netif_rx(skb);
+               int align __maybe_unused;
+
+#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+               /*
+                * 'align' will only take the values 0 or 2 here
+                * since all frames are required to be aligned
+                * to 2-byte boundaries when being passed to
+                * mac80211. That also explains the __skb_push()
+                * below.
+                */
+               align = (unsigned long)skb->data & 4;
+               if (align) {
+                       if (WARN_ON(skb_headroom(skb) < 3)) {
+                               dev_kfree_skb(skb);
+                               skb = NULL;
+                       } else {
+                               u8 *data = skb->data;
+                               size_t len = skb->len;
+                               u8 *new = __skb_push(skb, align);
+                               memmove(new, data, len);
+                               __skb_trim(skb, len);
+                       }
+               }
+#endif
+
+               if (skb) {
+                       /* deliver to local stack */
+                       skb->protocol = eth_type_trans(skb, dev);
+                       memset(skb->cb, 0, sizeof(skb->cb));
+                       netif_rx(skb);
+               }
        }
 
        if (xmit_skb) {
@@ -1339,14 +1453,20 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
                if (remaining <= subframe_len + padding)
                        frame = skb;
                else {
-                       frame = dev_alloc_skb(local->hw.extra_tx_headroom +
-                                             subframe_len);
+                       /*
+                        * Allocate and reserve two bytes more for payload
+                        * alignment since sizeof(struct ethhdr) is 14.
+                        */
+                       frame = dev_alloc_skb(
+                               ALIGN(local->hw.extra_tx_headroom, 4) +
+                               subframe_len + 2);
 
                        if (frame == NULL)
                                return RX_DROP_UNUSABLE;
 
-                       skb_reserve(frame, local->hw.extra_tx_headroom +
-                                   sizeof(struct ethhdr));
+                       skb_reserve(frame,
+                                   ALIGN(local->hw.extra_tx_headroom, 4) +
+                                   sizeof(struct ethhdr) + 2);
                        memcpy(skb_put(frame, ntohs(len)), skb->data,
                                ntohs(len));
 
@@ -1547,12 +1667,65 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
+static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
+                                          struct ieee80211_mgmt *mgmt,
+                                          size_t len)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *resp;
+
+       if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) {
+               /* Not to own unicast address */
+               return;
+       }
+
+       if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 ||
+           compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) {
+               /* Not from the current AP. */
+               return;
+       }
+
+       if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) {
+               /* Association in progress; ignore SA Query */
+               return;
+       }
+
+       if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) {
+               /* Too short SA Query request frame */
+               return;
+       }
+
+       skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom);
+       if (skb == NULL)
+               return;
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+       resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
+       memset(resp, 0, 24);
+       memcpy(resp->da, mgmt->sa, ETH_ALEN);
+       memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
+       memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN);
+       resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                         IEEE80211_STYPE_ACTION);
+       skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
+       resp->u.action.category = WLAN_CATEGORY_SA_QUERY;
+       resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE;
+       memcpy(resp->u.action.u.sa_query.trans_id,
+              mgmt->u.action.u.sa_query.trans_id,
+              WLAN_SA_QUERY_TR_ID_LEN);
+
+       ieee80211_tx_skb(sdata, skb, 1);
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
+       struct ieee80211_bss *bss;
        int len = rx->skb->len;
 
        if (!ieee80211_is_action(mgmt->frame_control))
@@ -1564,6 +1737,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        if (!(rx->flags & IEEE80211_RX_RA_MATCH))
                return RX_DROP_MONITOR;
 
+       if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
+               return RX_DROP_MONITOR;
+
        /* all categories we currently handle have action_code */
        if (len < IEEE80211_MIN_ACTION_SIZE + 1)
                return RX_DROP_MONITOR;
@@ -1601,6 +1777,42 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                                return RX_DROP_MONITOR;
                        ieee80211_process_measurement_req(sdata, mgmt, len);
                        break;
+               case WLAN_ACTION_SPCT_CHL_SWITCH:
+                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                  sizeof(mgmt->u.action.u.chan_switch)))
+                               return RX_DROP_MONITOR;
+
+                       if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0)
+                               return RX_DROP_MONITOR;
+
+                       bss = ieee80211_rx_bss_get(local, ifsta->bssid,
+                                          local->hw.conf.channel->center_freq,
+                                          ifsta->ssid, ifsta->ssid_len);
+                       if (!bss)
+                               return RX_DROP_MONITOR;
+
+                       ieee80211_process_chanswitch(sdata,
+                                    &mgmt->u.action.u.chan_switch.sw_elem, bss);
+                       ieee80211_rx_bss_put(local, bss);
+                       break;
+               }
+               break;
+       case WLAN_CATEGORY_SA_QUERY:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.sa_query)))
+                       return RX_DROP_MONITOR;
+               switch (mgmt->u.action.u.sa_query.action) {
+               case WLAN_ACTION_SA_QUERY_REQUEST:
+                       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+                               return RX_DROP_MONITOR;
+                       ieee80211_process_sa_query_req(sdata, mgmt, len);
+                       break;
+               case WLAN_ACTION_SA_QUERY_RESPONSE:
+                       /*
+                        * SA Query response is currently only used in AP mode
+                        * and it is processed in user space.
+                        */
+                       return RX_CONTINUE;
                }
                break;
        default:
@@ -1616,10 +1828,14 @@ static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
 
        if (!(rx->flags & IEEE80211_RX_RA_MATCH))
                return RX_DROP_MONITOR;
 
+       if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
+               return RX_DROP_MONITOR;
+
        if (ieee80211_vif_is_mesh(&sdata->vif))
                return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status);
 
@@ -1956,7 +2172,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                rx.flags |= IEEE80211_RX_IN_SCAN;
 
        ieee80211_parse_qos(&rx);
-       ieee80211_verify_ip_alignment(&rx);
+       ieee80211_verify_alignment(&rx);
 
        skb = rx.skb;
 
index f5c7c3371929a5c41651bcbefa45771149b5c2d4..282e6a0dec01c4b2f558135f4ea9b6e9751cd6a4 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/wireless.h>
 #include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
 #include <net/mac80211.h>
 #include <net/iw_handler.h>
 
@@ -395,7 +396,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
        return RX_QUEUED;
 }
 
-static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+void ieee80211_send_nullfunc(struct ieee80211_local *local,
                                    struct ieee80211_sub_if_data *sdata,
                                    int powersave)
 {
@@ -472,8 +473,11 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
        netif_addr_unlock(local->mdev);
        netif_tx_unlock_bh(local->mdev);
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+       mutex_lock(&local->iflist_mtx);
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               if (!netif_running(sdata->dev))
+                       continue;
+
                /* Tell AP we're back */
                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                        if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
@@ -482,8 +486,10 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
                        }
                } else
                        netif_tx_wake_all_queues(sdata->dev);
+
+               ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
        }
-       rcu_read_unlock();
+       mutex_unlock(&local->iflist_mtx);
 
  done:
        ieee80211_mlme_notify_scan_completed(local);
@@ -491,7 +497,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_scan_completed);
 
-
 void ieee80211_scan_work(struct work_struct *work)
 {
        struct ieee80211_local *local =
@@ -633,8 +638,13 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
 
        local->sw_scanning = true;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+       mutex_lock(&local->iflist_mtx);
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               if (!netif_running(sdata->dev))
+                       continue;
+
+               ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
+
                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                        if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
                                netif_tx_stop_all_queues(sdata->dev);
@@ -643,7 +653,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
                } else
                        netif_tx_stop_all_queues(sdata->dev);
        }
-       rcu_read_unlock();
+       mutex_unlock(&local->iflist_mtx);
 
        if (ssid) {
                local->scan_ssid_len = ssid_len;
index f72bad636d8e89fb2f2cc3331bb0ba5de7739af9..8d4ec2968f8f300dbfbfe868b5187eacd8e4ab55 100644 (file)
@@ -65,7 +65,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
                        IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED;
        msr_report->u.action.u.measurement.msr_elem.type = request_ie->type;
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       ieee80211_tx_skb(sdata, skb, 1);
 }
 
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
@@ -84,3 +84,101 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
                        mgmt->sa, mgmt->bssid,
                        mgmt->u.action.u.measurement.dialog_token);
 }
+
+void ieee80211_chswitch_work(struct work_struct *work)
+{
+       struct ieee80211_sub_if_data *sdata =
+               container_of(work, struct ieee80211_sub_if_data, u.sta.chswitch_work);
+       struct ieee80211_bss *bss;
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+       if (!netif_running(sdata->dev))
+               return;
+
+       bss = ieee80211_rx_bss_get(sdata->local, ifsta->bssid,
+                                  sdata->local->hw.conf.channel->center_freq,
+                                  ifsta->ssid, ifsta->ssid_len);
+       if (!bss)
+               goto exit;
+
+       sdata->local->oper_channel = sdata->local->csa_channel;
+       if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
+               bss->freq = sdata->local->oper_channel->center_freq;
+
+       ieee80211_rx_bss_put(sdata->local, bss);
+exit:
+       ifsta->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+       ieee80211_wake_queues_by_reason(&sdata->local->hw,
+                                       IEEE80211_QUEUE_STOP_REASON_CSA);
+}
+
+void ieee80211_chswitch_timer(unsigned long data)
+{
+       struct ieee80211_sub_if_data *sdata =
+               (struct ieee80211_sub_if_data *) data;
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+       queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work);
+}
+
+void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
+                                 struct ieee80211_channel_sw_ie *sw_elem,
+                                 struct ieee80211_bss *bss)
+{
+       struct ieee80211_channel *new_ch;
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
+
+       /* FIXME: Handle ADHOC later */
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+               return;
+
+       if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED)
+               return;
+
+       if (sdata->local->sw_scanning || sdata->local->hw_scanning)
+               return;
+
+       /* Disregard subsequent beacons if we are already running a timer
+          processing a CSA */
+
+       if (ifsta->flags & IEEE80211_STA_CSA_RECEIVED)
+               return;
+
+       new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
+       if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
+               return;
+
+       sdata->local->csa_channel = new_ch;
+
+       if (sw_elem->count <= 1) {
+               queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work);
+       } else {
+               ieee80211_stop_queues_by_reason(&sdata->local->hw,
+                                               IEEE80211_QUEUE_STOP_REASON_CSA);
+               ifsta->flags |= IEEE80211_STA_CSA_RECEIVED;
+               mod_timer(&ifsta->chswitch_timer,
+                         jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int));
+       }
+}
+
+void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+                                u16 capab_info, u8 *pwr_constr_elem,
+                                u8 pwr_constr_elem_len)
+{
+       struct ieee80211_conf *conf = &sdata->local->hw.conf;
+
+       if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
+               return;
+
+       /* Power constraint IE length should be 1 octet */
+       if (pwr_constr_elem_len != 1)
+               return;
+
+       if ((*pwr_constr_elem <= conf->channel->max_power) &&
+           (*pwr_constr_elem != sdata->local->power_constr_level)) {
+               sdata->local->power_constr_level = *pwr_constr_elem;
+               ieee80211_hw_config(sdata->local, 0);
+       }
+}
+
index e49a5b99cf10424daba5ed3d8f2bece1447a4b2b..d13a44b935e2946121df2cc78993e5ae89fa0f8a 100644 (file)
@@ -34,6 +34,7 @@
  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
  *     IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
  *     frame to this station is transmitted.
+ * @WLAN_STA_MFP: Management frame protection is used with this STA.
  */
 enum ieee80211_sta_info_flags {
        WLAN_STA_AUTH           = 1<<0,
@@ -46,6 +47,7 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_WDS            = 1<<7,
        WLAN_STA_PSPOLL         = 1<<8,
        WLAN_STA_CLEAR_PS_FILT  = 1<<9,
+       WLAN_STA_MFP            = 1<<10,
 };
 
 #define STA_TID_NUM 16
@@ -382,8 +384,6 @@ static inline u32 get_sta_flags(struct sta_info *sta)
 }
 
 
-/* Maximum number of concurrently registered stations */
-#define MAX_STA_COUNT 2007
 
 #define STA_HASH_SIZE 256
 #define STA_HASH(sta) (sta[5])
index 4278e545638fbeae16c5ffd0795a4835a4358c21..7b013fb0d27f15a631cc785217c11eb59b599020 100644 (file)
@@ -330,6 +330,22 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
        return TX_CONTINUE;
 }
 
+static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
+                            struct sk_buff *skb)
+{
+       if (!ieee80211_is_mgmt(fc))
+               return 0;
+
+       if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP))
+               return 0;
+
+       if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
+                                           skb->data))
+               return 0;
+
+       return 1;
+}
+
 static ieee80211_tx_result
 ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
@@ -409,11 +425,17 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                tx->key = NULL;
        else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
                tx->key = key;
+       else if (ieee80211_is_mgmt(hdr->frame_control) &&
+                (key = rcu_dereference(tx->sdata->default_mgmt_key)))
+               tx->key = key;
        else if ((key = rcu_dereference(tx->sdata->default_key)))
                tx->key = key;
        else if (tx->sdata->drop_unencrypted &&
                 (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) &&
-                !(info->flags & IEEE80211_TX_CTL_INJECTED)) {
+                !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
+                (!ieee80211_is_robust_mgmt_frame(hdr) ||
+                 (ieee80211_is_action(hdr->frame_control) &&
+                  tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
                return TX_DROP;
        } else
@@ -428,10 +450,19 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                        if (ieee80211_is_auth(hdr->frame_control))
                                break;
                case ALG_TKIP:
-               case ALG_CCMP:
                        if (!ieee80211_is_data_present(hdr->frame_control))
                                tx->key = NULL;
                        break;
+               case ALG_CCMP:
+                       if (!ieee80211_is_data_present(hdr->frame_control) &&
+                           !ieee80211_use_mfp(hdr->frame_control, tx->sta,
+                                              tx->skb))
+                               tx->key = NULL;
+                       break;
+               case ALG_AES_CMAC:
+                       if (!ieee80211_is_mgmt(hdr->frame_control))
+                               tx->key = NULL;
+                       break;
                }
        }
 
@@ -787,6 +818,8 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
                return ieee80211_crypto_tkip_encrypt(tx);
        case ALG_CCMP:
                return ieee80211_crypto_ccmp_encrypt(tx);
+       case ALG_AES_CMAC:
+               return ieee80211_crypto_aes_cmac_encrypt(tx);
        }
 
        /* not reached */
@@ -1053,7 +1086,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
        if (skb) {
                if (netif_subqueue_stopped(local->mdev, skb))
                        return IEEE80211_TX_AGAIN;
-               info =  IEEE80211_SKB_CB(skb);
 
                ret = local->ops->tx(local_to_hw(local), skb);
                if (ret)
@@ -1296,6 +1328,19 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
+       if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
+           local->hw.conf.dynamic_ps_timeout > 0) {
+               if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+                       ieee80211_stop_queues_by_reason(&local->hw,
+                                       IEEE80211_QUEUE_STOP_REASON_PS);
+                       queue_work(local->hw.workqueue,
+                                       &local->dynamic_ps_disable_work);
+               }
+
+               mod_timer(&local->dynamic_ps_timer, jiffies +
+                       msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+       }
+
        memset(info, 0, sizeof(*info));
 
        info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -1475,19 +1520,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
                goto fail;
        }
 
-       if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
-           local->dynamic_ps_timeout > 0) {
-               if (local->hw.conf.flags & IEEE80211_CONF_PS) {
-                       ieee80211_stop_queues_by_reason(&local->hw,
-                                                       IEEE80211_QUEUE_STOP_REASON_PS);
-                       queue_work(local->hw.workqueue,
-                                  &local->dynamic_ps_disable_work);
-               }
-
-               mod_timer(&local->dynamic_ps_timer, jiffies +
-                         msecs_to_jiffies(local->dynamic_ps_timeout));
-       }
-
        nh_pos = skb_network_header(skb) - skb->data;
        h_pos = skb_transport_header(skb) - skb->data;
 
index fb89e1d0aa0330ad893888c37697e6932bda47ec..73c7d7345abd19877e320dc40f559ed7d9180611 100644 (file)
@@ -41,6 +41,15 @@ const unsigned char rfc1042_header[] __aligned(2) =
 const unsigned char bridge_tunnel_header[] __aligned(2) =
        { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 
+struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
+{
+       struct ieee80211_local *local;
+       BUG_ON(!wiphy);
+
+       local = wiphy_priv(wiphy);
+       return &local->hw;
+}
+EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
 
 u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
                        enum nl80211_iftype type)
@@ -352,8 +361,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
        }
 }
 
-void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
-                                   enum queue_stop_reason reason)
+static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
+                                          enum queue_stop_reason reason)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        unsigned long flags;
@@ -382,8 +391,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
        netif_stop_subqueue(local->mdev, queue);
 }
 
-void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
-                                   enum queue_stop_reason reason)
+static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
+                                          enum queue_stop_reason reason)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        unsigned long flags;
@@ -459,7 +468,7 @@ void ieee80211_iterate_active_interfaces(
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
 
-       rtnl_lock();
+       mutex_lock(&local->iflist_mtx);
 
        list_for_each_entry(sdata, &local->interfaces, list) {
                switch (sdata->vif.type) {
@@ -480,7 +489,7 @@ void ieee80211_iterate_active_interfaces(
                                 &sdata->vif);
        }
 
-       rtnl_unlock();
+       mutex_unlock(&local->iflist_mtx);
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
 
@@ -653,6 +662,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
                        elems->pwr_constr_elem = pos;
                        elems->pwr_constr_elem_len = elen;
                        break;
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       elems->timeout_int = pos;
+                       elems->timeout_int_len = elen;
+                       break;
                default:
                        break;
                }
@@ -727,12 +740,12 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
        return ret;
 }
 
-u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
+u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
                              enum ieee80211_band band)
 {
        struct ieee80211_supported_band *sband;
        struct ieee80211_rate *bitrates;
-       u64 mandatory_rates;
+       u32 mandatory_rates;
        enum ieee80211_rate_flags mandatory_flag;
        int i;
 
index 7162d5816f39146adbf65a8fac47d6bd2b11ee86..5c88b8246bbb0e0902052bb78baa80fed8cf9709 100644 (file)
@@ -37,7 +37,14 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
        struct ieee80211_key *key;
        int err;
 
-       if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
+       if (alg == ALG_AES_CMAC) {
+               if (idx < NUM_DEFAULT_KEYS ||
+                   idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
+                       printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
+                              "(BIP)\n", sdata->dev->name, idx);
+                       return -EINVAL;
+               }
+       } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
                printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
                       sdata->dev->name, idx);
                return -EINVAL;
@@ -103,6 +110,9 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
 
                if (set_tx_key || (!sta && !sdata->default_key && key))
                        ieee80211_set_default_key(sdata, idx);
+               if (alg == ALG_AES_CMAC &&
+                   (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
+                       ieee80211_set_default_mgmt_key(sdata, idx);
        }
 
  out_unlock:
@@ -230,13 +240,15 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type == NL80211_IFTYPE_STATION)
+       if (sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+           sdata->vif.type == NL80211_IFTYPE_STATION)
                sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
 
        /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
        if (freq->e == 0) {
                if (freq->m < 0) {
-                       if (sdata->vif.type == NL80211_IFTYPE_STATION)
+                       if (sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+                           sdata->vif.type == NL80211_IFTYPE_STATION)
                                sdata->u.sta.flags |=
                                        IEEE80211_STA_AUTO_CHANNEL_SEL;
                        return 0;
@@ -549,10 +561,9 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
        else /* Automatic power level setting */
                new_power_level = chan->max_power;
 
-       if (local->hw.conf.power_level != new_power_level) {
-               local->hw.conf.power_level = new_power_level;
+       local->user_power_level = new_power_level;
+       if (local->hw.conf.power_level != new_power_level)
                reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
-       }
 
        if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
                local->hw.conf.radio_enabled = !(data->txpower.disabled);
@@ -836,6 +847,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
        int ret = 0, timeout = 0;
        bool ps;
 
+       if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+               return -EOPNOTSUPP;
+
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EINVAL;
 
@@ -852,31 +866,49 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
                ps = true;
                break;
        default:                /* Otherwise we ignore */
-               break;
+               return -EINVAL;
        }
 
+       if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
+               return -EINVAL;
+
        if (wrq->flags & IW_POWER_TIMEOUT)
                timeout = wrq->value / 1000;
 
-set:
-       if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
+ set:
+       if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
                return ret;
 
        local->powersave = ps;
-       local->dynamic_ps_timeout = timeout;
+       conf->dynamic_ps_timeout = timeout;
 
-       if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
-               if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
-                   local->dynamic_ps_timeout > 0)
-                       mod_timer(&local->dynamic_ps_timer, jiffies +
-                                 msecs_to_jiffies(local->dynamic_ps_timeout));
-               else {
-                       if (local->powersave)
-                               conf->flags |= IEEE80211_CONF_PS;
-                       else
-                               conf->flags &= ~IEEE80211_CONF_PS;
+       if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+               ret = ieee80211_hw_config(local,
+                                         IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
+
+       if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
+               return ret;
+
+       if (conf->dynamic_ps_timeout > 0 &&
+           !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
+               mod_timer(&local->dynamic_ps_timer, jiffies +
+                         msecs_to_jiffies(conf->dynamic_ps_timeout));
+       } else {
+               if (local->powersave) {
+                       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+                               ieee80211_send_nullfunc(local, sdata, 1);
+                       conf->flags |= IEEE80211_CONF_PS;
+                       ret = ieee80211_hw_config(local,
+                                       IEEE80211_CONF_CHANGE_PS);
+               } else {
+                       conf->flags &= ~IEEE80211_CONF_PS;
+                       ret = ieee80211_hw_config(local,
+                                       IEEE80211_CONF_CHANGE_PS);
+                       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+                               ieee80211_send_nullfunc(local, sdata, 0);
+                       del_timer_sync(&local->dynamic_ps_timer);
+                       cancel_work_sync(&local->dynamic_ps_enable_work);
                }
-               ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
        }
 
        return ret;
@@ -903,11 +935,22 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
 
        switch (data->flags & IW_AUTH_INDEX) {
        case IW_AUTH_WPA_VERSION:
-       case IW_AUTH_CIPHER_PAIRWISE:
        case IW_AUTH_CIPHER_GROUP:
        case IW_AUTH_WPA_ENABLED:
        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
        case IW_AUTH_KEY_MGMT:
+       case IW_AUTH_CIPHER_GROUP_MGMT:
+               break;
+       case IW_AUTH_CIPHER_PAIRWISE:
+               if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+                       if (data->value & (IW_AUTH_CIPHER_WEP40 |
+                           IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
+                               sdata->u.sta.flags |=
+                                       IEEE80211_STA_TKIP_WEP_USED;
+                       else
+                               sdata->u.sta.flags &=
+                                       ~IEEE80211_STA_TKIP_WEP_USED;
+               }
                break;
        case IW_AUTH_DROP_UNENCRYPTED:
                sdata->drop_unencrypted = !!data->value;
@@ -934,6 +977,17 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
                else
                        ret = -EOPNOTSUPP;
                break;
+       case IW_AUTH_MFP:
+               if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+               if (sdata->vif.type == NL80211_IFTYPE_STATION ||
+                   sdata->vif.type == NL80211_IFTYPE_ADHOC)
+                       sdata->u.sta.mfp = data->value;
+               else
+                       ret = -EOPNOTSUPP;
+               break;
        default:
                ret = -EOPNOTSUPP;
                break;
@@ -1017,6 +1071,9 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
        case IW_ENCODE_ALG_CCMP:
                alg = ALG_CCMP;
                break;
+       case IW_ENCODE_ALG_AES_CMAC:
+               alg = ALG_AES_CMAC;
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -1025,20 +1082,41 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
                remove = 1;
 
        idx = erq->flags & IW_ENCODE_INDEX;
-       if (idx < 1 || idx > 4) {
-               idx = -1;
-               if (!sdata->default_key)
-                       idx = 0;
-               else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                       if (sdata->default_key == sdata->keys[i]) {
-                               idx = i;
-                               break;
+       if (alg == ALG_AES_CMAC) {
+               if (idx < NUM_DEFAULT_KEYS + 1 ||
+                   idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
+                       idx = -1;
+                       if (!sdata->default_mgmt_key)
+                               idx = 0;
+                       else for (i = NUM_DEFAULT_KEYS;
+                                 i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
+                                 i++) {
+                               if (sdata->default_mgmt_key == sdata->keys[i])
+                               {
+                                       idx = i;
+                                       break;
+                               }
                        }
-               }
-               if (idx < 0)
-                       return -EINVAL;
-       } else
-               idx--;
+                       if (idx < 0)
+                               return -EINVAL;
+               } else
+                       idx--;
+       } else {
+               if (idx < 1 || idx > 4) {
+                       idx = -1;
+                       if (!sdata->default_key)
+                               idx = 0;
+                       else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                               if (sdata->default_key == sdata->keys[i]) {
+                                       idx = i;
+                                       break;
+                               }
+                       }
+                       if (idx < 0)
+                               return -EINVAL;
+               } else
+                       idx--;
+       }
 
        return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
                                        remove,
index 7aa63caf8d50c3c7c8b2b87b77b9a3515fd5a4ca..9101b48ec2ae69e3a6c0e00e823876f230818e81 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2008, Jouni Malinen <j@w1.fi>
  *
  * 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,6 +20,7 @@
 #include "michael.h"
 #include "tkip.h"
 #include "aes_ccm.h"
+#include "aes_cmac.h"
 #include "wpa.h"
 
 ieee80211_tx_result
@@ -266,7 +268,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
                                int encrypted)
 {
        __le16 mask_fc;
-       int a4_included;
+       int a4_included, mgmt;
        u8 qos_tid;
        u8 *b_0, *aad;
        u16 data_len, len_a;
@@ -277,12 +279,15 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
        aad = scratch + 4 * AES_BLOCK_LEN;
 
        /*
-        * Mask FC: zero subtype b4 b5 b6
+        * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
         * Retry, PwrMgt, MoreData; set Protected
         */
+       mgmt = ieee80211_is_mgmt(hdr->frame_control);
        mask_fc = hdr->frame_control;
-       mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY |
+       mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
                                IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
+       if (!mgmt)
+               mask_fc &= ~cpu_to_le16(0x0070);
        mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -300,8 +305,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 
        /* First block, b_0 */
        b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
-       /* Nonce: QoS Priority | A2 | PN */
-       b_0[1] = qos_tid;
+       /* Nonce: Nonce Flags | A2 | PN
+        * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
+        */
+       b_0[1] = qos_tid | (mgmt << 4);
        memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
        memcpy(&b_0[8], pn, CCMP_PN_LEN);
        /* l(m) */
@@ -360,9 +367,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        int hdrlen, len, tail;
        u8 *pos, *pn;
        int i;
+       bool skip_hw;
+
+       skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) &&
+               ieee80211_is_mgmt(hdr->frame_control);
 
        if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+           !skip_hw) {
                /* hwaccel - with no need for preallocated room for CCMP
                 * header or MIC fields */
                info->control.hw_key = &tx->key->conf;
@@ -397,7 +409,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
        ccmp_pn2hdr(pos, pn, key->conf.keyidx);
 
-       if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+       if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) {
                /* hwaccel - with preallocated room for CCMP header */
                info->control.hw_key = &tx->key->conf;
                return 0;
@@ -446,7 +458,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (!ieee80211_is_data(hdr->frame_control) &&
+           !ieee80211_is_robust_mgmt_frame(hdr))
                return RX_CONTINUE;
 
        data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
@@ -485,3 +498,126 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
        return RX_CONTINUE;
 }
+
+
+static void bip_aad(struct sk_buff *skb, u8 *aad)
+{
+       /* BIP AAD: FC(masked) || A1 || A2 || A3 */
+
+       /* FC type/subtype */
+       aad[0] = skb->data[0];
+       /* Mask FC Retry, PwrMgt, MoreData flags to zero */
+       aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
+       /* A1 || A2 || A3 */
+       memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
+}
+
+
+static inline void bip_ipn_swap(u8 *d, const u8 *s)
+{
+       *d++ = s[5];
+       *d++ = s[4];
+       *d++ = s[3];
+       *d++ = s[2];
+       *d++ = s[1];
+       *d = s[0];
+}
+
+
+ieee80211_tx_result
+ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
+{
+       struct sk_buff *skb = tx->skb;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_key *key = tx->key;
+       struct ieee80211_mmie *mmie;
+       u8 *pn, aad[20];
+       int i;
+
+       if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+               /* hwaccel */
+               info->control.hw_key = &tx->key->conf;
+               return 0;
+       }
+
+       if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
+               return TX_DROP;
+
+       mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie));
+       mmie->element_id = WLAN_EID_MMIE;
+       mmie->length = sizeof(*mmie) - 2;
+       mmie->key_id = cpu_to_le16(key->conf.keyidx);
+
+       /* PN = PN + 1 */
+       pn = key->u.aes_cmac.tx_pn;
+
+       for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) {
+               pn[i]++;
+               if (pn[i])
+                       break;
+       }
+       bip_ipn_swap(mmie->sequence_number, pn);
+
+       bip_aad(skb, aad);
+
+       /*
+        * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
+        */
+       ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf,
+                          aad, skb->data + 24, skb->len - 24, mmie->mic);
+
+       return TX_CONTINUE;
+}
+
+
+ieee80211_rx_result
+ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
+{
+       struct sk_buff *skb = rx->skb;
+       struct ieee80211_key *key = rx->key;
+       struct ieee80211_mmie *mmie;
+       u8 aad[20], mic[8], ipn[6];
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+       if (!ieee80211_is_mgmt(hdr->frame_control))
+               return RX_CONTINUE;
+
+       if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
+           (rx->status->flag & RX_FLAG_IV_STRIPPED))
+               return RX_CONTINUE;
+
+       if (skb->len < 24 + sizeof(*mmie))
+               return RX_DROP_UNUSABLE;
+
+       mmie = (struct ieee80211_mmie *)
+               (skb->data + skb->len - sizeof(*mmie));
+       if (mmie->element_id != WLAN_EID_MMIE ||
+           mmie->length != sizeof(*mmie) - 2)
+               return RX_DROP_UNUSABLE; /* Invalid MMIE */
+
+       bip_ipn_swap(ipn, mmie->sequence_number);
+
+       if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
+               key->u.aes_cmac.replays++;
+               return RX_DROP_UNUSABLE;
+       }
+
+       if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+               /* hardware didn't decrypt/verify MIC */
+               bip_aad(skb, aad);
+               ieee80211_aes_cmac(key->u.aes_cmac.tfm,
+                                  key->u.aes_cmac.rx_crypto_buf, aad,
+                                  skb->data + 24, skb->len - 24, mic);
+               if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+                       key->u.aes_cmac.icverrors++;
+                       return RX_DROP_UNUSABLE;
+               }
+       }
+
+       memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
+
+       /* Remove MMIE */
+       skb_trim(skb, skb->len - sizeof(*mmie));
+
+       return RX_CONTINUE;
+}
index d42d221d8a1dc324ce707bb1146864c0f8799148..baba0608313ef5419cccff809d28166b1178bf7b 100644 (file)
@@ -28,4 +28,9 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
 ieee80211_rx_result
 ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
 
+ieee80211_tx_result
+ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);
+ieee80211_rx_result
+ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
+
 #endif /* WPA_H */
index 6be5d4efa51ba58c9f13bb40b475bcb58c6795ca..5c48378a852fba2bf9f27156774daf02d67442e4 100644 (file)
@@ -149,8 +149,8 @@ static struct task_struct *sync_backup_thread;
 /* multicast addr */
 static struct sockaddr_in mcast_addr = {
        .sin_family             = AF_INET,
-       .sin_port               = __constant_htons(IP_VS_SYNC_PORT),
-       .sin_addr.s_addr        = __constant_htonl(IP_VS_SYNC_GROUP),
+       .sin_port               = cpu_to_be16(IP_VS_SYNC_PORT),
+       .sin_addr.s_addr        = cpu_to_be32(IP_VS_SYNC_GROUP),
 };
 
 
index 4f8fcf498545f302105535bfebaf34b9755908fe..07d9d8857e5db50b2d80bca709e137c4472b8724 100644 (file)
@@ -177,7 +177,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
                .me                     = THIS_MODULE,
                .help                   = amanda_help,
                .tuple.src.l3num        = AF_INET,
-               .tuple.src.u.udp.port   = __constant_htons(10080),
+               .tuple.src.u.udp.port   = cpu_to_be16(10080),
                .tuple.dst.protonum     = IPPROTO_UDP,
                .expect_policy          = &amanda_exp_policy,
        },
@@ -186,7 +186,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
                .me                     = THIS_MODULE,
                .help                   = amanda_help,
                .tuple.src.l3num        = AF_INET6,
-               .tuple.src.u.udp.port   = __constant_htons(10080),
+               .tuple.src.u.udp.port   = cpu_to_be16(10080),
                .tuple.dst.protonum     = IPPROTO_UDP,
                .expect_policy          = &amanda_exp_policy,
        },
index 687bd633c3d7020c277ba0f25b6e3033fd5053c7..66369490230e03eab8ac592365f296bc44704c7f 100644 (file)
@@ -1167,7 +1167,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
                .name                   = "Q.931",
                .me                     = THIS_MODULE,
                .tuple.src.l3num        = AF_INET,
-               .tuple.src.u.tcp.port   = __constant_htons(Q931_PORT),
+               .tuple.src.u.tcp.port   = cpu_to_be16(Q931_PORT),
                .tuple.dst.protonum     = IPPROTO_TCP,
                .help                   = q931_help,
                .expect_policy          = &q931_exp_policy,
@@ -1176,7 +1176,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
                .name                   = "Q.931",
                .me                     = THIS_MODULE,
                .tuple.src.l3num        = AF_INET6,
-               .tuple.src.u.tcp.port   = __constant_htons(Q931_PORT),
+               .tuple.src.u.tcp.port   = cpu_to_be16(Q931_PORT),
                .tuple.dst.protonum     = IPPROTO_TCP,
                .help                   = q931_help,
                .expect_policy          = &q931_exp_policy,
@@ -1741,7 +1741,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
                .name                   = "RAS",
                .me                     = THIS_MODULE,
                .tuple.src.l3num        = AF_INET,
-               .tuple.src.u.udp.port   = __constant_htons(RAS_PORT),
+               .tuple.src.u.udp.port   = cpu_to_be16(RAS_PORT),
                .tuple.dst.protonum     = IPPROTO_UDP,
                .help                   = ras_help,
                .expect_policy          = &ras_exp_policy,
@@ -1750,7 +1750,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
                .name                   = "RAS",
                .me                     = THIS_MODULE,
                .tuple.src.l3num        = AF_INET6,
-               .tuple.src.u.udp.port   = __constant_htons(RAS_PORT),
+               .tuple.src.u.udp.port   = cpu_to_be16(RAS_PORT),
                .tuple.dst.protonum     = IPPROTO_UDP,
                .help                   = ras_help,
                .expect_policy          = &ras_exp_policy,
index 5af4273b4668c3bf53b0ea1dc1937ed973831610..8a3875e36ec2d37ffbfa197fc4226e41a4a12fe4 100644 (file)
@@ -105,7 +105,7 @@ static struct nf_conntrack_expect_policy exp_policy = {
 static struct nf_conntrack_helper helper __read_mostly = {
        .name                   = "netbios-ns",
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.udp.port   = __constant_htons(NMBD_PORT),
+       .tuple.src.u.udp.port   = cpu_to_be16(NMBD_PORT),
        .tuple.dst.protonum     = IPPROTO_UDP,
        .me                     = THIS_MODULE,
        .help                   = help,
index 9e169ef2e85443eaff5c8224ccbeaad1d0f4a202..72cca638a82d1008eddfcc7318a0f74f2c433cb2 100644 (file)
@@ -591,7 +591,7 @@ static struct nf_conntrack_helper pptp __read_mostly = {
        .name                   = "pptp",
        .me                     = THIS_MODULE,
        .tuple.src.l3num        = AF_INET,
-       .tuple.src.u.tcp.port   = __constant_htons(PPTP_CONTROL_PORT),
+       .tuple.src.u.tcp.port   = cpu_to_be16(PPTP_CONTROL_PORT),
        .tuple.dst.protonum     = IPPROTO_TCP,
        .help                   = conntrack_pptp_help,
        .destroy                = pptp_destroy_siblings,
index e9c05b8f4f4517fc5b13b6295eebfd1cf75e0a1c..cba7849de98e26988d93bd4ee6058be4ce7f0558 100644 (file)
@@ -1432,7 +1432,7 @@ static int __init nr_proto_init(void)
                struct net_device *dev;
 
                sprintf(name, "nr%d", i);
-               dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup);
+               dev = alloc_netdev(0, name, nr_setup);
                if (!dev) {
                        printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
                        goto fail;
index 6caf459665f2c78e5d1f1b35344c227bdd5da813..351372463fedd23f5c61bd9b016cb8337c800f07 100644 (file)
@@ -42,7 +42,7 @@
 
 int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
 {
-       struct net_device_stats *stats = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
 
        if (!netif_running(dev)) {
                stats->rx_dropped++;
@@ -171,8 +171,7 @@ static int nr_close(struct net_device *dev)
 
 static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct nr_private *nr = netdev_priv(dev);
-       struct net_device_stats *stats = &nr->stats;
+       struct net_device_stats *stats = &dev->stats;
        unsigned int len = skb->len;
 
        if (!nr_route_frame(skb, NULL)) {
@@ -187,34 +186,27 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *nr_get_stats(struct net_device *dev)
-{
-       struct nr_private *nr = netdev_priv(dev);
-
-       return &nr->stats;
-}
-
 static const struct header_ops nr_header_ops = {
        .create = nr_header,
        .rebuild= nr_rebuild_header,
 };
 
+static const struct net_device_ops nr_netdev_ops = {
+       .ndo_open               = nr_open,
+       .ndo_stop               = nr_close,
+       .ndo_start_xmit         = nr_xmit,
+       .ndo_set_mac_address    = nr_set_mac_address,
+};
 
 void nr_setup(struct net_device *dev)
 {
        dev->mtu                = NR_MAX_PACKET_SIZE;
-       dev->hard_start_xmit    = nr_xmit;
-       dev->open               = nr_open;
-       dev->stop               = nr_close;
-
+       dev->netdev_ops         = &nr_netdev_ops;
        dev->header_ops         = &nr_header_ops;
        dev->hard_header_len    = NR_NETWORK_LEN + NR_TRANSPORT_LEN;
        dev->addr_len           = AX25_ADDR_LEN;
        dev->type               = ARPHRD_NETROM;
-       dev->set_mac_address    = nr_set_mac_address;
 
        /* New-style flags. */
        dev->flags              = IFF_NOARP;
-
-       dev->get_stats          = nr_get_stats;
 }
index 13cb323f8c382bad79f287bb5636ed0ee34271df..81795ea87794af8b10540451313c5969e0beb4d7 100644 (file)
@@ -275,8 +275,6 @@ static inline int can_respond(struct sk_buff *skb)
                return 0;
 
        ph = pn_hdr(skb);
-       if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev)
-               return 0; /* we are not the destination */
        if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5))
                return 0;
        if (ph->pn_res == PN_COMMGR) /* indications */
@@ -344,8 +342,8 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
                        struct packet_type *pkttype,
                        struct net_device *orig_dev)
 {
+       struct net *net = dev_net(dev);
        struct phonethdr *ph;
-       struct sock *sk;
        struct sockaddr_pn sa;
        u16 len;
 
@@ -364,28 +362,28 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
        skb_reset_transport_header(skb);
 
        pn_skb_get_dst_sockaddr(skb, &sa);
-       if (pn_sockaddr_get_addr(&sa) == 0)
-               goto out; /* currently, we cannot be device 0 */
 
-       sk = pn_find_sock_by_sa(dev_net(dev), &sa);
-       if (sk == NULL) {
+       /* check if we are the destination */
+       if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) {
+               /* Phonet packet input */
+               struct sock *sk = pn_find_sock_by_sa(net, &sa);
+
+               if (sk)
+                       return sk_receive_skb(sk, skb, 0);
+
                if (can_respond(skb)) {
                        send_obj_unreachable(skb);
                        send_reset_indications(skb);
                }
-               goto out;
        }
 
-       /* Push data to the socket (or other sockets connected to it). */
-       return sk_receive_skb(sk, skb, 0);
-
 out:
        kfree_skb(skb);
        return NET_RX_DROP;
 }
 
 static struct packet_type phonet_packet_type = {
-       .type = __constant_htons(ETH_P_PHONET),
+       .type = cpu_to_be16(ETH_P_PHONET),
        .dev = NULL,
        .func = phonet_rcv,
 };
@@ -428,16 +426,18 @@ static int __init phonet_init(void)
 {
        int err;
 
+       err = phonet_device_init();
+       if (err)
+               return err;
+
        err = sock_register(&phonet_proto_family);
        if (err) {
                printk(KERN_ALERT
                        "phonet protocol family initialization failed\n");
-               return err;
+               goto err_sock;
        }
 
-       phonet_device_init();
        dev_add_pack(&phonet_packet_type);
-       phonet_netlink_register();
        phonet_sysctl_init();
 
        err = isi_register();
@@ -449,6 +449,7 @@ err:
        phonet_sysctl_exit();
        sock_unregister(PF_PHONET);
        dev_remove_pack(&phonet_packet_type);
+err_sock:
        phonet_device_exit();
        return err;
 }
index 5491bf5e354bbe20b7eb33a078e2a710e4d10d0b..80a322d77909ac0d96000486580f20d2946fcbd3 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/phonet.h>
 #include <net/sock.h>
+#include <net/netns/generic.h>
 #include <net/phonet/pn_dev.h>
 
-/* when accessing, remember to lock with spin_lock(&pndevs.lock); */
-struct phonet_device_list pndevs = {
-       .list = LIST_HEAD_INIT(pndevs.list),
-       .lock = __SPIN_LOCK_UNLOCKED(pndevs.lock),
+struct phonet_net {
+       struct phonet_device_list pndevs;
 };
 
+int phonet_net_id;
+
+struct phonet_device_list *phonet_device_list(struct net *net)
+{
+       struct phonet_net *pnn = net_generic(net, phonet_net_id);
+       return &pnn->pndevs;
+}
+
 /* Allocate new Phonet device. */
 static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
        struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC);
        if (pnd == NULL)
                return NULL;
        pnd->netdev = dev;
        bitmap_zero(pnd->addrs, 64);
 
-       list_add(&pnd->list, &pndevs.list);
+       list_add(&pnd->list, &pndevs->list);
        return pnd;
 }
 
 static struct phonet_device *__phonet_get(struct net_device *dev)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
        struct phonet_device *pnd;
 
-       list_for_each_entry(pnd, &pndevs.list, list) {
+       list_for_each_entry(pnd, &pndevs->list, list) {
                if (pnd->netdev == dev)
                        return pnd;
        }
@@ -68,32 +77,33 @@ static void __phonet_device_free(struct phonet_device *pnd)
 
 struct net_device *phonet_device_get(struct net *net)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(net);
        struct phonet_device *pnd;
        struct net_device *dev;
 
-       spin_lock_bh(&pndevs.lock);
-       list_for_each_entry(pnd, &pndevs.list, list) {
+       spin_lock_bh(&pndevs->lock);
+       list_for_each_entry(pnd, &pndevs->list, list) {
                dev = pnd->netdev;
                BUG_ON(!dev);
 
-               if (net_eq(dev_net(dev), net) &&
-                       (dev->reg_state == NETREG_REGISTERED) &&
+               if ((dev->reg_state == NETREG_REGISTERED) &&
                        ((pnd->netdev->flags & IFF_UP)) == IFF_UP)
                        break;
                dev = NULL;
        }
        if (dev)
                dev_hold(dev);
-       spin_unlock_bh(&pndevs.lock);
+       spin_unlock_bh(&pndevs->lock);
        return dev;
 }
 
 int phonet_address_add(struct net_device *dev, u8 addr)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
        struct phonet_device *pnd;
        int err = 0;
 
-       spin_lock_bh(&pndevs.lock);
+       spin_lock_bh(&pndevs->lock);
        /* Find or create Phonet-specific device data */
        pnd = __phonet_get(dev);
        if (pnd == NULL)
@@ -102,31 +112,33 @@ int phonet_address_add(struct net_device *dev, u8 addr)
                err = -ENOMEM;
        else if (test_and_set_bit(addr >> 2, pnd->addrs))
                err = -EEXIST;
-       spin_unlock_bh(&pndevs.lock);
+       spin_unlock_bh(&pndevs->lock);
        return err;
 }
 
 int phonet_address_del(struct net_device *dev, u8 addr)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
        struct phonet_device *pnd;
        int err = 0;
 
-       spin_lock_bh(&pndevs.lock);
+       spin_lock_bh(&pndevs->lock);
        pnd = __phonet_get(dev);
        if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs))
                err = -EADDRNOTAVAIL;
        else if (bitmap_empty(pnd->addrs, 64))
                __phonet_device_free(pnd);
-       spin_unlock_bh(&pndevs.lock);
+       spin_unlock_bh(&pndevs->lock);
        return err;
 }
 
 /* Gets a source address toward a destination, through a interface. */
 u8 phonet_address_get(struct net_device *dev, u8 addr)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
        struct phonet_device *pnd;
 
-       spin_lock_bh(&pndevs.lock);
+       spin_lock_bh(&pndevs->lock);
        pnd = __phonet_get(dev);
        if (pnd) {
                BUG_ON(bitmap_empty(pnd->addrs, 64));
@@ -136,30 +148,31 @@ u8 phonet_address_get(struct net_device *dev, u8 addr)
                        addr = find_first_bit(pnd->addrs, 64) << 2;
        } else
                addr = PN_NO_ADDR;
-       spin_unlock_bh(&pndevs.lock);
+       spin_unlock_bh(&pndevs->lock);
        return addr;
 }
 
 int phonet_address_lookup(struct net *net, u8 addr)
 {
+       struct phonet_device_list *pndevs = phonet_device_list(net);
        struct phonet_device *pnd;
+       int err = -EADDRNOTAVAIL;
 
-       spin_lock_bh(&pndevs.lock);
-       list_for_each_entry(pnd, &pndevs.list, list) {
-               if (!net_eq(dev_net(pnd->netdev), net))
-                       continue;
+       spin_lock_bh(&pndevs->lock);
+       list_for_each_entry(pnd, &pndevs->list, list) {
                /* Don't allow unregistering devices! */
                if ((pnd->netdev->reg_state != NETREG_REGISTERED) ||
                                ((pnd->netdev->flags & IFF_UP)) != IFF_UP)
                        continue;
 
                if (test_bit(addr >> 2, pnd->addrs)) {
-                       spin_unlock_bh(&pndevs.lock);
-                       return 0;
+                       err = 0;
+                       goto found;
                }
        }
-       spin_unlock_bh(&pndevs.lock);
-       return -EADDRNOTAVAIL;
+found:
+       spin_unlock_bh(&pndevs->lock);
+       return err;
 }
 
 /* notify Phonet of device events */
@@ -169,14 +182,16 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what,
        struct net_device *dev = arg;
 
        if (what == NETDEV_UNREGISTER) {
+               struct phonet_device_list *pndevs;
                struct phonet_device *pnd;
 
                /* Destroy phonet-specific device data */
-               spin_lock_bh(&pndevs.lock);
+               pndevs = phonet_device_list(dev_net(dev));
+               spin_lock_bh(&pndevs->lock);
                pnd = __phonet_get(dev);
                if (pnd)
                        __phonet_device_free(pnd);
-               spin_unlock_bh(&pndevs.lock);
+               spin_unlock_bh(&pndevs->lock);
        }
        return 0;
 
@@ -187,24 +202,52 @@ static struct notifier_block phonet_device_notifier = {
        .priority = 0,
 };
 
-/* Initialize Phonet devices list */
-void phonet_device_init(void)
+/* Per-namespace Phonet devices handling */
+static int phonet_init_net(struct net *net)
 {
-       register_netdevice_notifier(&phonet_device_notifier);
+       struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
+       if (!pnn)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&pnn->pndevs.list);
+       spin_lock_init(&pnn->pndevs.lock);
+       net_assign_generic(net, phonet_net_id, pnn);
+       return 0;
 }
 
-void phonet_device_exit(void)
+static void phonet_exit_net(struct net *net)
 {
+       struct phonet_net *pnn = net_generic(net, phonet_net_id);
        struct phonet_device *pnd, *n;
 
-       rtnl_unregister_all(PF_PHONET);
-       rtnl_lock();
-       spin_lock_bh(&pndevs.lock);
-
-       list_for_each_entry_safe(pnd, n, &pndevs.list, list)
+       list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list)
                __phonet_device_free(pnd);
 
-       spin_unlock_bh(&pndevs.lock);
-       rtnl_unlock();
+       kfree(pnn);
+}
+
+static struct pernet_operations phonet_net_ops = {
+       .init = phonet_init_net,
+       .exit = phonet_exit_net,
+};
+
+/* Initialize Phonet devices list */
+int __init phonet_device_init(void)
+{
+       int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops);
+       if (err)
+               return err;
+
+       register_netdevice_notifier(&phonet_device_notifier);
+       err = phonet_netlink_register();
+       if (err)
+               phonet_device_exit();
+       return err;
+}
+
+void phonet_device_exit(void)
+{
+       rtnl_unregister_all(PF_PHONET);
        unregister_netdevice_notifier(&phonet_device_notifier);
+       unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops);
 }
index 242fe8f8c322d5fb048d737a46d36b99797f47aa..1ceea1f92413d2d4b03d545152f339e628ab9b33 100644 (file)
@@ -123,17 +123,16 @@ nla_put_failure:
 
 static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct net *net = sock_net(skb->sk);
+       struct phonet_device_list *pndevs;
        struct phonet_device *pnd;
        int dev_idx = 0, dev_start_idx = cb->args[0];
        int addr_idx = 0, addr_start_idx = cb->args[1];
 
-       spin_lock_bh(&pndevs.lock);
-       list_for_each_entry(pnd, &pndevs.list, list) {
+       pndevs = phonet_device_list(sock_net(skb->sk));
+       spin_lock_bh(&pndevs->lock);
+       list_for_each_entry(pnd, &pndevs->list, list) {
                u8 addr;
 
-               if (!net_eq(dev_net(pnd->netdev), net))
-                       continue;
                if (dev_idx > dev_start_idx)
                        addr_start_idx = 0;
                if (dev_idx++ < dev_start_idx)
@@ -153,16 +152,21 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
        }
 
 out:
-       spin_unlock_bh(&pndevs.lock);
+       spin_unlock_bh(&pndevs->lock);
        cb->args[0] = dev_idx;
        cb->args[1] = addr_idx;
 
        return skb->len;
 }
 
-void __init phonet_netlink_register(void)
+int __init phonet_netlink_register(void)
 {
-       rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
-       rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
-       rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
+       int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
+       if (err)
+               return err;
+
+       /* Further __rtnl_register() cannot fail */
+       __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
+       __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
+       return 0;
 }
index 01392649b4626d930eaba64175a5e50f1dc1f57c..6501396265819eec021f89eade0f4f7e1551bdfe 100644 (file)
@@ -1587,8 +1587,7 @@ static int __init rose_proto_init(void)
                char name[IFNAMSIZ];
 
                sprintf(name, "rose%d", i);
-               dev = alloc_netdev(sizeof(struct net_device_stats),
-                                  name, rose_setup);
+               dev = alloc_netdev(0, name, rose_setup);
                if (!dev) {
                        printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
                        rc = -ENOMEM;
index 12cfcf09556ba25a22185b99a25060a24548312e..7dcf2569613b612eb3a19f9777cbc71edaed902a 100644 (file)
@@ -57,7 +57,7 @@ static int rose_rebuild_header(struct sk_buff *skb)
 {
 #ifdef CONFIG_INET
        struct net_device *dev = skb->dev;
-       struct net_device_stats *stats = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
        unsigned char *bp = (unsigned char *)skb->data;
        struct sk_buff *skbn;
        unsigned int len;
@@ -133,7 +133,7 @@ static int rose_close(struct net_device *dev)
 
 static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct net_device_stats *stats = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
 
        if (!netif_running(dev)) {
                printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
@@ -144,30 +144,28 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *rose_get_stats(struct net_device *dev)
-{
-       return netdev_priv(dev);
-}
-
 static const struct header_ops rose_header_ops = {
        .create = rose_header,
        .rebuild= rose_rebuild_header,
 };
 
+static const struct net_device_ops rose_netdev_ops = {
+       .ndo_open               = rose_open,
+       .ndo_stop               = rose_close,
+       .ndo_start_xmit         = rose_xmit,
+       .ndo_set_mac_address    = rose_set_mac_address,
+};
+
 void rose_setup(struct net_device *dev)
 {
        dev->mtu                = ROSE_MAX_PACKET_SIZE - 2;
-       dev->hard_start_xmit    = rose_xmit;
-       dev->open               = rose_open;
-       dev->stop               = rose_close;
+       dev->netdev_ops         = &rose_netdev_ops;
 
        dev->header_ops         = &rose_header_ops;
        dev->hard_header_len    = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
        dev->addr_len           = ROSE_ADDR_LEN;
        dev->type               = ARPHRD_ROSE;
-       dev->set_mac_address    = rose_set_mac_address;
 
        /* New-style flags. */
        dev->flags              = IFF_NOARP;
-       dev->get_stats = rose_get_stats;
 }
index 0fc4a18fd96f7d83ec21e95bc6d0740025f6a219..32009793307be7fb39d969aa5fb029e03e01a1f6 100644 (file)
@@ -444,6 +444,17 @@ out:
 }
 EXPORT_SYMBOL(qdisc_calculate_pkt_len);
 
+void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc)
+{
+       if (!(qdisc->flags & TCQ_F_WARN_NONWC)) {
+               printk(KERN_WARNING
+                      "%s: %s qdisc %X: is non-work-conserving?\n",
+                      txt, qdisc->ops->id, qdisc->handle >> 16);
+               qdisc->flags |= TCQ_F_WARN_NONWC;
+       }
+}
+EXPORT_SYMBOL(qdisc_warn_nonwc);
+
 static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
 {
        struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
index 45c31b1a4e1dd0b488e6f6e20cc966e7aad70467..74226b265528cb9d2e37a5aed39cb48dc0c2f6db 100644 (file)
@@ -887,8 +887,7 @@ qdisc_peek_len(struct Qdisc *sch)
 
        skb = sch->ops->peek(sch);
        if (skb == NULL) {
-               if (net_ratelimit())
-                       printk("qdisc_peek_len: non work-conserving qdisc ?\n");
+               qdisc_warn_nonwc("qdisc_peek_len", sch);
                return 0;
        }
        len = qdisc_pkt_len(skb);
@@ -1642,8 +1641,7 @@ hfsc_dequeue(struct Qdisc *sch)
 
        skb = qdisc_dequeue_peeked(cl->qdisc);
        if (skb == NULL) {
-               if (net_ratelimit())
-                       printk("HFSC: Non-work-conserving qdisc ?\n");
+               qdisc_warn_nonwc("HFSC", cl->qdisc);
                return NULL;
        }
 
index 2f0f0b04d3fb127efa75b362beeb62c9aab11bde..355974f610c5946286eadbbcb978b337061698e8 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/list.h>
 #include <linux/compiler.h>
 #include <linux/rbtree.h>
+#include <linux/workqueue.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 
@@ -114,8 +115,6 @@ struct htb_class {
        struct tcf_proto *filter_list;
        int filter_cnt;
 
-       int warned;             /* only one warning about non work conserving .. */
-
        /* token bucket parameters */
        struct qdisc_rate_table *rate;  /* rate table of the class itself */
        struct qdisc_rate_table *ceil;  /* ceiling rate (limits borrows too) */
@@ -155,6 +154,10 @@ struct htb_sched {
        int direct_qlen;        /* max qlen of above */
 
        long direct_pkts;
+
+#define HTB_WARN_TOOMANYEVENTS 0x1
+       unsigned int warned;    /* only one warning */
+       struct work_struct work;
 };
 
 /* find class in global hash table using given handle */
@@ -658,7 +661,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
  * htb_do_events - make mode changes to classes at the level
  *
  * Scans event queue for pending events and applies them. Returns time of
- * next pending event (0 for no event in pq).
+ * next pending event (0 for no event in pq, q->now for too many events).
  * Note: Applied are events whose have cl->pq_key <= q->now.
  */
 static psched_time_t htb_do_events(struct htb_sched *q, int level,
@@ -686,8 +689,14 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
                if (cl->cmode != HTB_CAN_SEND)
                        htb_add_to_wait_tree(q, cl, diff);
        }
-       /* too much load - let's continue on next jiffie (including above) */
-       return q->now + 2 * PSCHED_TICKS_PER_SEC / HZ;
+
+       /* too much load - let's continue after a break for scheduling */
+       if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
+               printk(KERN_WARNING "htb: too many events!\n");
+               q->warned |= HTB_WARN_TOOMANYEVENTS;
+       }
+
+       return q->now;
 }
 
 /* Returns class->node+prio from id-tree where classe's id is >= id. NULL
@@ -809,13 +818,8 @@ next:
                skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
                if (likely(skb != NULL))
                        break;
-               if (!cl->warned) {
-                       printk(KERN_WARNING
-                              "htb: class %X isn't work conserving ?!\n",
-                              cl->common.classid);
-                       cl->warned = 1;
-               }
 
+               qdisc_warn_nonwc("htb", cl->un.leaf.q);
                htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
                                  ptr[0]) + prio);
                cl = htb_lookup_leaf(q->row[level] + prio, prio,
@@ -892,7 +896,10 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
                }
        }
        sch->qstats.overlimits++;
-       qdisc_watchdog_schedule(&q->watchdog, next_event);
+       if (likely(next_event > q->now))
+               qdisc_watchdog_schedule(&q->watchdog, next_event);
+       else
+               schedule_work(&q->work);
 fin:
        return skb;
 }
@@ -962,6 +969,14 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
        [TCA_HTB_RTAB]  = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
 };
 
+static void htb_work_func(struct work_struct *work)
+{
+       struct htb_sched *q = container_of(work, struct htb_sched, work);
+       struct Qdisc *sch = q->watchdog.qdisc;
+
+       __netif_schedule(qdisc_root(sch));
+}
+
 static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 {
        struct htb_sched *q = qdisc_priv(sch);
@@ -996,6 +1011,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
                INIT_LIST_HEAD(q->drops + i);
 
        qdisc_watchdog_init(&q->watchdog, sch);
+       INIT_WORK(&q->work, htb_work_func);
        skb_queue_head_init(&q->direct_queue);
 
        q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
@@ -1188,7 +1204,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
        kfree(cl);
 }
 
-/* always caled under BH & queue lock */
 static void htb_destroy(struct Qdisc *sch)
 {
        struct htb_sched *q = qdisc_priv(sch);
@@ -1196,6 +1211,7 @@ static void htb_destroy(struct Qdisc *sch)
        struct htb_class *cl;
        unsigned int i;
 
+       cancel_work_sync(&q->work);
        qdisc_watchdog_cancel(&q->watchdog);
        /* This line used to be after htb_destroy_class call below
           and surprisingly it worked in 2.4. But it must precede it
index ceaa4aa066eaea3e00162d200f6d9bcb0c1d31f3..786227566696354bce2ef9e6d902b96875fe2ea6 100644 (file)
@@ -97,8 +97,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
                        addr->a.v6.sin6_port = 0;
-                       memcpy(&addr->a.v6.sin6_addr, &ifa->addr,
-                                sizeof(struct in6_addr));
+                       ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifa->addr);
                        addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
                        addr->valid = 1;
                        spin_lock_bh(&sctp_local_addr_lock);
index 73639355157e8bea9659b5539fb2d83f6c67a919..47bfba6c03ecf66996b94b229a5849a5e8e23220 100644 (file)
@@ -367,7 +367,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        struct sctp_transport *tp = packet->transport;
        struct sctp_association *asoc = tp->asoc;
        struct sctphdr *sh;
-       __be32 crc32 = __constant_cpu_to_be32(0);
+       __be32 crc32 = cpu_to_be32(0);
        struct sk_buff *nskb;
        struct sctp_chunk *chunk, *tmp;
        struct sock *sk;
index fd8acb48c3f2827f069c36b8ef01e0fd34f14349..b40e95f9851b243870f2c1306c730ee7ff72e215 100644 (file)
@@ -100,11 +100,11 @@ int sctp_chunk_iif(const struct sctp_chunk *chunk)
  */
 static const struct sctp_paramhdr ecap_param = {
        SCTP_PARAM_ECN_CAPABLE,
-       __constant_htons(sizeof(struct sctp_paramhdr)),
+       cpu_to_be16(sizeof(struct sctp_paramhdr)),
 };
 static const struct sctp_paramhdr prsctp_param = {
        SCTP_PARAM_FWD_TSN_SUPPORT,
-       __constant_htons(sizeof(struct sctp_paramhdr)),
+       cpu_to_be16(sizeof(struct sctp_paramhdr)),
 };
 
 /* A helper to initialize to initialize an op error inside a
index b96fc0c3f1c446132cf71e3e0464a6a2ff4edd84..12522647608917c400d2fb905f04863930f65bcc 100644 (file)
@@ -273,10 +273,16 @@ int wiphy_register(struct wiphy *wiphy)
 
                sband->band = band;
 
-               if (!sband->n_channels || !sband->n_bitrates) {
-                       WARN_ON(1);
+               if (WARN_ON(!sband->n_channels || !sband->n_bitrates))
+                       return -EINVAL;
+
+               /*
+                * Since we use a u32 for rate bitmaps in
+                * ieee80211_get_response_rate, we cannot
+                * have more than 32 legacy rates.
+                */
+               if (WARN_ON(sband->n_bitrates > 32))
                        return -EINVAL;
-               }
 
                for (i = 0; i < sband->n_channels; i++) {
                        sband->channels[i].orig_flags =
index 1e728fff474eb97bce9c983fac4afbc005f66fd1..e69da8d204740ecb0f51789f0f385f1fe35a9c9a 100644 (file)
@@ -105,6 +105,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
 
        [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
                                         .len = NL80211_HT_CAPABILITY_LEN },
+
+       [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
+       [NL80211_ATTR_IE] = { .type = NLA_BINARY,
+                             .len = IEEE80211_MAX_DATA_LEN },
 };
 
 /* message building helper */
@@ -738,7 +742,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_KEY_IDX])
                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 
-       if (key_idx > 3)
+       if (key_idx > 5)
                return -EINVAL;
 
        if (info->attrs[NL80211_ATTR_MAC])
@@ -804,30 +808,41 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
        int err;
        struct net_device *dev;
        u8 key_idx;
+       int (*func)(struct wiphy *wiphy, struct net_device *netdev,
+                   u8 key_index);
 
        if (!info->attrs[NL80211_ATTR_KEY_IDX])
                return -EINVAL;
 
        key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 
-       if (key_idx > 3)
+       if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) {
+               if (key_idx < 4 || key_idx > 5)
+                       return -EINVAL;
+       } else if (key_idx > 3)
                return -EINVAL;
 
        /* currently only support setting default key */
-       if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
+       if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] &&
+           !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
                return -EINVAL;
 
        err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
        if (err)
                return err;
 
-       if (!drv->ops->set_default_key) {
+       if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
+               func = drv->ops->set_default_key;
+       else
+               func = drv->ops->set_default_mgmt_key;
+
+       if (!func) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
        rtnl_lock();
-       err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
+       err = func(&drv->wiphy, dev, key_idx);
        rtnl_unlock();
 
  out:
@@ -863,7 +878,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_MAC])
                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       if (key_idx > 3)
+       if (key_idx > 5)
                return -EINVAL;
 
        /*
@@ -894,6 +909,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
                if (params.key_len != 13)
                        return -EINVAL;
                break;
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+               if (params.key_len != 16)
+                       return -EINVAL;
+               break;
        default:
                return -EINVAL;
        }
@@ -928,7 +947,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_KEY_IDX])
                key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
 
-       if (key_idx > 3)
+       if (key_idx > 5)
                return -EINVAL;
 
        if (info->attrs[NL80211_ATTR_MAC])
@@ -1889,6 +1908,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
        mutex_lock(&cfg80211_drv_mutex);
        r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY);
        mutex_unlock(&cfg80211_drv_mutex);
+       /* This means the regulatory domain was already set, however
+        * we don't want to confuse userspace with a "successful error"
+        * message so lets just treat it as a success */
+       if (r == -EALREADY)
+               r = 0;
        return r;
 }
 
@@ -2134,6 +2158,43 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
        return -EINVAL;
 }
 
+static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb,
+                                    struct genl_info *info)
+{
+       struct cfg80211_registered_device *drv;
+       int err;
+       struct net_device *dev;
+       struct mgmt_extra_ie_params params;
+
+       memset(&params, 0, sizeof(params));
+
+       if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE])
+               return -EINVAL;
+       params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
+       if (params.subtype > 15)
+               return -EINVAL; /* FC Subtype field is 4 bits (0..15) */
+
+       if (info->attrs[NL80211_ATTR_IE]) {
+               params.ies = nla_data(info->attrs[NL80211_ATTR_IE]);
+               params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+       }
+
+       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       if (err)
+               return err;
+
+       if (drv->ops->set_mgmt_extra_ie) {
+               rtnl_lock();
+               err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, &params);
+               rtnl_unlock();
+       } else
+               err = -EOPNOTSUPP;
+
+       cfg80211_put_dev(drv);
+       dev_put(dev);
+       return err;
+}
+
 static struct genl_ops nl80211_ops[] = {
        {
                .cmd = NL80211_CMD_GET_WIPHY,
@@ -2295,6 +2356,12 @@ static struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
        },
+       {
+               .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE,
+               .doit = nl80211_set_mgmt_extra_ie,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+       },
 };
 
 /* multicast groups */
index 85c9034c59b276fb3a3606f3845e81ea714bc1c5..f643d39811023d2fad15c54fc4300f468757ce1c 100644 (file)
 #include "core.h"
 #include "reg.h"
 
-/**
- * struct regulatory_request - receipt of last regulatory request
- *
- * @wiphy: this is set if this request's initiator is
- *     %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
- *     can be used by the wireless core to deal with conflicts
- *     and potentially inform users of which devices specifically
- *     cased the conflicts.
- * @initiator: indicates who sent this request, could be any of
- *     of those set in reg_set_by, %REGDOM_SET_BY_*
- * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
- *     regulatory domain. We have a few special codes:
- *     00 - World regulatory domain
- *     99 - built by driver but a specific alpha2 cannot be determined
- *     98 - result of an intersection between two regulatory domains
- * @intersect: indicates whether the wireless core should intersect
- *     the requested regulatory domain with the presently set regulatory
- *     domain.
- * @country_ie_checksum: checksum of the last processed and accepted
- *     country IE
- * @country_ie_env: lets us know if the AP is telling us we are outdoor,
- *     indoor, or if it doesn't matter
- */
-struct regulatory_request {
-       struct wiphy *wiphy;
-       enum reg_set_by initiator;
-       char alpha2[2];
-       bool intersect;
-       u32 country_ie_checksum;
-       enum environment_cap country_ie_env;
-};
-
 /* Receipt of information from last regulatory request */
 static struct regulatory_request *last_request;
 
@@ -790,42 +758,35 @@ static u32 map_regdom_flags(u32 rd_flags)
        return channel_flags;
 }
 
-/**
- * freq_reg_info - get regulatory information for the given frequency
- * @center_freq: Frequency in KHz for which we want regulatory information for
- * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one
- *     you can set this to 0. If this frequency is allowed we then set
- *     this value to the maximum allowed bandwidth.
- * @reg_rule: the regulatory rule which we have for this frequency
- *
- * Use this function to get the regulatory rule for a specific frequency on
- * a given wireless device. If the device has a specific regulatory domain
- * it wants to follow we respect that unless a country IE has been received
- * and processed already.
- *
- * Returns 0 if it was able to find a valid regulatory rule which does
- * apply to the given center_freq otherwise it returns non-zero. It will
- * also return -ERANGE if we determine the given center_freq does not even have
- * a regulatory rule for a frequency range in the center_freq's band. See
- * freq_in_rule_band() for our current definition of a band -- this is purely
- * subjective and right now its 802.11 specific.
- */
-static int freq_reg_info(u32 center_freq, u32 *bandwidth,
-                        const struct ieee80211_reg_rule **reg_rule)
+static int freq_reg_info_regd(struct wiphy *wiphy,
+                             u32 center_freq,
+                             u32 *bandwidth,
+                             const struct ieee80211_reg_rule **reg_rule,
+                             const struct ieee80211_regdomain *custom_regd)
 {
        int i;
        bool band_rule_found = false;
+       const struct ieee80211_regdomain *regd;
        u32 max_bandwidth = 0;
 
-       if (!cfg80211_regdomain)
+       regd = custom_regd ? custom_regd : cfg80211_regdomain;
+
+       /* Follow the driver's regulatory domain, if present, unless a country
+        * IE has been processed or a user wants to help complaince further */
+       if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE &&
+           last_request->initiator != REGDOM_SET_BY_USER &&
+           wiphy->regd)
+               regd = wiphy->regd;
+
+       if (!regd)
                return -EINVAL;
 
-       for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) {
+       for (i = 0; i < regd->n_reg_rules; i++) {
                const struct ieee80211_reg_rule *rr;
                const struct ieee80211_freq_range *fr = NULL;
                const struct ieee80211_power_rule *pr = NULL;
 
-               rr = &cfg80211_regdomain->reg_rules[i];
+               rr = &regd->reg_rules[i];
                fr = &rr->freq_range;
                pr = &rr->power_rule;
 
@@ -849,6 +810,14 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
 
        return !max_bandwidth;
 }
+EXPORT_SYMBOL(freq_reg_info);
+
+int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth,
+                        const struct ieee80211_reg_rule **reg_rule)
+{
+       return freq_reg_info_regd(wiphy, center_freq,
+               bandwidth, reg_rule, NULL);
+}
 
 static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
                           unsigned int chan_idx)
@@ -867,7 +836,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
 
        flags = chan->orig_flags;
 
-       r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq),
+       r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq),
                &max_bandwidth, &reg_rule);
 
        if (r) {
@@ -907,6 +876,22 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
 
        power_rule = &reg_rule->power_rule;
 
+       if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
+           last_request->wiphy && last_request->wiphy == wiphy &&
+           last_request->wiphy->strict_regulatory) {
+               /* This gaurantees the driver's requested regulatory domain
+                * will always be used as a base for further regulatory
+                * settings */
+               chan->flags = chan->orig_flags =
+                       map_regdom_flags(reg_rule->flags);
+               chan->max_antenna_gain = chan->orig_mag =
+                       (int) MBI_TO_DBI(power_rule->max_antenna_gain);
+               chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth);
+               chan->max_power = chan->orig_mpwr =
+                       (int) MBM_TO_DBM(power_rule->max_eirp);
+               return;
+       }
+
        chan->flags = flags | map_regdom_flags(reg_rule->flags);
        chan->max_antenna_gain = min(chan->orig_mag,
                (int) MBI_TO_DBI(power_rule->max_antenna_gain));
@@ -935,7 +920,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
        if (!last_request)
                return true;
        if (setby == REGDOM_SET_BY_CORE &&
-                 wiphy->fw_handles_regulatory)
+                 wiphy->custom_regulatory)
+               return true;
+       /* wiphy->regd will be set once the device has its own
+        * desired regulatory domain set */
+       if (wiphy->strict_regulatory && !wiphy->regd &&
+           !is_world_regdom(last_request->alpha2))
                return true;
        return false;
 }
@@ -945,20 +935,103 @@ static void update_all_wiphy_regulatory(enum reg_set_by setby)
        struct cfg80211_registered_device *drv;
 
        list_for_each_entry(drv, &cfg80211_drv_list, list)
-               if (!ignore_reg_update(&drv->wiphy, setby))
-                       wiphy_update_regulatory(&drv->wiphy, setby);
+               wiphy_update_regulatory(&drv->wiphy, setby);
 }
 
 void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
 {
        enum ieee80211_band band;
+
+       if (ignore_reg_update(wiphy, setby))
+               return;
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (wiphy->bands[band])
                        handle_band(wiphy, band);
-               if (wiphy->reg_notifier)
-                       wiphy->reg_notifier(wiphy, setby);
+       }
+       if (wiphy->reg_notifier)
+               wiphy->reg_notifier(wiphy, last_request);
+}
+
+static void handle_channel_custom(struct wiphy *wiphy,
+                                 enum ieee80211_band band,
+                                 unsigned int chan_idx,
+                                 const struct ieee80211_regdomain *regd)
+{
+       int r;
+       u32 max_bandwidth = 0;
+       const struct ieee80211_reg_rule *reg_rule = NULL;
+       const struct ieee80211_power_rule *power_rule = NULL;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *chan;
+
+       sband = wiphy->bands[band];
+       BUG_ON(chan_idx >= sband->n_channels);
+       chan = &sband->channels[chan_idx];
+
+       r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
+               &max_bandwidth, &reg_rule, regd);
+
+       if (r) {
+               chan->flags = IEEE80211_CHAN_DISABLED;
+               return;
+       }
+
+       power_rule = &reg_rule->power_rule;
+
+       chan->flags |= map_regdom_flags(reg_rule->flags);
+       chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
+       chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth);
+       chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+}
+
+static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
+                              const struct ieee80211_regdomain *regd)
+{
+       unsigned int i;
+       struct ieee80211_supported_band *sband;
+
+       BUG_ON(!wiphy->bands[band]);
+       sband = wiphy->bands[band];
+
+       for (i = 0; i < sband->n_channels; i++)
+               handle_channel_custom(wiphy, band, i, regd);
+}
+
+/* Used by drivers prior to wiphy registration */
+void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
+                                  const struct ieee80211_regdomain *regd)
+{
+       enum ieee80211_band band;
+       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               if (wiphy->bands[band])
+                       handle_band_custom(wiphy, band, regd);
        }
 }
+EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
+
+static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
+                        const struct ieee80211_regdomain *src_regd)
+{
+       struct ieee80211_regdomain *regd;
+       int size_of_regd = 0;
+       unsigned int i;
+
+       size_of_regd = sizeof(struct ieee80211_regdomain) +
+         ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule));
+
+       regd = kzalloc(size_of_regd, GFP_KERNEL);
+       if (!regd)
+               return -ENOMEM;
+
+       memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
+
+       for (i = 0; i < src_regd->n_reg_rules; i++)
+               memcpy(&regd->reg_rules[i], &src_regd->reg_rules[i],
+                       sizeof(struct ieee80211_reg_rule));
+
+       *dst_regd = regd;
+       return 0;
+}
 
 /* Return value which can be used by ignore_request() to indicate
  * it has been determined we should intersect two regulatory domains */
@@ -1007,9 +1080,14 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
                }
                return REG_INTERSECT;
        case REGDOM_SET_BY_DRIVER:
-               if (last_request->initiator == REGDOM_SET_BY_DRIVER)
+               if (last_request->initiator == REGDOM_SET_BY_CORE) {
+                       if (is_old_static_regdom(cfg80211_regdomain))
+                               return 0;
+                       if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
+                               return 0;
                        return -EALREADY;
-               return 0;
+               }
+               return REG_INTERSECT;
        case REGDOM_SET_BY_USER:
                if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
                        return REG_INTERSECT;
@@ -1018,6 +1096,20 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
                if (last_request->initiator == REGDOM_SET_BY_USER &&
                          last_request->intersect)
                        return -EOPNOTSUPP;
+               /* Process user requests only after previous user/driver/core
+                * requests have been processed */
+               if (last_request->initiator == REGDOM_SET_BY_CORE ||
+                   last_request->initiator == REGDOM_SET_BY_DRIVER ||
+                   last_request->initiator == REGDOM_SET_BY_USER) {
+                       if (!alpha2_equal(last_request->alpha2,
+                           cfg80211_regdomain->alpha2))
+                               return -EAGAIN;
+               }
+
+               if (!is_old_static_regdom(cfg80211_regdomain) &&
+                   alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
+                       return -EALREADY;
+
                return 0;
        }
 
@@ -1036,11 +1128,28 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
 
        r = ignore_request(wiphy, set_by, alpha2);
 
-       if (r == REG_INTERSECT)
+       if (r == REG_INTERSECT) {
+               if (set_by == REGDOM_SET_BY_DRIVER) {
+                       r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
+                       if (r)
+                               return r;
+               }
                intersect = true;
-       else if (r)
+       } else if (r) {
+               /* If the regulatory domain being requested by the
+                * driver has already been set just copy it to the
+                * wiphy */
+               if (r == -EALREADY && set_by == REGDOM_SET_BY_DRIVER) {
+                       r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
+                       if (r)
+                               return r;
+                       r = -EALREADY;
+                       goto new_request;
+               }
                return r;
+       }
 
+new_request:
        request = kzalloc(sizeof(struct regulatory_request),
                          GFP_KERNEL);
        if (!request)
@@ -1056,6 +1165,11 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
 
        kfree(last_request);
        last_request = request;
+
+       /* When r == REG_INTERSECT we do need to call CRDA */
+       if (r < 0)
+               return r;
+
        /*
         * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled
         * AND if CRDA is NOT present nothing will happen, if someone
@@ -1071,10 +1185,15 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
 
 void regulatory_hint(struct wiphy *wiphy, const char *alpha2)
 {
+       int r;
        BUG_ON(!alpha2);
 
        mutex_lock(&cfg80211_drv_mutex);
-       __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY);
+       r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER,
+               alpha2, 0, ENVIRON_ANY);
+       /* This is required so that the orig_* parameters are saved */
+       if (r == -EALREADY && wiphy->strict_regulatory)
+               wiphy_update_regulatory(wiphy, REGDOM_SET_BY_DRIVER);
        mutex_unlock(&cfg80211_drv_mutex);
 }
 EXPORT_SYMBOL(regulatory_hint);
@@ -1247,7 +1366,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
                                        "domain intersected: \n");
                } else
                                printk(KERN_INFO "cfg80211: Current regulatory "
-                                       "intersected: \n");
+                                       "domain intersected: \n");
        } else if (is_world_regdom(rd->alpha2))
                printk(KERN_INFO "cfg80211: World regulatory "
                        "domain updated:\n");
@@ -1349,6 +1468,23 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
        }
 
        if (!last_request->intersect) {
+               int r;
+
+               if (last_request->initiator != REGDOM_SET_BY_DRIVER) {
+                       reset_regdomains();
+                       cfg80211_regdomain = rd;
+                       return 0;
+               }
+
+               /* For a driver hint, lets copy the regulatory domain the
+                * driver wanted to the wiphy to deal with conflicts */
+
+               BUG_ON(last_request->wiphy->regd);
+
+               r = reg_copy_regd(&last_request->wiphy->regd, rd);
+               if (r)
+                       return r;
+
                reset_regdomains();
                cfg80211_regdomain = rd;
                return 0;
@@ -1362,8 +1498,14 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
                if (!intersected_rd)
                        return -EINVAL;
 
-               /* We can trash what CRDA provided now */
-               kfree(rd);
+               /* We can trash what CRDA provided now.
+                * However if a driver requested this specific regulatory
+                * domain we keep it for its private use */
+               if (last_request->initiator == REGDOM_SET_BY_DRIVER)
+                       last_request->wiphy->regd = rd;
+               else
+                       kfree(rd);
+
                rd = NULL;
 
                reset_regdomains();
@@ -1447,6 +1589,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
 /* Caller must hold cfg80211_drv_mutex */
 void reg_device_remove(struct wiphy *wiphy)
 {
+       kfree(wiphy->regd);
        if (!last_request || !last_request->wiphy)
                return;
        if (last_request->wiphy != wiphy)
index a76ea3ff7cd6af1a9da0044a7b8eca2afabea85a..eb1dd5bc9b270d4e47a94fa1f8b599ab8f2986b4 100644 (file)
@@ -11,13 +11,6 @@ void regulatory_exit(void);
 
 int set_regdom(const struct ieee80211_regdomain *rd);
 
-enum environment_cap {
-       ENVIRON_ANY,
-       ENVIRON_INDOOR,
-       ENVIRON_OUTDOOR,
-};
-
-
 /**
  * __regulatory_hint - hint to the wireless core a regulatory domain
  * @wiphy: if the hint comes from country information from an AP, this
index 79a38287764165c41b74533efa0043aaae4a6c3f..26a72b0797a09e5c6c2ff4595dab1309d007c627 100644 (file)
@@ -55,6 +55,34 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
 }
 #endif
 
+static int wiphy_suspend(struct device *dev, pm_message_t state)
+{
+       struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
+       int ret = 0;
+
+       if (rdev->ops->suspend) {
+               rtnl_lock();
+               ret = rdev->ops->suspend(&rdev->wiphy);
+               rtnl_unlock();
+       }
+
+       return ret;
+}
+
+static int wiphy_resume(struct device *dev)
+{
+       struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
+       int ret = 0;
+
+       if (rdev->ops->resume) {
+               rtnl_lock();
+               ret = rdev->ops->resume(&rdev->wiphy);
+               rtnl_unlock();
+       }
+
+       return ret;
+}
+
 struct class ieee80211_class = {
        .name = "ieee80211",
        .owner = THIS_MODULE,
@@ -63,6 +91,8 @@ struct class ieee80211_class = {
 #ifdef CONFIG_HOTPLUG
        .dev_uevent = wiphy_uevent,
 #endif
+       .suspend = wiphy_suspend,
+       .resume = wiphy_resume,
 };
 
 int wiphy_sysfs_init(void)
index e76cc28b034557fc1dfcadbae21a09307f6fee5c..487cdd9bcffcb0137fb3f6dd04db210c005eae06 100644 (file)
@@ -9,7 +9,7 @@
 
 struct ieee80211_rate *
 ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
-                           u64 basic_rates, int bitrate)
+                           u32 basic_rates, int bitrate)
 {
        struct ieee80211_rate *result = &sband->bitrates[0];
        int i;
index 9fc5b023d1118a990944cbe32ff5ab2c81e07f5b..8f76f4009c24d3c2c1d596afea65f36317c7d335 100644 (file)
@@ -1609,7 +1609,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
 SOCKOPS_WRAP(x25_proto, AF_X25);
 
 static struct packet_type x25_packet_type = {
-       .type = __constant_htons(ETH_P_X25),
+       .type = cpu_to_be16(ETH_P_X25),
        .func = x25_lapb_receive_frame,
 };