Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

Conflicts:

	drivers/message/fusion/mptlan.c
	drivers/net/sfc/ethtool.c
	net/mac80211/debugfs_sta.c
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index c28a2ac..77eb6b1 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -120,13 +120,6 @@
 
 ---------------------------
 
-What:   eepro100 network driver
-When:   January 2007
-Why:    replaced by the e100 driver
-Who:    Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
 	(temporary transition config option provided until then)
 	The transition config option will also be removed at the same time.
diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200
index 4f2a40f..80c7285 100644
--- a/Documentation/networking/README.ipw2200
+++ b/Documentation/networking/README.ipw2200
@@ -147,7 +147,7 @@
 	driver.  If disabled, the driver will not attempt to scan 
 	for and associate to a network until it has been configured with 
 	one or more properties for the target network, for example configuring 
-	the network SSID.  Default is 1 (auto-associate)
+	the network SSID.  Default is 0 (do not auto-associate)
 	
 	Example: % modprobe ipw2200 associate=0
 
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 688dfe1..5ede747 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -194,6 +194,48 @@
 
 	The parameters are as follows:
 
+ad_select
+
+	Specifies the 802.3ad aggregation selection logic to use.  The
+	possible values and their effects are:
+
+	stable or 0
+
+		The active aggregator is chosen by largest aggregate
+		bandwidth.
+
+		Reselection of the active aggregator occurs only when all
+		slaves of the active aggregator are down or the active
+		aggregator has no slaves.
+
+		This is the default value.
+
+	bandwidth or 1
+
+		The active aggregator is chosen by largest aggregate
+		bandwidth.  Reselection occurs if:
+
+		- A slave is added to or removed from the bond
+
+		- Any slave's link state changes
+
+		- Any slave's 802.3ad association state changes
+
+		- The bond's adminstrative state changes to up
+
+	count or 2
+
+		The active aggregator is chosen by the largest number of
+		ports (slaves).  Reselection occurs as described under the
+		"bandwidth" setting, above.
+
+	The bandwidth and count selection policies permit failover of
+	802.3ad aggregations when partial failure of the active aggregator
+	occurs.  This keeps the aggregator with the highest availability
+	(either in bandwidth or in number of ports) active at all times.
+
+	This option was added in bonding version 3.4.0.
+
 arp_interval
 
 	Specifies the ARP link monitoring frequency in milliseconds.
@@ -551,6 +593,16 @@
 	affects only the active-backup mode.  This option was added for
 	bonding version 3.3.0.
 
+num_unsol_na
+
+	Specifies the number of unsolicited IPv6 Neighbor Advertisements
+	to be issued after a failover event.  One unsolicited NA is issued
+	immediately after the failover.
+
+	The valid range is 0 - 255; the default value is 1.  This option
+	affects only the active-backup mode.  This option was added for
+	bonding version 3.4.0.
+
 primary
 
 	A string (eth0, eth2, etc) specifying which slave is the
@@ -922,17 +974,19 @@
 NETMASK, NETWORK and BROADCAST) to match your network configuration.
 
 	For later versions of initscripts, such as that found with Fedora
-7 and Red Hat Enterprise Linux version 5 (or later), it is possible, and,
-indeed, preferable, to specify the bonding options in the ifcfg-bond0
+7 (or later) and Red Hat Enterprise Linux version 5 (or later), it is possible,
+and, indeed, preferable, to specify the bonding options in the ifcfg-bond0
 file, e.g. a line of the format:
 
-BONDING_OPTS="mode=active-backup arp_interval=60 arp_ip_target=+192.168.1.254"
+BONDING_OPTS="mode=active-backup arp_interval=60 arp_ip_target=192.168.1.254"
 
 	will configure the bond with the specified options.  The options
 specified in BONDING_OPTS are identical to the bonding module parameters
-except for the arp_ip_target field.  Each target should be included as a
-separate option and should be preceded by a '+' to indicate it should be
-added to the list of queried targets, e.g.,
+except for the arp_ip_target field when using versions of initscripts older
+than and 8.57 (Fedora 8) and 8.45.19 (Red Hat Enterprise Linux 5.2).  When
+using older versions each target should be included as a separate option and
+should be preceded by a '+' to indicate it should be added to the list of
+queried targets, e.g.,
 
 	arp_ip_target=+192.168.1.1 arp_ip_target=+192.168.1.2
 
@@ -940,7 +994,7 @@
 options via BONDING_OPTS, it is not necessary to edit /etc/modules.conf or
 /etc/modprobe.conf.
 
-	For older versions of initscripts that do not support
+	For even older versions of initscripts that do not support
 BONDING_OPTS, it is necessary to edit /etc/modules.conf (or
 /etc/modprobe.conf, depending upon your distro) to load the bonding module
 with your desired options when the bond0 interface is brought up.  The
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index d849326..c771278 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -27,6 +27,12 @@
 	The advertised MSS depends on the first hop route MTU, but will
 	never be lower than this setting.
 
+rt_cache_rebuild_count - INTEGER
+	The per net-namespace route cache emergency rebuild threshold.
+	Any net-namespace having its route cache rebuilt due to
+	a hash bucket chain being too long more than this many times
+	will have its route caching disabled
+
 IP Fragmentation:
 
 ipfrag_high_thresh - INTEGER
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index a96989a..dcf3164 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -131,11 +131,13 @@
 
 	r = zd_reg2alpha2(mac->regdomain, alpha2);
 	if (!r)
-		regulatory_hint(hw->wiphy, alpha2, NULL);
+		regulatory_hint(hw->wiphy, alpha2);
 
 Example code - drivers providing a built in regulatory domain:
 --------------------------------------------------------------
 
+[NOTE: This API is not currently available, it can be added when required]
+
 If you have regulatory information you can obtain from your
 driver and you *need* to use this we let you build a regulatory domain
 structure and pass it to the wireless core. To do this you should
@@ -167,7 +169,6 @@
 
 Then in some part of your code after your wiphy has been registered:
 
-	int r;
 	struct ieee80211_regdomain *rd;
 	int size_of_regd;
 	int num_rules = mydriver_jp_regdom.n_reg_rules;
@@ -178,17 +179,12 @@
 
 	rd = kzalloc(size_of_regd, GFP_KERNEL);
 	if (!rd)
-	return -ENOMEM;
+		return -ENOMEM;
 
 	memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain));
 
-	for (i=0; i < num_rules; i++) {
-		memcpy(&rd->reg_rules[i], &mydriver_jp_regdom.reg_rules[i],
-			sizeof(struct ieee80211_reg_rule));
-	}
-	r = regulatory_hint(hw->wiphy, NULL, rd);
-	if (r) {
-		kfree(rd);
-		return r;
-	}
-
+	for (i=0; i < num_rules; i++)
+		memcpy(&rd->reg_rules[i],
+		       &mydriver_jp_regdom.reg_rules[i],
+		       sizeof(struct ieee80211_reg_rule));
+	regulatory_struct_hint(rd);
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index b65f079..4d3ee31 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -191,12 +191,20 @@
 	  to tell the devices registered with the rfkill class to change
 	  their state (i.e. translates the input layer event into real
 	  action).
+
 	* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
 	  (power off all transmitters) in a special way: it ignores any
 	  overrides and local state cache and forces all transmitters to the
 	  RFKILL_STATE_SOFT_BLOCKED state (including those which are already
-	  supposed to be BLOCKED).  Note that the opposite event (power on all
-	  transmitters) is handled normally.
+	  supposed to be BLOCKED).
+	* rfkill EPO will remain active until rfkill-input receives an
+	  EV_SW SW_RFKILL_ALL 1 event.  While the EPO is active, transmitters
+	  are locked in the blocked state (rfkill will refuse to unblock them).
+	* rfkill-input implements different policies that the user can
+	  select for handling EV_SW SW_RFKILL_ALL 1.  It will unlock rfkill,
+	  and either do nothing (leave transmitters blocked, but now unlocked),
+	  restore the transmitters to their state before the EPO, or unblock
+	  them all.
 
 Userspace uevent handler or kernel platform-specific drivers hooked to the
 rfkill notifier chain:
@@ -331,11 +339,9 @@
 correct event for your switch/button.  These events are emergency power-off
 events when they are trying to turn the transmitters off.  An example of an
 input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill
-switch in a laptop which is NOT a hotkey, but a real switch that kills radios
-in hardware, even if the O.S. has gone to lunch.  An example of an input device
-which SHOULD NOT generate *_RFKILL_ALL events by default, is any sort of hot
-key that does nothing by itself, as well as any hot key that is type-specific
-(e.g. the one for WLAN).
+switch in a laptop which is NOT a hotkey, but a real sliding/rocker switch.
+An example of an input device which SHOULD NOT generate *_RFKILL_ALL events by
+default, is any sort of hot key that is type-specific (e.g. the one for WLAN).
 
 
 3.1 Guidelines for wireless device drivers
diff --git a/MAINTAINERS b/MAINTAINERS
index 53e78c8..19f1a4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -742,7 +742,7 @@
 P:	Nick Kossifidis
 M:	mickflemm@gmail.com
 P:	Luis R. Rodriguez
-M:	mcgrof@gmail.com
+M:	lrodriguez@atheros.com
 P:	Bob Copeland
 M:	me@bobcopeland.com
 L:	linux-wireless@vger.kernel.org
@@ -1606,11 +1606,6 @@
 W:	http://sourceforge.net/projects/acpi4asus
 S:	Maintained
 
-EEPRO100 NETWORK DRIVER
-P:	Andrey V. Savochkin
-M:	saw@saw.sw.com.sg
-S:	Maintained
-
 EFS FILESYSTEM
 W:	http://aeschi.ch.eu.org/efs/
 S:	Orphan
@@ -3889,6 +3884,12 @@
 L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
+SMSC911x ETHERNET DRIVER
+P:	Steve Glendinning
+M:	steve.glendinning@smsc.com
+L:	netdev@vger.kernel.org
+S:	Supported
+
 SMX UIO Interface
 P:	Ben Nizette
 M:	bn@niasdigital.com
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index e7c6386..5add22f 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -177,7 +177,6 @@
 
 static void __init fsg_init(void)
 {
-	DECLARE_MAC_BUF(mac_buf);
 	uint8_t __iomem *f;
 
 	ixp4xx_sys_init();
@@ -256,10 +255,10 @@
 #endif
 		iounmap(f);
 	}
-	printk(KERN_INFO "FSG: Using MAC address %s for port 0\n",
-	       print_mac(mac_buf, fsg_plat_eth[0].hwaddr));
-	printk(KERN_INFO "FSG: Using MAC address %s for port 1\n",
-	       print_mac(mac_buf, fsg_plat_eth[1].hwaddr));
+	printk(KERN_INFO "FSG: Using MAC address %pM for port 0\n",
+	       fsg_plat_eth[0].hwaddr);
+	printk(KERN_INFO "FSG: Using MAC address %pM for port 1\n",
+	       fsg_plat_eth[1].hwaddr);
 
 }
 
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 0acd95e..921c947 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -231,7 +231,6 @@
 
 static void __init nas100d_init(void)
 {
-	DECLARE_MAC_BUF(mac_buf);
 	uint8_t __iomem *f;
 	int i;
 
@@ -294,8 +293,8 @@
 #endif
 		iounmap(f);
 	}
-	printk(KERN_INFO "NAS100D: Using MAC address %s for port 0\n",
-	       print_mac(mac_buf, nas100d_plat_eth[0].hwaddr));
+	printk(KERN_INFO "NAS100D: Using MAC address %pM for port 0\n",
+	       nas100d_plat_eth[0].hwaddr);
 
 }
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index bc9d920..ff6a08d 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -220,7 +220,6 @@
 
 static void __init nslu2_init(void)
 {
-	DECLARE_MAC_BUF(mac_buf);
 	uint8_t __iomem *f;
 	int i;
 
@@ -275,8 +274,8 @@
 #endif
 		iounmap(f);
 	}
-	printk(KERN_INFO "NSLU2: Using MAC address %s for port 0\n",
-	       print_mac(mac_buf, nslu2_plat_eth[0].hwaddr));
+	printk(KERN_INFO "NSLU2: Using MAC address %pM for port 0\n",
+	       nslu2_plat_eth[0].hwaddr);
 
 }
 
diff --git a/arch/sparc64/kernel/idprom.c b/arch/sparc64/kernel/idprom.c
index 5b45a80..a62ff83 100644
--- a/arch/sparc64/kernel/idprom.c
+++ b/arch/sparc64/kernel/idprom.c
@@ -42,8 +42,5 @@
 			    idprom->id_cksum, calc_idprom_cksum(idprom));
 	}
 
-	printk("Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       idprom->id_ethaddr[0], idprom->id_ethaddr[1],
-	       idprom->id_ethaddr[2], idprom->id_ethaddr[3],
-	       idprom->id_ethaddr[4], idprom->id_ethaddr[5]);
+	printk("Ethernet address: %pM\n", idprom->id_ethaddr);
 }
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 5b4ca8d..74f1a17 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -418,12 +418,7 @@
 
 	setup_etheraddr(mac, device->mac, dev->name);
 
-	printk(KERN_INFO "Netdevice %d ", n);
-	printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
-	       device->mac[0], device->mac[1],
-	       device->mac[2], device->mac[3],
-	       device->mac[4], device->mac[5]);
-	printk(": ");
+	printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac);
 
 	lp = dev->priv;
 	/* This points to the transport private data. It's still clear, but we
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index 11a20ad..87f47ca 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -660,10 +660,7 @@
 
 	printk(KERN_INFO "Netdevice %d ", index);
 	if (lp->have_mac)
-		printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
-				lp->mac[0], lp->mac[1],
-				lp->mac[2], lp->mac[3],
-				lp->mac[4], lp->mac[5]);
+		printk("(%pM) ", lp->mac);
 	printk(": ");
 
 	/* sysfs register */
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 4353414..3ab3e4a 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -284,15 +284,12 @@
 		/*
 		 * IPV4
 		 */
-		str += sprintf(buf, NIPQUAD_FMT, ip[12],
-			       ip[13], ip[14], ip[15]);
+		str += sprintf(buf, "%pI4", ip + 12);
 	} else {
 		/*
 		 * IPv6
 		 */
-		str += sprintf(str, NIP6_FMT, ntohs(ip[0]), ntohs(ip[1]),
-			       ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]),
-			       ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));
+		str += sprintf(str, "%pI6", ip);
 	}
 	str += sprintf(str, "\n");
 	return str - buf;
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 4d10421..4f4d1bb 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -262,15 +262,7 @@
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-		       be16_to_cpu(((__be16 *) gid.raw)[0]),
-		       be16_to_cpu(((__be16 *) gid.raw)[1]),
-		       be16_to_cpu(((__be16 *) gid.raw)[2]),
-		       be16_to_cpu(((__be16 *) gid.raw)[3]),
-		       be16_to_cpu(((__be16 *) gid.raw)[4]),
-		       be16_to_cpu(((__be16 *) gid.raw)[5]),
-		       be16_to_cpu(((__be16 *) gid.raw)[6]),
-		       be16_to_cpu(((__be16 *) gid.raw)[7]));
+	return sprintf(buf, "%pI6\n", gid.raw);
 }
 
 static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 3f5f948..d4c8105 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -87,17 +87,7 @@
 	}
 
 	if (0)
-		mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
-			  "%04x:%04x:%04x:%04x is %04x\n",
-			  be16_to_cpu(((__be16 *) gid)[0]),
-			  be16_to_cpu(((__be16 *) gid)[1]),
-			  be16_to_cpu(((__be16 *) gid)[2]),
-			  be16_to_cpu(((__be16 *) gid)[3]),
-			  be16_to_cpu(((__be16 *) gid)[4]),
-			  be16_to_cpu(((__be16 *) gid)[5]),
-			  be16_to_cpu(((__be16 *) gid)[6]),
-			  be16_to_cpu(((__be16 *) gid)[7]),
-			  *hash);
+		mthca_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
 
 	*index = *hash;
 	*prev  = -1;
@@ -264,16 +254,7 @@
 		goto out;
 
 	if (index == -1) {
-		mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
-			  "not found\n",
-			  be16_to_cpu(((__be16 *) gid->raw)[0]),
-			  be16_to_cpu(((__be16 *) gid->raw)[1]),
-			  be16_to_cpu(((__be16 *) gid->raw)[2]),
-			  be16_to_cpu(((__be16 *) gid->raw)[3]),
-			  be16_to_cpu(((__be16 *) gid->raw)[4]),
-			  be16_to_cpu(((__be16 *) gid->raw)[5]),
-			  be16_to_cpu(((__be16 *) gid->raw)[6]),
-			  be16_to_cpu(((__be16 *) gid->raw)[7]));
+		mthca_err(dev, "MGID %pI6 not found\n", gid->raw);
 		err = -EINVAL;
 		goto out;
 	}
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index a2b04d6..fb7d243 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -138,14 +138,9 @@
 	struct nes_device *nesdev;
 	struct net_device *netdev;
 	struct nes_vnic *nesvnic;
-	unsigned int addr;
-	unsigned int mask;
 
-	addr = ntohl(ifa->ifa_address);
-	mask = ntohl(ifa->ifa_mask);
-	nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address " NIPQUAD_FMT
-		  ", netmask " NIPQUAD_FMT ".\n",
-		  HIPQUAD(addr), HIPQUAD(mask));
+	nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n",
+		  &ifa->ifa_address, &ifa->ifa_mask);
 	list_for_each_entry(nesdev, &nes_dev_list, list) {
 		nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n",
 				nesdev, nesdev->netdev[0]->name);
@@ -356,10 +351,8 @@
  */
 static void nes_print_macaddr(struct net_device *netdev)
 {
-	DECLARE_MAC_BUF(mac);
-
-	nes_debug(NES_DBG_INIT, "%s: %s, IRQ %u\n",
-		  netdev->name, print_mac(mac, netdev->dev_addr), netdev->irq);
+	nes_debug(NES_DBG_INIT, "%s: %pM, IRQ %u\n",
+		  netdev->name, netdev->dev_addr, netdev->irq);
 }
 
 /**
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 2caf9da..2854a6f 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -823,8 +823,8 @@
 	/* get a handle on the hte */
 	hte = &cm_core->connected_nodes;
 
-	nes_debug(NES_DBG_CM, "Searching for an owner node: " NIPQUAD_FMT ":%x from core %p->%p\n",
-		  HIPQUAD(loc_addr), loc_port, cm_core, hte);
+	nes_debug(NES_DBG_CM, "Searching for an owner node: %pI4:%x from core %p->%p\n",
+		  &loc_addr, loc_port, cm_core, hte);
 
 	/* walk list and find cm_node associated with this session ID */
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -873,8 +873,8 @@
 	}
 	spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
-	nes_debug(NES_DBG_CM, "Unable to find listener for " NIPQUAD_FMT ":%x\n",
-		  HIPQUAD(dst_addr), dst_port);
+	nes_debug(NES_DBG_CM, "Unable to find listener for %pI4:%x\n",
+		  &dst_addr, dst_port);
 
 	/* no listener */
 	return NULL;
@@ -1027,7 +1027,6 @@
 	struct flowi fl;
 	struct neighbour *neigh;
 	int rc = -1;
-	DECLARE_MAC_BUF(mac);
 
 	memset(&fl, 0, sizeof fl);
 	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
@@ -1041,8 +1040,8 @@
 	if (neigh) {
 		if (neigh->nud_state & NUD_VALID) {
 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
-				  " is %s, Gateway is 0x%08X \n", dst_ip,
-				  print_mac(mac, neigh->ha), ntohl(rt->rt_gateway));
+				  " is %pM, Gateway is 0x%08X \n", dst_ip,
+				  neigh->ha, ntohl(rt->rt_gateway));
 			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
 					     dst_ip, NES_ARP_ADD);
 			rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
@@ -1071,7 +1070,6 @@
 	int arpindex = 0;
 	struct nes_device *nesdev;
 	struct nes_adapter *nesadapter;
-	DECLARE_MAC_BUF(mac);
 
 	/* create an hte and cm_node for this instance */
 	cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
@@ -1084,10 +1082,9 @@
 	cm_node->loc_port = cm_info->loc_port;
 	cm_node->rem_port = cm_info->rem_port;
 	cm_node->send_write0 = send_first;
-	nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT
-			":%x, rem = " NIPQUAD_FMT ":%x\n",
-			HIPQUAD(cm_node->loc_addr), cm_node->loc_port,
-			HIPQUAD(cm_node->rem_addr), cm_node->rem_port);
+	nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
+		  &cm_node->loc_addr, cm_node->loc_port,
+		  &cm_node->rem_addr, cm_node->rem_port);
 	cm_node->listener = listener;
 	cm_node->netdev = nesvnic->netdev;
 	cm_node->cm_id = cm_info->cm_id;
@@ -1137,8 +1134,8 @@
 
 	/* copy the mac addr to node context */
 	memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN);
-	nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %s\n",
-		  print_mac(mac, cm_node->rem_mac));
+	nes_debug(NES_DBG_CM, "Remote mac addr from arp table: %pM\n",
+		  cm_node->rem_mac);
 
 	add_hte_node(cm_core, cm_node);
 	atomic_inc(&cm_nodes_created);
@@ -2068,10 +2065,8 @@
 	nfo.rem_addr = ntohl(iph->saddr);
 	nfo.rem_port = ntohs(tcph->source);
 
-	nes_debug(NES_DBG_CM, "Received packet: dest=" NIPQUAD_FMT
-		  ":0x%04X src=" NIPQUAD_FMT ":0x%04X\n",
-		  NIPQUAD(iph->daddr), tcph->dest,
-		  NIPQUAD(iph->saddr), tcph->source);
+	nes_debug(NES_DBG_CM, "Received packet: dest=%pI4:0x%04X src=%pI4:0x%04X\n",
+		  &iph->daddr, tcph->dest, &iph->saddr, tcph->source);
 
 	do {
 		cm_node = find_node(cm_core,
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 7303586..3c96203 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -797,14 +797,13 @@
 	int i;
 	u32 macaddr_low;
 	u16 macaddr_high;
-	DECLARE_MAC_BUF(mac);
 
 	if (!is_valid_ether_addr(mac_addr->sa_data))
 		return -EADDRNOTAVAIL;
 
 	memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
-	printk(PFX "%s: Address length = %d, Address = %s\n",
-	       __func__, netdev->addr_len, print_mac(mac, mac_addr->sa_data));
+	printk(PFX "%s: Address length = %d, Address = %pM\n",
+	       __func__, netdev->addr_len, mac_addr->sa_data);
 	macaddr_high  = ((u16)netdev->dev_addr[0]) << 8;
 	macaddr_high += (u16)netdev->dev_addr[1];
 	macaddr_low   = ((u32)netdev->dev_addr[2]) << 24;
@@ -909,9 +908,8 @@
 			if (mc_index >= max_pft_entries_avaiable)
 				break;
 			if (multicast_addr) {
-				DECLARE_MAC_BUF(mac);
-				nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %s to register 0x%04X nic_idx=%d\n",
-					  print_mac(mac, multicast_addr->dmi_addr),
+				nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n",
+					  multicast_addr->dmi_addr,
 					  perfect_filter_register_address+(mc_index * 8),
 					  mc_nic_index);
 				macaddr_high  = ((u16)multicast_addr->dmi_addr[0]) << 8;
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index fb8cbd7..9f16f7a 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -679,9 +679,8 @@
 
 	/* DELETE or RESOLVE */
 	if (arp_index == nesadapter->arp_table_size) {
-		nes_debug(NES_DBG_NETDEV, "MAC for " NIPQUAD_FMT " not in ARP table - cannot %s\n",
-			  HIPQUAD(ip_addr),
-			  action == NES_ARP_RESOLVE ? "resolve" : "delete");
+		nes_debug(NES_DBG_NETDEV, "MAC for %pI4 not in ARP table - cannot %s\n",
+			  &ip_addr, action == NES_ARP_RESOLVE ? "resolve" : "delete");
 		return -1;
 	}
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index e0c7dfa..753a983 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -732,29 +732,6 @@
 	do { (void) (priv); } while (0)
 #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG_DATA */
 
-
-#define IPOIB_GID_FMT		"%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:" \
-				"%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x"
-
-#define IPOIB_GID_RAW_ARG(gid)	((u8 *)(gid))[0], \
-				((u8 *)(gid))[1], \
-				((u8 *)(gid))[2], \
-				((u8 *)(gid))[3], \
-				((u8 *)(gid))[4], \
-				((u8 *)(gid))[5], \
-				((u8 *)(gid))[6], \
-				((u8 *)(gid))[7], \
-				((u8 *)(gid))[8], \
-				((u8 *)(gid))[9], \
-				((u8 *)(gid))[10],\
-				((u8 *)(gid))[11],\
-				((u8 *)(gid))[12],\
-				((u8 *)(gid))[13],\
-				((u8 *)(gid))[14],\
-				((u8 *)(gid))[15]
-
-#define IPOIB_GID_ARG(gid)	IPOIB_GID_RAW_ARG((gid).raw)
-
 #define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff)
 
 #endif /* _IPOIB_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 7b14c2c..47d588b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1128,8 +1128,8 @@
 		goto err_send_cm;
 	}
 
-	ipoib_dbg(priv, "Request connection 0x%x for gid " IPOIB_GID_FMT " qpn 0x%x\n",
-		  p->qp->qp_num, IPOIB_GID_ARG(pathrec->dgid), qpn);
+	ipoib_dbg(priv, "Request connection 0x%x for gid %pI6 qpn 0x%x\n",
+		  p->qp->qp_num, pathrec->dgid.raw, qpn);
 
 	return 0;
 
@@ -1276,8 +1276,8 @@
 	if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
 		list_move(&tx->list, &priv->cm.reap_list);
 		queue_work(ipoib_workqueue, &priv->cm.reap_task);
-		ipoib_dbg(priv, "Reap connection for gid " IPOIB_GID_FMT "\n",
-			  IPOIB_GID_ARG(tx->neigh->dgid));
+		ipoib_dbg(priv, "Reap connection for gid %pI6\n",
+			  tx->neigh->dgid.raw);
 		tx->neigh = NULL;
 	}
 }
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fddded7..b3a6718 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -359,9 +359,9 @@
 	spin_lock_irq(&priv->lock);
 
 	list_for_each_entry_safe(path, tp, &priv->path_list, list) {
-		ipoib_dbg(priv, "mark path LID 0x%04x GID " IPOIB_GID_FMT " invalid\n",
+		ipoib_dbg(priv, "mark path LID 0x%04x GID %pI6 invalid\n",
 			be16_to_cpu(path->pathrec.dlid),
-			IPOIB_GID_ARG(path->pathrec.dgid));
+			path->pathrec.dgid.raw);
 		path->valid =  0;
 	}
 
@@ -413,11 +413,11 @@
 	unsigned long flags;
 
 	if (!status)
-		ipoib_dbg(priv, "PathRec LID 0x%04x for GID " IPOIB_GID_FMT "\n",
-			  be16_to_cpu(pathrec->dlid), IPOIB_GID_ARG(pathrec->dgid));
+		ipoib_dbg(priv, "PathRec LID 0x%04x for GID %pI6\n",
+			  be16_to_cpu(pathrec->dlid), pathrec->dgid.raw);
 	else
-		ipoib_dbg(priv, "PathRec status %d for GID " IPOIB_GID_FMT "\n",
-			  status, IPOIB_GID_ARG(path->pathrec.dgid));
+		ipoib_dbg(priv, "PathRec status %d for GID %pI6\n",
+			  status, path->pathrec.dgid.raw);
 
 	skb_queue_head_init(&skqueue);
 
@@ -527,8 +527,8 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	ipoib_dbg(priv, "Start path record lookup for " IPOIB_GID_FMT "\n",
-		  IPOIB_GID_ARG(path->pathrec.dgid));
+	ipoib_dbg(priv, "Start path record lookup for %pI6\n",
+		  path->pathrec.dgid.raw);
 
 	init_completion(&path->done);
 
@@ -764,12 +764,11 @@
 
 			if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
 			    (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
-				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x "
-					   IPOIB_GID_FMT "\n",
+				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
 					   skb->dst ? "neigh" : "dst",
 					   be16_to_cpup((__be16 *) skb->data),
 					   IPOIB_QPN(phdr->hwaddr),
-					   IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
+					   phdr->hwaddr + 4);
 				dev_kfree_skb_any(skb);
 				++dev->stats.tx_dropped;
 				return NETDEV_TX_OK;
@@ -845,9 +844,9 @@
 	else
 		return;
 	ipoib_dbg(priv,
-		  "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
+		  "neigh_cleanup for %06x %pI6\n",
 		  IPOIB_QPN(n->ha),
-		  IPOIB_GID_RAW_ARG(n->ha + 4));
+		  n->ha + 4);
 
 	spin_lock_irqsave(&priv->lock, flags);
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index d9d1223..a2eb3b9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -71,9 +71,8 @@
 	struct ipoib_neigh *neigh, *tmp;
 	int tx_dropped = 0;
 
-	ipoib_dbg_mcast(netdev_priv(dev),
-			"deleting multicast group " IPOIB_GID_FMT "\n",
-			IPOIB_GID_ARG(mcast->mcmember.mgid));
+	ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group %pI6\n",
+			mcast->mcmember.mgid.raw);
 
 	spin_lock_irq(&priv->lock);
 
@@ -205,9 +204,8 @@
 
 	if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
 		if (test_and_set_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
-			ipoib_warn(priv, "multicast group " IPOIB_GID_FMT
-				   " already attached\n",
-				   IPOIB_GID_ARG(mcast->mcmember.mgid));
+			ipoib_warn(priv, "multicast group %pI6 already attached\n",
+				   mcast->mcmember.mgid.raw);
 
 			return 0;
 		}
@@ -215,9 +213,8 @@
 		ret = ipoib_mcast_attach(dev, be16_to_cpu(mcast->mcmember.mlid),
 					 &mcast->mcmember.mgid, set_qkey);
 		if (ret < 0) {
-			ipoib_warn(priv, "couldn't attach QP to multicast group "
-				   IPOIB_GID_FMT "\n",
-				   IPOIB_GID_ARG(mcast->mcmember.mgid));
+			ipoib_warn(priv, "couldn't attach QP to multicast group %pI6\n",
+				   mcast->mcmember.mgid.raw);
 
 			clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags);
 			return ret;
@@ -248,9 +245,8 @@
 			mcast->ah = ah;
 			spin_unlock_irq(&priv->lock);
 
-			ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT
-					" AV %p, LID 0x%04x, SL %d\n",
-					IPOIB_GID_ARG(mcast->mcmember.mgid),
+			ipoib_dbg_mcast(priv, "MGID %pI6 AV %p, LID 0x%04x, SL %d\n",
+					mcast->mcmember.mgid.raw,
 					mcast->ah->ah,
 					be16_to_cpu(mcast->mcmember.mlid),
 					mcast->mcmember.sl);
@@ -295,9 +291,8 @@
 
 	if (status) {
 		if (mcast->logcount++ < 20)
-			ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for "
-					IPOIB_GID_FMT ", status %d\n",
-					IPOIB_GID_ARG(mcast->mcmember.mgid), status);
+			ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for %pI6, status %d\n",
+					mcast->mcmember.mgid.raw, status);
 
 		/* Flush out any queued packets */
 		netif_tx_lock_bh(dev);
@@ -356,9 +351,8 @@
 		ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
 			   ret);
 	} else {
-		ipoib_dbg_mcast(priv, "no multicast record for " IPOIB_GID_FMT
-				", starting join\n",
-				IPOIB_GID_ARG(mcast->mcmember.mgid));
+		ipoib_dbg_mcast(priv, "no multicast record for %pI6, starting join\n",
+				mcast->mcmember.mgid.raw);
 	}
 
 	return ret;
@@ -386,9 +380,8 @@
 	struct net_device *dev = mcast->dev;
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	ipoib_dbg_mcast(priv, "join completion for " IPOIB_GID_FMT
-			" (status %d)\n",
-			IPOIB_GID_ARG(mcast->mcmember.mgid), status);
+	ipoib_dbg_mcast(priv, "join completion for %pI6 (status %d)\n",
+			mcast->mcmember.mgid.raw, status);
 
 	/* We trap for port events ourselves. */
 	if (status == -ENETRESET)
@@ -417,15 +410,11 @@
 
 	if (mcast->logcount++ < 20) {
 		if (status == -ETIMEDOUT) {
-			ipoib_dbg_mcast(priv, "multicast join failed for " IPOIB_GID_FMT
-					", status %d\n",
-					IPOIB_GID_ARG(mcast->mcmember.mgid),
-					status);
+			ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n",
+					mcast->mcmember.mgid.raw, status);
 		} else {
-			ipoib_warn(priv, "multicast join failed for "
-				   IPOIB_GID_FMT ", status %d\n",
-				   IPOIB_GID_ARG(mcast->mcmember.mgid),
-				   status);
+			ipoib_warn(priv, "multicast join failed for %pI6, status %d\n",
+				   mcast->mcmember.mgid.raw, status);
 		}
 	}
 
@@ -457,8 +446,7 @@
 	ib_sa_comp_mask comp_mask;
 	int ret = 0;
 
-	ipoib_dbg_mcast(priv, "joining MGID " IPOIB_GID_FMT "\n",
-			IPOIB_GID_ARG(mcast->mcmember.mgid));
+	ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
 
 	rec.mgid     = mcast->mcmember.mgid;
 	rec.port_gid = priv->local_gid;
@@ -643,8 +631,8 @@
 		ib_sa_free_multicast(mcast->mc);
 
 	if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
-		ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
-				IPOIB_GID_ARG(mcast->mcmember.mgid));
+		ipoib_dbg_mcast(priv, "leaving MGID %pI6\n",
+				mcast->mcmember.mgid.raw);
 
 		/* Remove ourselves from the multicast group */
 		ret = ib_detach_mcast(priv->qp, &mcast->mcmember.mgid,
@@ -675,8 +663,8 @@
 	mcast = __ipoib_mcast_find(dev, mgid);
 	if (!mcast) {
 		/* Let's create a new send only group now */
-		ipoib_dbg_mcast(priv, "setting up send only multicast group for "
-				IPOIB_GID_FMT "\n", IPOIB_GID_RAW_ARG(mgid));
+		ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n",
+				mgid);
 
 		mcast = ipoib_mcast_alloc(dev, 0);
 		if (!mcast) {
@@ -809,14 +797,14 @@
 			/* ignore group which is directly joined by userspace */
 			if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&
 			    !ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {
-				ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid "
-						IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mgid));
+				ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %pI6\n",
+						mgid.raw);
 				continue;
 			}
 
 			/* Not found or send-only group, let's add a new entry */
-			ipoib_dbg_mcast(priv, "adding multicast entry for mgid "
-					IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mgid));
+			ipoib_dbg_mcast(priv, "adding multicast entry for mgid %pI6\n",
+					mgid.raw);
 
 			nmcast = ipoib_mcast_alloc(dev, 0);
 			if (!nmcast) {
@@ -849,8 +837,8 @@
 	list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
 		if (!test_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags) &&
 		    !test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
-			ipoib_dbg_mcast(priv, "deleting multicast group " IPOIB_GID_FMT "\n",
-					IPOIB_GID_ARG(mcast->mcmember.mgid));
+			ipoib_dbg_mcast(priv, "deleting multicast group %pI6\n",
+					mcast->mcmember.mgid.raw);
 
 			rb_erase(&mcast->rb_node, &priv->multicast_tree);
 
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 26ff621..e418b96 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -515,14 +515,14 @@
 	struct sockaddr *src, *dst;
 	int err = 0;
 
-	sprintf(ib_conn->name,"%d.%d.%d.%d:%d",
-		NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port);
+	sprintf(ib_conn->name, "%pI4:%d",
+		&dst_addr->sin_addr.s_addr, dst_addr->sin_port);
 
 	/* the device is known only --after-- address resolution */
 	ib_conn->device = NULL;
 
-	iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n",
-		 NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port);
+	iser_err("connecting to: %pI4, port 0x%x\n",
+		 &dst_addr->sin_addr, dst_addr->sin_port);
 
 	ib_conn->state = ISER_CONN_PENDING;
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 5b8b533..7c13db8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1514,15 +1514,7 @@
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
-	return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[0]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[1]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[2]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[3]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[4]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[5]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[6]),
-		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
+	return sprintf(buf, "%pI6\n", target->path.dgid.raw);
 }
 
 static ssize_t show_orig_dgid(struct device *dev,
@@ -1534,15 +1526,7 @@
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
-	return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-		       be16_to_cpu(target->orig_dgid[0]),
-		       be16_to_cpu(target->orig_dgid[1]),
-		       be16_to_cpu(target->orig_dgid[2]),
-		       be16_to_cpu(target->orig_dgid[3]),
-		       be16_to_cpu(target->orig_dgid[4]),
-		       be16_to_cpu(target->orig_dgid[5]),
-		       be16_to_cpu(target->orig_dgid[6]),
-		       be16_to_cpu(target->orig_dgid[7]));
+	return sprintf(buf, "%pI6\n", target->orig_dgid);
 }
 
 static ssize_t show_zero_req_lim(struct device *dev,
@@ -1883,19 +1867,12 @@
 
 	shost_printk(KERN_DEBUG, target->scsi_host, PFX
 		     "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
-		     "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+		     "service_id %016llx dgid %pI6\n",
 	       (unsigned long long) be64_to_cpu(target->id_ext),
 	       (unsigned long long) be64_to_cpu(target->ioc_guid),
 	       be16_to_cpu(target->path.pkey),
 	       (unsigned long long) be64_to_cpu(target->service_id),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[0]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[2]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[4]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[6]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[8]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[10]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[12]),
-	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[14]));
+	       target->path.dgid.raw);
 
 	ret = srp_create_target_ib(target);
 	if (ret)
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index bb904a0..60c82d7 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1654,9 +1654,10 @@
 	unsigned char *p;
 	int period;
 	u32 code;
-	u32 my_seq, addr;
-	u32 your_seq, mask;
-	u32 local;
+	u32 my_seq;
+	u32 your_seq;
+	__be32 local;
+	__be32 *addr, *mask;
 	u16 unused;
 
 	if (skb->len < 14)
@@ -1671,27 +1672,20 @@
 		isdn_net_ciscohdlck_slarp_send_reply(lp);
 		break;
 	case CISCO_SLARP_REPLY:
-		addr = ntohl(*(u32 *)p);
-		mask = ntohl(*(u32 *)(p+4));
-		if (mask != 0xfffffffc)
+		addr = (__be32 *)p;
+		mask = (__be32 *)(p + 4);
+		if (*mask != cpu_to_be32(0xfffffffc))
 			goto slarp_reply_out;
-		if ((addr & 3) == 0 || (addr & 3) == 3)
+		if ((*addr & cpu_to_be32(3)) == cpu_to_be32(0) ||
+		    (*addr & cpu_to_be32(3)) == cpu_to_be32(3))
 			goto slarp_reply_out;
-		local = addr ^ 3;
-		printk(KERN_INFO "%s: got slarp reply: "
-			"remote ip: %d.%d.%d.%d, "
-			"local ip: %d.%d.%d.%d "
-			"mask: %d.%d.%d.%d\n",
-		       lp->netdev->dev->name,
-		       HIPQUAD(addr),
-		       HIPQUAD(local),
-		       HIPQUAD(mask));
+		local = *addr ^ cpu_to_be32(3);
+		printk(KERN_INFO "%s: got slarp reply: remote ip: %pI4, local ip: %pI4 mask: %pI4\n",
+		       lp->netdev->dev->name, addr, &local, mask);
 		break;
   slarp_reply_out:
-		 printk(KERN_INFO "%s: got invalid slarp "
-				 "reply (%d.%d.%d.%d/%d.%d.%d.%d) "
-				 "- ignored\n", lp->netdev->dev->name,
-				 HIPQUAD(addr), HIPQUAD(mask));
+		printk(KERN_INFO "%s: got invalid slarp reply (%pI4/%pI4) - ignored\n",
+		       lp->netdev->dev->name, addr, mask);
 		break;
 	case CISCO_SLARP_KEEPALIVE:
 		period = (int)((jiffies - lp->cisco_last_slarp_in
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 5f79c8d..676413a 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -270,7 +270,7 @@
 	/* do the MAC address reading after initializing the dvb_adapter */
 	if (fc->get_mac_addr(fc, 0) == 0) {
 		u8 *b = fc->dvb_adapter.proposed_mac;
-		info("MAC address = %02x:%02x:%02x:%02x:%02x:%02x", b[0],b[1],b[2],b[3],b[4],b[5]);
+		info("MAC address = %pM", b);
 		flexcop_set_mac_filter(fc,b);
 		flexcop_mac_filter_ctrl(fc,1);
 	} else
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index aa3db57..29e8f15 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -917,9 +917,7 @@
 	}
 	memset(&state->mac_address, '\0', 8);
 	memcpy(&state->mac_address, &state->rxbuffer, 6);
-	dprintk(verbose, DST_ERROR, 1, "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]",
-		state->mac_address[0], state->mac_address[1], state->mac_address[2],
-		state->mac_address[4], state->mac_address[5], state->mac_address[6]);
+	dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
 
 	return 0;
 }
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 14e627e..d15984e 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -697,8 +697,7 @@
 	};
 
 	dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
-	dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac);
 }
 
 static int __devinit dm1105_probe(struct pci_dev *pdev,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index ce8cd0c..8a7d87b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -91,10 +91,7 @@
 
 	if (adap->dev->props.read_mac_address) {
 		if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0)
-			info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",adap->dvb_adap.proposed_mac[0],
-					adap->dvb_adap.proposed_mac[1], adap->dvb_adap.proposed_mac[2],
-					adap->dvb_adap.proposed_mac[3], adap->dvb_adap.proposed_mac[4],
-					adap->dvb_adap.proposed_mac[5]);
+			info("MAC address: %pM",adap->dvb_adap.proposed_mac);
 		else
 			err("MAC address reading failed.");
 	}
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index a9653c6..d101b30 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -560,8 +560,7 @@
 	mac[4] = (val >> 8) & 0xff;
 	mac[5] = (val >> 0) & 0xff;
 
-	dev_info(&pluto->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	dev_info(&pluto->pdev->dev, "MAC %pM\n", mac);
 }
 
 static int __devinit pluto_read_serial(struct pluto *pluto)
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 603ffd0..eeef0bd 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -1427,11 +1427,9 @@
 		printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
 		       "registered as '%s'\n", ioc->name, dev->name);
 		printk(KERN_INFO MYNAM ": %s/%s: "
-		       "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+		       "LanAddr = %pM\n",
 		       IOC_AND_NETDEV_NAMES_s_s(dev),
-		       dev->dev_addr[0], dev->dev_addr[1],
-		       dev->dev_addr[2], dev->dev_addr[3],
-		       dev->dev_addr[4], dev->dev_addr[5]);
+		       dev->dev_addr);
 	
 		ioc->netdev = dev;
 
@@ -1516,9 +1514,8 @@
 
 		printk (KERN_WARNING MYNAM ": %s: WARNING - Broadcast swap F/W bug detected!\n",
 				NETDEV_PTR_TO_IOC_NAME_s(dev));
-		printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-				fch->saddr[0], fch->saddr[1], fch->saddr[2],
-				fch->saddr[3], fch->saddr[4], fch->saddr[5]);
+		printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %pM\n",
+				fch->saddr);
 	}
 
 	if (*fch->daddr & 1) {
@@ -1537,7 +1534,6 @@
 
 	fcllc = (struct fcllc *)skb->data;
 
-
 	/* Strip the SNAP header from ARP packets since we don't
 	 * pass them through to the 802.2/SNAP layers.
 	 */
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 7d15e7c..3a44db1 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -725,7 +725,6 @@
 		insb(DATAPORT, skb_put(skb, pkt_len), pkt_len);
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += pkt_len;
 	}
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 900b0ff..95bd95f 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -177,7 +177,6 @@
     int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
     static unsigned version_printed;
     unsigned long vendor_id;
-    DECLARE_MAC_BUF(mac);
 
     if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
 	return -EBUSY;
@@ -228,7 +227,7 @@
     /* Retrieve and print the ethernet address. */
     for (i = 0; i < 6; i++)
 	dev->dev_addr[i] = inb(ioaddr + i);
-    printk("%s", print_mac(mac, dev->dev_addr));
+    printk("%pM", dev->dev_addr);
 
     /* Map the 8390 back into the window. */
     outb(ECNTRL_THIN, ioaddr + 0x406);
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index a424869..e669da7 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -672,7 +672,6 @@
 					skb->protocol = eth_type_trans(skb,dev);
 					dev->stats.rx_bytes += skb->len;
 					netif_rx(skb);
-					dev->last_rx = jiffies;
 				}
 			}
 			adapter->dmaing = 0;
@@ -1385,7 +1384,6 @@
 	unsigned long timeout;
 	unsigned long cookie = 0;
 	int err = -ENODEV;
-	DECLARE_MAC_BUF(mac);
 
 	/*
 	 *  setup adapter structure
@@ -1522,9 +1520,9 @@
 	 * print remainder of startup message
 	 */
 	printk(KERN_INFO "%s: 3c505 at %#lx, irq %d, dma %d, "
-	       "addr %s, ",
+	       "addr %pM, ",
 	       dev->name, dev->base_addr, dev->irq, dev->dma,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 	/*
 	 * read more information from the adapter
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 030c147..b8585ec 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -357,7 +357,6 @@
 	static unsigned char init_ID_done, version_printed;
 	int i, irq, irqval, retval;
 	struct net_local *lp;
-	DECLARE_MAC_BUF(mac);
 
 	if (init_ID_done == 0) {
 		ushort lrs_state = 0xff;
@@ -405,7 +404,7 @@
 	outb(0x01, ioaddr + MISC_CTRL);
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + i);
-	printk(" %s", print_mac(mac, dev->dev_addr));
+	printk(" %pM", dev->dev_addr);
 
 	if (mem_start)
 		net_debug = mem_start & 7;
@@ -866,7 +865,6 @@
 
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index c7a4f3b..535c234 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -541,7 +541,6 @@
 {
 	struct el3_private *lp = netdev_priv(dev);
 	int err;
-	DECLARE_MAC_BUF(mac);
 	const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
 
 	spin_lock_init(&lp->lock);
@@ -575,9 +574,9 @@
 	}
 
 	printk(KERN_INFO "%s: 3c5x9 found at %#3.3lx, %s port, "
-	       "address %s, IRQ %d.\n",
+	       "address %pM, IRQ %d.\n",
 	       dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
-	       print_mac(mac, dev->dev_addr), dev->irq);
+	       dev->dev_addr, dev->irq);
 
 	if (el3_debug > 0)
 		printk(KERN_INFO "%s", version);
@@ -1075,7 +1074,6 @@
 				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
 				skb->protocol = eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_bytes += pkt_len;
 				dev->stats.rx_packets++;
 				continue;
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index a0f8b6e..7f99500 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -570,7 +570,6 @@
 	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
 	int i;
 	int irq;
-	DECLARE_MAC_BUF(mac);
 
 #ifdef __ISAPNP__
 	if (idev) {
@@ -636,7 +635,7 @@
 	checksum = (checksum ^ (checksum >> 8)) & 0xff;
 	if (checksum != 0x00)
 		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
-	printk(" %s", print_mac(mac, dev->dev_addr));
+	printk(" %pM", dev->dev_addr);
 	if (eeprom[16] == 0x11c7) {	/* Corkscrew */
 		if (request_dma(dev->dma, "3c515")) {
 			printk(", DMA %d allocation failed", dev->dma);
@@ -1302,7 +1301,6 @@
 				outw(RxDiscard, ioaddr + EL3_CMD);	/* Pop top Rx packet. */
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 				/* Wait a limited time to go to next packet. */
@@ -1389,7 +1387,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 		entry = (++vp->cur_rx) % RX_RING_SIZE;
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index e2ce41d..0885aee 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -383,7 +383,6 @@
 {
 	int len = 0;
 	struct net_device *dev = d;
-	DECLARE_MAC_BUF(mac);
 
 	if (dev == NULL)
 		return len;
@@ -398,8 +397,8 @@
 	len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ?
 		       "External" : "Internal");
 	len += sprintf(buf + len, "Device: %s\n", dev->name);
-	len += sprintf(buf + len, "Hardware Address: %s\n",
-		       print_mac(mac, dev->dev_addr));
+	len += sprintf(buf + len, "Hardware Address: %pM\n",
+		       dev->dev_addr);
 
 	return len;
 }				/* elmc_getinfo() */
@@ -417,7 +416,6 @@
 	unsigned int size = 0;
 	int retval;
 	struct priv *pr = dev->priv;
-	DECLARE_MAC_BUF(mac);
 
 	if (MCA_bus == 0) {
 		return -ENODEV;
@@ -543,8 +541,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(dev->base_addr + i);
 
-	printk(KERN_INFO "%s: hardware address %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: hardware address %pM\n",
+	       dev->name, dev->dev_addr);
 
 	dev->open = &elmc_open;
 	dev->stop = &elmc_close;
@@ -985,7 +983,6 @@
 					skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
-					dev->last_rx = jiffies;
 					dev->stats.rx_packets++;
 					dev->stats.rx_bytes += totlen;
 				} else {
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index abc84f7..2df3af3 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -335,7 +335,6 @@
 		"82586 initialisation failure",
 		"Adapter list configuration error"
 	};
-	DECLARE_MAC_BUF(mac);
 
 	/* Time to play MCA games */
 
@@ -405,7 +404,7 @@
 		dev->dev_addr[i] = mca_read_pos(slot,3);
 	}
 
-	printk("%s: Address %s", dev->name, print_mac(mac, dev->dev_addr));
+	printk("%s: Address %pM", dev->name, dev->dev_addr);
 
 	mca_write_pos(slot, 6, 0);
 	mca_write_pos(slot, 7, 0);
@@ -1187,7 +1186,6 @@
 			}
 
 			skb->protocol=eth_type_trans(skb,dev);
-			dev->last_rx = jiffies;
  			dev->stats.rx_packets++;
  			dev->stats.rx_bytes += length;
 			netif_rx(skb);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 9ba295d..3893f50 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1013,7 +1013,6 @@
 	const char *print_name = "3c59x";
 	struct pci_dev *pdev = NULL;
 	struct eisa_device *edev = NULL;
-	DECLARE_MAC_BUF(mac);
 
 	if (!printed_version) {
 		printk (version);
@@ -1026,7 +1025,7 @@
 		}
 
 		if ((edev = DEVICE_EISA(gendev))) {
-			print_name = edev->dev.bus_id;
+			print_name = dev_name(&edev->dev);
 		}
 	}
 
@@ -1206,7 +1205,7 @@
 		((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 	if (print_info)
-		printk(" %s", print_mac(mac, dev->dev_addr));
+		printk(" %pM", dev->dev_addr);
 	/* Unfortunately an all zero eeprom passes the checksum and this
 	   gets found in the wild in failure cases. Crypto is hard 8) */
 	if (!is_valid_ether_addr(dev->dev_addr)) {
@@ -2447,7 +2446,6 @@
 				iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				/* Wait a limited time to go to next packet. */
 				for (i = 200; i >= 0; i--)
@@ -2530,7 +2528,6 @@
 				}
 			}
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 		entry = (++vp->cur_rx) % RX_RING_SIZE;
@@ -2886,7 +2883,7 @@
 		strcpy(info->bus_info, pci_name(VORTEX_PCI(vp)));
 	} else {
 		if (VORTEX_EISA(vp))
-			sprintf(info->bus_info, vp->gendev->bus_id);
+			sprintf(info->bus_info, dev_name(vp->gendev));
 		else
 			sprintf(info->bus_info, "EISA 0x%lx %d",
 					dev->base_addr, dev->irq);
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index ad6b8a5..7a331ac 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -336,7 +336,6 @@
                                          len);
                         skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += len;
                 }
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 9ba1f0b..664bd73 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -457,7 +457,6 @@
 
 	cp->dev->stats.rx_packets++;
 	cp->dev->stats.rx_bytes += skb->len;
-	cp->dev->last_rx = jiffies;
 
 #if CP_VLAN_TAG_USED
 	if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) {
@@ -1826,7 +1825,6 @@
 	void __iomem *regs;
 	resource_size_t pciaddr;
 	unsigned int addr_len, i, pci_using_dac;
-	DECLARE_MAC_BUF(mac);
 
 #ifndef MODULE
 	static int version_printed;
@@ -1967,10 +1965,10 @@
 		goto err_out_iomap;
 
 	printk (KERN_INFO "%s: RTL-8139C+ at 0x%lx, "
-		"%s, IRQ %d\n",
+		"%pM, IRQ %d\n",
 		dev->name,
 		dev->base_addr,
-		print_mac(mac, dev->dev_addr),
+		dev->dev_addr,
 		dev->irq);
 
 	pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 63f906b..37456ad 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -925,7 +925,6 @@
 	int i, addr_len, option;
 	void __iomem *ioaddr;
 	static int board_idx = -1;
-	DECLARE_MAC_BUF(mac);
 
 	assert (pdev != NULL);
 	assert (ent != NULL);
@@ -1024,11 +1023,11 @@
 	pci_set_drvdata (pdev, dev);
 
 	printk (KERN_INFO "%s: %s at 0x%lx, "
-		"%s, IRQ %d\n",
+		"%pM, IRQ %d\n",
 		dev->name,
 		board_info[ent->driver_data].name,
 		dev->base_addr,
-		print_mac(mac, dev->dev_addr),
+		dev->dev_addr,
 		dev->irq);
 
 	printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",
@@ -2026,7 +2025,6 @@
 
 			skb->protocol = eth_type_trans (skb, dev);
 
-			dev->last_rx = jiffies;
 			dev->stats.rx_bytes += pkt_size;
 			dev->stats.rx_packets++;
 
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index da292e6..717fe2f 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -841,7 +841,6 @@
 						pkt_len);
 #endif
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes+=pkt_len;
 			}
@@ -1116,12 +1115,8 @@
 
 static void print_eth(unsigned char *add, char *str)
 {
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-
-	printk(KERN_DEBUG "i596 0x%p, %s --> %s %02X%02X, %s\n",
-	       add, print_mac(mac, add + 6), print_mac(mac2, add),
-	       add[12], add[13], str);
+	printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
+	       add, add + 6, add, add[12], add[13], str);
 }
 
 static int io = 0x300;
@@ -1544,7 +1539,6 @@
 		struct dev_mc_list *dmi;
 		unsigned char *cp;
 		struct mc_cmd *cmd;
-		DECLARE_MAC_BUF(mac);
 
 		if (wait_cfg(dev, &lp->mc_cmd.cmd, 1000, "multicast list change request timed out"))
 			return;
@@ -1555,8 +1549,8 @@
 		for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
 			memcpy(cp, dmi->dmi_addr, 6);
 			if (i596_debug > 1)
-				DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %s\n",
-						dev->name, print_mac(mac, cp)));
+				DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %pM\n",
+						dev->name, cp));
 		}
 		i596_add_cmd(dev, &cmd->cmd);
 	}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 11f143f..732ea83 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -61,6 +61,7 @@
 config BONDING
 	tristate "Bonding driver support"
 	depends on INET
+	depends on IPV6 || IPV6=n
 	---help---
 	  Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
 	  Channels together. This is called 'Etherchannel' by Cisco,
@@ -978,6 +979,20 @@
 	  called smc911x.  If you want to compile it as a module, say M 
 	  here and read <file:Documentation/kbuild/modules.txt>
 
+config SMSC911X
+	tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
+	depends on ARM || SUPERH
+	select CRC32
+	select MII
+	select PHYLIB
+	---help---
+	  Say Y here if you want support for SMSC LAN911x and LAN921x families
+	  of ethernet controllers.
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/networking/net-modules.txt>. The module
+	  will be called smsc911x.
+
 config NET_VENDOR_RACAL
 	bool "Racal-Interlan (Micom) NI cards"
 	depends on ISA
@@ -1414,19 +1429,6 @@
 	depends on NET_PCI && PCI && MIPS
 	select PHYLIB
 
-config EEPRO100
-	tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
-	depends on NET_PCI && PCI
-	select MII
-	help
-	  If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
-	  card, say Y and read the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called eepro100.
-
-
 config E100
 	tristate "Intel(R) PRO/100+ support"
 	depends on NET_PCI && PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f19acf8..e06829a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -53,7 +53,6 @@
 obj-$(CONFIG_TYPHOON) += typhoon.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_E100) += e100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o
@@ -220,6 +219,7 @@
 obj-$(CONFIG_MYRI10GE) += myri10ge/
 obj-$(CONFIG_SMC91X) += smc91x.o
 obj-$(CONFIG_SMC911X) += smc911x.o
+obj-$(CONFIG_SMSC911X) += smsc911x.o
 obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 9c08374..7a60bdd 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -324,7 +324,6 @@
 					 len);
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += len;
 		}
@@ -710,7 +709,6 @@
 	unsigned long board, base_addr, mem_start;
 	struct resource *r1, *r2;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	board = z->resource.start;
 	base_addr = board+A2065_LANCE;
@@ -787,8 +785,7 @@
 	zorro_set_drvdata(z, dev);
 
 	printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address "
-	       "%s\n", dev->name, board,
-	       print_mac(mac, dev->dev_addr));
+	       "%pM\n", dev->name, board, dev->dev_addr);
 
 	return 0;
 }
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index b144863..071a851 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -146,7 +146,6 @@
 static int __init ac_probe1(int ioaddr, struct net_device *dev)
 {
 	int i, retval;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -171,8 +170,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
 
-	printk(KERN_DEBUG "AC3200 in EISA slot %d, node %s",
-	       ioaddr/0x1000, print_mac(mac, dev->dev_addr));
+	printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
+	       ioaddr/0x1000, dev->dev_addr);
 #if 0
 	/* Check the vendor ID/prefix. Redundant after checking the EISA ID */
 	if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 66de80b..b9d35f6 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -892,7 +892,6 @@
 	int board_idx, ecode = 0;
 	short i;
 	unsigned char cache_size;
-	DECLARE_MAC_BUF(mac);
 
 	ap = netdev_priv(dev);
 	regs = ap->regs;
@@ -1019,7 +1018,7 @@
 	dev->dev_addr[4] = (mac2 >> 8) & 0xff;
 	dev->dev_addr[5] = mac2 & 0xff;
 
-	printk("MAC: %s\n", print_mac(mac, dev->dev_addr));
+	printk("MAC: %pM\n", dev->dev_addr);
 
 	/*
 	 * Looks like this is necessary to deal with on all architectures,
@@ -2034,7 +2033,6 @@
 #endif
 			netif_rx(skb);
 
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += retdesc->size;
 
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 07a6697..0bc4f54 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -809,7 +809,6 @@
 			lp->coal_conf.rx_packets++;
 			lp->coal_conf.rx_bytes += pkt_len;
 			num_rx_pkt++;
-			dev->last_rx = jiffies;
 
 		err_next_pkt:
 			lp->rx_ring[rx_index].buff_phy_addr
@@ -1821,7 +1820,6 @@
 	unsigned long reg_addr,reg_len;
 	struct amd8111e_priv* lp;
 	struct net_device* dev;
-	DECLARE_MAC_BUF(mac);
 
 	err = pci_enable_device(pdev);
 	if(err){
@@ -1963,8 +1961,8 @@
     	chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
 	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
 	       dev->name,MODULE_VERS);
-	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %s\n",
-	       dev->name, chip_version, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
+	       dev->name, chip_version, dev->dev_addr);
 	if (lp->ext_phy_id)
 		printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
 		       dev->name, lp->ext_phy_id, lp->ext_phy_addr);
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 867f6ff..7426f69 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -207,7 +207,6 @@
     int neX000, ctron;
 #endif
     static unsigned version_printed;
-    DECLARE_MAC_BUF(mac);
 
     if (ei_debug  &&  version_printed++ == 0)
 	printk(version);
@@ -323,7 +322,7 @@
     for(i = 0; i < ETHER_ADDR_LEN; i++)
 	dev->dev_addr[i] = SA_prom[i];
 
-    printk(" %s\n", print_mac(mac, dev->dev_addr));
+    printk(" %pM\n", dev->dev_addr);
 
     printk("%s: %s found.\n", dev->name, name);
 
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 735fc94..0c4e3c5 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -851,7 +851,6 @@
 
         /* Send packet to a higher place. */
         netif_rx(skb);
-	dev->last_rx = jiffies;
 }
 
 static void cops_timeout(struct net_device *dev)
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index fef5560..8d109a5 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -783,7 +783,6 @@
 
 	/* toss it onwards */
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	return 0;
 }
 
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index e0a18e7..60088b3 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -125,7 +125,6 @@
 	skb->protocol = __constant_htons(ETH_P_ARCNET);
 ;
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 }
 
 
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c
index 02cb8f1..67bc47a 100644
--- a/drivers/net/arcnet/capmode.c
+++ b/drivers/net/arcnet/capmode.c
@@ -151,7 +151,6 @@
 	skb->protocol = __constant_htons(ETH_P_ARCNET);
 ;
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 }
 
 
diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
index dab185b..994be49 100644
--- a/drivers/net/arcnet/rfc1051.c
+++ b/drivers/net/arcnet/rfc1051.c
@@ -159,7 +159,6 @@
 
 	skb->protocol = type_trans(skb, dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 }
 
 
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
index 6d6d95c..962641e 100644
--- a/drivers/net/arcnet/rfc1201.c
+++ b/drivers/net/arcnet/rfc1201.c
@@ -230,7 +230,6 @@
 
 		skb->protocol = type_trans(skb, dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 	} else {		/* split packet */
 		/*
 		 * NOTE: MSDOS ARP packet correction should only need to apply to
@@ -366,7 +365,6 @@
 
 			skb->protocol = type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 		}
 	}
 }
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 29e53eb..e1d72e0 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -165,7 +165,6 @@
     struct net_device *dev;
     struct ariadne_private *priv;
     int err;
-    DECLARE_MAC_BUF(mac);
 
     r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
     if (!r1)
@@ -215,9 +214,8 @@
     }
     zorro_set_drvdata(z, dev);
 
-    printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address "
-	   "%s\n", dev->name, board,
-	   print_mac(mac, dev->dev_addr));
+    printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
+           dev->name, board, dev->dev_addr);
 
     return 0;
 }
@@ -613,14 +611,10 @@
 
 #if 0
 {
-    DECLARE_MAC_BUF(mac);
-    DECLARE_MAC_BUF(mac2);
-
-    printk(KERN_DEBUG "TX pkt type 0x%04x from %s to %s "
+    printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
 	   " data 0x%08x len %d\n",
 	   ((u_short *)skb->data)[6],
-	   print_mac(mac, ((const u8 *)skb->data)+6),
-	   print_mac(mac, (const u8 *)skb->data),
+	   skb->data + 6, skb->data,
 	   (int)skb->data, (int)skb->len);
 }
 #endif
@@ -743,25 +737,22 @@
 	    skb->protocol=eth_type_trans(skb,dev);
 #if 0
 {
-	    DECLARE_MAC_BUF(mac);
-
 	    printk(KERN_DEBUG "RX pkt type 0x%04x from ",
 		   ((u_short *)skb->data)[6]);
 	    {
 		u_char *ptr = &((u_char *)skb->data)[6];
-		printk("%s", print_mac(mac, ptr));
+		printk("%pM", ptr);
 	    }
 	    printk(" to ");
 	    {
 		u_char *ptr = (u_char *)skb->data;
-		printk("%s", print_mac(mac, ptr));
+		printk("%pM", ptr);
 	    }
 	    printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
 }
 #endif
 
 	    netif_rx(skb);
-	    dev->last_rx = jiffies;
 	    dev->stats.rx_packets++;
 	    dev->stats.rx_bytes += pkt_len;
 	}
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index aa4a524..0c628a9 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -532,7 +532,6 @@
 			am_writeword(dev, hdraddr + 2, RMD_OWN);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			priv->stats.rx_bytes += len;
 			priv->stats.rx_packets ++;
 		} else {
@@ -745,10 +744,8 @@
 
 	ret = register_netdev(dev);
 	if (ret == 0) {
-		DECLARE_MAC_BUF(mac);
-
-		printk(KERN_INFO "%s: ether address %s\n",
-		       dev->name, print_mac(mac, dev->dev_addr));
+		printk(KERN_INFO "%s: ether address %pM\n",
+		       dev->name, dev->dev_addr);
 		return 0;
 	}
 
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 6f431a8..442938d 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -485,7 +485,6 @@
 static int set_mac_address(struct net_device *dev, void* addr)
 {
 	struct sockaddr *address = addr;
-	DECLARE_MAC_BUF(mac);
 
 	if (!is_valid_ether_addr(address->sa_data))
 		return -EADDRNOTAVAIL;
@@ -493,8 +492,8 @@
 	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
 	update_mac_address(dev);
 
-	printk("%s: Setting MAC address to %s\n", dev->name,
-	       print_mac(mac, dev->dev_addr));
+	printk("%s: Setting MAC address to %pM\n", dev->name,
+	       dev->dev_addr);
 
 	return 0;
 }
@@ -894,7 +893,6 @@
 			memcpy(skb_put(skb, pktlen), p_recv, pktlen);
 
 			skb->protocol = eth_type_trans(skb, dev);
-			dev->last_rx = jiffies;
 			dev->stats.rx_bytes += pktlen;
 			netif_rx(skb);
 		}
@@ -978,7 +976,6 @@
 	struct at91_private *lp;
 	unsigned int val;
 	int res;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(sizeof(struct at91_private));
 	if (!dev)
@@ -1084,11 +1081,11 @@
 		gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
 
 	/* Display ethernet banner */
-	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%s)\n",
+	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
 	       dev->name, (uint) dev->base_addr, dev->irq,
 	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
 	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
 		printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
 	else if (phy_type == MII_LXT971A_ID)
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 1267444..588c973 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -259,8 +259,6 @@
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, dev);
 
-			dev->last_rx = jiffies;
-
 			netif_receive_skb(skb);
 
 			ep->stats.rx_packets++;
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index 3bb9e29..e380de4 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -996,7 +996,6 @@
 {
 	struct net_device *dev;
 	int i, ret = 0;
-	DECLARE_MAC_BUF(mac);
 
 	ether1_banner();
 
@@ -1044,8 +1043,8 @@
 	if (ret)
 		goto free;
 
-	printk(KERN_INFO "%s: ether1 in slot %d, %s\n",
-		dev->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: ether1 in slot %d, %pM\n",
+		dev->name, ec->slot_no, dev->dev_addr);
     
 	ecard_set_drvdata(ec, dev);
 	return 0;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 67e96ae..21a7bef 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -776,7 +776,6 @@
 	const struct ether3_data *data = id->data;
 	struct net_device *dev;
 	int bus_type, ret;
-	DECLARE_MAC_BUF(mac);
 
 	ether3_banner();
 
@@ -859,8 +858,8 @@
 	if (ret)
 		goto free;
 
-	printk("%s: %s in slot %d, %s\n",
-	       dev->name, data->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+	printk("%s: %s in slot %d, %pM\n",
+	       dev->name, data->name, ec->slot_no, dev->dev_addr);
 
 	ecard_set_drvdata(ec, dev);
 	return 0;
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 5c5f1e4..9eb9d1b 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -648,7 +648,6 @@
 	struct net_device *dev;
 	struct etherh_priv *eh;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	etherh_banner();
 
@@ -746,8 +745,8 @@
 	if (ret)
 		goto free;
 
-	printk(KERN_INFO "%s: %s in slot %d, %s\n",
-		dev->name, data->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: %s in slot %d, %pM\n",
+		dev->name, data->name, ec->slot_no, dev->dev_addr);
 
 	ecard_set_drvdata(ec, dev);
 
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index e2d702b..14ffa2a 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -588,7 +588,6 @@
 		debug_pkt(dev, "eth_poll", skb->data, skb->len);
 
 		skb->protocol = eth_type_trans(skb, dev);
-		dev->last_rx = jiffies;
 		port->stat.rx_packets++;
 		port->stat.rx_bytes += skb->len;
 		netif_receive_skb(skb);
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 7e874d4..2d4b5c3 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -265,7 +265,6 @@
 	unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
 	int slot, ret = -ENODEV;
 	struct net_local *lp = netdev_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -397,7 +396,7 @@
 			dev->dev_addr[i] = val;
 		}
 	}
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 
 	/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
 	   rather than 150 ohm shielded twisted pair compensation.
@@ -768,7 +767,6 @@
 			insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
 			skb->protocol=eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 0860cc280..701214b 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -466,7 +466,6 @@
 	int 					i;
 	static int 				did_version;
 	unsigned short			save1, save2;
-	DECLARE_MAC_BUF(mac);
 
 	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
 				  (long)memaddr, (long)ioaddr ));
@@ -595,7 +594,7 @@
 		i = IO->mem;
 		break;
 	}
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 	if (lp->cardtype == OLD_RIEBL) {
 		printk( "%s: Warning: This is a default ethernet address!\n",
 				dev->name );
@@ -778,8 +777,6 @@
 	int entry, len;
 	struct lance_tx_head *head;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
 				  dev->name, DREG ));
@@ -802,12 +799,10 @@
 
 	/* Fill in a Tx ring entry */
 	if (lance_debug >= 3) {
-		printk( "%s: TX pkt type 0x%04x from "
-				"%s to %s"
+		printk( "%s: TX pkt type 0x%04x from %pM to %pM"
 				" data at 0x%08x len %d\n",
 				dev->name, ((u_short *)skb->data)[6],
-				print_mac(mac, &skb->data[6]),
-				print_mac(mac2, skb->data),
+				&skb->data[6], skb->data,
 				(int)skb->data, (int)skb->len );
 	}
 
@@ -1019,14 +1014,12 @@
 
 				if (lance_debug >= 3) {
 					u_char *data = PKTBUF_ADDR(head);
-					DECLARE_MAC_BUF(mac);
-					DECLARE_MAC_BUF(mac2);
 
-					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %s to %s "
+					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
 						   "data %02x %02x %02x %02x %02x %02x %02x %02x "
 						   "len %d\n",
 						   dev->name, ((u_short *)data)[6],
-						   print_mac(mac, &data[6]), print_mac(mac2, data),
+						   &data[6], data,
 						   data[15], data[16], data[17], data[18],
 						   data[19], data[20], data[21], data[22],
 						   pkt_len);
@@ -1037,7 +1030,6 @@
 				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 			}
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 9b60352..0f8c752 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -1460,7 +1460,6 @@
 				netif_receive_skb(skb);
 			}
 
-			netdev->last_rx = jiffies;
 skip_pkt:
 	/* skip current packet whether it's ok or not. */
 			rx_page->read_offset +=
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 246d92b..09ed2fd 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1390,7 +1390,8 @@
 	/* auto-neg, insert timer to re-config phy */
 	if (!adapter->phy_timer_pending) {
 		adapter->phy_timer_pending = true;
-		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+		mod_timer(&adapter->phy_config_timer,
+			  round_jiffies(jiffies + 3 * HZ));
 	}
 
 	return 0;
@@ -1662,6 +1663,7 @@
 
 static void atl1_inc_smb(struct atl1_adapter *adapter)
 {
+	struct net_device *netdev = adapter->netdev;
 	struct stats_msg_block *smb = adapter->smb.smb;
 
 	/* Fill out the OS statistics structure */
@@ -1704,30 +1706,30 @@
 	adapter->soft_stats.tx_trunc += smb->tx_trunc;
 	adapter->soft_stats.tx_pause += smb->tx_pause;
 
-	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
-	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
-	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
-	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
-	adapter->net_stats.multicast = adapter->soft_stats.multicast;
-	adapter->net_stats.collisions = adapter->soft_stats.collisions;
-	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
-	adapter->net_stats.rx_over_errors =
+	netdev->stats.rx_packets = adapter->soft_stats.rx_packets;
+	netdev->stats.tx_packets = adapter->soft_stats.tx_packets;
+	netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;
+	netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;
+	netdev->stats.multicast = adapter->soft_stats.multicast;
+	netdev->stats.collisions = adapter->soft_stats.collisions;
+	netdev->stats.rx_errors = adapter->soft_stats.rx_errors;
+	netdev->stats.rx_over_errors =
 		adapter->soft_stats.rx_missed_errors;
-	adapter->net_stats.rx_length_errors =
+	netdev->stats.rx_length_errors =
 		adapter->soft_stats.rx_length_errors;
-	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
-	adapter->net_stats.rx_frame_errors =
+	netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+	netdev->stats.rx_frame_errors =
 		adapter->soft_stats.rx_frame_errors;
-	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
-	adapter->net_stats.rx_missed_errors =
+	netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+	netdev->stats.rx_missed_errors =
 		adapter->soft_stats.rx_missed_errors;
-	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
-	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
-	adapter->net_stats.tx_aborted_errors =
+	netdev->stats.tx_errors = adapter->soft_stats.tx_errors;
+	netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+	netdev->stats.tx_aborted_errors =
 		adapter->soft_stats.tx_aborted_errors;
-	adapter->net_stats.tx_window_errors =
+	netdev->stats.tx_window_errors =
 		adapter->soft_stats.tx_window_errors;
-	adapter->net_stats.tx_carrier_errors =
+	netdev->stats.tx_carrier_errors =
 		adapter->soft_stats.tx_carrier_errors;
 }
 
@@ -1860,7 +1862,7 @@
 				       adapter->rx_buffer_len + NET_IP_ALIGN);
 		if (unlikely(!skb)) {
 			/* Better luck next round */
-			adapter->net_stats.rx_dropped++;
+			adapter->netdev->stats.rx_dropped++;
 			break;
 		}
 
@@ -2026,8 +2028,6 @@
 		buffer_info->skb = NULL;
 		buffer_info->alloced = 0;
 		rrd->xsz.valid = 0;
-
-		adapter->netdev->last_rx = jiffies;
 	}
 
 	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
@@ -2524,17 +2524,6 @@
 	return IRQ_HANDLED;
 }
 
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
-	/* Reset the timer */
-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
 
 /*
  * atl1_phy_config - Timer Call-back
@@ -2607,7 +2596,6 @@
 	if (unlikely(err))
 		goto err_up;
 
-	mod_timer(&adapter->watchdog_timer, jiffies);
 	atlx_irq_enable(adapter);
 	atl1_check_link(adapter);
 	netif_start_queue(netdev);
@@ -2625,7 +2613,6 @@
 	struct net_device *netdev = adapter->netdev;
 
 	netif_stop_queue(netdev);
-	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_config_timer);
 	adapter->phy_timer_pending = false;
 
@@ -2983,7 +2970,7 @@
 	netdev->open = &atl1_open;
 	netdev->stop = &atl1_close;
 	netdev->hard_start_xmit = &atl1_xmit_frame;
-	netdev->get_stats = &atlx_get_stats;
+
 	netdev->set_multicast_list = &atlx_set_multi;
 	netdev->set_mac_address = &atl1_set_mac;
 	netdev->change_mtu = &atl1_change_mtu;
@@ -3049,13 +3036,8 @@
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &atl1_watchdog;
-	adapter->watchdog_timer.data = (unsigned long)adapter;
-
-	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = &atl1_phy_config;
-	adapter->phy_config_timer.data = (unsigned long)adapter;
+	setup_timer(&adapter->phy_config_timer, &atl1_phy_config,
+		    (unsigned long)adapter);
 	adapter->phy_timer_pending = false;
 
 	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
@@ -3173,8 +3155,6 @@
 	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
 	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
 	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
-	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
-	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
 	{"multicast", ATL1_STAT(soft_stats.multicast)},
 	{"collisions", ATL1_STAT(soft_stats.collisions)},
 	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
index ffa73fc..146372f 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/atlx/atl1.h
@@ -754,7 +754,7 @@
 struct atl1_adapter {
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-	struct net_device_stats net_stats;
+
 	struct atl1_sft_stats soft_stats;
 	struct vlan_group *vlgrp;
 	u32 rx_buffer_len;
@@ -765,7 +765,7 @@
 	struct work_struct tx_timeout_task;
 	struct work_struct link_chg_task;
 	struct work_struct pcie_dma_to_rst_task;
-	struct timer_list watchdog_timer;
+
 	struct timer_list phy_config_timer;
 	bool phy_timer_pending;
 
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index f5bdc92..60c9e53 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -418,7 +418,7 @@
 				 * Check that some rx space is free. If not,
 				 * free one and mark stats->rx_dropped++.
 				 */
-				adapter->net_stats.rx_dropped++;
+				netdev->stats.rx_dropped++;
 				break;
 			}
 			skb_reserve(skb, NET_IP_ALIGN);
@@ -435,20 +435,19 @@
 			} else
 #endif
 			netif_rx(skb);
-			adapter->net_stats.rx_bytes += rx_size;
-			adapter->net_stats.rx_packets++;
-			netdev->last_rx = jiffies;
+			netdev->stats.rx_bytes += rx_size;
+			netdev->stats.rx_packets++;
 		} else {
-			adapter->net_stats.rx_errors++;
+			netdev->stats.rx_errors++;
 
 			if (rxd->status.ok && rxd->status.pkt_size <= 60)
-				adapter->net_stats.rx_length_errors++;
+				netdev->stats.rx_length_errors++;
 			if (rxd->status.mcast)
-				adapter->net_stats.multicast++;
+				netdev->stats.multicast++;
 			if (rxd->status.crc)
-				adapter->net_stats.rx_crc_errors++;
+				netdev->stats.rx_crc_errors++;
 			if (rxd->status.align)
-				adapter->net_stats.rx_frame_errors++;
+				netdev->stats.rx_frame_errors++;
 		}
 
 		/* advance write ptr */
@@ -463,6 +462,7 @@
 
 static void atl2_intr_tx(struct atl2_adapter *adapter)
 {
+	struct net_device *netdev = adapter->netdev;
 	u32 txd_read_ptr;
 	u32 txs_write_ptr;
 	struct tx_pkt_status *txs;
@@ -522,20 +522,20 @@
 
 		/* tx statistics: */
 		if (txs->ok) {
-			adapter->net_stats.tx_bytes += txs->pkt_size;
-			adapter->net_stats.tx_packets++;
+			netdev->stats.tx_bytes += txs->pkt_size;
+			netdev->stats.tx_packets++;
 		}
 		else
-			adapter->net_stats.tx_errors++;
+			netdev->stats.tx_errors++;
 
 		if (txs->defer)
-			adapter->net_stats.collisions++;
+			netdev->stats.collisions++;
 		if (txs->abort_col)
-			adapter->net_stats.tx_aborted_errors++;
+			netdev->stats.tx_aborted_errors++;
 		if (txs->late_col)
-			adapter->net_stats.tx_window_errors++;
+			netdev->stats.tx_window_errors++;
 		if (txs->underun)
-			adapter->net_stats.tx_fifo_errors++;
+			netdev->stats.tx_fifo_errors++;
 	} while (1);
 
 	if (free_hole) {
@@ -621,7 +621,7 @@
 
 	/* link event */
 	if (status & (ISR_PHY | ISR_MANUAL)) {
-		adapter->net_stats.tx_carrier_errors++;
+		adapter->netdev->stats.tx_carrier_errors++;
 		atl2_check_for_link(adapter);
 	}
 
@@ -723,7 +723,7 @@
 
 	clear_bit(__ATL2_DOWN, &adapter->flags);
 
-	mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ);
+	mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 4*HZ));
 
 	val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
 	ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
@@ -900,19 +900,6 @@
 }
 
 /*
- * atl2_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atl2_get_stats(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	return &adapter->net_stats;
-}
-
-/*
  * atl2_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
  * @new_mtu: new value for maximum frame size
@@ -1050,18 +1037,21 @@
 static void atl2_watchdog(unsigned long data)
 {
 	struct atl2_adapter *adapter = (struct atl2_adapter *) data;
-	u32 drop_rxd, drop_rxs;
-	unsigned long flags;
 
 	if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
+		u32 drop_rxd, drop_rxs;
+		unsigned long flags;
+
 		spin_lock_irqsave(&adapter->stats_lock, flags);
 		drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV);
 		drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV);
-		adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs);
 		spin_unlock_irqrestore(&adapter->stats_lock, flags);
 
+		adapter->netdev->stats.rx_over_errors += drop_rxd + drop_rxs;
+
 		/* Reset the timer */
-		mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ);
+		mod_timer(&adapter->watchdog_timer,
+			  round_jiffies(jiffies + 4 * HZ));
 	}
 }
 
@@ -1265,7 +1255,8 @@
 	 * (if interval smaller than 5 seconds, something strange) */
 	if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
 		if (!test_and_set_bit(0, &adapter->cfg_phy))
-			mod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ);
+			mod_timer(&adapter->phy_config_timer,
+				  round_jiffies(jiffies + 5 * HZ));
 	}
 
 	return 0;
@@ -1396,7 +1387,6 @@
 	netdev->open = &atl2_open;
 	netdev->stop = &atl2_close;
 	netdev->hard_start_xmit = &atl2_xmit_frame;
-	netdev->get_stats = &atl2_get_stats;
 	netdev->set_multicast_list = &atl2_set_multi;
 	netdev->set_mac_address = &atl2_set_mac;
 	netdev->change_mtu = &atl2_change_mtu;
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
index 09974df..d918bbe 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/atlx/atl2.h
@@ -453,7 +453,6 @@
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-	struct net_device_stats net_stats;
 #ifdef NETIF_F_HW_VLAN_TX
 	struct vlan_group *vlgrp;
 #endif
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index 3cc9d10..3dc0142 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -182,19 +182,6 @@
 }
 
 /*
- * atlx_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atlx_get_stats(struct net_device *netdev)
-{
-	struct atlx_adapter *adapter = netdev_priv(netdev);
-	return &adapter->net_stats;
-}
-
-/*
  * atlx_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
  */
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index c10cd80..405c2dc 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -248,7 +248,6 @@
 	struct net_local *lp;
 	int saved_ctrl_reg, status, i;
 	int res;
-	DECLARE_MAC_BUF(mac);
 
 	outb(0xff, ioaddr + PAR_DATA);
 	/* Save the original value of the Control register, in case we guessed
@@ -324,8 +323,8 @@
 #endif
 
 	printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, "
-	       "SAPROM %s.\n",
-	       dev->name, dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr));
+	       "SAPROM %pM.\n",
+	       dev->name, dev->base_addr, dev->irq, dev->dev_addr);
 
 	/* Reset the ethernet hardware and activate the printer pass-through. */
 	write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 019b13c..2b69b2b 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1240,7 +1240,6 @@
 		/* next descriptor */
 		prxd = aup->rx_dma_ring[aup->rx_head];
 		buff_stat = prxd->buff_stat;
-		dev->last_rx = jiffies;
 	}
 	return 0;
 }
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 9a314d8..337488e 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -758,13 +758,10 @@
 #endif
 	ax_NS8390_init(dev, 0);
 
-	if (first_init) {
-		DECLARE_MAC_BUF(mac);
-
-		dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %s\n",
+	if (first_init)
+		dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %pM\n",
 			 ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
-			 print_mac(mac, dev->dev_addr));
-	}
+			 dev->dev_addr);
 
 	ret = register_netdev(dev);
 	if (ret)
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index c3bda5c..2c7a32e 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -829,7 +829,6 @@
 		skb->ip_summed = CHECKSUM_NONE;
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		netif_receive_skb(skb);
-		bp->dev->last_rx = jiffies;
 		received++;
 		budget--;
 	next_pkt:
@@ -2117,7 +2116,6 @@
 	struct net_device *dev;
 	struct b44 *bp;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	instance++;
 
@@ -2213,8 +2211,8 @@
 	 */
 	b44_chip_reset(bp, B44_CHIP_RESET_FULL);
 
-	printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
+	       dev->name, dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index b458d60..78e31aa 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -741,7 +741,6 @@
 	blackfin_dcache_invalidate_range((unsigned long)skb->head,
 					 (unsigned long)skb->tail);
 
-	dev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, dev);
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
 	skb->csum = current_rx_ptr->status.ip_payload_csum;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index a42bd19..8a546a3 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -716,13 +716,11 @@
 			skb_put(skb, nb);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			++dev->stats.rx_packets;
 			dev->stats.rx_bytes += nb;
 		} else {
 			++dev->stats.rx_dropped;
 		}
-		dev->last_rx = jiffies;
 		if ((skb = bp->rx_bufs[i]) == NULL) {
 			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
 			if (skb != NULL)
@@ -1258,7 +1256,6 @@
 	unsigned char addr[6];
 	struct net_device *dev;
 	int is_bmac_plus = ((int)match->data) != 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
 		printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
@@ -1368,8 +1365,8 @@
 		goto err_out_irq2;
 	}
 
-	printk(KERN_INFO "%s: BMAC%s at %s",
-	       dev->name, (is_bmac_plus ? "+" : ""), print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: BMAC%s at %pM",
+	       dev->name, (is_bmac_plus ? "+" : ""), dev->dev_addr);
 	XXDEBUG((", base_addr=%#0lx", dev->base_addr));
 	printk("\n");
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 430d430..51b163a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3000,7 +3000,6 @@
 #endif
 			netif_receive_skb(skb);
 
-		bp->dev->last_rx = jiffies;
 		rx_pkt++;
 
 next_rx:
@@ -7700,7 +7699,6 @@
 	struct bnx2 *bp;
 	int rc;
 	char str[40];
-	DECLARE_MAC_BUF(mac);
 
 	if (version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -7767,14 +7765,14 @@
 	}
 
 	printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
-		"IRQ %d, node addr %s\n",
+		"IRQ %d, node addr %pM\n",
 		dev->name,
 		board_info[ent->driver_data].name,
 		((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
 		((CHIP_ID(bp) & 0x0ff0) >> 4),
 		bnx2_bus_string(bp, str),
 		dev->base_addr,
-		bp->pdev->irq, print_mac(mac, dev->dev_addr));
+		bp->pdev->irq, dev->dev_addr);
 
 	return 0;
 }
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 600210d..49f8e78 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -1328,7 +1328,6 @@
 			dev_kfree_skb(skb);
 		}
 
-		bp->dev->last_rx = jiffies;
 
 		/* put new skb in bin */
 		fp->tpa_pool[queue].skb = new_skb;
@@ -1557,7 +1556,6 @@
 #endif
 			netif_receive_skb(skb);
 
-		bp->dev->last_rx = jiffies;
 
 next_rx:
 		rx_buf->skb = NULL;
@@ -8769,7 +8767,6 @@
 	rc = 0;
 
 test_loopback_rx_exit:
-	bp->dev->last_rx = jiffies;
 
 	fp->rx_bd_cons = NEXT_RX_IDX(fp->rx_bd_cons);
 	fp->rx_bd_prod = NEXT_RX_IDX(fp->rx_bd_prod);
@@ -9853,11 +9850,8 @@
 			     mclist && (i < dev->mc_count);
 			     i++, mclist = mclist->next) {
 
-				DP(NETIF_MSG_IFUP, "Adding mcast MAC: "
-				   "%02x:%02x:%02x:%02x:%02x:%02x\n",
-				   mclist->dmi_addr[0], mclist->dmi_addr[1],
-				   mclist->dmi_addr[2], mclist->dmi_addr[3],
-				   mclist->dmi_addr[4], mclist->dmi_addr[5]);
+				DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+				   mclist->dmi_addr);
 
 				crc = crc32c_le(0, mclist->dmi_addr, ETH_ALEN);
 				bit = (crc >> 24) & 0xff;
@@ -10092,8 +10086,7 @@
 
 	dev->irq = pdev->irq;
 
-	bp->regview = ioremap_nocache(dev->base_addr,
-				      pci_resource_len(pdev, 0));
+	bp->regview = pci_ioremap_bar(pdev, 0);
 	if (!bp->regview) {
 		printk(KERN_ERR PFX "Cannot map register space, aborting\n");
 		rc = -ENOMEM;
@@ -10194,7 +10187,6 @@
 	struct net_device *dev = NULL;
 	struct bnx2x *bp;
 	int rc;
-	DECLARE_MAC_BUF(mac);
 
 	if (version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -10238,7 +10230,7 @@
 	       bnx2x_get_pcie_width(bp),
 	       (bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
 	       dev->base_addr, bp->pdev->irq);
-	printk(KERN_CONT "node addr %s\n", print_mac(mac, dev->dev_addr));
+	printk(KERN_CONT "node addr %pM\n", dev->dev_addr);
 	return 0;
 
 init_one_exit:
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index 5cdae2b..6f9c6fa 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -6,3 +6,6 @@
 
 bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
 
+ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
+bonding-objs += $(ipv6-y)
+
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6106660..ba1372f 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -27,6 +27,7 @@
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
+#include <linux/etherdevice.h>
 #include <linux/if_bonding.h>
 #include <linux/pkt_sched.h>
 #include <net/net_namespace.h>
@@ -236,6 +237,17 @@
 	return &(SLAVE_AD_INFO(slave->next).aggregator);
 }
 
+/*
+ * __agg_has_partner
+ *
+ * Return nonzero if aggregator has a partner (denoted by a non-zero ether
+ * address for the partner).  Return 0 if not.
+ */
+static inline int __agg_has_partner(struct aggregator *agg)
+{
+	return !is_zero_ether_addr(agg->partner_system.mac_addr_value);
+}
+
 /**
  * __disable_port - disable the port's slave
  * @port: the port we're looking at
@@ -274,14 +286,14 @@
  * __get_agg_selection_mode - get the aggregator selection mode
  * @port: the port we're looking at
  *
- * Get the aggregator selection mode. Can be %BANDWIDTH or %COUNT.
+ * Get the aggregator selection mode. Can be %STABLE, %BANDWIDTH or %COUNT.
  */
 static inline u32 __get_agg_selection_mode(struct port *port)
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
 	if (bond == NULL) {
-		return AD_BANDWIDTH;
+		return BOND_AD_STABLE;
 	}
 
 	return BOND_AD_INFO(bond).agg_select_mode;
@@ -1414,9 +1426,82 @@
 	// else set ready=FALSE in all aggregator's ports
 	__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
 
-	if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) {
-		ad_agg_selection_logic(aggregator);
+	aggregator = __get_first_agg(port);
+	ad_agg_selection_logic(aggregator);
+}
+
+/*
+ * Decide if "agg" is a better choice for the new active aggregator that
+ * the current best, according to the ad_select policy.
+ */
+static struct aggregator *ad_agg_selection_test(struct aggregator *best,
+						struct aggregator *curr)
+{
+	/*
+	 * 0. If no best, select current.
+	 *
+	 * 1. If the current agg is not individual, and the best is
+	 *    individual, select current.
+	 *
+	 * 2. If current agg is individual and the best is not, keep best.
+	 *
+	 * 3. Therefore, current and best are both individual or both not
+	 *    individual, so:
+	 *
+	 * 3a. If current agg partner replied, and best agg partner did not,
+	 *     select current.
+	 *
+	 * 3b. If current agg partner did not reply and best agg partner
+	 *     did reply, keep best.
+	 *
+	 * 4.  Therefore, current and best both have partner replies or
+	 *     both do not, so perform selection policy:
+	 *
+	 * BOND_AD_COUNT: Select by count of ports.  If count is equal,
+	 *     select by bandwidth.
+	 *
+	 * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth.
+	 */
+	if (!best)
+		return curr;
+
+	if (!curr->is_individual && best->is_individual)
+		return curr;
+
+	if (curr->is_individual && !best->is_individual)
+		return best;
+
+	if (__agg_has_partner(curr) && !__agg_has_partner(best))
+		return curr;
+
+	if (!__agg_has_partner(curr) && __agg_has_partner(best))
+		return best;
+
+	switch (__get_agg_selection_mode(curr->lag_ports)) {
+	case BOND_AD_COUNT:
+		if (curr->num_of_ports > best->num_of_ports)
+			return curr;
+
+		if (curr->num_of_ports < best->num_of_ports)
+			return best;
+
+		/*FALLTHROUGH*/
+	case BOND_AD_STABLE:
+	case BOND_AD_BANDWIDTH:
+		if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best))
+			return curr;
+
+		break;
+
+	default:
+		printk(KERN_WARNING DRV_NAME
+		       ": %s: Impossible agg select mode %d\n",
+		       curr->slave->dev->master->name,
+		       __get_agg_selection_mode(curr->lag_ports));
+		break;
 	}
+
+	return best;
 }
 
 /**
@@ -1424,156 +1509,138 @@
  * @aggregator: the aggregator we're looking at
  *
  * It is assumed that only one aggregator may be selected for a team.
- * The logic of this function is to select (at first time) the aggregator with
- * the most ports attached to it, and to reselect the active aggregator only if
- * the previous aggregator has no more ports related to it.
+ *
+ * The logic of this function is to select the aggregator according to
+ * the ad_select policy:
+ *
+ * BOND_AD_STABLE: select the aggregator with the most ports attached to
+ * it, and to reselect the active aggregator only if the previous
+ * aggregator has no more ports related to it.
+ *
+ * BOND_AD_BANDWIDTH: select the aggregator with the highest total
+ * bandwidth, and reselect whenever a link state change takes place or the
+ * set of slaves in the bond changes.
+ *
+ * BOND_AD_COUNT: select the aggregator with largest number of ports
+ * (slaves), and reselect whenever a link state change takes place or the
+ * set of slaves in the bond changes.
  *
  * FIXME: this function MUST be called with the first agg in the bond, or
  * __get_active_agg() won't work correctly. This function should be better
  * called with the bond itself, and retrieve the first agg from it.
  */
-static void ad_agg_selection_logic(struct aggregator *aggregator)
+static void ad_agg_selection_logic(struct aggregator *agg)
 {
-	struct aggregator *best_aggregator = NULL, *active_aggregator = NULL;
-	struct aggregator *last_active_aggregator = NULL, *origin_aggregator;
+	struct aggregator *best, *active, *origin;
 	struct port *port;
-	u16 num_of_aggs=0;
 
-	origin_aggregator = aggregator;
+	origin = agg;
 
-	//get current active aggregator
-	last_active_aggregator = __get_active_agg(aggregator);
+	active = __get_active_agg(agg);
+	best = active;
 
-	// search for the aggregator with the most ports attached to it.
 	do {
-		// count how many candidate lag's we have
-		if (aggregator->lag_ports) {
-			num_of_aggs++;
-		}
-		if (aggregator->is_active && !aggregator->is_individual &&   // if current aggregator is the active aggregator
-		    MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) {   // and partner answers to 802.3ad PDUs
-			if (aggregator->num_of_ports) {	// if any ports attached to the current aggregator
-				best_aggregator=NULL;	 // disregard the best aggregator that was chosen by now
-				break;		 // stop the selection of other aggregator if there are any ports attached to this active aggregator
-			} else { // no ports attached to this active aggregator
-				aggregator->is_active = 0; // mark this aggregator as not active anymore
-			}
-		}
-		if (aggregator->num_of_ports) {	// if any ports attached
-			if (best_aggregator) {	// if there is a candidte aggregator
-				//The reasons for choosing new best aggregator:
-				// 1. if current agg is NOT individual and the best agg chosen so far is individual OR
-				// current and best aggs are both individual or both not individual, AND
-				// 2a.  current agg partner reply but best agg partner do not reply OR
-				// 2b.  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND
-				//      current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN
-				//      current agg become best agg so far
+		agg->is_active = 0;
 
-				//if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator
-				if (!aggregator->is_individual && best_aggregator->is_individual) {
-					best_aggregator=aggregator;
-				}
-				// current and best aggs are both individual or both not individual
-				else if ((aggregator->is_individual && best_aggregator->is_individual) ||
-					 (!aggregator->is_individual && !best_aggregator->is_individual)) {
-					//  current and best aggs are both individual or both not individual AND
-					//  current agg partner reply but best agg partner do not reply
-					if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
-					     !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
-						best_aggregator=aggregator;
-					}
-					//  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply
-					else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
-						    MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
-						if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&&
-						    (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) {
-							best_aggregator=aggregator;
-						} else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) {
-							if (((aggregator->num_of_ports > best_aggregator->num_of_ports) &&
-							     (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))||
-							    ((aggregator->num_of_ports == best_aggregator->num_of_ports) &&
-							     ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) >
-							      (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) {
-								best_aggregator=aggregator;
-							}
-						}
-					}
-				}
-			} else {
-				best_aggregator=aggregator;
-			}
-		}
-		aggregator->is_active = 0; // mark all aggregators as not active anymore
-	} while ((aggregator = __get_next_agg(aggregator)));
+		if (agg->num_of_ports)
+			best = ad_agg_selection_test(best, agg);
 
-	// if we have new aggregator selected, don't replace the old aggregator if it has an answering partner,
-	// or if both old aggregator and new aggregator don't have answering partner
-	if (best_aggregator) {
-		if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled &&
-		    (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) ||   // partner answers OR
-		     (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) &&	// both old and new
-		      !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr))))     // partner do not answer
-		   ) {
-			// if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing)
-			// -> don't replace otherwise.
-			if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) {
-				best_aggregator=NULL;
-				last_active_aggregator->is_active = 1; // don't replace good old aggregator
+	} while ((agg = __get_next_agg(agg)));
 
+	if (best &&
+	    __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
+		/*
+		 * For the STABLE policy, don't replace the old active
+		 * aggregator if it's still active (it has an answering
+		 * partner) or if both the best and active don't have an
+		 * answering partner.
+		 */
+		if (active && active->lag_ports &&
+		    active->lag_ports->is_enabled &&
+		    (__agg_has_partner(active) ||
+		     (!__agg_has_partner(active) && !__agg_has_partner(best)))) {
+			if (!(!active->actor_oper_aggregator_key &&
+			      best->actor_oper_aggregator_key)) {
+				best = NULL;
+				active->is_active = 1;
 			}
 		}
 	}
 
-	// if there is new best aggregator, activate it
-	if (best_aggregator) {
-		for (aggregator = __get_first_agg(best_aggregator->lag_ports);
-		    aggregator;
-		    aggregator = __get_next_agg(aggregator)) {
+	if (best && (best == active)) {
+		best = NULL;
+		active->is_active = 1;
+	}
 
-			dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
-					aggregator->aggregator_identifier, aggregator->num_of_ports,
-					aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
-					aggregator->is_individual, aggregator->is_active);
+	// if there is new best aggregator, activate it
+	if (best) {
+		dprintk("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+		       best->aggregator_identifier, best->num_of_ports,
+		       best->actor_oper_aggregator_key,
+		       best->partner_oper_aggregator_key,
+		       best->is_individual, best->is_active);
+		dprintk("best ports %p slave %p %s\n",
+		       best->lag_ports, best->slave,
+		       best->slave ? best->slave->dev->name : "NULL");
+
+		for (agg = __get_first_agg(best->lag_ports); agg;
+		     agg = __get_next_agg(agg)) {
+
+			dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+				agg->aggregator_identifier, agg->num_of_ports,
+				agg->actor_oper_aggregator_key,
+				agg->partner_oper_aggregator_key,
+				agg->is_individual, agg->is_active);
 		}
 
 		// check if any partner replys
-		if (best_aggregator->is_individual) {
-			printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from "
-			       "the link partner for any adapters in the bond\n",
-			       best_aggregator->slave->dev->master->name);
+		if (best->is_individual) {
+			printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad"
+			       " response from the link partner for any"
+			       " adapters in the bond\n",
+			       best->slave->dev->master->name);
 		}
 
-		// check if there are more than one aggregator
-		if (num_of_aggs > 1) {
-			dprintk("Warning: More than one Link Aggregation Group was "
-				"found in the bond. Only one group will function in the bond\n");
-		}
-
-		best_aggregator->is_active = 1;
-		dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier);
-		dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
-				best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
-				best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
-				best_aggregator->is_individual, best_aggregator->is_active);
+		best->is_active = 1;
+		dprintk("LAG %d chosen as the active LAG\n",
+			best->aggregator_identifier);
+		dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+			best->aggregator_identifier, best->num_of_ports,
+			best->actor_oper_aggregator_key,
+			best->partner_oper_aggregator_key,
+			best->is_individual, best->is_active);
 
 		// disable the ports that were related to the former active_aggregator
-		if (last_active_aggregator) {
-			for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+		if (active) {
+			for (port = active->lag_ports; port;
+			     port = port->next_port_in_aggregator) {
 				__disable_port(port);
 			}
 		}
 	}
 
-	// if the selected aggregator is of join individuals(partner_system is NULL), enable their ports
-	active_aggregator = __get_active_agg(origin_aggregator);
+	/*
+	 * if the selected aggregator is of join individuals
+	 * (partner_system is NULL), enable their ports
+	 */
+	active = __get_active_agg(origin);
 
-	if (active_aggregator) {
-		if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) {
-			for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+	if (active) {
+		if (!__agg_has_partner(active)) {
+			for (port = active->lag_ports; port;
+			     port = port->next_port_in_aggregator) {
 				__enable_port(port);
 			}
 		}
 	}
+
+	if (origin->slave) {
+		struct bonding *bond;
+
+		bond = bond_get_bond_by_slave(origin->slave);
+		if (bond)
+			bond_3ad_set_carrier(bond);
+	}
 }
 
 /**
@@ -1830,6 +1897,19 @@
 // Check aggregators status in team every T seconds
 #define AD_AGGREGATOR_SELECTION_TIMER  8
 
+/*
+ * bond_3ad_initiate_agg_selection(struct bonding *bond)
+ *
+ * Set the aggregation selection timer, to initiate an agg selection in
+ * the very near future.  Called during first initialization, and during
+ * any down to up transitions of the bond.
+ */
+void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
+{
+	BOND_AD_INFO(bond).agg_select_timer = timeout;
+	BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
+}
+
 static u16 aggregator_identifier;
 
 /**
@@ -1854,9 +1934,9 @@
 		// initialize how many times this module is called in one second(should be about every 100ms)
 		ad_ticks_per_sec = tick_resolution;
 
-		// initialize the aggregator selection timer(to activate an aggregation selection after initialize)
-		BOND_AD_INFO(bond).agg_select_timer = (AD_AGGREGATOR_SELECTION_TIMER * ad_ticks_per_sec);
-		BOND_AD_INFO(bond).agg_select_mode = AD_BANDWIDTH;
+		bond_3ad_initiate_agg_selection(bond,
+						AD_AGGREGATOR_SELECTION_TIMER *
+						ad_ticks_per_sec);
 	}
 }
 
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index b5ee45f..a803fe0 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -42,10 +42,11 @@
 	u8 mac_addr_value[ETH_ALEN];
 } mac_addr_t;
 
-typedef enum {
-	AD_BANDWIDTH = 0,
-	AD_COUNT
-} agg_selection_t;
+enum {
+	BOND_AD_STABLE = 0,
+	BOND_AD_BANDWIDTH = 1,
+	BOND_AD_COUNT = 2,
+};
 
 // rx machine states(43.4.11 in the 802.3ad standard)
 typedef enum {
@@ -277,6 +278,7 @@
 int  bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct work_struct *);
+void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
 void bond_3ad_adapter_speed_changed(struct slave *slave);
 void bond_3ad_adapter_duplex_changed(struct slave *slave);
 void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 87437c7..e170fa2 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -346,14 +346,18 @@
 
 static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
 {
-	struct bonding *bond = bond_dev->priv;
+	struct bonding *bond;
 	struct arp_pkt *arp = (struct arp_pkt *)skb->data;
 	int res = NET_RX_DROP;
 
 	if (dev_net(bond_dev) != &init_net)
 		goto out;
 
-	if (!(bond_dev->flags & IFF_MASTER))
+	while (bond_dev->priv_flags & IFF_802_1Q_VLAN)
+		bond_dev = vlan_dev_real_dev(bond_dev);
+
+	if (!(bond_dev->priv_flags & IFF_BONDING) ||
+	    !(bond_dev->flags & IFF_MASTER))
 		goto out;
 
 	if (!arp) {
@@ -368,6 +372,9 @@
 
 	if (arp->op_code == htons(ARPOP_REPLY)) {
 		/* update rx hash table for this ARP */
+		printk("rar: update orig %s bond_dev %s\n", orig_dev->name,
+		       bond_dev->name);
+		bond = bond_dev->priv;
 		rlb_update_entry_from_arp(bond, arp);
 		dprintk("Server received an ARP Reply from client\n");
 	}
@@ -818,7 +825,7 @@
 
 	/*initialize packet type*/
 	pk_type->type = __constant_htons(ETH_P_ARP);
-	pk_type->dev = bond->dev;
+	pk_type->dev = NULL;
 	pk_type->func = rlb_arp_recv;
 
 	/* register to receive ARPs */
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
new file mode 100644
index 0000000..7c78b7b
--- /dev/null
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright(c) 2008 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+
+//#define BONDING_DEBUG 1
+
+#include <linux/types.h>
+#include <linux/if_vlan.h>
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/addrconf.h>
+#include "bonding.h"
+
+/*
+ * Assign bond->master_ipv6 to the next IPv6 address in the list, or
+ * zero it out if there are none.
+ */
+static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+
+	if (!dev)
+		return;
+
+	idev = in6_dev_get(dev);
+	if (!idev)
+		return;
+
+	read_lock_bh(&idev->lock);
+	ifa = idev->addr_list;
+	if (ifa)
+		ipv6_addr_copy(addr, &ifa->addr);
+	else
+		ipv6_addr_set(addr, 0, 0, 0, 0);
+
+	read_unlock_bh(&idev->lock);
+
+	in6_dev_put(idev);
+}
+
+static void bond_na_send(struct net_device *slave_dev,
+			 struct in6_addr *daddr,
+			 int router,
+			 unsigned short vlan_id)
+{
+	struct in6_addr mcaddr;
+	struct icmp6hdr icmp6h = {
+		.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
+	};
+	struct sk_buff *skb;
+
+	icmp6h.icmp6_router = router;
+	icmp6h.icmp6_solicited = 0;
+	icmp6h.icmp6_override = 1;
+
+	addrconf_addr_solict_mult(daddr, &mcaddr);
+
+	dprintk("ipv6 na on slave %s: dest %pI6, src %pI6\n",
+	       slave->name, &mcaddr, daddr);
+
+	skb = ndisc_build_skb(slave_dev, &mcaddr, daddr, &icmp6h, daddr,
+			      ND_OPT_TARGET_LL_ADDR);
+
+	if (!skb) {
+		printk(KERN_ERR DRV_NAME ": NA packet allocation failed\n");
+		return;
+	}
+
+	if (vlan_id) {
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
+			return;
+		}
+	}
+
+	ndisc_send_skb(skb, slave_dev, NULL, &mcaddr, daddr, &icmp6h);
+}
+
+/*
+ * Kick out an unsolicited Neighbor Advertisement for an IPv6 address on
+ * the bonding master.  This will help the switch learn our address
+ * if in active-backup mode.
+ *
+ * Caller must hold curr_slave_lock for read or better
+ */
+void bond_send_unsolicited_na(struct bonding *bond)
+{
+	struct slave *slave = bond->curr_active_slave;
+	struct vlan_entry *vlan;
+	struct inet6_dev *idev;
+	int is_router;
+
+	dprintk("bond_send_unsol_na: bond %s slave %s\n", bond->dev->name,
+				slave ? slave->dev->name : "NULL");
+
+	if (!slave || !bond->send_unsol_na ||
+	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
+		return;
+
+	bond->send_unsol_na--;
+
+	idev = in6_dev_get(bond->dev);
+	if (!idev)
+		return;
+
+	is_router = !!idev->cnf.forwarding;
+
+	in6_dev_put(idev);
+
+	if (!ipv6_addr_any(&bond->master_ipv6))
+		bond_na_send(slave->dev, &bond->master_ipv6, is_router, 0);
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		if (!ipv6_addr_any(&vlan->vlan_ipv6)) {
+			bond_na_send(slave->dev, &vlan->vlan_ipv6, is_router,
+				     vlan->vlan_id);
+		}
+	}
+}
+
+/*
+ * bond_inet6addr_event: handle inet6addr notifier chain events.
+ *
+ * We keep track of device IPv6 addresses primarily to use as source
+ * addresses in NS probes.
+ *
+ * We track one IPv6 for the main device (if it has one).
+ */
+static int bond_inet6addr_event(struct notifier_block *this,
+				unsigned long event,
+				void *ptr)
+{
+	struct inet6_ifaddr *ifa = ptr;
+	struct net_device *vlan_dev, *event_dev = ifa->idev->dev;
+	struct bonding *bond;
+	struct vlan_entry *vlan;
+
+	if (dev_net(event_dev) != &init_net)
+		return NOTIFY_DONE;
+
+	list_for_each_entry(bond, &bond_dev_list, bond_list) {
+		if (bond->dev == event_dev) {
+			switch (event) {
+			case NETDEV_UP:
+				if (ipv6_addr_any(&bond->master_ipv6))
+					ipv6_addr_copy(&bond->master_ipv6,
+						       &ifa->addr);
+				return NOTIFY_OK;
+			case NETDEV_DOWN:
+				if (ipv6_addr_equal(&bond->master_ipv6,
+						    &ifa->addr))
+					bond_glean_dev_ipv6(bond->dev,
+							    &bond->master_ipv6);
+				return NOTIFY_OK;
+			default:
+				return NOTIFY_DONE;
+			}
+		}
+
+		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+			vlan_dev = vlan_group_get_device(bond->vlgrp,
+							 vlan->vlan_id);
+			if (vlan_dev == event_dev) {
+				switch (event) {
+				case NETDEV_UP:
+					if (ipv6_addr_any(&vlan->vlan_ipv6))
+						ipv6_addr_copy(&vlan->vlan_ipv6,
+							       &ifa->addr);
+					return NOTIFY_OK;
+				case NETDEV_DOWN:
+					if (ipv6_addr_equal(&vlan->vlan_ipv6,
+							    &ifa->addr))
+						bond_glean_dev_ipv6(vlan_dev,
+								    &vlan->vlan_ipv6);
+					return NOTIFY_OK;
+				default:
+					return NOTIFY_DONE;
+				}
+			}
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block bond_inet6addr_notifier = {
+	.notifier_call = bond_inet6addr_event,
+};
+
+void bond_register_ipv6_notifier(void)
+{
+	register_inet6addr_notifier(&bond_inet6addr_notifier);
+}
+
+void bond_unregister_ipv6_notifier(void)
+{
+	unregister_inet6addr_notifier(&bond_inet6addr_notifier);
+}
+
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a3efba5..02de3e0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -89,6 +89,7 @@
 
 static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
 static int num_grat_arp = 1;
+static int num_unsol_na = 1;
 static int miimon	= BOND_LINK_MON_INTERV;
 static int updelay	= 0;
 static int downdelay	= 0;
@@ -96,6 +97,7 @@
 static char *mode	= NULL;
 static char *primary	= NULL;
 static char *lacp_rate	= NULL;
+static char *ad_select  = NULL;
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
@@ -107,6 +109,8 @@
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
 module_param(num_grat_arp, int, 0644);
 MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
+module_param(num_unsol_na, int, 0644);
+MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event");
 module_param(miimon, int, 0);
 MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
 module_param(updelay, int, 0);
@@ -127,6 +131,8 @@
 module_param(lacp_rate, charp, 0);
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
 			    "(slow/fast)");
+module_param(ad_select, charp, 0);
+MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)");
 module_param(xmit_hash_policy, charp, 0);
 MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
 				   ", 1 for layer 3+4");
@@ -197,6 +203,13 @@
 {	NULL,			-1},
 };
 
+struct bond_parm_tbl ad_select_tbl[] = {
+{	"stable",	BOND_AD_STABLE},
+{	"bandwidth",	BOND_AD_BANDWIDTH},
+{	"count",	BOND_AD_COUNT},
+{	NULL,		-1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -242,14 +255,13 @@
 	dprintk("bond: %s, vlan id %d\n",
 		(bond ? bond->dev->name: "None"), vlan_id);
 
-	vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+	vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL);
 	if (!vlan) {
 		return -ENOMEM;
 	}
 
 	INIT_LIST_HEAD(&vlan->vlan_list);
 	vlan->vlan_id = vlan_id;
-	vlan->vlan_ip = 0;
 
 	write_lock_bh(&bond->lock);
 
@@ -1208,6 +1220,9 @@
 			bond->send_grat_arp = bond->params.num_grat_arp;
 			bond_send_gratuitous_arp(bond);
 
+			bond->send_unsol_na = bond->params.num_unsol_na;
+			bond_send_unsolicited_na(bond);
+
 			write_unlock_bh(&bond->curr_slave_lock);
 			read_unlock(&bond->lock);
 
@@ -1791,7 +1806,6 @@
 	struct slave *slave, *oldcurrent;
 	struct sockaddr addr;
 	int mac_addr_differ;
-	DECLARE_MAC_BUF(mac);
 
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
@@ -1820,11 +1834,11 @@
 		if (!mac_addr_differ && (bond->slave_cnt > 1))
 			printk(KERN_WARNING DRV_NAME
 			       ": %s: Warning: the permanent HWaddr of %s - "
-			       "%s - is still in use by %s. "
+			       "%pM - is still in use by %s. "
 			       "Set the HWaddr of %s to a different address "
 			       "to avoid conflicts.\n",
 			       bond_dev->name, slave_dev->name,
-			       print_mac(mac, slave->perm_hwaddr),
+			       slave->perm_hwaddr,
 			       bond_dev->name, slave_dev->name);
 	}
 
@@ -2464,6 +2478,12 @@
 		read_unlock(&bond->curr_slave_lock);
 	}
 
+	if (bond->send_unsol_na) {
+		read_lock(&bond->curr_slave_lock);
+		bond_send_unsolicited_na(bond);
+		read_unlock(&bond->curr_slave_lock);
+	}
+
 	if (bond_miimon_inspect(bond)) {
 		read_unlock(&bond->lock);
 		rtnl_lock();
@@ -2586,8 +2606,8 @@
 		if (rv) {
 			if (net_ratelimit()) {
 				printk(KERN_WARNING DRV_NAME
-			     ": %s: no route to arp_ip_target %u.%u.%u.%u\n",
-				       bond->dev->name, NIPQUAD(fl.fl4_dst));
+			     ": %s: no route to arp_ip_target %pI4\n",
+				       bond->dev->name, &fl.fl4_dst);
 			}
 			continue;
 		}
@@ -2623,8 +2643,8 @@
 
 		if (net_ratelimit()) {
 			printk(KERN_WARNING DRV_NAME
-	       ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n",
-			       bond->dev->name, NIPQUAD(fl.fl4_dst),
+	       ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n",
+			       bond->dev->name, &fl.fl4_dst,
 			       rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
 		}
 		ip_rt_put(rt);
@@ -2673,10 +2693,8 @@
 
 	targets = bond->params.arp_targets;
 	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
-		dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
-			"%u.%u.%u.%u bhti(tip) %d\n",
-		       NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
-		       bond_has_this_ip(bond, tip));
+		dprintk("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n",
+			&sip, &tip, i, &targets[i], bond_has_this_ip(bond, tip));
 		if (sip == targets[i]) {
 			if (bond_has_this_ip(bond, tip))
 				slave->last_arp_rx = jiffies;
@@ -2728,10 +2746,10 @@
 	arp_ptr += 4 + dev->addr_len;
 	memcpy(&tip, arp_ptr, 4);
 
-	dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
-		" tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
-		slave->state, bond->params.arp_validate,
-		slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+	dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
+		bond->dev->name, slave->dev->name, slave->state,
+		bond->params.arp_validate, slave_do_arp_validate(bond, slave),
+		&sip, &tip);
 
 	/*
 	 * Backup slaves won't see the ARP reply, but do come through
@@ -3161,6 +3179,12 @@
 		read_unlock(&bond->curr_slave_lock);
 	}
 
+	if (bond->send_unsol_na) {
+		read_lock(&bond->curr_slave_lock);
+		bond_send_unsolicited_na(bond);
+		read_unlock(&bond->curr_slave_lock);
+	}
+
 	if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
 		read_unlock(&bond->lock);
 		rtnl_lock();
@@ -3239,7 +3263,6 @@
 	struct bonding *bond = seq->private;
 	struct slave *curr;
 	int i;
-	u32 target;
 
 	read_lock(&bond->curr_slave_lock);
 	curr = bond->curr_active_slave;
@@ -3293,8 +3316,7 @@
 				continue;
 			if (printed)
 				seq_printf(seq, ",");
-			target = ntohl(bond->params.arp_targets[i]);
-			seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target));
+			seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
 			printed = 1;
 		}
 		seq_printf(seq, "\n");
@@ -3302,11 +3324,12 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		DECLARE_MAC_BUF(mac);
 
 		seq_puts(seq, "\n802.3ad info\n");
 		seq_printf(seq, "LACP rate: %s\n",
 			   (bond->params.lacp_fast) ? "fast" : "slow");
+		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
+			   ad_select_tbl[bond->params.ad_select].modename);
 
 		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 			seq_printf(seq, "bond %s has no active aggregator\n",
@@ -3322,8 +3345,8 @@
 				   ad_info.actor_key);
 			seq_printf(seq, "\tPartner Key: %d\n",
 				   ad_info.partner_key);
-			seq_printf(seq, "\tPartner Mac Address: %s\n",
-				   print_mac(mac, ad_info.partner_system));
+			seq_printf(seq, "\tPartner Mac Address: %pM\n",
+				   ad_info.partner_system);
 		}
 	}
 }
@@ -3331,7 +3354,6 @@
 static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
 {
 	struct bonding *bond = seq->private;
-	DECLARE_MAC_BUF(mac);
 
 	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
 	seq_printf(seq, "MII Status: %s\n",
@@ -3339,9 +3361,7 @@
 	seq_printf(seq, "Link Failure Count: %u\n",
 		   slave->link_failure_count);
 
-	seq_printf(seq,
-		   "Permanent HW addr: %s\n",
-		   print_mac(mac, slave->perm_hwaddr));
+	seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		const struct aggregator *agg
@@ -3816,6 +3836,7 @@
 		queue_delayed_work(bond->wq, &bond->ad_work, 0);
 		/* register to receive LACPDUs */
 		bond_register_lacpdu(bond);
+		bond_3ad_initiate_agg_selection(bond, 1);
 	}
 
 	return 0;
@@ -3836,6 +3857,7 @@
 	write_lock_bh(&bond->lock);
 
 	bond->send_grat_arp = 0;
+	bond->send_unsol_na = 0;
 
 	/* signal timers not to re-arm */
 	bond->kill_timers = 1;
@@ -4551,6 +4573,7 @@
 	bond->primary_slave = NULL;
 	bond->dev = bond_dev;
 	bond->send_grat_arp = 0;
+	bond->send_unsol_na = 0;
 	bond->setup_by_slave = 0;
 	INIT_LIST_HEAD(&bond->vlan_list);
 
@@ -4573,6 +4596,8 @@
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 	bond_dev->priv_flags |= IFF_BONDING;
+	if (bond->params.arp_interval)
+		bond_dev->priv_flags |= IFF_MASTER_ARPMON;
 
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
@@ -4751,6 +4776,23 @@
 		}
 	}
 
+	if (ad_select) {
+		params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
+		if (params->ad_select == -1) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: Invalid ad_select \"%s\"\n",
+			       ad_select == NULL ? "NULL" : ad_select);
+			return -EINVAL;
+		}
+
+		if (bond_mode != BOND_MODE_8023AD) {
+			printk(KERN_WARNING DRV_NAME
+			       ": ad_select param only affects 802.3ad mode\n");
+		}
+	} else {
+		params->ad_select = BOND_AD_STABLE;
+	}
+
 	if (max_bonds < 0 || max_bonds > INT_MAX) {
 		printk(KERN_WARNING DRV_NAME
 		       ": Warning: max_bonds (%d) not in range %d-%d, so it "
@@ -4798,6 +4840,13 @@
 		num_grat_arp = 1;
 	}
 
+	if (num_unsol_na < 0 || num_unsol_na > 255) {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: num_unsol_na (%d) not in range 0-255 so it "
+		       "was reset to 1 \n", num_unsol_na);
+		num_unsol_na = 1;
+	}
+
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
 		if (!miimon) {
@@ -4999,6 +5048,7 @@
 	params->xmit_policy = xmit_hashtype;
 	params->miimon = miimon;
 	params->num_grat_arp = num_grat_arp;
+	params->num_unsol_na = num_unsol_na;
 	params->arp_interval = arp_interval;
 	params->arp_validate = arp_validate_value;
 	params->updelay = updelay;
@@ -5151,6 +5201,7 @@
 
 	register_netdevice_notifier(&bond_netdev_notifier);
 	register_inetaddr_notifier(&bond_inetaddr_notifier);
+	bond_register_ipv6_notifier();
 
 	goto out;
 err:
@@ -5173,6 +5224,7 @@
 {
 	unregister_netdevice_notifier(&bond_netdev_notifier);
 	unregister_inetaddr_notifier(&bond_inetaddr_notifier);
+	bond_unregister_ipv6_notifier();
 
 	bond_destroy_sysfs();
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 3bdb473..aaf2927 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -48,6 +48,7 @@
 extern struct bond_params bonding_defaults;
 extern struct bond_parm_tbl bond_mode_tbl[];
 extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl ad_select_tbl[];
 extern struct bond_parm_tbl xmit_hashtype_tbl[];
 extern struct bond_parm_tbl arp_validate_tbl[];
 extern struct bond_parm_tbl fail_over_mac_tbl[];
@@ -620,6 +621,8 @@
 	       ": %s: Setting ARP monitoring interval to %d.\n",
 	       bond->dev->name, new_value);
 	bond->params.arp_interval = new_value;
+	if (bond->params.arp_interval)
+		bond->dev->priv_flags |= IFF_MASTER_ARPMON;
 	if (bond->params.miimon) {
 		printk(KERN_INFO DRV_NAME
 		       ": %s: ARP monitoring cannot be used with MII monitoring. "
@@ -672,8 +675,8 @@
 
 	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
 		if (bond->params.arp_targets[i])
-			res += sprintf(buf + res, "%u.%u.%u.%u ",
-			       NIPQUAD(bond->params.arp_targets[i]));
+			res += sprintf(buf + res, "%pI4 ",
+				       &bond->params.arp_targets[i]);
 	}
 	if (res)
 		buf[res-1] = '\n'; /* eat the leftover space */
@@ -695,8 +698,8 @@
 	if (buf[0] == '+') {
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
 			printk(KERN_ERR DRV_NAME
-			       ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n",
- 			       bond->dev->name, NIPQUAD(newtarget));
+			       ": %s: invalid ARP target %pI4 specified for addition\n",
+			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -704,8 +707,8 @@
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
 			if (targets[i] == newtarget) { /* duplicate */
 				printk(KERN_ERR DRV_NAME
-				       ": %s: ARP target %u.%u.%u.%u is already present\n",
-				       bond->dev->name, NIPQUAD(newtarget));
+				       ": %s: ARP target %pI4 is already present\n",
+				       bond->dev->name, &newtarget);
 				if (done)
 					targets[i] = 0;
 				ret = -EINVAL;
@@ -713,8 +716,8 @@
 			}
 			if (targets[i] == 0 && !done) {
 				printk(KERN_INFO DRV_NAME
-				       ": %s: adding ARP target %d.%d.%d.%d.\n",
-				       bond->dev->name, NIPQUAD(newtarget));
+				       ": %s: adding ARP target %pI4.\n",
+				       bond->dev->name, &newtarget);
 				done = 1;
 				targets[i] = newtarget;
 			}
@@ -731,8 +734,8 @@
 	else if (buf[0] == '-')	{
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
 			printk(KERN_ERR DRV_NAME
-			       ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n",
-			       bond->dev->name, NIPQUAD(newtarget));
+			       ": %s: invalid ARP target %pI4 specified for removal\n",
+			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -740,16 +743,16 @@
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
 			if (targets[i] == newtarget) {
 				printk(KERN_INFO DRV_NAME
-				       ": %s: removing ARP target %d.%d.%d.%d.\n",
-				       bond->dev->name, NIPQUAD(newtarget));
+				       ": %s: removing ARP target %pI4.\n",
+				       bond->dev->name, &newtarget);
 				targets[i] = 0;
 				done = 1;
 			}
 		}
 		if (!done) {
 			printk(KERN_INFO DRV_NAME
-			       ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n",
-			       bond->dev->name, NIPQUAD(newtarget));
+			       ": %s: unable to remove nonexistent ARP target %pI4.\n",
+			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -942,6 +945,53 @@
 }
 static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
 
+static ssize_t bonding_show_ad_select(struct device *d,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct bonding *bond = to_bond(d);
+
+	return sprintf(buf, "%s %d\n",
+		ad_select_tbl[bond->params.ad_select].modename,
+		bond->params.ad_select);
+}
+
+
+static ssize_t bonding_store_ad_select(struct device *d,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(d);
+
+	if (bond->dev->flags & IFF_UP) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to update ad_select because interface "
+		       "is up.\n", bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	new_value = bond_parse_parm(buf, ad_select_tbl);
+
+	if (new_value != -1) {
+		bond->params.ad_select = new_value;
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Setting ad_select to %s (%d).\n",
+		       bond->dev->name, ad_select_tbl[new_value].modename,
+		       new_value);
+	} else {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Ignoring invalid ad_select value %.*s.\n",
+		       bond->dev->name, (int)strlen(buf) - 1, buf);
+		ret = -EINVAL;
+	}
+out:
+	return ret;
+}
+
+static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select);
+
 /*
  * Show and set the number of grat ARP to send after a failover event.
  */
@@ -981,6 +1031,47 @@
 	return ret;
 }
 static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
+
+/*
+ * Show and set the number of unsolicted NA's to send after a failover event.
+ */
+static ssize_t bonding_show_n_unsol_na(struct device *d,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct bonding *bond = to_bond(d);
+
+	return sprintf(buf, "%d\n", bond->params.num_unsol_na);
+}
+
+static ssize_t bonding_store_n_unsol_na(struct device *d,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(d);
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no num_unsol_na value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (new_value < 0 || new_value > 255) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
+		       bond->dev->name, new_value);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		bond->params.num_unsol_na = new_value;
+	}
+out:
+	return ret;
+}
+static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na);
+
 /*
  * Show and set the MII monitor interval.  There are two tricky bits
  * here.  First, if MII monitoring is activated, then we must disable
@@ -1039,6 +1130,7 @@
 			       "ARP monitoring. Disabling ARP monitoring...\n",
 			       bond->dev->name);
 			bond->params.arp_interval = 0;
+			bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
 			if (bond->params.arp_validate) {
 				bond_unregister_arp(bond);
 				bond->params.arp_validate =
@@ -1391,13 +1483,11 @@
 {
 	int count = 0;
 	struct bonding *bond = to_bond(d);
-	DECLARE_MAC_BUF(mac);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
 		if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
-			count = sprintf(buf,"%s\n",
-					print_mac(mac, ad_info.partner_system));
+			count = sprintf(buf, "%pM\n", ad_info.partner_system);
 		}
 	}
 
@@ -1417,8 +1507,10 @@
 	&dev_attr_downdelay.attr,
 	&dev_attr_updelay.attr,
 	&dev_attr_lacp_rate.attr,
+	&dev_attr_ad_select.attr,
 	&dev_attr_xmit_hash_policy.attr,
 	&dev_attr_num_grat_arp.attr,
+	&dev_attr_num_unsol_na.attr,
 	&dev_attr_miimon.attr,
 	&dev_attr_primary.attr,
 	&dev_attr_use_carrier.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ffb668d..b5eb8e6 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -19,16 +19,19 @@
 #include <linux/proc_fs.h>
 #include <linux/if_bonding.h>
 #include <linux/kobject.h>
+#include <linux/in6.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"3.3.0"
-#define DRV_RELDATE	"June 10, 2008"
+#define DRV_VERSION	"3.5.0"
+#define DRV_RELDATE	"November 4, 2008"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
 #define BOND_MAX_ARP_TARGETS	16
 
+extern struct list_head bond_dev_list;
+
 #ifdef BONDING_DEBUG
 #define dprintk(fmt, args...) \
 	printk(KERN_DEBUG     \
@@ -126,6 +129,7 @@
 	int xmit_policy;
 	int miimon;
 	int num_grat_arp;
+	int num_unsol_na;
 	int arp_interval;
 	int arp_validate;
 	int use_carrier;
@@ -133,6 +137,7 @@
 	int updelay;
 	int downdelay;
 	int lacp_fast;
+	int ad_select;
 	char primary[IFNAMSIZ];
 	__be32 arp_targets[BOND_MAX_ARP_TARGETS];
 };
@@ -148,6 +153,9 @@
 	struct list_head vlan_list;
 	__be32 vlan_ip;
 	unsigned short vlan_id;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct in6_addr vlan_ipv6;
+#endif
 };
 
 struct slave {
@@ -195,6 +203,7 @@
 	rwlock_t curr_slave_lock;
 	s8       kill_timers;
 	s8	 send_grat_arp;
+	s8	 send_unsol_na;
 	s8	 setup_by_slave;
 	struct   net_device_stats stats;
 #ifdef CONFIG_PROC_FS
@@ -218,6 +227,9 @@
 	struct   delayed_work arp_work;
 	struct   delayed_work alb_work;
 	struct   delayed_work ad_work;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct   in6_addr master_ipv6;
+#endif
 };
 
 /**
@@ -341,5 +353,24 @@
 extern struct bond_parm_tbl arp_validate_tbl[];
 extern struct bond_parm_tbl fail_over_mac_tbl[];
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+void bond_send_unsolicited_na(struct bonding *bond);
+void bond_register_ipv6_notifier(void);
+void bond_unregister_ipv6_notifier(void);
+#else
+static inline void bond_send_unsolicited_na(struct bonding *bond)
+{
+	return;
+}
+static inline void bond_register_ipv6_notifier(void)
+{
+	return;
+}
+static inline void bond_unregister_ipv6_notifier(void)
+{
+	return;
+}
+#endif
+
 #endif /* _LINUX_BONDING_H */
 
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 86909cf..bc84c4c 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2405,7 +2405,6 @@
 		cp->net_stats[ring].rx_packets++;
 		cp->net_stats[ring].rx_bytes += len;
 		spin_unlock(&cp->stat_lock[ring]);
-		cp->dev->last_rx = jiffies;
 
 	next:
 		npackets++;
@@ -4988,7 +4987,6 @@
 	int i, err, pci_using_dac;
 	u16 pci_cmd;
 	u8 orig_cacheline_size = 0, cas_cacheline_size = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (cas_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -5201,12 +5199,12 @@
 
 	i = readl(cp->regs + REG_BIM_CFG);
 	printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) "
-	       "Ethernet[%d] %s\n",  dev->name,
+	       "Ethernet[%d] %pM\n",  dev->name,
 	       (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "",
 	       (i & BIM_CFG_32BIT) ? "32" : "64",
 	       (i & BIM_CFG_66MHZ) ? "66" : "33",
 	       (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 	pci_set_drvdata(pdev, dev);
 	cp->hw_running = 1;
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index d6c7d2a..fa0a1f1 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1385,7 +1385,6 @@
 	st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
 
 	skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
-	skb->dev->last_rx = jiffies;
 	if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
 	    skb->protocol == htons(ETH_P_IP) &&
 	    (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 017a536..d39a77c 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1103,7 +1103,6 @@
 	struct cpmac_priv *priv;
 	struct net_device *dev;
 	struct plat_cpmac_data *pdata;
-	DECLARE_MAC_BUF(mac);
 
 	pdata = pdev->dev.platform_data;
 
@@ -1180,8 +1179,8 @@
 	if (netif_msg_probe(priv)) {
 		printk(KERN_INFO
 		       "cpmac: device %s (regs: %p, irq: %d, phy: %s, "
-		       "mac: %s)\n", dev->name, (void *)mem->start, dev->irq,
-		       priv->phy_name, print_mac(mac, dev->dev_addr));
+		       "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq,
+		       priv->phy_name, dev->dev_addr);
 	}
 	return 0;
 
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 7e8a631..c9806c5 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -419,7 +419,6 @@
 {
 	struct net_local *np = netdev_priv(dev);
 	struct sockaddr *addr = p;
-	DECLARE_MAC_BUF(mac);
 
 	spin_lock(&np->lock); /* preemption protection */
 
@@ -440,8 +439,7 @@
 
 	/* show it in the log as well */
 
-	printk(KERN_INFO "%s: changed MAC to %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: changed MAC to %pM\n", dev->name, dev->dev_addr);
 
 	spin_unlock(&np->lock);
 
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 7107620..b063395 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -521,7 +521,6 @@
 	unsigned rev_type = 0;
 	int eeprom_buff[CHKSUM_LEN];
 	int retval;
-	DECLARE_MAC_BUF(mac);
 
 	/* Initialize the device structure. */
 	if (!modular) {
@@ -846,7 +845,7 @@
 	}
 
 	/* print the ethernet address. */
-	printk(", MAC %s", print_mac(mac, dev->dev_addr));
+	printk(", MAC %pM", dev->dev_addr);
 
 	dev->open		= net_open;
 	dev->stop		= net_close;
@@ -1025,7 +1024,6 @@
 	}
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += length;
 }
@@ -1719,7 +1717,6 @@
 
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += length;
 }
@@ -1817,11 +1814,10 @@
 
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
-	if (net_debug) {
-		DECLARE_MAC_BUF(mac);
-		printk("%s: Setting MAC address to %s.\n",
-		       dev->name, print_mac(mac, dev->dev_addr));
-	}
+	if (net_debug)
+		printk("%s: Setting MAC address to %pM.\n",
+		       dev->name, dev->dev_addr);
+
 	/* set the Ethernet address */
 	for (i=0; i < ETH_ALEN/2; i++)
 		writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 1ace41a..e1746ee 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -494,6 +494,36 @@
 }
 
 /**
+ *	set_qset_lro - Turn a queue set's LRO capability on and off
+ *	@dev: the device the qset is attached to
+ *	@qset_idx: the queue set index
+ *	@val: the LRO switch
+ *
+ *	Sets LRO on or off for a particular queue set.
+ *	the device's features flag is updated to reflect the LRO
+ *	capability when all queues belonging to the device are
+ *	in the same state.
+ */
+static void set_qset_lro(struct net_device *dev, int qset_idx, int val)
+{
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adapter = pi->adapter;
+	int i, lro_on = 1;
+
+	adapter->params.sge.qset[qset_idx].lro = !!val;
+	adapter->sge.qs[qset_idx].lro_enabled = !!val;
+
+	/* let ethtool report LRO on only if all queues are LRO enabled */
+	for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; ++i)
+		lro_on &= adapter->params.sge.qset[i].lro;
+
+	if (lro_on)
+		dev->features |= NETIF_F_LRO;
+	else
+		dev->features &= ~NETIF_F_LRO;
+}
+
+/**
  *	setup_sge_qsets - configure SGE Tx/Rx/response queues
  *	@adap: the adapter
  *
@@ -516,8 +546,7 @@
 		pi->qs = &adap->sge.qs[pi->first_qset];
 		for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
 		     ++j, ++qset_idx) {
-			if (!pi->rx_csum_offload)
-				adap->params.sge.qset[qset_idx].lro = 0;
+			set_qset_lro(dev, qset_idx, pi->rx_csum_offload);
 			err = t3_sge_alloc_qset(adap, qset_idx, 1,
 				(adap->flags & USING_MSIX) ? qset_idx + 1 :
 							     irq_idx,
@@ -1632,13 +1661,10 @@
 
 	p->rx_csum_offload = data;
 	if (!data) {
-		struct adapter *adap = p->adapter;
 		int i;
 
-		for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
-			adap->params.sge.qset[i].lro = 0;
-			adap->sge.qs[i].lro_enabled = 0;
-		}
+		for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
+			set_qset_lro(dev, i, 0);
 	}
 	return 0;
 }
@@ -1793,6 +1819,25 @@
 	memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
 
+static int cxgb3_set_flags(struct net_device *dev, u32 data)
+{
+	struct port_info *pi = netdev_priv(dev);
+	int i;
+
+	if (data & ETH_FLAG_LRO) {
+		if (!pi->rx_csum_offload)
+			return -EINVAL;
+
+		for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
+			set_qset_lro(dev, i, 1);
+
+	} else
+		for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
+			set_qset_lro(dev, i, 0);
+
+	return 0;
+}
+
 static const struct ethtool_ops cxgb_ethtool_ops = {
 	.get_settings = get_settings,
 	.set_settings = set_settings,
@@ -1822,6 +1867,8 @@
 	.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)
@@ -1938,11 +1985,9 @@
 				}
 			}
 		}
-		if (t.lro >= 0) {
-			struct sge_qset *qs = &adapter->sge.qs[t.qset_idx];
-			q->lro = t.lro;
-			qs->lro_enabled = t.lro;
-		}
+		if (t.lro >= 0)
+			set_qset_lro(dev, t.qset_idx, t.lro);
+
 		break;
 	}
 	case CHELSIO_GET_QSET_PARAMS:{
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index c6480be..268f158 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1876,7 +1876,6 @@
 
 	skb_pull(skb, sizeof(*p) + pad);
 	skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
-	skb->dev->last_rx = jiffies;
 	pi = netdev_priv(skb->dev);
 	if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
 	    !p->fragment) {
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index cb849b0..970f820 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -369,7 +369,6 @@
 	netif_rx(skb);
 
 	/* update stats */
-	dev->last_rx = jiffies;
 	dev->stats.rx_packets++; /* count all receives */
 	dev->stats.rx_bytes += size; /* count all received bytes */
 
@@ -384,7 +383,6 @@
 	int	i;
 	struct net_device *dev;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(0);
 	if (!dev)
@@ -439,7 +437,7 @@
 		goto out1;
 	}
 
-	printk(", Ethernet Address: %s\n", print_mac(mac, dev->dev_addr));
+	printk(", Ethernet Address: %pM\n", dev->dev_addr);
 
 	dev->open = de600_open;
 	dev->stop = de600_close;
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index d454e14..0d4b6ac 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -686,7 +686,6 @@
 			PRINTK(("Read %d bytes\n", size));
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb); /* deliver it "upstairs" */
-			dev->last_rx = jiffies;
 			/* count all receives */
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += size;
@@ -800,7 +799,6 @@
 	struct net_device *dev;
 	int err = -ENOMEM;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(0);
 	if (!dev)
@@ -853,7 +851,7 @@
 		dev->broadcast[i] = 0xff;
 	}
 
-	printk(", Ethernet Address: %s", print_mac(mac, dev->dev_addr));
+	printk(", Ethernet Address: %pM", dev->dev_addr);
 
 	printk(" (%dk RAM,",
 		(nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
@@ -876,10 +874,7 @@
 	if (de620_debug) {
 		printk("\nEEPROM contents:\n");
 		printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);
-		printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n",
-			nic_data.NodeID[0], nic_data.NodeID[1],
-			nic_data.NodeID[2], nic_data.NodeID[3],
-			nic_data.NodeID[4], nic_data.NodeID[5]);
+		printk("NodeID = %pM\n", nic_data.NodeID);
 		printk("Model = %d\n", nic_data.Model);
 		printk("Media = %d\n", nic_data.Media);
 		printk("SCR = 0x%02x\n", nic_data.SCR);
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 3e35064..f6988d7 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -622,7 +622,6 @@
 
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 
@@ -1023,7 +1022,6 @@
 	int i, ret;
 	unsigned long esar_base;
 	unsigned char *esar;
-	DECLARE_MAC_BUF(mac);
 
 	if (dec_lance_debug && version_printed++ == 0)
 		printk(version);
@@ -1223,8 +1221,7 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = esar[i * 4];
 
-	printk(", addr = %s, irq = %d\n",
-	       print_mac(mac, dev->dev_addr), dev->irq);
+	printk(", addr = %pM, irq = %d\n", dev->dev_addr, dev->irq);
 
 	dev->open = &lance_open;
 	dev->stop = &lance_close;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index c062aac..6e6583b 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -511,7 +511,7 @@
 	int dfx_bus_pci = DFX_BUS_PCI(bdev);
 	int dfx_bus_tc = DFX_BUS_TC(bdev);
 	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-	char *print_name = bdev->bus_id;
+	const char *print_name = dev_name(bdev);
 	struct net_device *dev;
 	DFX_board_t	  *bp;			/* board pointer */
 	resource_size_t bar_start = 0;		/* pointer to port */
@@ -3103,7 +3103,6 @@
 					netif_rx(skb);
 
 					/* Update the rcv counters */
-					bp->dev->last_rx = jiffies;
 					bp->rcv_total_frames++;
 					if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
 						bp->rcv_multicast_frames++;
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index ace39ec..fda1226 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -573,7 +573,6 @@
 	s16 nicsr;
 	u_long ioaddr;
 	u_long mem_start;
-	DECLARE_MAC_BUF(mac);
 
 	/*
 	 * We are now supposed to enter this function with the
@@ -633,7 +632,7 @@
 
 	printk(", h/w address ");
 	status = get_hw_addr(dev);
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 	if (status != 0) {
 		printk("      which has an Ethernet PROM CRC error.\n");
 		return -ENXIO;
@@ -1057,7 +1056,6 @@
 					/*
 					   ** Update stats
 					 */
-					dev->last_rx = jiffies;
 					dev->stats.rx_packets++;
 					dev->stats.rx_bytes += pkt_len;
 					for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) {
@@ -1841,7 +1839,6 @@
 	u_long ioaddr = dev->base_addr;
 	struct depca_init *p = &lp->init_block;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	if (depca_debug > 1) {
 		/* Do not copy the shadow init block into shared memory */
@@ -1880,7 +1877,7 @@
 		printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
 		printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start);
 		printk("        mode: 0x%4.4x\n", p->mode);
-		printk("        physical address: %s\n", print_mac(mac, p->phys_addr));
+		printk("        physical address: %pM\n", p->phys_addr);
 		printk("        multicast hash table: ");
 		for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) {
 			printk("%2.2x:", p->mcast_table[i]);
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index f803711..9ec9785 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -97,7 +97,6 @@
 	static int version_printed;
 	void *ring_space;
 	dma_addr_t ring_dma;
-	DECLARE_MAC_BUF(mac);
 
 	if (!version_printed++)
 		printk ("%s", version);
@@ -257,8 +256,8 @@
 
 	card_idx++;
 
-	printk (KERN_INFO "%s: %s, %s, IRQ %d\n",
-		dev->name, np->name, print_mac(mac, dev->dev_addr), irq);
+	printk (KERN_INFO "%s: %s, %pM, IRQ %d\n",
+		dev->name, np->name, dev->dev_addr, irq);
 	if (tx_coalesce > 1)
 		printk(KERN_INFO "tx_coalesce:\t%d packets\n",
 				tx_coalesce);
@@ -892,7 +891,6 @@
 			}
 #endif
 			netif_rx (skb);
-			dev->last_rx = jiffies;
 		}
 		entry = (entry + 1) % RX_RING_SIZE;
 	}
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 5a9083e..22dd308 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1385,13 +1385,11 @@
 	platform_set_drvdata(pdev, ndev);
 	ret = register_netdev(ndev);
 
-	if (ret == 0) {
-		DECLARE_MAC_BUF(mac);
-		printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
+	if (ret == 0)
+		printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
 		       ndev->name, dm9000_type_to_char(db->type),
 		       db->io_addr, db->io_data, ndev->irq,
-		       print_mac(mac, ndev->dev_addr), mac_src);
-	}
+		       ndev->dev_addr, mac_src);
 	return 0;
 
 out:
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 3d69fae..62cdefa 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1880,7 +1880,6 @@
 	} else {
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += actual_size;
-		nic->netdev->last_rx = jiffies;
 		netif_receive_skb(skb);
 		if(work_done)
 			(*work_done)++;
@@ -2322,7 +2321,8 @@
 {
 	struct nic *nic = netdev_priv(netdev);
 
-	if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+	if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) ||
+	    !device_can_wakeup(&nic->pdev->dev))
 		return -EOPNOTSUPP;
 
 	if(wol->wolopts)
@@ -2330,6 +2330,8 @@
 	else
 		nic->flags &= ~wol_magic;
 
+	device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts);
+
 	e100_exec_cb(nic, NULL, e100_configure);
 
 	return 0;
@@ -2616,7 +2618,6 @@
 	struct net_device *netdev;
 	struct nic *nic;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
 		if(((1 << debug) - 1) & NETIF_MSG_PROBE)
@@ -2734,8 +2735,10 @@
 
 	/* Wol magic packet can be enabled from eeprom */
 	if((nic->mac >= mac_82558_D101_A4) &&
-	   (nic->eeprom[eeprom_id] & eeprom_id_wol))
+	   (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
 		nic->flags |= wol_magic;
+		device_set_wakeup_enable(&pdev->dev, true);
+	}
 
 	/* ack any pending wake events, disable PME */
 	pci_pme_active(pdev, false);
@@ -2746,9 +2749,9 @@
 		goto err_out_free;
 	}
 
-	DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n",
+	DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n",
 		(unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
-		pdev->irq, print_mac(mac, netdev->dev_addr));
+		pdev->irq, netdev->dev_addr);
 
 	return 0;
 
@@ -2794,11 +2797,10 @@
 	pci_save_state(pdev);
 
 	if ((nic->flags & wol_magic) | e100_asf(nic)) {
-		pci_enable_wake(pdev, PCI_D3hot, 1);
-		pci_enable_wake(pdev, PCI_D3cold, 1);
+		if (pci_enable_wake(pdev, PCI_D3cold, true))
+			pci_enable_wake(pdev, PCI_D3hot, true);
 	} else {
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);
+		pci_enable_wake(pdev, PCI_D3hot, false);
 	}
 
 	pci_disable_device(pdev);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index fac8215..78a4250 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -912,7 +912,6 @@
 	u16 eeprom_data = 0;
 	u16 eeprom_apme_mask = E1000_EEPROM_APME;
 	int bars, need_ioport;
-	DECLARE_MAC_BUF(mac);
 
 	/* do not allocate ioport bars when not needed */
 	need_ioport = e1000_is_need_ioport(pdev);
@@ -967,8 +966,7 @@
 	hw->back = adapter;
 
 	err = -EIO;
-	hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
-			      pci_resource_len(pdev, BAR_0));
+	hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
 	if (!hw->hw_addr)
 		goto err_ioremap;
 
@@ -1016,9 +1014,7 @@
 	 * because it depends on mac_type */
 	if ((hw->mac_type == e1000_ich8lan) &&
 	   (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-		hw->flash_address =
-			ioremap(pci_resource_start(pdev, 1),
-				pci_resource_len(pdev, 1));
+		hw->flash_address = pci_ioremap_bar(pdev, 1);
 		if (!hw->flash_address)
 			goto err_flashmap;
 	}
@@ -1194,7 +1190,7 @@
 		 (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
 		 "32-bit"));
 
-	printk("%s\n", print_mac(mac, netdev->dev_addr));
+	printk("%pM\n", netdev->dev_addr);
 
 	if (hw->bus_type == e1000_bus_type_pci_express) {
 		DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
@@ -4103,8 +4099,6 @@
 			netif_receive_skb(skb);
 		}
 
-		netdev->last_rx = jiffies;
-
 next_desc:
 		rx_desc->status = 0;
 
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index abd492b..63e5688 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -103,8 +103,6 @@
 					 le16_to_cpu(vlan));
 	else
 		netif_receive_skb(skb);
-
-	netdev->last_rx = jiffies;
 }
 
 /**
@@ -4652,14 +4650,12 @@
 	u32 pba_num;
 
 	/* print bus type/speed/width info */
-	e_info("(PCI Express:2.5GB/s:%s) %02x:%02x:%02x:%02x:%02x:%02x\n",
+	e_info("(PCI Express:2.5GB/s:%s) %pM\n",
 	       /* bus width */
 	       ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
 	        "Width x1"),
 	       /* MAC address */
-	       netdev->dev_addr[0], netdev->dev_addr[1],
-	       netdev->dev_addr[2], netdev->dev_addr[3],
-	       netdev->dev_addr[4], netdev->dev_addr[5]);
+	       netdev->dev_addr);
 	e_info("Intel(R) PRO/%s Network Connection\n",
 	       (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
 	e1000e_read_pba_num(hw, &pba_num);
@@ -4906,10 +4902,7 @@
 	memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
 
 	if (!is_valid_ether_addr(netdev->perm_addr)) {
-		e_err("Invalid MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
-		      netdev->perm_addr[0], netdev->perm_addr[1],
-		      netdev->perm_addr[2], netdev->perm_addr[3],
-		      netdev->perm_addr[4], netdev->perm_addr[5]);
+		e_err("Invalid MAC Address: %pM\n", netdev->perm_addr);
 		err = -EIO;
 		goto err_eeprom;
 	}
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 1f11350..93387f1 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -690,7 +690,6 @@
 	struct eepro_local *	lp = netdev_priv(dev);
 	int			i;
 	const char *		ifmap[] = {"AUI", "10Base2", "10BaseT"};
-	DECLARE_MAC_BUF(mac);
 
 	i = inb(dev->base_addr + ID_REG);
 	printk(KERN_DEBUG " id: %#x ",i);
@@ -715,7 +714,7 @@
 			break;
 	}
 
-	printk(" %s", print_mac(mac, dev->dev_addr));
+	printk(" %pM", dev->dev_addr);
 
 	if (net_debug > 3)
 		printk(KERN_DEBUG ", %dK RCV buffer",
@@ -1581,7 +1580,6 @@
 
 			skb->protocol = eth_type_trans(skb,dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
deleted file mode 100644
index e3e26c5..0000000
--- a/drivers/net/eepro100.c
+++ /dev/null
@@ -1,2401 +0,0 @@
-/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
-/*
-	Written 1996-1999 by Donald Becker.
-
-	The driver also contains updates by different kernel developers
-	(see incomplete list below).
-	Current maintainer is Andrey V. Savochkin <saw@saw.sw.com.sg>.
-	Please use this email address and linux-kernel mailing list for bug reports.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
-	It should work with all i82557/558/559 boards.
-
-	Version history:
-	1998 Apr - 2000 Feb  Andrey V. Savochkin <saw@saw.sw.com.sg>
-		Serious fixes for multicast filter list setting, TX timeout routine;
-		RX ring refilling logic;  other stuff
-	2000 Feb  Jeff Garzik <jgarzik@pobox.com>
-		Convert to new PCI driver interface
-	2000 Mar 24  Dragan Stancevic <visitor@valinux.com>
-		Disabled FC and ER, to avoid lockups when when we get FCP interrupts.
-	2000 Jul 17 Goutham Rao <goutham.rao@intel.com>
-		PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary
-	2000 Aug 31 David Mosberger <davidm@hpl.hp.com>
-		rx_align support: enables rx DMA without causing unaligned accesses.
-*/
-
-static const char * const version =
-"eepro100.c:v1.09j-t 9/29/99 Donald Becker\n"
-"eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
-
-/* A few user-configurable values that apply to all boards.
-   First set is undocumented and spelled per Intel recommendations. */
-
-static int congenb /* = 0 */; /* Enable congestion control in the DP83840. */
-static int txfifo = 8;		/* Tx FIFO threshold in 4 byte units, 0-15 */
-static int rxfifo = 8;		/* Rx FIFO threshold, default 32 bytes. */
-/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
-static int txdmacount = 128;
-static int rxdmacount /* = 0 */;
-
-#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
-	defined(__arm__)
-  /* align rx buffers to 2 bytes so that IP header is aligned */
-# define rx_align(skb)		skb_reserve((skb), 2)
-# define RxFD_ALIGNMENT		__attribute__ ((aligned (2), packed))
-#else
-# define rx_align(skb)
-# define RxFD_ALIGNMENT
-#endif
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
-   Lower values use more memory, but are faster. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
-
-/* 'options' is used to pass a transceiver override or full-duplex flag
-   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE	64
-#define RX_RING_SIZE	64
-/* How much slots multicast filter setup may take.
-   Do not descrease without changing set_rx_mode() implementaion. */
-#define TX_MULTICAST_SIZE   2
-#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2)
-/* Actual number of TX packets queued, must be
-   <= TX_RING_SIZE-TX_MULTICAST_RESERV. */
-#define TX_QUEUE_LIMIT  (TX_RING_SIZE-TX_MULTICAST_RESERV)
-/* Hysteresis marking queue as no longer full. */
-#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4)
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT		(2*HZ)
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ		1536
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-
-static int use_io;
-static int debug = -1;
-#define DEBUG_DEFAULT		(NETIF_MSG_DRV		| \
-				 NETIF_MSG_HW		| \
-				 NETIF_MSG_RX_ERR	| \
-				 NETIF_MSG_TX_ERR)
-#define DEBUG			((debug >= 0) ? (1<<debug)-1 : DEBUG_DEFAULT)
-
-
-MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>");
-MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver");
-MODULE_LICENSE("GPL");
-module_param(use_io, int, 0);
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-module_param(congenb, int, 0);
-module_param(txfifo, int, 0);
-module_param(rxfifo, int, 0);
-module_param(txdmacount, int, 0);
-module_param(rxdmacount, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(multicast_filter_limit, int, 0);
-MODULE_PARM_DESC(debug, "debug level (0-6)");
-MODULE_PARM_DESC(options, "Bits 0-3: transceiver type, bit 4: full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
-MODULE_PARM_DESC(congenb, "Enable congestion control (1)");
-MODULE_PARM_DESC(txfifo, "Tx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(rxfifo, "Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmacount, "Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmacount, "Rx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rx_copybreak, "copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-MODULE_PARM_DESC(multicast_filter_limit, "maximum number of filtered multicast addresses");
-
-#define RUN_AT(x) (jiffies + (x))
-
-#define netdevice_start(dev)
-#define netdevice_stop(dev)
-#define netif_set_tx_timeout(dev, tf, tm) \
-								do { \
-									(dev)->tx_timeout = (tf); \
-									(dev)->watchdog_timeo = (tm); \
-								} while(0)
-
-
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the Intel i82557 "Speedo3" chip, Intel's
-single-chip fast Ethernet controller for PCI, as used on the Intel
-EtherExpress Pro 100 adapter.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line.  While it's
-possible to share PCI interrupt lines, it negatively impacts performance and
-only recent kernels support it.
-
-III. Driver operation
-
-IIIA. General
-The Speedo3 is very similar to other Intel network chips, that is to say
-"apparently designed on a different planet".  This chips retains the complex
-Rx and Tx descriptors and multiple buffers pointers as previous chips, but
-also has simplified Tx and Rx buffer modes.  This driver uses the "flexible"
-Tx mode, but in a simplified lower-overhead manner: it associates only a
-single buffer descriptor with each frame descriptor.
-
-Despite the extra space overhead in each receive skbuff, the driver must use
-the simplified Rx buffer mode to assure that only a single data buffer is
-associated with each RxFD. The driver implements this by reserving space
-for the Rx descriptor at the head of each Rx skbuff.
-
-The Speedo-3 has receive and command unit base addresses that are added to
-almost all descriptor pointers.  The driver sets these to zero, so that all
-pointer fields are absolute addresses.
-
-The System Control Block (SCB) of some previous Intel chips exists on the
-chip in both PCI I/O and memory space.  This driver uses the I/O space
-registers, but might switch to memory mapped mode to better support non-x86
-processors.
-
-IIIB. Transmit structure
-
-The driver must use the complex Tx command+descriptor mode in order to
-have a indirect pointer to the skbuff data section.  Each Tx command block
-(TxCB) is associated with two immediately appended Tx Buffer Descriptor
-(TxBD).  A fixed ring of these TxCB+TxBD pairs are kept as part of the
-speedo_private data structure for each adapter instance.
-
-The newer i82558 explicitly supports this structure, and can read the two
-TxBDs in the same PCI burst as the TxCB.
-
-This ring structure is used for all normal transmit packets, but the
-transmit packet descriptors aren't long enough for most non-Tx commands such
-as CmdConfigure.  This is complicated by the possibility that the chip has
-already loaded the link address in the previous descriptor.  So for these
-commands we convert the next free descriptor on the ring to a NoOp, and point
-that descriptor's link to the complex command.
-
-An additional complexity of these non-transmit commands are that they may be
-added asynchronous to the normal transmit queue, so we disable interrupts
-whenever the Tx descriptor ring is manipulated.
-
-A notable aspect of these special configure commands is that they do
-work with the normal Tx ring entry scavenge method.  The Tx ring scavenge
-is done at interrupt time using the 'dirty_tx' index, and checking for the
-command-complete bit.  While the setup frames may have the NoOp command on the
-Tx ring marked as complete, but not have completed the setup command, this
-is not a problem.  The tx_ring entry can be still safely reused, as the
-tx_skbuff[] entry is always empty for config_cmd and mc_setup frames.
-
-Commands may have bits set e.g. CmdSuspend in the command word to either
-suspend or stop the transmit/command unit.  This driver always flags the last
-command with CmdSuspend, erases the CmdSuspend in the previous command, and
-then issues a CU_RESUME.
-Note: Watch out for the potential race condition here: imagine
-	erasing the previous suspend
-		the chip processes the previous command
-		the chip processes the final command, and suspends
-	doing the CU_RESUME
-		the chip processes the next-yet-valid post-final-command.
-So blindly sending a CU_RESUME is only safe if we do it immediately after
-after erasing the previous CmdSuspend, without the possibility of an
-intervening delay.  Thus the resume command is always within the
-interrupts-disabled region.  This is a timing dependence, but handling this
-condition in a timing-independent way would considerably complicate the code.
-
-Note: In previous generation Intel chips, restarting the command unit was a
-notoriously slow process.  This is presumably no longer true.
-
-IIIC. Receive structure
-
-Because of the bus-master support on the Speedo3 this driver uses the new
-SKBUFF_RX_COPYBREAK scheme, rather than a fixed intermediate receive buffer.
-This scheme allocates full-sized skbuffs as receive buffers.  The value
-SKBUFF_RX_COPYBREAK is used as the copying breakpoint: it is chosen to
-trade-off the memory wasted by passing the full-sized skbuff to the queue
-layer for all frames vs. the copying cost of copying a frame to a
-correctly-sized skbuff.
-
-For small frames the copying cost is negligible (esp. considering that we
-are pre-loading the cache with immediately useful header information), so we
-allocate a new, minimally-sized skbuff.  For large frames the copying cost
-is non-trivial, and the larger copy might flush the cache of useful data, so
-we pass up the skbuff the packet was received into.
-
-IV. Notes
-
-Thanks to Steve Williams of Intel for arranging the non-disclosure agreement
-that stated that I could disclose the information.  But I still resent
-having to sign an Intel NDA when I'm helping Intel sell their own product!
-
-*/
-
-static int speedo_found1(struct pci_dev *pdev, void __iomem *ioaddr, int fnd_cnt, int acpi_idle_state);
-
-/* Offsets to the various registers.
-   All accesses need not be longword aligned. */
-enum speedo_offsets {
-	SCBStatus = 0, SCBCmd = 2,	/* Rx/Command Unit command and status. */
-	SCBIntmask = 3,
-	SCBPointer = 4,				/* General purpose pointer. */
-	SCBPort = 8,				/* Misc. commands and operands.  */
-	SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
-	SCBCtrlMDI = 16,			/* MDI interface control. */
-	SCBEarlyRx = 20,			/* Early receive byte count. */
-};
-/* Commands that can be put in a command list entry. */
-enum commands {
-	CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
-	CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
-	CmdDump = 0x60000, CmdDiagnose = 0x70000,
-	CmdSuspend = 0x40000000,	/* Suspend after completion. */
-	CmdIntr = 0x20000000,		/* Interrupt after completion. */
-	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */
-};
-/* Clear CmdSuspend (1<<30) avoiding interference with the card access to the
-   status bits.  Previous driver versions used separate 16 bit fields for
-   commands and statuses.  --SAW
- */
-#if defined(__alpha__)
-# define clear_suspend(cmd)  clear_bit(30, &(cmd)->cmd_status);
-#else
-# define clear_suspend(cmd)  ((__le16 *)&(cmd)->cmd_status)[1] &= ~cpu_to_le16(1<<14)
-#endif
-
-enum SCBCmdBits {
-	SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
-	SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
-	SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
-	/* The rest are Rx and Tx commands. */
-	CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
-	CUCmdBase=0x0060,	/* CU Base address (set to zero) . */
-	CUDumpStats=0x0070, /* Dump then reset stats counters. */
-	RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
-	RxResumeNoResources=0x0007,
-};
-
-enum SCBPort_cmds {
-	PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
-};
-
-/* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor {			    /* A generic descriptor. */
-	volatile __le32 cmd_status;	/* All command and status fields. */
-	__le32 link;				    /* struct descriptor *  */
-	unsigned char params[0];
-};
-
-/* The Speedo3 Rx and Tx buffer descriptors. */
-struct RxFD {					/* Receive frame descriptor. */
-	volatile __le32 status;
-	__le32 link;					/* struct RxFD * */
-	__le32 rx_buf_addr;			/* void * */
-	__le32 count;
-} RxFD_ALIGNMENT;
-
-/* Selected elements of the Tx/RxFD.status word. */
-enum RxFD_bits {
-	RxComplete=0x8000, RxOK=0x2000,
-	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
-	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
-	TxUnderrun=0x1000,  StatusComplete=0x8000,
-};
-
-#define CONFIG_DATA_SIZE 22
-struct TxFD {					/* Transmit frame descriptor set. */
-	__le32 status;
-	__le32 link;					/* void * */
-	__le32 tx_desc_addr;			/* Always points to the tx_buf_addr element. */
-	__le32 count;					/* # of TBD (=1), Tx start thresh., etc. */
-	/* This constitutes two "TBD" entries -- we only use one. */
-#define TX_DESCR_BUF_OFFSET 16
-	__le32 tx_buf_addr0;			/* void *, frame to be transmitted.  */
-	__le32 tx_buf_size0;			/* Length of Tx frame. */
-	__le32 tx_buf_addr1;			/* void *, frame to be transmitted.  */
-	__le32 tx_buf_size1;			/* Length of Tx frame. */
-	/* the structure must have space for at least CONFIG_DATA_SIZE starting
-	 * from tx_desc_addr field */
-};
-
-/* Multicast filter setting block.  --SAW */
-struct speedo_mc_block {
-	struct speedo_mc_block *next;
-	unsigned int tx;
-	dma_addr_t frame_dma;
-	unsigned int len;
-	struct descriptor frame __attribute__ ((__aligned__(16)));
-};
-
-/* Elements of the dump_statistics block. This block must be lword aligned. */
-struct speedo_stats {
-	__le32 tx_good_frames;
-	__le32 tx_coll16_errs;
-	__le32 tx_late_colls;
-	__le32 tx_underruns;
-	__le32 tx_lost_carrier;
-	__le32 tx_deferred;
-	__le32 tx_one_colls;
-	__le32 tx_multi_colls;
-	__le32 tx_total_colls;
-	__le32 rx_good_frames;
-	__le32 rx_crc_errs;
-	__le32 rx_align_errs;
-	__le32 rx_resource_errs;
-	__le32 rx_overrun_errs;
-	__le32 rx_colls_errs;
-	__le32 rx_runt_errs;
-	__le32 done_marker;
-};
-
-enum Rx_ring_state_bits {
-	RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,
-};
-
-/* Do not change the position (alignment) of the first few elements!
-   The later elements are grouped for cache locality.
-
-   Unfortunately, all the positions have been shifted since there.
-   A new re-alignment is required.  2000/03/06  SAW */
-struct speedo_private {
-    void __iomem *regs;
-	struct TxFD	*tx_ring;		/* Commands (usually CmdTxPacket). */
-	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
-	/* The addresses of a Tx/Rx-in-place packets/buffers. */
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	/* Mapped addresses of the rings. */
-	dma_addr_t tx_ring_dma;
-#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD))
-	dma_addr_t rx_ring_dma[RX_RING_SIZE];
-	struct descriptor *last_cmd;		/* Last command sent. */
-	unsigned int cur_tx, dirty_tx;		/* The ring entries to be free()ed. */
-	spinlock_t lock;			/* Group with Tx control cache line. */
-	u32 tx_threshold;			/* The value for txdesc.count. */
-	struct RxFD *last_rxf;			/* Last filled RX buffer. */
-	dma_addr_t last_rxf_dma;
-	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
-	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
-	struct net_device_stats stats;
-	struct speedo_stats *lstats;
-	dma_addr_t lstats_dma;
-	int chip_id;
-	struct pci_dev *pdev;
-	struct timer_list timer;		/* Media selection timer. */
-	struct speedo_mc_block *mc_setup_head;	/* Multicast setup frame list head. */
-	struct speedo_mc_block *mc_setup_tail;	/* Multicast setup frame list tail. */
-	long in_interrupt;			/* Word-aligned dev->interrupt */
-	unsigned char acpi_pwr;
-	signed char rx_mode;			/* Current PROMISC/ALLMULTI setting. */
-	unsigned int tx_full:1;			/* The Tx queue is full. */
-	unsigned int flow_ctrl:1;		/* Use 802.3x flow control. */
-	unsigned int rx_bug:1;			/* Work around receiver hang errata. */
-	unsigned char default_port:8;		/* Last dev->if_port value. */
-	unsigned char rx_ring_state;		/* RX ring status flags. */
-	unsigned short phy[2];			/* PHY media interfaces available. */
-	unsigned short partner;			/* Link partner caps. */
-	struct mii_if_info mii_if;		/* MII API hooks, info */
-	u32 msg_enable;				/* debug message level */
-};
-
-/* The parameters for a CmdConfigure operation.
-   There are so many options that it would be difficult to document each bit.
-   We mostly use the default or recommended settings. */
-static const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
-	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
-	0, 0x2E, 0,  0x60, 0,
-	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */
-	0x3f, 0x05, };
-static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
-	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
-	0, 0x2E, 0,  0x60, 0x08, 0x88,
-	0x68, 0, 0x40, 0xf2, 0x84,		/* Disable FC */
-	0x31, 0x05, };
-
-/* PHY media interface chips. */
-static const char * const phys[] = {
-	"None", "i82553-A/B", "i82553-C", "i82503",
-	"DP83840", "80c240", "80c24", "i82555",
-	"unknown-8", "unknown-9", "DP83840A", "unknown-11",
-	"unknown-12", "unknown-13", "unknown-14", "unknown-15", };
-enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
-					 S80C24, I82555, DP83840A=10, };
-static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
-#define EE_READ_CMD		(6)
-
-static int eepro100_init_one(struct pci_dev *pdev,
-		const struct pci_device_id *ent);
-
-static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static int speedo_open(struct net_device *dev);
-static void speedo_resume(struct net_device *dev);
-static void speedo_timer(unsigned long data);
-static void speedo_init_rx_ring(struct net_device *dev);
-static void speedo_tx_timeout(struct net_device *dev);
-static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void speedo_refill_rx_buffers(struct net_device *dev, int force);
-static int speedo_rx(struct net_device *dev);
-static void speedo_tx_buffer_gc(struct net_device *dev);
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance);
-static int speedo_close(struct net_device *dev);
-static struct net_device_stats *speedo_get_stats(struct net_device *dev);
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct net_device *dev);
-static void speedo_show_state(struct net_device *dev);
-static const struct ethtool_ops ethtool_ops;
-
-
-
-#ifdef honor_default_port
-/* Optional driver feature to allow forcing the transceiver setting.
-   Not recommended. */
-static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
-						   0x2000, 0x2100, 0x0400, 0x3100};
-#endif
-
-/* How to wait for the command unit to accept a command.
-   Typically this takes 0 ticks. */
-static inline unsigned char wait_for_cmd_done(struct net_device *dev,
-											  	struct speedo_private *sp)
-{
-	int wait = 1000;
-	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
-	unsigned char r;
-
-	do  {
-		udelay(1);
-		r = ioread8(cmd_ioaddr);
-	} while(r && --wait >= 0);
-
-	if (wait < 0)
-		printk(KERN_ALERT "%s: wait_for_cmd_done timeout!\n", dev->name);
-	return r;
-}
-
-static int __devinit eepro100_init_one (struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	void __iomem *ioaddr;
-	int irq, pci_bar;
-	int acpi_idle_state = 0, pm;
-	static int cards_found /* = 0 */;
-	unsigned long pci_base;
-
-#ifndef MODULE
-	/* when built-in, we only print version if device is found */
-	static int did_version;
-	if (did_version++ == 0)
-		printk(version);
-#endif
-
-	/* save power state before pci_enable_device overwrites it */
-	pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (pm) {
-		u16 pwr_command;
-		pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
-		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
-	}
-
-	if (pci_enable_device(pdev))
-		goto err_out_free_mmio_region;
-
-	pci_set_master(pdev);
-
-	if (!request_region(pci_resource_start(pdev, 1),
-			pci_resource_len(pdev, 1), "eepro100")) {
-		dev_err(&pdev->dev, "eepro100: cannot reserve I/O ports\n");
-		goto err_out_none;
-	}
-	if (!request_mem_region(pci_resource_start(pdev, 0),
-			pci_resource_len(pdev, 0), "eepro100")) {
-		dev_err(&pdev->dev, "eepro100: cannot reserve MMIO region\n");
-		goto err_out_free_pio_region;
-	}
-
-	irq = pdev->irq;
-	pci_bar = use_io ? 1 : 0;
-	pci_base = pci_resource_start(pdev, pci_bar);
-	if (DEBUG & NETIF_MSG_PROBE)
-		printk("Found Intel i82557 PCI Speedo at %#lx, IRQ %d.\n",
-		       pci_base, irq);
-
-	ioaddr = pci_iomap(pdev, pci_bar, 0);
-	if (!ioaddr) {
-		dev_err(&pdev->dev, "eepro100: cannot remap IO\n");
-		goto err_out_free_mmio_region;
-	}
-
-	if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
-		cards_found++;
-	else
-		goto err_out_iounmap;
-
-	return 0;
-
-err_out_iounmap: ;
-	pci_iounmap(pdev, ioaddr);
-err_out_free_mmio_region:
-	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_out_free_pio_region:
-	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
-err_out_none:
-	return -ENODEV;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-
-static void poll_speedo (struct net_device *dev)
-{
-	/* disable_irq is not very nice, but with the funny lockless design
-	   we have no other choice. */
-	disable_irq(dev->irq);
-	speedo_interrupt (dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static int __devinit speedo_found1(struct pci_dev *pdev,
-		void __iomem *ioaddr, int card_idx, int acpi_idle_state)
-{
-	struct net_device *dev;
-	struct speedo_private *sp;
-	const char *product;
-	int i, option;
-	u16 eeprom[0x100];
-	int size;
-	void *tx_ring_space;
-	dma_addr_t tx_ring_dma;
-	DECLARE_MAC_BUF(mac);
-
-	size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats);
-	tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma);
-	if (tx_ring_space == NULL)
-		return -1;
-
-	dev = alloc_etherdev(sizeof(struct speedo_private));
-	if (dev == NULL) {
-		printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");
-		pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);
-		return -1;
-	}
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	if (dev->mem_start > 0)
-		option = dev->mem_start;
-	else if (card_idx >= 0  &&  options[card_idx] >= 0)
-		option = options[card_idx];
-	else
-		option = 0;
-
-	rtnl_lock();
-	if (dev_alloc_name(dev, dev->name) < 0)
-		goto err_free_unlock;
-
-	/* Read the station address EEPROM before doing the reset.
-	   Nominally his should even be done before accepting the device, but
-	   then we wouldn't have a device name with which to report the error.
-	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.
-	*/
-	{
-		void __iomem *iobase;
-		int read_cmd, ee_size;
-		u16 sum;
-		int j;
-
-		/* Use IO only to avoid postponed writes and satisfy EEPROM timing
-		   requirements. */
-		iobase = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
-		if (!iobase)
-			goto err_free_unlock;
-		if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000)
-			== 0xffe0000) {
-			ee_size = 0x100;
-			read_cmd = EE_READ_CMD << 24;
-		} else {
-			ee_size = 0x40;
-			read_cmd = EE_READ_CMD << 22;
-		}
-
-		for (j = 0, i = 0, sum = 0; i < ee_size; i++) {
-			u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27);
-			eeprom[i] = value;
-			sum += value;
-			if (i < 3) {
-				dev->dev_addr[j++] = value;
-				dev->dev_addr[j++] = value >> 8;
-			}
-		}
-		if (sum != 0xBABA)
-			printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, "
-				   "check settings before activating this device!\n",
-				   dev->name, sum);
-		/* Don't  unregister_netdev(dev);  as the EEPro may actually be
-		   usable, especially if the MAC address is set later.
-		   On the other hand, it may be unusable if MDI data is corrupted. */
-
-		pci_iounmap(pdev, iobase);
-	}
-
-	/* Reset the chip: stop Tx and Rx processes and clear counters.
-	   This takes less than 10usec and will easily finish before the next
-	   action. */
-	iowrite32(PortReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort);
-	udelay(10);
-
-	if (eeprom[3] & 0x0100)
-		product = "OEM i82557/i82558 10/100 Ethernet";
-	else
-		product = pci_name(pdev);
-
-	printk(KERN_INFO "%s: %s, %s, IRQ %d.\n", dev->name, product,
-		   print_mac(mac, dev->dev_addr), pdev->irq);
-
-	sp = netdev_priv(dev);
-
-	/* we must initialize this early, for mdio_{read,write} */
-	sp->regs = ioaddr;
-
-#if 1 || defined(kernel_bloat)
-	/* OK, this is pure kernel bloat.  I don't like it when other drivers
-	   waste non-pageable kernel space to emit similar messages, but I need
-	   them for bug reports. */
-	{
-		const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};
-		/* The self-test results must be paragraph aligned. */
-		volatile s32 *self_test_results;
-		int boguscnt = 16000;	/* Timeout for set-test. */
-		if ((eeprom[3] & 0x03) != 0x03)
-			printk(KERN_INFO "  Receiver lock-up bug exists -- enabling"
-				   " work-around.\n");
-		printk(KERN_INFO "  Board assembly %4.4x%2.2x-%3.3d, Physical"
-			   " connectors present:",
-			   eeprom[8], eeprom[9]>>8, eeprom[9] & 0xff);
-		for (i = 0; i < 4; i++)
-			if (eeprom[5] & (1<<i))
-				printk(connectors[i]);
-		printk("\n"KERN_INFO"  Primary interface chip %s PHY #%d.\n",
-			   phys[(eeprom[6]>>8)&15], eeprom[6] & 0x1f);
-		if (eeprom[7] & 0x0700)
-			printk(KERN_INFO "    Secondary interface chip %s.\n",
-				   phys[(eeprom[7]>>8)&7]);
-		if (((eeprom[6]>>8) & 0x3f) == DP83840
-			||  ((eeprom[6]>>8) & 0x3f) == DP83840A) {
-			int mdi_reg23 = mdio_read(dev, eeprom[6] & 0x1f, 23) | 0x0422;
-			if (congenb)
-			  mdi_reg23 |= 0x0100;
-			printk(KERN_INFO"  DP83840 specific setup, setting register 23 to %4.4x.\n",
-				   mdi_reg23);
-			mdio_write(dev, eeprom[6] & 0x1f, 23, mdi_reg23);
-		}
-		if ((option >= 0) && (option & 0x70)) {
-			printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",
-				   (option & 0x20 ? 100 : 10),
-				   (option & 0x10 ? "full" : "half"));
-			mdio_write(dev, eeprom[6] & 0x1f, MII_BMCR,
-					   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */
-					   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
-		}
-
-		/* Perform a system self-test. */
-		self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf);
-		self_test_results[0] = 0;
-		self_test_results[1] = -1;
-		iowrite32(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
-		do {
-			udelay(10);
-		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);
-
-		if (boguscnt < 0) {		/* Test optimized out. */
-			printk(KERN_ERR "Self test failed, status %8.8x:\n"
-				   KERN_ERR " Failure to initialize the i82557.\n"
-				   KERN_ERR " Verify that the card is a bus-master"
-				   " capable slot.\n",
-				   self_test_results[1]);
-		} else
-			printk(KERN_INFO "  General self-test: %s.\n"
-				   KERN_INFO "  Serial sub-system self-test: %s.\n"
-				   KERN_INFO "  Internal registers self-test: %s.\n"
-				   KERN_INFO "  ROM checksum self-test: %s (%#8.8x).\n",
-				   self_test_results[1] & 0x1000 ? "failed" : "passed",
-				   self_test_results[1] & 0x0020 ? "failed" : "passed",
-				   self_test_results[1] & 0x0008 ? "failed" : "passed",
-				   self_test_results[1] & 0x0004 ? "failed" : "passed",
-				   self_test_results[0]);
-	}
-#endif  /* kernel_bloat */
-
-	iowrite32(PortReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort);
-	udelay(10);
-
-	/* Return the chip to its original power state. */
-	pci_set_power_state(pdev, acpi_idle_state);
-
-	pci_set_drvdata (pdev, dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	dev->irq = pdev->irq;
-
-	sp->pdev = pdev;
-	sp->msg_enable = DEBUG;
-	sp->acpi_pwr = acpi_idle_state;
-	sp->tx_ring = tx_ring_space;
-	sp->tx_ring_dma = tx_ring_dma;
-	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
-	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
-	init_timer(&sp->timer); /* used in ioctl() */
-	spin_lock_init(&sp->lock);
-
-	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
-	if (card_idx >= 0) {
-		if (full_duplex[card_idx] >= 0)
-			sp->mii_if.full_duplex = full_duplex[card_idx];
-	}
-	sp->default_port = option >= 0 ? (option & 0x0f) : 0;
-
-	sp->phy[0] = eeprom[6];
-	sp->phy[1] = eeprom[7];
-
-	sp->mii_if.phy_id = eeprom[6] & 0x1f;
-	sp->mii_if.phy_id_mask = 0x1f;
-	sp->mii_if.reg_num_mask = 0x1f;
-	sp->mii_if.dev = dev;
-	sp->mii_if.mdio_read = mdio_read;
-	sp->mii_if.mdio_write = mdio_write;
-
-	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
-	if (((pdev->device > 0x1030 && (pdev->device < 0x103F)))
-	    || (pdev->device == 0x2449) || (pdev->device == 0x2459)
-            || (pdev->device == 0x245D)) {
-	    	sp->chip_id = 1;
-	}
-
-	if (sp->rx_bug)
-		printk(KERN_INFO "  Receiver lock-up workaround activated.\n");
-
-	/* The Speedo-specific entries in the device structure. */
-	dev->open = &speedo_open;
-	dev->hard_start_xmit = &speedo_start_xmit;
-	netif_set_tx_timeout(dev, &speedo_tx_timeout, TX_TIMEOUT);
-	dev->stop = &speedo_close;
-	dev->get_stats = &speedo_get_stats;
-	dev->set_multicast_list = &set_rx_mode;
-	dev->do_ioctl = &speedo_ioctl;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = &poll_speedo;
-#endif
-
-	if (register_netdevice(dev))
-		goto err_free_unlock;
-	rtnl_unlock();
-
-	return 0;
-
- err_free_unlock:
-	rtnl_unlock();
-	free_netdev(dev);
-	return -1;
-}
-
-static void do_slow_command(struct net_device *dev, struct speedo_private *sp, int cmd)
-{
-	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
-	int wait = 0;
-	do
-		if (ioread8(cmd_ioaddr) == 0) break;
-	while(++wait <= 200);
-	if (wait > 100)
-		printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n",
-		       ioread8(cmd_ioaddr), wait);
-
-	iowrite8(cmd, cmd_ioaddr);
-
-	for (wait = 0; wait <= 100; wait++)
-		if (ioread8(cmd_ioaddr) == 0) return;
-	for (; wait <= 20000; wait++)
-		if (ioread8(cmd_ioaddr) == 0) return;
-		else udelay(1);
-	printk(KERN_ERR "Command %4.4x was not accepted after %d polls!"
-	       "  Current status %8.8x.\n",
-	       cmd, wait, ioread32(sp->regs + SCBStatus));
-}
-
-/* Serial EEPROM section.
-   A "bit" grungy, but we work our way through bit-by-bit :->. */
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x01	/* EEPROM shift clock. */
-#define EE_CS			0x02	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
-#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
-#define EE_ENB			(0x4800 | EE_CS)
-#define EE_WRITE_0		0x4802
-#define EE_WRITE_1		0x4806
-#define EE_OFFSET		SCBeeprom
-
-/* The fixes for the code were kindly provided by Dragan Stancevic
-   <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
-   access timing.
-   The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
-   interval for serial EEPROM.  However, it looks like that there is an
-   additional requirement dictating larger udelay's in the code below.
-   2000/05/24  SAW */
-static int __devinit do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
-{
-	unsigned retval = 0;
-	void __iomem *ee_addr = ioaddr + SCBeeprom;
-
-	iowrite16(EE_ENB, ee_addr); udelay(2);
-	iowrite16(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
-
-	/* Shift the command bits out. */
-	do {
-		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
-		iowrite16(dataval, ee_addr); udelay(2);
-		iowrite16(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
-		retval = (retval << 1) | ((ioread16(ee_addr) & EE_DATA_READ) ? 1 : 0);
-	} while (--cmd_len >= 0);
-	iowrite16(EE_ENB, ee_addr); udelay(2);
-
-	/* Terminate the EEPROM access. */
-	iowrite16(EE_ENB & ~EE_CS, ee_addr);
-	return retval;
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	iowrite32(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
-	do {
-		val = ioread32(ioaddr + SCBCtrlMDI);
-		if (--boguscnt < 0) {
-			printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
-			break;
-		}
-	} while (! (val & 0x10000000));
-	return val & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	iowrite32(0x04000000 | (location<<16) | (phy_id<<21) | value,
-		 ioaddr + SCBCtrlMDI);
-	do {
-		val = ioread32(ioaddr + SCBCtrlMDI);
-		if (--boguscnt < 0) {
-			printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
-			break;
-		}
-	} while (! (val & 0x10000000));
-}
-
-static int
-speedo_open(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int retval;
-
-	if (netif_msg_ifup(sp))
-		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
-
-	pci_set_power_state(sp->pdev, PCI_D0);
-
-	/* Set up the Tx queue early.. */
-	sp->cur_tx = 0;
-	sp->dirty_tx = 0;
-	sp->last_cmd = NULL;
-	sp->tx_full = 0;
-	sp->in_interrupt = 0;
-
-	/* .. we can safely take handler calls during init. */
-	retval = request_irq(dev->irq, &speedo_interrupt, IRQF_SHARED, dev->name, dev);
-	if (retval) {
-		return retval;
-	}
-
-	dev->if_port = sp->default_port;
-
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
-	/* Retrigger negotiation to reset previous errors. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int phy_addr = sp->phy[0] & 0x1f ;
-		/* Use 0x3300 for restarting NWay, other values to force xcvr:
-		   0x0000 10-HD
-		   0x0100 10-FD
-		   0x2000 100-HD
-		   0x2100 100-FD
-		*/
-#ifdef honor_default_port
-		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
-		mdio_write(dev, phy_addr, MII_BMCR, 0x3300);
-#endif
-	}
-#endif
-
-	speedo_init_rx_ring(dev);
-
-	/* Fire up the hardware. */
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-	speedo_resume(dev);
-
-	netdevice_start(dev);
-	netif_start_queue(dev);
-
-	/* Setup the chip and configure the multicast list. */
-	sp->mc_setup_head = NULL;
-	sp->mc_setup_tail = NULL;
-	sp->flow_ctrl = sp->partner = 0;
-	sp->rx_mode = -1;			/* Invalid -> always reset the mode. */
-	set_rx_mode(dev);
-	if ((sp->phy[0] & 0x8000) == 0)
-		sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE);
-
-	mii_check_link(&sp->mii_if);
-
-	if (netif_msg_ifup(sp)) {
-		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-	}
-
-	/* Set the timer.  The timer serves a dual purpose:
-	   1) to monitor the media interface (e.g. link beat) and perhaps switch
-	   to an alternate media type
-	   2) to monitor Rx activity, and restart the Rx process if the receiver
-	   hangs. */
-	sp->timer.expires = RUN_AT((24*HZ)/10); 			/* 2.4 sec. */
-	sp->timer.data = (unsigned long)dev;
-	sp->timer.function = &speedo_timer;					/* timer handler */
-	add_timer(&sp->timer);
-
-	/* No need to wait for the command unit to accept here. */
-	if ((sp->phy[0] & 0x8000) == 0)
-		mdio_read(dev, sp->phy[0] & 0x1f, MII_BMCR);
-
-	return 0;
-}
-
-/* Start the chip hardware after a full reset. */
-static void speedo_resume(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
-	sp->tx_threshold = 0x01208000;
-
-	/* Set the segment registers to '0'. */
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		iowrite32(PortPartialReset, ioaddr + SCBPort);
-		udelay(10);
-	}
-
-        iowrite32(0, ioaddr + SCBPointer);
-        ioread32(ioaddr + SCBPointer);			/* Flush to PCI. */
-        udelay(10);			/* Bogus, but it avoids the bug. */
-
-        /* Note: these next two operations can take a while. */
-        do_slow_command(dev, sp, RxAddrLoad);
-        do_slow_command(dev, sp, CUCmdBase);
-
-	/* Load the statistics block and rx ring addresses. */
-	iowrite32(sp->lstats_dma, ioaddr + SCBPointer);
-	ioread32(ioaddr + SCBPointer);			/* Flush to PCI */
-
-	iowrite8(CUStatsAddr, ioaddr + SCBCmd);
-	sp->lstats->done_marker = 0;
-	wait_for_cmd_done(dev, sp);
-
-	if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
-		if (netif_msg_rx_err(sp))
-			printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
-					dev->name);
-	} else {
-		iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
-			 ioaddr + SCBPointer);
-		ioread32(ioaddr + SCBPointer);		/* Flush to PCI */
-	}
-
-	/* Note: RxStart should complete instantly. */
-	do_slow_command(dev, sp, RxStart);
-	do_slow_command(dev, sp, CUDumpStats);
-
-	/* Fill the first command with our physical address. */
-	{
-		struct descriptor *ias_cmd;
-
-		ias_cmd =
-			(struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE];
-		/* Avoid a bug(?!) here by marking the command already completed. */
-		ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
-		ias_cmd->link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
-		memcpy(ias_cmd->params, dev->dev_addr, 6);
-		if (sp->last_cmd)
-			clear_suspend(sp->last_cmd);
-		sp->last_cmd = ias_cmd;
-	}
-
-	/* Start the chip's Tx process and unmask interrupts. */
-	iowrite32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
-		 ioaddr + SCBPointer);
-	/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
-	   remain masked --Dragan */
-	iowrite16(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
-}
-
-/*
- * Sometimes the receiver stops making progress.  This routine knows how to
- * get it going again, without losing packets or being otherwise nasty like
- * a chip reset would be.  Previously the driver had a whole sequence
- * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
- * do another, etc.  But those things don't really matter.  Separate logic
- * in the ISR provides for allocating buffers--the other half of operation
- * is just making sure the receiver is active.  speedo_rx_soft_reset does that.
- * This problem with the old, more involved algorithm is shown up under
- * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
- */
-static void
-speedo_rx_soft_reset(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rfd;
-	void __iomem *ioaddr;
-
-	ioaddr = sp->regs;
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		printk("%s: previous command stalled\n", dev->name);
-		return;
-	}
-	/*
-	* Put the hardware into a known state.
-	*/
-	iowrite8(RxAbort, ioaddr + SCBCmd);
-
-	rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
-
-	rfd->rx_buf_addr = cpu_to_le32(0xffffffff);
-
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		printk("%s: RxAbort command stalled\n", dev->name);
-		return;
-	}
-	iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
-		ioaddr + SCBPointer);
-	iowrite8(RxStart, ioaddr + SCBCmd);
-}
-
-
-/* Media monitoring and control. */
-static void speedo_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int phy_num = sp->phy[0] & 0x1f;
-
-	/* We have MII and lost link beat. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int partner = mdio_read(dev, phy_num, MII_LPA);
-		if (partner != sp->partner) {
-			int flow_ctrl = sp->mii_if.advertising & partner & 0x0400 ? 1 : 0;
-			if (netif_msg_link(sp)) {
-				printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
-				printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n",
-					   dev->name, sp->partner, partner, sp->mii_if.advertising);
-			}
-			sp->partner = partner;
-			if (flow_ctrl != sp->flow_ctrl) {
-				sp->flow_ctrl = flow_ctrl;
-				sp->rx_mode = -1;	/* Trigger a reload. */
-			}
-		}
-	}
-	mii_check_link(&sp->mii_if);
-	if (netif_msg_timer(sp)) {
-		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-	}
-	if (sp->rx_mode < 0  ||
-		(sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
-		/* We haven't received a packet in a Long Time.  We might have been
-		   bitten by the receiver hang bug.  This can be cleared by sending
-		   a set multicast list command. */
-		if (netif_msg_timer(sp))
-			printk(KERN_DEBUG "%s: Sending a multicast list set command"
-				   " from a timer routine,"
-				   " m=%d, j=%ld, l=%ld.\n",
-				   dev->name, sp->rx_mode, jiffies, sp->last_rx_time);
-		set_rx_mode(dev);
-	}
-	/* We must continue to monitor the media. */
-	sp->timer.expires = RUN_AT(2*HZ); 			/* 2.0 sec. */
-	add_timer(&sp->timer);
-}
-
-static void speedo_show_state(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int i;
-
-	if (netif_msg_pktdata(sp)) {
-		printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %u / %u:\n",
-		    dev->name, sp->cur_tx, sp->dirty_tx);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(KERN_DEBUG "%s:  %c%c%2d %8.8x.\n", dev->name,
-			    i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
-			    i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
-			    i, sp->tx_ring[i].status);
-
-		printk(KERN_DEBUG "%s: Printing Rx ring"
-		    " (next to receive into %u, dirty index %u).\n",
-		    dev->name, sp->cur_rx, sp->dirty_rx);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name,
-			    sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ',
-			    i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ',
-			    i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ',
-			    i, (sp->rx_ringp[i] != NULL) ?
-			    (unsigned)sp->rx_ringp[i]->status : 0);
-	}
-
-#if 0
-	{
-		void __iomem *ioaddr = sp->regs;
-		int phy_num = sp->phy[0] & 0x1f;
-		for (i = 0; i < 16; i++) {
-			/* FIXME: what does it mean?  --SAW */
-			if (i == 6) i = 21;
-			printk(KERN_DEBUG "%s:  PHY index %d register %d is %4.4x.\n",
-				   dev->name, phy_num, i, mdio_read(dev, phy_num, i));
-		}
-	}
-#endif
-
-}
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-speedo_init_rx_ring(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rxf, *last_rxf = NULL;
-	dma_addr_t last_rxf_dma = 0 /* to shut up the compiler */;
-	int i;
-
-	sp->cur_rx = 0;
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb;
-		skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-		if (skb)
-			rx_align(skb);        /* Align IP on 16 byte boundary */
-		sp->rx_skbuff[i] = skb;
-		if (skb == NULL)
-			break;			/* OK.  Just initially short of Rx bufs. */
-		skb->dev = dev;			/* Mark as being used by this device. */
-		rxf = (struct RxFD *)skb->data;
-		sp->rx_ringp[i] = rxf;
-		sp->rx_ring_dma[i] =
-			pci_map_single(sp->pdev, rxf,
-					PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_BIDIRECTIONAL);
-		skb_reserve(skb, sizeof(struct RxFD));
-		if (last_rxf) {
-			last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
-			pci_dma_sync_single_for_device(sp->pdev, last_rxf_dma,
-										   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-		}
-		last_rxf = rxf;
-		last_rxf_dma = sp->rx_ring_dma[i];
-		rxf->status = cpu_to_le32(0x00000001);	/* '1' is flag value only. */
-		rxf->link = 0;						/* None yet. */
-		/* This field unused by i82557. */
-		rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
-		rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
-		pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[i],
-									   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	}
-	sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-	/* Mark the last entry as end-of-list. */
-	last_rxf->status = cpu_to_le32(0xC0000002);	/* '2' is flag value only. */
-	pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1],
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	sp->last_rxf = last_rxf;
-	sp->last_rxf_dma = last_rxf_dma;
-}
-
-static void speedo_purge_tx(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry;
-
-	while ((int)(sp->cur_tx - sp->dirty_tx) > 0) {
-		entry = sp->dirty_tx % TX_RING_SIZE;
-		if (sp->tx_skbuff[entry]) {
-			sp->stats.tx_errors++;
-			pci_unmap_single(sp->pdev,
-					le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
-					sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq(sp->tx_skbuff[entry]);
-			sp->tx_skbuff[entry] = NULL;
-		}
-		sp->dirty_tx++;
-	}
-	while (sp->mc_setup_head != NULL) {
-		struct speedo_mc_block *t;
-		if (netif_msg_tx_err(sp))
-			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
-		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
-				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	sp->mc_setup_tail = NULL;
-	sp->tx_full = 0;
-	netif_wake_queue(dev);
-}
-
-static void reset_mii(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-
-	/* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int phy_addr = sp->phy[0] & 0x1f;
-		int advertising = mdio_read(dev, phy_addr, MII_ADVERTISE);
-		int mii_bmcr = mdio_read(dev, phy_addr, MII_BMCR);
-		mdio_write(dev, phy_addr, MII_BMCR, 0x0400);
-		mdio_write(dev, phy_addr, MII_BMSR, 0x0000);
-		mdio_write(dev, phy_addr, MII_ADVERTISE, 0x0000);
-		mdio_write(dev, phy_addr, MII_BMCR, 0x8000);
-#ifdef honor_default_port
-		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
-		mdio_read(dev, phy_addr, MII_BMCR);
-		mdio_write(dev, phy_addr, MII_BMCR, mii_bmcr);
-		mdio_write(dev, phy_addr, MII_ADVERTISE, advertising);
-#endif
-	}
-}
-
-static void speedo_tx_timeout(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int status = ioread16(ioaddr + SCBStatus);
-	unsigned long flags;
-
-	if (netif_msg_tx_err(sp)) {
-		printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
-		   " %4.4x at %d/%d command %8.8x.\n",
-		   dev->name, status, ioread16(ioaddr + SCBCmd),
-		   sp->dirty_tx, sp->cur_tx,
-		   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
-
-	}
-	speedo_show_state(dev);
-#if 0
-	if ((status & 0x00C0) != 0x0080
-		&&  (status & 0x003C) == 0x0010) {
-		/* Only the command unit has stopped. */
-		printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
-			   dev->name);
-		iowrite32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
-			 ioaddr + SCBPointer);
-		iowrite16(CUStart, ioaddr + SCBCmd);
-		reset_mii(dev);
-	} else {
-#else
-	{
-#endif
-		del_timer_sync(&sp->timer);
-		/* Reset the Tx and Rx units. */
-		iowrite32(PortReset, ioaddr + SCBPort);
-		/* We may get spurious interrupts here.  But I don't think that they
-		   may do much harm.  1999/12/09 SAW */
-		udelay(10);
-		/* Disable interrupts. */
-		iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-		synchronize_irq(dev->irq);
-		speedo_tx_buffer_gc(dev);
-		/* Free as much as possible.
-		   It helps to recover from a hang because of out-of-memory.
-		   It also simplifies speedo_resume() in case TX ring is full or
-		   close-to-be full. */
-		speedo_purge_tx(dev);
-		speedo_refill_rx_buffers(dev, 1);
-		spin_lock_irqsave(&sp->lock, flags);
-		speedo_resume(dev);
-		sp->rx_mode = -1;
-		dev->trans_start = jiffies;
-		spin_unlock_irqrestore(&sp->lock, flags);
-		set_rx_mode(dev); /* it takes the spinlock itself --SAW */
-		/* Reset MII transceiver.  Do it before starting the timer to serialize
-		   mdio_xxx operations.  Yes, it's a paranoya :-)  2000/05/09 SAW */
-		reset_mii(dev);
-		sp->timer.expires = RUN_AT(2*HZ);
-		add_timer(&sp->timer);
-	}
-	return;
-}
-
-static int
-speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int entry;
-
-	/* Prevent interrupts from changing the Tx ring from underneath us. */
-	unsigned long flags;
-
-	spin_lock_irqsave(&sp->lock, flags);
-
-	/* Check if there are enough space. */
-	if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-		printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name);
-		netif_stop_queue(dev);
-		sp->tx_full = 1;
-		spin_unlock_irqrestore(&sp->lock, flags);
-		return 1;
-	}
-
-	/* Calculate the Tx descriptor entry. */
-	entry = sp->cur_tx++ % TX_RING_SIZE;
-
-	sp->tx_skbuff[entry] = skb;
-	sp->tx_ring[entry].status =
-		cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
-	if (!(entry & ((TX_RING_SIZE>>2)-1)))
-		sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr);
-	sp->tx_ring[entry].link =
-		cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
-	sp->tx_ring[entry].tx_desc_addr =
-		cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET);
-	/* The data region is always in one buffer descriptor. */
-	sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
-	sp->tx_ring[entry].tx_buf_addr0 =
-		cpu_to_le32(pci_map_single(sp->pdev, skb->data,
-					   skb->len, PCI_DMA_TODEVICE));
-	sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
-
-	/* workaround for hardware bug on 10 mbit half duplex */
-
-	if ((sp->partner == 0) && (sp->chip_id == 1)) {
-		wait_for_cmd_done(dev, sp);
-		iowrite8(0 , ioaddr + SCBCmd);
-		udelay(1);
-	}
-
-	/* Trigger the command unit resume. */
-	wait_for_cmd_done(dev, sp);
-	clear_suspend(sp->last_cmd);
-	/* We want the time window between clearing suspend flag on the previous
-	   command and resuming CU to be as small as possible.
-	   Interrupts in between are very undesired.  --SAW */
-	iowrite8(CUResume, ioaddr + SCBCmd);
-	sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-	/* Leave room for set_rx_mode(). If there is no more space than reserved
-	   for multicast filter mark the ring as full. */
-	if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-		netif_stop_queue(dev);
-		sp->tx_full = 1;
-	}
-
-	spin_unlock_irqrestore(&sp->lock, flags);
-
-	dev->trans_start = jiffies;
-
-	return 0;
-}
-
-static void speedo_tx_buffer_gc(struct net_device *dev)
-{
-	unsigned int dirty_tx;
-	struct speedo_private *sp = netdev_priv(dev);
-
-	dirty_tx = sp->dirty_tx;
-	while ((int)(sp->cur_tx - dirty_tx) > 0) {
-		int entry = dirty_tx % TX_RING_SIZE;
-		int status = le32_to_cpu(sp->tx_ring[entry].status);
-
-		if (netif_msg_tx_done(sp))
-			printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
-				   entry, status);
-		if ((status & StatusComplete) == 0)
-			break;			/* It still hasn't been processed. */
-		if (status & TxUnderrun)
-			if (sp->tx_threshold < 0x01e08000) {
-				if (netif_msg_tx_err(sp))
-					printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n",
-						   dev->name);
-				sp->tx_threshold += 0x00040000;
-			}
-		/* Free the original skb. */
-		if (sp->tx_skbuff[entry]) {
-			sp->stats.tx_packets++;	/* Count only user packets. */
-			sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
-			pci_unmap_single(sp->pdev,
-					le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
-					sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq(sp->tx_skbuff[entry]);
-			sp->tx_skbuff[entry] = NULL;
-		}
-		dirty_tx++;
-	}
-
-	if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
-		printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
-			   " full=%d.\n",
-			   dirty_tx, sp->cur_tx, sp->tx_full);
-		dirty_tx += TX_RING_SIZE;
-	}
-
-	while (sp->mc_setup_head != NULL
-		   && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) {
-		struct speedo_mc_block *t;
-		if (netif_msg_tx_err(sp))
-			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
-		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
-				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	if (sp->mc_setup_head == NULL)
-		sp->mc_setup_tail = NULL;
-
-	sp->dirty_tx = dirty_tx;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *dev = (struct net_device *)dev_instance;
-	struct speedo_private *sp;
-	void __iomem *ioaddr;
-	long boguscnt = max_interrupt_work;
-	unsigned short status;
-	unsigned int handled = 0;
-
-	sp = netdev_priv(dev);
-	ioaddr = sp->regs;
-
-#ifndef final_version
-	/* A lock to prevent simultaneous entry on SMP machines. */
-	if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		sp->in_interrupt = 0;	/* Avoid halting machine. */
-		return IRQ_NONE;
-	}
-#endif
-
-	do {
-		status = ioread16(ioaddr + SCBStatus);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		/* Will change from 0xfc00 to 0xff00 when we start handling
-		   FCP and ER interrupts --Dragan */
-		iowrite16(status & 0xfc00, ioaddr + SCBStatus);
-
-		if (netif_msg_intr(sp))
-			printk(KERN_DEBUG "%s: interrupt  status=%#4.4x.\n",
-				   dev->name, status);
-
-		if ((status & 0xfc00) == 0)
-			break;
-		handled = 1;
-
-
-		if ((status & 0x5000) ||	/* Packet received, or Rx error. */
-			(sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)
-									/* Need to gather the postponed packet. */
-			speedo_rx(dev);
-
-		/* Always check if all rx buffers are allocated.  --SAW */
-		speedo_refill_rx_buffers(dev, 0);
-
-		spin_lock(&sp->lock);
-		/*
-		 * The chip may have suspended reception for various reasons.
-		 * Check for that, and re-prime it should this be the case.
-		 */
-		switch ((status >> 2) & 0xf) {
-		case 0: /* Idle */
-			break;
-		case 1:	/* Suspended */
-		case 2:	/* No resources (RxFDs) */
-		case 9:	/* Suspended with no more RBDs */
-		case 10: /* No resources due to no RBDs */
-		case 12: /* Ready with no RBDs */
-			speedo_rx_soft_reset(dev);
-			break;
-		case 3:  case 5:  case 6:  case 7:  case 8:
-		case 11:  case 13:  case 14:  case 15:
-			/* these are all reserved values */
-			break;
-		}
-
-
-		/* User interrupt, Command/Tx unit interrupt or CU not active. */
-		if (status & 0xA400) {
-			speedo_tx_buffer_gc(dev);
-			if (sp->tx_full
-				&& (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) {
-				/* The ring is no longer full. */
-				sp->tx_full = 0;
-				netif_wake_queue(dev); /* Attention: under a spinlock.  --SAW */
-			}
-		}
-
-		spin_unlock(&sp->lock);
-
-		if (--boguscnt < 0) {
-			printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n",
-				   dev->name, status);
-			/* Clear all interrupt sources. */
-			/* Will change from 0xfc00 to 0xff00 when we start handling
-			   FCP and ER interrupts --Dragan */
-			iowrite16(0xfc00, ioaddr + SCBStatus);
-			break;
-		}
-	} while (1);
-
-	if (netif_msg_intr(sp))
-		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-
-	clear_bit(0, (void*)&sp->in_interrupt);
-	return IRQ_RETVAL(handled);
-}
-
-static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rxf;
-	struct sk_buff *skb;
-	/* Get a fresh skbuff to replace the consumed one. */
-	skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-	if (skb)
-		rx_align(skb);		/* Align IP on 16 byte boundary */
-	sp->rx_skbuff[entry] = skb;
-	if (skb == NULL) {
-		sp->rx_ringp[entry] = NULL;
-		return NULL;
-	}
-	rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->data;
-	sp->rx_ring_dma[entry] =
-		pci_map_single(sp->pdev, rxf,
-					   PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-	skb->dev = dev;
-	skb_reserve(skb, sizeof(struct RxFD));
-	rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
-	pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	return rxf;
-}
-
-static inline void speedo_rx_link(struct net_device *dev, int entry,
-								  struct RxFD *rxf, dma_addr_t rxf_dma)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	rxf->status = cpu_to_le32(0xC0000001); 	/* '1' for driver use only. */
-	rxf->link = 0;			/* None yet. */
-	rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
-	sp->last_rxf->link = cpu_to_le32(rxf_dma);
-	sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
-	pci_dma_sync_single_for_device(sp->pdev, sp->last_rxf_dma,
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	sp->last_rxf = rxf;
-	sp->last_rxf_dma = rxf_dma;
-}
-
-static int speedo_refill_rx_buf(struct net_device *dev, int force)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry;
-	struct RxFD *rxf;
-
-	entry = sp->dirty_rx % RX_RING_SIZE;
-	if (sp->rx_skbuff[entry] == NULL) {
-		rxf = speedo_rx_alloc(dev, entry);
-		if (rxf == NULL) {
-			unsigned int forw;
-			int forw_entry;
-			if (netif_msg_rx_err(sp) || !(sp->rx_ring_state & RrOOMReported)) {
-				printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n",
-						dev->name, force);
-				sp->rx_ring_state |= RrOOMReported;
-			}
-			speedo_show_state(dev);
-			if (!force)
-				return -1;	/* Better luck next time!  */
-			/* Borrow an skb from one of next entries. */
-			for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++)
-				if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL)
-					break;
-			if (forw == sp->cur_rx)
-				return -1;
-			forw_entry = forw % RX_RING_SIZE;
-			sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry];
-			sp->rx_skbuff[forw_entry] = NULL;
-			rxf = sp->rx_ringp[forw_entry];
-			sp->rx_ringp[forw_entry] = NULL;
-			sp->rx_ringp[entry] = rxf;
-		}
-	} else {
-		rxf = sp->rx_ringp[entry];
-	}
-	speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]);
-	sp->dirty_rx++;
-	sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */
-	return 0;
-}
-
-static void speedo_refill_rx_buffers(struct net_device *dev, int force)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-
-	/* Refill the RX ring. */
-	while ((int)(sp->cur_rx - sp->dirty_rx) > 0 &&
-			speedo_refill_rx_buf(dev, force) != -1);
-}
-
-static int
-speedo_rx(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry = sp->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
-	int alloc_ok = 1;
-	int npkts = 0;
-
-	if (netif_msg_intr(sp))
-		printk(KERN_DEBUG " In speedo_rx().\n");
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while (sp->rx_ringp[entry] != NULL) {
-		int status;
-		int pkt_len;
-
-		pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
-									sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-		status = le32_to_cpu(sp->rx_ringp[entry]->status);
-		pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
-
-		if (!(status & RxComplete))
-			break;
-
-		if (--rx_work_limit < 0)
-			break;
-
-		/* Check for a rare out-of-memory case: the current buffer is
-		   the last buffer allocated in the RX ring.  --SAW */
-		if (sp->last_rxf == sp->rx_ringp[entry]) {
-			/* Postpone the packet.  It'll be reaped at an interrupt when this
-			   packet is no longer the last packet in the ring. */
-			if (netif_msg_rx_err(sp))
-				printk(KERN_DEBUG "%s: RX packet postponed!\n",
-					   dev->name);
-			sp->rx_ring_state |= RrPostponed;
-			break;
-		}
-
-		if (netif_msg_rx_status(sp))
-			printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
-				   pkt_len);
-		if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
-			if (status & RxErrTooBig)
-				printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
-					   "status %8.8x!\n", dev->name, status);
-			else if (! (status & RxOK)) {
-				/* There was a fatal error.  This *should* be impossible. */
-				sp->stats.rx_errors++;
-				printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
-					   "status %8.8x.\n",
-					   dev->name, status);
-			}
-		} else {
-			struct sk_buff *skb;
-
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len < rx_copybreak
-				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
-											sizeof(struct RxFD) + pkt_len,
-											PCI_DMA_FROMDEVICE);
-
-#if 1 || USE_IP_CSUM
-				/* Packet is in one chunk -- we can copy + cksum. */
-				skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
-				skb_put(skb, pkt_len);
-#else
-				skb_copy_from_linear_data(sp->rx_skbuff[entry],
-							  skb_put(skb, pkt_len),
-							  pkt_len);
-#endif
-				pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
-											   sizeof(struct RxFD) + pkt_len,
-											   PCI_DMA_FROMDEVICE);
-				npkts++;
-			} else {
-				/* Pass up the already-filled skbuff. */
-				skb = sp->rx_skbuff[entry];
-				if (skb == NULL) {
-					printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n",
-						   dev->name);
-					break;
-				}
-				sp->rx_skbuff[entry] = NULL;
-				skb_put(skb, pkt_len);
-				npkts++;
-				sp->rx_ringp[entry] = NULL;
-				pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
-								 PKT_BUF_SZ + sizeof(struct RxFD),
-								 PCI_DMA_FROMDEVICE);
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			sp->stats.rx_packets++;
-			sp->stats.rx_bytes += pkt_len;
-		}
-		entry = (++sp->cur_rx) % RX_RING_SIZE;
-		sp->rx_ring_state &= ~RrPostponed;
-		/* Refill the recently taken buffers.
-		   Do it one-by-one to handle traffic bursts better. */
-		if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1)
-			alloc_ok = 0;
-	}
-
-	/* Try hard to refill the recently taken buffers. */
-	speedo_refill_rx_buffers(dev, 1);
-
-	if (npkts)
-		sp->last_rx_time = jiffies;
-
-	return 0;
-}
-
-static int
-speedo_close(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int i;
-
-	netdevice_stop(dev);
-	netif_stop_queue(dev);
-
-	if (netif_msg_ifdown(sp))
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-
-	/* Shut off the media monitoring timer. */
-	del_timer_sync(&sp->timer);
-
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-
-	/* Shutting down the chip nicely fails to disable flow control. So.. */
-	iowrite32(PortPartialReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort); /* flush posted write */
-	/*
-	 * The chip requires a 10 microsecond quiet period.  Wait here!
-	 */
-	udelay(10);
-
-	free_irq(dev->irq, dev);
-	speedo_show_state(dev);
-
-    /* Free all the skbuffs in the Rx and Tx queues. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = sp->rx_skbuff[i];
-		sp->rx_skbuff[i] = NULL;
-		/* Clear the Rx descriptors. */
-		if (skb) {
-			pci_unmap_single(sp->pdev,
-					 sp->rx_ring_dma[i],
-					 PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(skb);
-		}
-	}
-
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		struct sk_buff *skb = sp->tx_skbuff[i];
-		sp->tx_skbuff[i] = NULL;
-		/* Clear the Tx descriptors. */
-		if (skb) {
-			pci_unmap_single(sp->pdev,
-					 le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
-		}
-	}
-
-	/* Free multicast setting blocks. */
-	for (i = 0; sp->mc_setup_head != NULL; i++) {
-		struct speedo_mc_block *t;
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	sp->mc_setup_tail = NULL;
-	if (netif_msg_ifdown(sp))
-		printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
-
-	pci_set_power_state(sp->pdev, PCI_D2);
-
-	return 0;
-}
-
-/* The Speedo-3 has an especially awkward and unusable method of getting
-   statistics out of the chip.  It takes an unpredictable length of time
-   for the dump-stats command to complete.  To avoid a busy-wait loop we
-   update the stats with the previous dump results, and then trigger a
-   new dump.
-
-   Oh, and incoming frames are dropped while executing dump-stats!
-   */
-static struct net_device_stats *
-speedo_get_stats(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	/* Update only if the previous dump finished. */
-	if (sp->lstats->done_marker == cpu_to_le32(0xA007)) {
-		sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats->tx_coll16_errs);
-		sp->stats.tx_window_errors += le32_to_cpu(sp->lstats->tx_late_colls);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_underruns);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_lost_carrier);
-		/*sp->stats.tx_deferred += le32_to_cpu(sp->lstats->tx_deferred);*/
-		sp->stats.collisions += le32_to_cpu(sp->lstats->tx_total_colls);
-		sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats->rx_crc_errs);
-		sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats->rx_align_errs);
-		sp->stats.rx_over_errors += le32_to_cpu(sp->lstats->rx_resource_errs);
-		sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats->rx_overrun_errs);
-		sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs);
-		sp->lstats->done_marker = 0x0000;
-		if (netif_running(dev)) {
-			unsigned long flags;
-			/* Take a spinlock to make wait_for_cmd_done and sending the
-			   command atomic.  --SAW */
-			spin_lock_irqsave(&sp->lock, flags);
-			wait_for_cmd_done(dev, sp);
-			iowrite8(CUDumpStats, ioaddr + SCBCmd);
-			spin_unlock_irqrestore(&sp->lock, flags);
-		}
-	}
-	return &sp->stats;
-}
-
-static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	strncpy(info->driver, "eepro100", sizeof(info->driver)-1);
-	strncpy(info->version, version, sizeof(info->version)-1);
-	if (sp->pdev)
-		strcpy(info->bus_info, pci_name(sp->pdev));
-}
-
-static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	spin_lock_irq(&sp->lock);
-	mii_ethtool_gset(&sp->mii_if, ecmd);
-	spin_unlock_irq(&sp->lock);
-	return 0;
-}
-
-static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int res;
-	spin_lock_irq(&sp->lock);
-	res = mii_ethtool_sset(&sp->mii_if, ecmd);
-	spin_unlock_irq(&sp->lock);
-	return res;
-}
-
-static int speedo_nway_reset(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return mii_nway_restart(&sp->mii_if);
-}
-
-static u32 speedo_get_link(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return mii_link_ok(&sp->mii_if);
-}
-
-static u32 speedo_get_msglevel(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return sp->msg_enable;
-}
-
-static void speedo_set_msglevel(struct net_device *dev, u32 v)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	sp->msg_enable = v;
-}
-
-static const struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = speedo_get_drvinfo,
-	.get_settings = speedo_get_settings,
-	.set_settings = speedo_set_settings,
-	.nway_reset = speedo_nway_reset,
-	.get_link = speedo_get_link,
-	.get_msglevel = speedo_get_msglevel,
-	.set_msglevel = speedo_set_msglevel,
-};
-
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(rq);
-	int phy = sp->phy[0] & 0x1f;
-	int saved_acpi;
-	int t;
-
-    switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		data->phy_id = phy;
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		/* FIXME: these operations need to be serialized with MDIO
-		   access from the timeout handler.
-		   They are currently serialized only with MDIO access from the
-		   timer routine.  2000/05/09 SAW */
-		saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
-		t = del_timer_sync(&sp->timer);
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-		if (t)
-			add_timer(&sp->timer); /* may be set to the past  --SAW */
-		pci_set_power_state(sp->pdev, saved_acpi);
-		return 0;
-
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
-		t = del_timer_sync(&sp->timer);
-		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
-		if (t)
-			add_timer(&sp->timer); /* may be set to the past  --SAW */
-		pci_set_power_state(sp->pdev, saved_acpi);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This is very ugly with Intel chips -- we usually have to execute an
-   entire configuration command, plus process a multicast command.
-   This is complicated.  We must put a large configuration command and
-   an arbitrarily-sized multicast command in the transmit list.
-   To minimize the disruption -- the previous command might have already
-   loaded the link -- we convert the current command block, normally a Tx
-   command, into a no-op and link it to the new command.
-*/
-static void set_rx_mode(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	struct descriptor *last_cmd;
-	char new_rx_mode;
-	unsigned long flags;
-	int entry, i;
-
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		new_rx_mode = 3;
-	} else if ((dev->flags & IFF_ALLMULTI)  ||
-			   dev->mc_count > multicast_filter_limit) {
-		new_rx_mode = 1;
-	} else
-		new_rx_mode = 0;
-
-	if (netif_msg_rx_status(sp))
-		printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name,
-				sp->rx_mode, new_rx_mode);
-
-	if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) {
-	    /* The Tx ring is full -- don't add anything!  Hope the mode will be
-		 * set again later. */
-		sp->rx_mode = -1;
-		return;
-	}
-
-	if (new_rx_mode != sp->rx_mode) {
-		u8 *config_cmd_data;
-
-		spin_lock_irqsave(&sp->lock, flags);
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-		sp->tx_skbuff[entry] = NULL;			/* Redundant. */
-		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
-		sp->tx_ring[entry].link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-		config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
-		/* Construct a full CmdConfig frame. */
-		memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE);
-		config_cmd_data[1] = (txfifo << 4) | rxfifo;
-		config_cmd_data[4] = rxdmacount;
-		config_cmd_data[5] = txdmacount + 0x80;
-		config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
-		/* 0x80 doesn't disable FC 0x84 does.
-		   Disable Flow control since we are not ACK-ing any FC interrupts
-		   for now. --Dragan */
-		config_cmd_data[19] = 0x84;
-		config_cmd_data[19] |= sp->mii_if.full_duplex ? 0x40 : 0;
-		config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
-		if (sp->phy[0] & 0x8000) {			/* Use the AUI port instead. */
-			config_cmd_data[15] |= 0x80;
-			config_cmd_data[8] = 0;
-		}
-		/* Trigger the command unit resume. */
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		iowrite8(CUResume, ioaddr + SCBCmd);
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-	}
-
-	if (new_rx_mode == 0  &&  dev->mc_count < 4) {
-		/* The simple case of 0-3 multicast list entries occurs often, and
-		   fits within one tx_ring[] entry. */
-		struct dev_mc_list *mclist;
-		__le16 *setup_params, *eaddrs;
-
-		spin_lock_irqsave(&sp->lock, flags);
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-		sp->tx_skbuff[entry] = NULL;
-		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
-		sp->tx_ring[entry].link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-		sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
-		setup_params = (__le16 *)&sp->tx_ring[entry].tx_desc_addr;
-		*setup_params++ = cpu_to_le16(dev->mc_count*6);
-		/* Fill in the multicast addresses. */
-		for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			eaddrs = (__le16 *)mclist->dmi_addr;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-		}
-
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		/* Immediately trigger the command unit resume. */
-		iowrite8(CUResume, ioaddr + SCBCmd);
-
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-	} else if (new_rx_mode == 0) {
-		struct dev_mc_list *mclist;
-		__le16 *setup_params, *eaddrs;
-		struct speedo_mc_block *mc_blk;
-		struct descriptor *mc_setup_frm;
-		int i;
-
-		mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6,
-						 GFP_ATOMIC);
-		if (mc_blk == NULL) {
-			printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
-				   dev->name);
-			sp->rx_mode = -1; /* We failed, try again. */
-			return;
-		}
-		mc_blk->next = NULL;
-		mc_blk->len = 2 + multicast_filter_limit*6;
-		mc_blk->frame_dma =
-			pci_map_single(sp->pdev, &mc_blk->frame, mc_blk->len,
-					PCI_DMA_TODEVICE);
-		mc_setup_frm = &mc_blk->frame;
-
-		/* Fill the setup frame. */
-		if (netif_msg_ifup(sp))
-			printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n",
-				   dev->name, mc_setup_frm);
-		mc_setup_frm->cmd_status =
-			cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
-		/* Link set below. */
-		setup_params = (__le16 *)&mc_setup_frm->params;
-		*setup_params++ = cpu_to_le16(dev->mc_count*6);
-		/* Fill in the multicast addresses. */
-		for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			eaddrs = (__le16 *)mclist->dmi_addr;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-		}
-
-		/* Disable interrupts while playing with the Tx Cmd list. */
-		spin_lock_irqsave(&sp->lock, flags);
-
-		if (sp->mc_setup_tail)
-			sp->mc_setup_tail->next = mc_blk;
-		else
-			sp->mc_setup_head = mc_blk;
-		sp->mc_setup_tail = mc_blk;
-		mc_blk->tx = sp->cur_tx;
-
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = mc_setup_frm;
-
-		/* Change the command to a NoOp, pointing to the CmdMulti command. */
-		sp->tx_skbuff[entry] = NULL;
-		sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
-		sp->tx_ring[entry].link = cpu_to_le32(mc_blk->frame_dma);
-
-		/* Set the link in the setup frame. */
-		mc_setup_frm->link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-
-		pci_dma_sync_single_for_device(sp->pdev, mc_blk->frame_dma,
-									   mc_blk->len, PCI_DMA_TODEVICE);
-
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		/* Immediately trigger the command unit resume. */
-		iowrite8(CUResume, ioaddr + SCBCmd);
-
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-
-		if (netif_msg_rx_status(sp))
-			printk(" CmdMCSetup frame length %d in entry %d.\n",
-				   dev->mc_count, entry);
-	}
-
-	sp->rx_mode = new_rx_mode;
-}
-
-#ifdef CONFIG_PM
-static int eepro100_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	pci_save_state(pdev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	del_timer_sync(&sp->timer);
-
-	netif_device_detach(dev);
-	iowrite32(PortPartialReset, ioaddr + SCBPort);
-
-	/* XXX call pci_set_power_state ()? */
-	pci_disable_device(pdev);
-	pci_set_power_state (pdev, PCI_D3hot);
-	return 0;
-}
-
-static int eepro100_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int rc;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-
-	rc = pci_enable_device(pdev);
-	if (rc)
-		return rc;
-
-	pci_set_master(pdev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	/* I'm absolutely uncertain if this part of code may work.
-	   The problems are:
-	    - correct hardware reinitialization;
-		- correct driver behavior between different steps of the
-		  reinitialization;
-		- serialization with other driver calls.
-	   2000/03/08  SAW */
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-	speedo_resume(dev);
-	netif_device_attach(dev);
-	sp->rx_mode = -1;
-	sp->flow_ctrl = sp->partner = 0;
-	set_rx_mode(dev);
-	sp->timer.expires = RUN_AT(2*HZ);
-	add_timer(&sp->timer);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static void __devexit eepro100_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-
-	unregister_netdev(dev);
-
-	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
-	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-
-	pci_iounmap(pdev, sp->regs);
-	pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
-								+ sizeof(struct speedo_stats),
-						sp->tx_ring, sp->tx_ring_dma);
-	pci_disable_device(pdev);
-	free_netdev(dev);
-}
-
-static struct pci_device_id eepro100_pci_tbl[] = {
-	{ PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0,}
-};
-MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
-
-static struct pci_driver eepro100_driver = {
-	.name		= "eepro100",
-	.id_table	= eepro100_pci_tbl,
-	.probe		= eepro100_init_one,
-	.remove		= __devexit_p(eepro100_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= eepro100_suspend,
-	.resume		= eepro100_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init eepro100_init_module(void)
-{
-#ifdef MODULE
-	printk(version);
-#endif
-	return pci_register_driver(&eepro100_driver);
-}
-
-static void __exit eepro100_cleanup_module(void)
-{
-	pci_unregister_driver(&eepro100_driver);
-}
-
-module_init(eepro100_init_module);
-module_exit(eepro100_cleanup_module);
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index b751c1b..a125e41 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -967,7 +967,6 @@
 			        insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1);
 				skb->protocol = eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 			}
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 002d918..9930d5f 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0095"
+#define DRV_VERSION	"EHEA_0096"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 422fcb9..44c9ae1 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -728,7 +728,6 @@
 			}
 
 			ehea_proc_skb(pr, cqe, skb);
-			dev->last_rx = jiffies;
 		} else {
 			pr->p_stats.poll_receive_errors++;
 			port_reset = ehea_treat_poll_error(pr, rq, cqe,
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 9d00687..3c0ec82 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -653,7 +653,7 @@
 		int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
 		int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
 		int idx = i & EHEA_INDEX_MASK;
-		
+
 		if (add) {
 			int ret = ehea_init_bmap(ehea_bmap, top, dir);
 			if (ret)
@@ -780,7 +780,7 @@
 
 	kfree(ehea_bmap);
 	ehea_bmap = NULL;
-out_destroy:	
+out_destroy:
 	mutex_unlock(&ehea_busmap_mutex);
 }
 
@@ -858,10 +858,10 @@
 	for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
 		if (!ehea_bmap->top[top]->dir[dir]->ent[idx])
 			continue;
-		
+
 		hret = ehea_reg_mr_section(top, dir, idx, pt, adapter, mr);
 		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-			    	return hret;
+			return hret;
 	}
 	return hret;
 }
@@ -879,7 +879,7 @@
 
 		hret = ehea_reg_mr_sections(top, dir, pt, adapter, mr);
 		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-			    	return hret;
+			return hret;
 	}
 	return hret;
 }
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index e1b441e..32c1979 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -477,12 +477,10 @@
 
 	mutex_lock(&priv->lock);
 	if (!priv->hw_enable) {
-		if (netif_msg_drv(priv)) {
-			DECLARE_MAC_BUF(mac);
+		if (netif_msg_drv(priv))
 			printk(KERN_INFO DRV_NAME
-				": %s: Setting MAC address to %s\n",
-				ndev->name, print_mac(mac, ndev->dev_addr));
-		}
+				": %s: Setting MAC address to %pM\n",
+				ndev->name, ndev->dev_addr);
 		/* NOTE: MAC address in ENC28J60 is byte-backward */
 		nolock_regb_write(priv, MAADR5, ndev->dev_addr[0]);
 		nolock_regb_write(priv, MAADR4, ndev->dev_addr[1]);
@@ -946,7 +944,6 @@
 			/* update statistics */
 			ndev->stats.rx_packets++;
 			ndev->stats.rx_bytes += len;
-			ndev->last_rx = jiffies;
 			netif_rx(skb);
 		}
 	}
@@ -1328,11 +1325,9 @@
 		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		if (netif_msg_ifup(priv)) {
-			DECLARE_MAC_BUF(mac);
-			dev_err(&dev->dev, "invalid MAC address %s\n",
-				print_mac(mac, dev->dev_addr));
-		}
+		if (netif_msg_ifup(priv))
+			dev_err(&dev->dev, "invalid MAC address %pM\n",
+				dev->dev_addr);
 		return -EADDRNOTAVAIL;
 	}
 	/* Reset the hardware here (and take it out of low power mode) */
@@ -1453,7 +1448,7 @@
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 	strlcpy(info->bus_info,
-		dev->dev.parent->bus_id, sizeof(info->bus_info));
+		dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
 static int
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 180e968..8594d7f 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -951,7 +951,6 @@
 		}
 
 		skb->dev = enic->netdev;
-		enic->netdev->last_rx = jiffies;
 
 		if (enic->vlan_group && vlan_stripped) {
 
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 95184b9..e5fc938 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -90,11 +90,8 @@
 
 	c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
 
-	printk(KERN_INFO PFX "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
-		"wq/rq %d/%d\n",
-		enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
-		enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
-		c->wq_desc_count, c->rq_desc_count);
+	printk(KERN_INFO PFX "vNIC MAC addr %pM wq/rq %d/%d\n",
+		enic->mac_addr, c->wq_desc_count, c->rq_desc_count);
 	printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d "
 		"intr timer %d\n",
 		c->mtu, ENIC_SETTING(enic, TXCSUM),
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 4d104f5..9afd33c 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -489,10 +489,7 @@
 
 	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
 	if (err)
-		printk(KERN_ERR
-			"Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
-			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
-			err);
+		printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err);
 }
 
 void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
@@ -507,10 +504,7 @@
 
 	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
 	if (err)
-		printk(KERN_ERR
-			"Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
-			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
-			err);
+		printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err);
 }
 
 int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 76118ddd..6f399bd 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -322,7 +322,6 @@
 	int i, ret, option = 0, duplex = 0;
 	void *ring_space;
 	dma_addr_t ring_dma;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -364,7 +363,7 @@
 	ioaddr = pci_resource_start (pdev, 0);
 #else
 	ioaddr = pci_resource_start (pdev, 1);
-	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
+	ioaddr = (long) pci_ioremap_bar(pdev, 1);
 	if (!ioaddr) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		goto err_out_free_netdev;
@@ -499,9 +498,9 @@
 	if (ret < 0)
 		goto err_out_unmap_rx;
 
-	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %s\n",
+	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
 	       dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 out:
 	return ret;
@@ -1223,7 +1222,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_receive_skb(skb);
-			dev->last_rx = jiffies;
 			ep->stats.rx_packets++;
 			ep->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index deefa51..e7df9f4 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -179,7 +179,6 @@
 {
 	int i, retval;
 	unsigned long eisa_id;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
 		return -ENODEV;
@@ -205,14 +204,14 @@
 	if (dev->dev_addr[0] != ES_ADDR0 ||
 	    dev->dev_addr[1] != ES_ADDR1 ||
 	    dev->dev_addr[2] != ES_ADDR2) {
-		printk("es3210.c: card not found %s (invalid_prefix).\n",
-		       print_mac(mac, dev->dev_addr));
+		printk("es3210.c: card not found %pM (invalid_prefix).\n",
+		       dev->dev_addr);
 		retval = -ENODEV;
 		goto out;
 	}
 
-	printk("es3210.c: ES3210 rev. %ld at %#x, node %s",
-	       eisa_id>>24, ioaddr, print_mac(mac, dev->dev_addr));
+	printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
+	       eisa_id>>24, ioaddr, dev->dev_addr);
 
 	/* Snarf the interrupt now. */
 	if (dev->irq == 0) {
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index bee8b3f..88b1be0 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1205,7 +1205,6 @@
 				printk(KERN_DEBUG ".\n");
 			}
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 593a120..f3b664a 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -396,7 +396,6 @@
 	u_long mem_start, shmem_length;
 	u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0;
 	u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0;
-	DECLARE_MAC_BUF(mac);
 
 	/*
 	** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot.
@@ -461,7 +460,7 @@
 	if (lemac != LeMAC2)
 		DevicePresent(iobase);	/* need after EWRK3_INIT */
 	status = get_hw_addr(dev, eeprom_image, lemac);
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 
 	if (status) {
 		printk("      which has an EEPROM CRC error.\n");
@@ -646,10 +645,8 @@
 			ewrk3_init(dev);
 
 			if (ewrk3_debug > 1) {
-				DECLARE_MAC_BUF(mac);
 				printk("%s: ewrk3 open with irq %d\n", dev->name, dev->irq);
-				printk("  physical address: %s\n",
-				       print_mac(mac, dev->dev_addr));
+				printk("  physical address: %pM\n", dev->dev_addr);
 				if (lp->shmem_length == 0) {
 					printk("  no shared memory, I/O only mode\n");
 				} else {
@@ -1029,7 +1026,6 @@
 						/*
 						   ** Update stats
 						 */
-						dev->last_rx = jiffies;
 						dev->stats.rx_packets++;
 						dev->stats.rx_bytes += pkt_len;
 					} else {
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index b455ae9..31ab1ff 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -486,7 +486,6 @@
 #else
 	int bar = 1;
 #endif
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -665,9 +664,9 @@
 	if (err)
 		goto err_out_free_tx;
 
-	printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
 	       dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr,
-	       print_mac(mac, dev->dev_addr), irq);
+	       dev->dev_addr, irq);
 
 	return 0;
 
@@ -1727,7 +1726,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			np->stats.rx_packets++;
 			np->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index ecd5c71..2487d83 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -2562,7 +2562,6 @@
 {
 	struct net_device *dev;
 	int i, err;
-	DECLARE_MAC_BUF(mac);
 
 	printk("FEC ENET Version 0.2\n");
 
@@ -2581,8 +2580,7 @@
 			return -EIO;
 		}
 
-		printk("%s: ethernet %s\n",
-		       dev->name, print_mac(mac, dev->dev_addr));
+		printk("%s: ethernet %pM\n", dev->name, dev->dev_addr);
 	}
 	return 0;
 }
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index aec3b97..cd8e98b 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -216,7 +216,7 @@
 	struct phy_device *phydev;
 	char phy_id[BUS_ID_SIZE];
 
-	snprintf(phy_id, BUS_ID_SIZE, "%x:%02x",
+	snprintf(phy_id, sizeof(phy_id), "%x:%02x",
 			(unsigned int)dev->base_addr, priv->phy_addr);
 
 	priv->link = PHY_DOWN;
@@ -487,7 +487,6 @@
 			rskb->protocol = eth_type_trans(rskb, dev);
 
 			netif_rx(rskb);
-			dev->last_rx = jiffies;
 		} else {
 			/* Can't get a new one : reuse the same & drop pkt */
 			dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index cc7328b..765210e 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -818,7 +818,7 @@
  * Maximum number of loops until we assume that a bit in the irq mask
  * is stuck. Overridable with module param.
  */
-static int max_interrupt_work = 5;
+static int max_interrupt_work = 15;
 
 /*
  * Optimization can be either throuput mode or cpu mode
@@ -2735,7 +2735,6 @@
 #else
 		netif_rx(skb);
 #endif
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += len;
 next_pkt:
@@ -2848,7 +2847,6 @@
 				}
 			}
 
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += len;
 		} else {
@@ -5420,7 +5418,6 @@
 	u32 powerstate, txreg;
 	u32 phystate_orig = 0, phystate;
 	int phyinitialized = 0;
-	DECLARE_MAC_BUF(mac);
 	static int printed_version;
 
 	if (!printed_version++)
@@ -5653,8 +5650,8 @@
 		 * to 01:23:45:67:89:ab
 		 */
 		dev_printk(KERN_ERR, &pci_dev->dev,
-			"Invalid Mac address detected: %s\n",
-		        print_mac(mac, dev->dev_addr));
+			"Invalid Mac address detected: %pM\n",
+		        dev->dev_addr);
 		dev_printk(KERN_ERR, &pci_dev->dev,
 			"Please complain to your hardware vendor. Switching to a random MAC.\n");
 		dev->dev_addr[0] = 0x00;
@@ -5663,8 +5660,8 @@
 		get_random_bytes(&dev->dev_addr[3], 3);
 	}
 
-	dprintk(KERN_DEBUG "%s: MAC Address %s\n",
-		pci_name(pci_dev), print_mac(mac, dev->dev_addr));
+	dprintk(KERN_DEBUG "%s: MAC Address %pM\n",
+		pci_name(pci_dev), dev->dev_addr);
 
 	/* set mac address */
 	nv_copy_mac_to_hw(dev);
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index a6f49d0..df66d62 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1117,10 +1117,7 @@
 	if (ret)
 		goto out_free_bd;
 
-	printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       ndev->name,
-	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
-	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+	printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 83a5cb6..451f6b8 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -162,7 +162,6 @@
 	struct gianfar_platform_data *einfo;
 	struct resource *r;
 	int err = 0, irq;
-	DECLARE_MAC_BUF(mac);
 
 	einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
 
@@ -364,8 +363,7 @@
 	gfar_init_sysfs(dev);
 
 	/* Print out the device info */
-	printk(KERN_INFO DEVICE_NAME "%s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO DEVICE_NAME "%pM\n", dev->name, dev->dev_addr);
 
 	/* Even more device info helps when determining which kernel */
 	/* provided which set of benchmarks. */
@@ -548,7 +546,7 @@
 	priv->oldspeed = 0;
 	priv->oldduplex = -1;
 
-	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
+	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
 
 	interface = gfar_get_interface(dev);
 
@@ -1695,8 +1693,6 @@
 			dev->stats.rx_bytes += pkt_len;
 		}
 
-		dev->last_rx = jiffies;
-
 		priv->rx_skbuff[priv->skb_currx] = newskb;
 
 		/* Setup the new bdp */
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 3199526..77f2b29 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -582,7 +582,6 @@
 	void *ring_space;
 	dma_addr_t ring_dma;
 	int ret = -ENOMEM;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -744,9 +743,9 @@
 		goto err_out_unmap_rx;
 	}
 
-	printk(KERN_INFO "%s: %s type %x at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s type %x at %p, %pM, IRQ %d.\n",
 		   dev->name, chip_tbl[chip_id].name, readl(ioaddr + ChipRev),
-		   ioaddr, print_mac(mac, dev->dev_addr), irq);
+		   ioaddr, dev->dev_addr, irq);
 	i = readb(ioaddr + PCIClkMeas);
 	printk(KERN_INFO "%s:  %d-bit %d Mhz PCI bus (%d), Virtual Jumpers "
 		   "%2.2x, LPA %4.4x.\n",
@@ -1646,7 +1645,6 @@
 #endif  /* RX_CHECKSUM */
 
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			hmp->stats.rx_packets++;
 		}
 		entry = (++hmp->cur_rx) % RX_RING_SIZE;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 0f501d2..50f1e17 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -373,7 +373,6 @@
 	memcpy(ptr, sp->cooked_buf + 1, count);
 	skb->protocol = ax25_type_trans(skb, sp->dev);
 	netif_rx(skb);
-	sp->dev->last_rx = jiffies;
 	sp->dev->stats.rx_packets++;
 
 	return;
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 00bc7fb..81a65e3 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -555,7 +555,6 @@
 	memcpy(cp, bc->hdlcrx.buf, pktlen - 1);
 	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	bc->stats.rx_packets++;
 }
 
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 58f4b1d..46f8f33 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -230,7 +230,6 @@
 
 	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 unlock:
 
 	rcu_read_unlock();
@@ -441,16 +440,15 @@
 			 "dev   ether      destination        accept from\n");
 	else {
 		const struct bpqdev *bpqdev = v;
-		DECLARE_MAC_BUF(mac);
 
-		seq_printf(seq, "%-5s %-10s %s  ",
+		seq_printf(seq, "%-5s %-10s %pM  ",
 			bpqdev->axdev->name, bpqdev->ethdev->name,
-			print_mac(mac, bpqdev->dest_addr));
+			bpqdev->dest_addr);
 
 		if (is_multicast_ether_addr(bpqdev->acpt_addr))
 			seq_printf(seq, "*\n");
 		else
-			seq_printf(seq, "%s\n", print_mac(mac, bpqdev->acpt_addr));
+			seq_printf(seq, "%pM\n", bpqdev->acpt_addr);
 
 	}
 	return 0;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index e8cfade..7e46114 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -1283,7 +1283,6 @@
 			memcpy(&data[1], priv->rx_buf[i], cb);
 			skb->protocol = ax25_type_trans(skb, priv->dev);
 			netif_rx(skb);
-			priv->dev->last_rx = jiffies;
 			priv->stats.rx_packets++;
 			priv->stats.rx_bytes += cb;
 		}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index c258a05..8eba61a 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -162,7 +162,6 @@
 	memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
 	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	s->stats.rx_packets++;
 }
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index b8e25c4..7570c73 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -303,7 +303,6 @@
 	memcpy(skb_put(skb,count), ax->rbuff, count);
 	skb->protocol = ax25_type_trans(skb, ax->dev);
 	netif_rx(skb);
-	ax->dev->last_rx = jiffies;
 	ax->stats.rx_packets++;
 	ax->stats.rx_bytes += count;
 	spin_unlock_bh(&ax->buflock);
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index c17e39b..802d1c7 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1627,7 +1627,6 @@
 	skb->protocol = ax25_type_trans(skb, scc->dev);
 	
 	netif_rx(skb);
-	scc->dev->last_rx = jiffies;
 	return;
 }
 
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 1c94286..5407f74 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -515,7 +515,6 @@
 				memcpy(cp, yp->rx_buf, pkt_len - 1);
 				skb->protocol = ax25_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				++yp->stats.rx_packets;
 			}
 		}
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index fbbd3e6..9026fd6 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -166,7 +166,6 @@
 	const char name[] = "HP-PC-LAN+";
 	int mem_start;
 	static unsigned version_printed;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -193,7 +192,7 @@
 	}
 	checksum += inb(ioaddr + 14);
 
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 
 	if (checksum != 0xff) {
 		printk(" bad checksum %2.2x.\n", checksum);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 0a8c649..3669194 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -127,7 +127,6 @@
 	int i, retval, board_id, wordmode;
 	const char *name;
 	static unsigned version_printed;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -161,7 +160,7 @@
 	for(i = 0; i < ETHER_ADDR_LEN; i++)
 		dev->dev_addr[i] = inb(ioaddr + i);
 
-	printk(" %s", print_mac(mac, dev->dev_addr));
+	printk(" %pM", dev->dev_addr);
 
 	/* Snarf the interrupt now.  Someday this could be moved to open(). */
 	if (dev->irq < 2) {
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 571dd80..4dda9b0 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1834,7 +1834,6 @@
 					ptr[9], ptr[10], ptr[11]);
 #endif
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes += pkt_len;
 		}
@@ -1925,7 +1924,6 @@
 
 				netif_rx(ptr->skb);	/* Up and away... */
 
-				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				lp->stats.rx_bytes += pkt_len;
 			}
@@ -2093,9 +2091,8 @@
 				addrs = dmi->dmi_addr;
 				if ((*addrs & 0x01) == 0x01) {	/* multicast address? */
 #ifdef HP100_DEBUG
-					DECLARE_MAC_BUF(mac);
-					printk("hp100: %s: multicast = %s, ",
-						     dev->name, print_mac(mac, addrs));
+					printk("hp100: %s: multicast = %pM, ",
+						     dev->name, addrs);
 #endif
 					for (j = idx = 0; j < 6; j++) {
 						idx ^= *addrs++ & 0x3f;
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index b96cf2d..b0ae076 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -103,7 +103,6 @@
     int start_page, stop_page;
     int j;
     int err;
-    DECLARE_MAC_BUF(mac);
 
     static u32 hydra_offsets[16] = {
 	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
@@ -163,8 +162,8 @@
     zorro_set_drvdata(z, dev);
 
     printk(KERN_INFO "%s: Hydra at 0x%08lx, address "
-	   "%s (hydra.c " HYDRA_VERSION ")\n",
-	   dev->name, z->resource.start, print_mac(mac, dev->dev_addr));
+	   "%pM (hydra.c " HYDRA_VERSION ")\n",
+	   dev->name, z->resource.start, dev->dev_addr);
 
     return 0;
 }
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 901212a..87a7066 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -396,9 +396,7 @@
 
 	for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
 		int slot, reg, mask;
-		DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
-		     dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
-		     dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+		DBG2(dev, "mc %pM" NL, dmi->dmi_addr);
 
 		slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr));
 		reg = EMAC_XAHT_SLOT_TO_REG(dev, slot);
@@ -2865,11 +2863,8 @@
 	wake_up_all(&emac_probe_wait);
 
 
-	printk(KERN_INFO
-	       "%s: EMAC-%d %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       ndev->name, dev->cell_index, np->full_name,
-	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
-	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+	printk(KERN_INFO "%s: EMAC-%d %s, MAC %pM\n",
+	       ndev->name, dev->cell_index, np->full_name, ndev->dev_addr);
 
 	if (dev->phy_mode == PHY_MODE_SGMII)
 		printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index f027647..5b5bf9f 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -605,7 +605,6 @@
 				skb->ip_summed = CHECKSUM_NONE;
 
 				/* bookkeeping */
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += rda.length;
 
@@ -914,7 +913,6 @@
 	int base = 0, irq = 0, iobase = 0, memlen = 0;
 	ibmlana_priv *priv;
 	ibmlana_medium medium;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(sizeof(ibmlana_priv));
 	if (!dev)
@@ -990,10 +988,10 @@
 	/* print config */
 
 	printk(KERN_INFO "%s: IRQ %d, I/O %#lx, memory %#lx-%#lx, "
-	       "MAC address %s.\n",
+	       "MAC address %pM.\n",
 	       dev->name, priv->realirq, dev->base_addr,
 	       dev->mem_start, dev->mem_end - 1,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 	printk(KERN_INFO "%s: %s medium\n", dev->name, MediaNames[priv->medium]);
 
 	/* reset board */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index c2d57f8..2c40957 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1014,7 +1014,6 @@
 			netdev->stats.rx_packets++;
 			netdev->stats.rx_bytes += length;
 			frames_processed++;
-			netdev->last_rx = jiffies;
 		}
 	} while (frames_processed < budget);
 
@@ -1371,13 +1370,12 @@
 	struct ibmveth_adapter *adapter = seq->private;
 	char *current_mac = ((char*) &adapter->netdev->dev_addr);
 	char *firmware_mac = ((char*) &adapter->mac_addr) ;
-	DECLARE_MAC_BUF(mac);
 
 	seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
 
 	seq_printf(seq, "Unit Address:    0x%x\n", adapter->vdev->unit_address);
-	seq_printf(seq, "Current MAC:     %s\n", print_mac(mac, current_mac));
-	seq_printf(seq, "Firmware MAC:    %s\n", print_mac(mac, firmware_mac));
+	seq_printf(seq, "Current MAC:     %pM\n", current_mac);
+	seq_printf(seq, "Firmware MAC:    %pM\n", firmware_mac);
 
 	seq_printf(seq, "\nAdapter Statistics:\n");
 	seq_printf(seq, "  TX:  vio_map_single failres:      %ld\n", adapter->tx_map_failed);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 1f397cd..89ffc07 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1275,16 +1275,14 @@
 
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info */
-	dev_info(&pdev->dev,
-		 "%s: (PCIe:%s:%s) %02x:%02x:%02x:%02x:%02x:%02x\n",
+	dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
 		 netdev->name,
 		 ((hw->bus.speed == e1000_bus_speed_2500)
 		  ? "2.5Gb/s" : "unknown"),
 		 ((hw->bus.width == e1000_bus_width_pcie_x4)
 		  ? "Width x4" : (hw->bus.width == e1000_bus_width_pcie_x1)
 		  ? "Width x1" : "unknown"),
-		 netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-		 netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+		 netdev->dev_addr);
 
 	igb_read_part_num(hw, &part_num);
 	dev_info(&pdev->dev, "%s: PBA No: %06x-%03x\n", netdev->name,
@@ -3942,8 +3940,6 @@
 
 		igb_receive_skb(rx_ring, staterr, rx_desc, skb);
 
-		netdev->last_rx = jiffies;
-
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
 
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 1f25263..170b12d 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -390,11 +390,8 @@
 	}
 
 	printk("Found %s NIC", type);
-	if (type != unknown) {
-		printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
-			" CRC %02x", serial[0], serial[1], serial[2],
-			serial[3], serial[4], serial[5], crc);
-	}
+	if (type != unknown)
+		printk (" registration number %pM, CRC %02x", serial, crc);
 	printk(".\n");
 
 	return 0;
@@ -443,12 +440,9 @@
  */
 static void ioc3_get_eaddr(struct ioc3_private *ip)
 {
-	DECLARE_MAC_BUF(mac);
-
 	ioc3_get_eaddr_nic(ip);
 
-	printk("Ethernet address is %s.\n",
-	       print_mac(mac, priv_netdev(ip)->dev_addr));
+	printk("Ethernet address is %pM.\n", priv_netdev(ip)->dev_addr);
 }
 
 static void __ioc3_set_mac_address(struct net_device *dev)
@@ -627,7 +621,6 @@
 			rxb = (struct ioc3_erxbuf *) new_skb->data;
 			skb_reserve(new_skb, RX_OFFSET);
 
-			priv_netdev(ip)->last_rx = jiffies;
 			ip->stats.rx_packets++;		/* Statistics */
 			ip->stats.rx_bytes += len;
 		} else {
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 7373daf..24c777a 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -1222,7 +1222,6 @@
 	skb->protocol = eth_type_trans(skb, dev);
 	skb->ip_summed = CHECKSUM_NONE;
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	sp->rx_buff[entry] = NULL;
 }
 
@@ -1256,7 +1255,6 @@
 	jumbo->skb = skb;
 
 	sp->rx_buff[entry] = NULL;
-	dev->last_rx = jiffies;
 }
 
 static void ipg_nic_rx_with_end(struct net_device *dev,
@@ -1292,7 +1290,6 @@
 			}
 		}
 
-		dev->last_rx = jiffies;
 		jumbo->found_start = 0;
 		jumbo->current_size = 0;
 		jumbo->skb = NULL;
@@ -1325,7 +1322,6 @@
 					       skb->data, sp->rxfrag_size);
 				}
 			}
-			dev->last_rx = jiffies;
 			ipg_nic_rx_free_skb(dev);
 		}
 	} else {
@@ -1494,11 +1490,6 @@
 			 * when processing completes.
 			 */
 			netif_rx(skb);
-
-			/* Record frame receive time (jiffies = Linux
-			 * kernel current time stamp).
-			 */
-			dev->last_rx = jiffies;
 		}
 
 		/* Assure RX buffer is not reused by IPG. */
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 2ff1818..9fde748 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -1931,7 +1931,6 @@
 			skb_reset_mac_header(skb);
 			skb->protocol = htons(ETH_P_IRDA);
 			netif_rx(skb);
-			self->netdev->last_rx = jiffies;
 		}
 	}
 	
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index a1e4508..6c4b53f 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -620,7 +620,6 @@
 		/* next descriptor */
 		prxd = aup->rx_ring[aup->rx_head];
 		flags = prxd->flags;
-		dev->last_rx = jiffies;
 
 	}
 	return 0;
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index b5d6b9a..761ed8c 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -929,7 +929,6 @@
 	/* Keep stats up to date */
 	self->stats.rx_bytes += len;
 	self->stats.rx_packets++;
-	self->netdev->last_rx = jiffies;
 
 done:
 	/* Note : at this point, the URB we've just received (urb)
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index e1429fc..c747c87 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -235,7 +235,6 @@
 						  &kingsun->stats,
 						  &kingsun->rx_buff, bytes[i]);
 			}
-			kingsun->netdev->last_rx = jiffies;
 			do_gettimeofday(&kingsun->rx_time);
 			kingsun->receiving =
 				(kingsun->rx_buff.state != OUTSIDE_FRAME)
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
index 2e67ae0..600d96f 100644
--- a/drivers/net/irda/ks959-sir.c
+++ b/drivers/net/irda/ks959-sir.c
@@ -474,7 +474,6 @@
 						  bytes[i]);
 			}
 		}
-		kingsun->netdev->last_rx = jiffies;
 		do_gettimeofday(&kingsun->rx_time);
 		kingsun->receiving =
 		    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c
index 3843b5f..0e7f893 100644
--- a/drivers/net/irda/ksdazzle-sir.c
+++ b/drivers/net/irda/ksdazzle-sir.c
@@ -371,7 +371,6 @@
 			async_unwrap_char(kingsun->netdev, &kingsun->stats,
 					  &kingsun->rx_unwrap_buff, bytes[i]);
 		}
-		kingsun->netdev->last_rx = jiffies;
 		kingsun->receiving =
 		    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
 	}
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index ad92d3f..904c961 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -806,7 +806,6 @@
 			mcs_unwrap_fir(mcs, urb->transfer_buffer,
 				urb->actual_length);
 		}
-		mcs->netdev->last_rx = jiffies;
 		do_gettimeofday(&mcs->rx_time);
 	}
 
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 8583d95..4e1bc08 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1896,7 +1896,6 @@
 			skb_reset_mac_header(skb);
 			skb->protocol = htons(ETH_P_IRDA);
 			netif_rx(skb);
-			self->netdev->last_rx = jiffies;
 		}
 	}
 	/* Restore bank register */
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index c5b02b6..a0ee053 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -225,7 +225,6 @@
 			}
 			lsr = STLSR;
 		}
-		dev->last_rx = jiffies;
 		si->last_oscr = OSCR;
 		break;
 
@@ -237,7 +236,6 @@
 		    si->stats.rx_bytes++;
 	            async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
 	  	} while (STLSR & LSR_DR);
-	  	dev->last_rx = jiffies;
 		si->last_oscr = OSCR;
 	  	break;
 
@@ -397,8 +395,6 @@
 
 		si->stats.rx_packets++;
 		si->stats.rx_bytes += len;
-
-		dev->last_rx = jiffies;
 	}
 }
 
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index a951889..aa6fef8 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -410,7 +410,6 @@
 					  Ser2UTDR);
 		} while (Ser2UTSR1 & UTSR1_RNE);
 
-		dev->last_rx = jiffies;
 	}
 
 	if (status & UTSR0_TFS && si->tx_buff.len) {
@@ -515,7 +514,6 @@
 		sa1100_irda_rx_alloc(si);
 
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 	} else {
 		/*
 		 * Remap the buffer.
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 3575804..ca4cd92 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -824,7 +824,6 @@
 		unwrap_chars(stir, urb->transfer_buffer,
 			     urb->actual_length);
 		
-		stir->netdev->last_rx = jiffies;
 		do_gettimeofday(&stir->rx_time);
 	}
 
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 9c926d2..a3d27d7 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -600,7 +600,6 @@
 		netif_rx(skb);
 	else
 		netif_rx_ni(skb);
-	ndev->last_rx = jiffies;
 
 done:
 	rd_set_status(rd, 0);
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 002a6d7..fa60020 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -923,7 +923,6 @@
 			skb_reset_mac_header(skb);
 			skb->protocol = htons(ETH_P_IRDA);
 			netif_rx(skb);
-			self->netdev->last_rx = jiffies;
 		}
 	}
 	/* Restore set register */
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index d6ff26a..15ebae9 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -192,7 +192,6 @@
 	static unsigned version_printed;
 	int i;
 	int err = -ENODEV;
-	DECLARE_MAC_BUF(mac);
 
 	/* Grab the region so that no one else tries to probe our ioports. */
 	if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname))
@@ -220,7 +219,7 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + i);
 
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 
 	err = -EAGAIN;
 #ifdef jumpered_interrupts
@@ -584,7 +583,6 @@
 			insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
 
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index be3c7dc..cb7d1a6 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -381,8 +381,7 @@
 	adapter->hw.back = adapter;
 	adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
 
-	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
-	                              pci_resource_len(pdev, BAR_0));
+	adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);
 	if (!adapter->hw.hw_addr) {
 		err = -EIO;
 		goto err_ioremap;
@@ -1981,7 +1980,6 @@
 		} else {
 			netif_receive_skb(skb);
 		}
-		netdev->last_rx = jiffies;
 
 rxdesc_done:
 		/* clean up descriptor, might be written over by hw */
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e116d34..132854f 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -267,6 +267,7 @@
 #define IXGBE_FLAG_RSS_CAPABLE                  (u32)(1 << 17)
 #define IXGBE_FLAG_VMDQ_CAPABLE                 (u32)(1 << 18)
 #define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 19)
+#define IXGBE_FLAG_FAN_FAIL_CAPABLE             (u32)(1 << 20)
 #define IXGBE_FLAG_NEED_LINK_UPDATE             (u32)(1 << 22)
 #define IXGBE_FLAG_IN_WATCHDOG_TASK             (u32)(1 << 23)
 
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 7cddcfb..c2cdb04 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -59,6 +59,11 @@
 
 	/* PHY Init */
 	switch (phy->type) {
+	case ixgbe_phy_tn:
+		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+		phy->ops.get_firmware_version =
+		             &ixgbe_get_phy_firmware_version_tnx;
+		break;
 	default:
 		break;
 	}
@@ -189,6 +194,9 @@
 	case IXGBE_DEV_ID_82598EB_XF_LR:
 		media_type = ixgbe_media_type_fiber;
 		break;
+	case IXGBE_DEV_ID_82598AT:
+		media_type = ixgbe_media_type_copper;
+		break;
 	default:
 		media_type = ixgbe_media_type_unknown;
 		break;
@@ -872,6 +880,10 @@
 	case IXGBE_DEV_ID_82598EB_XF_LR:
 		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
 		break;
+	case IXGBE_DEV_ID_82598AT:
+		physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
+		                  IXGBE_PHYSICAL_LAYER_1000BASE_T);
+		break;
 
 	default:
 		physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 81a9c4b..fee56a3 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -149,6 +149,8 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
+	u32 advertised, old;
+	s32 err;
 
 	switch (hw->phy.media_type) {
 	case ixgbe_media_type_fiber:
@@ -157,6 +159,31 @@
 			return -EINVAL;
 		/* in this case we currently only support 10Gb/FULL */
 		break;
+	case ixgbe_media_type_copper:
+		/* 10000/copper and 1000/copper must autoneg
+		 * this function does not support any duplex forcing, but can
+		 * limit the advertising of the adapter to only 10000 or 1000 */
+		if (ecmd->autoneg == AUTONEG_DISABLE)
+			return -EINVAL;
+
+		old = hw->phy.autoneg_advertised;
+		advertised = 0;
+		if (ecmd->advertising & ADVERTISED_10000baseT_Full)
+			advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+		if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+			advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+		if (old == advertised)
+			break;
+		/* this sets the link speed and restarts auto-neg */
+		err = hw->mac.ops.setup_link_speed(hw, advertised, true, true);
+		if (err) {
+			DPRINTK(PROBE, INFO,
+			        "setup link failed with code %d\n", err);
+			hw->mac.ops.setup_link_speed(hw, old, true, true);
+		}
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 7548fb73..b3be579 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -68,6 +68,8 @@
 	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
 	 board_82598 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT),
+	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
 	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
@@ -666,7 +668,6 @@
 
 		skb->protocol = eth_type_trans(skb, adapter->netdev);
 		ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
-		adapter->netdev->last_rx = jiffies;
 
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
@@ -904,6 +905,17 @@
 	return;
 }
 
+static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) &&
+	    (eicr & IXGBE_EICR_GPI_SDP1)) {
+		DPRINTK(PROBE, CRIT, "Fan has stopped, replace the adapter\n");
+		/* write to clear the interrupt */
+		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+	}
+}
 
 static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
 {
@@ -928,6 +940,8 @@
 	if (eicr & IXGBE_EICR_LSC)
 		ixgbe_check_lsc(adapter);
 
+	ixgbe_check_fan_failure(adapter, eicr);
+
 	if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
 
@@ -1316,6 +1330,8 @@
 	if (eicr & IXGBE_EICR_LSC)
 		ixgbe_check_lsc(adapter);
 
+	ixgbe_check_fan_failure(adapter, eicr);
+
 	if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
 		adapter->tx_ring[0].total_packets = 0;
 		adapter->tx_ring[0].total_bytes = 0;
@@ -1418,6 +1434,8 @@
 {
 	u32 mask;
 	mask = IXGBE_EIMS_ENABLE_MASK;
+	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
+		mask |= IXGBE_EIMS_GPI_SDP1;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 }
@@ -1927,6 +1945,13 @@
 		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
 	}
 
+	/* Enable fan failure interrupt if media type is copper */
+	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+		gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+		gpie |= IXGBE_SDP1_GPIEN;
+		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+	}
+
 	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -2564,6 +2589,9 @@
 	rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
 	adapter->ring_feature[RING_F_RSS].indices = rss;
 	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+	if (hw->mac.ops.get_media_type &&
+	    (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper))
+		adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
 
 	/* default flow control settings */
 	hw->fc.original_type = ixgbe_fc_none;
@@ -3691,6 +3719,10 @@
 	/* must always autoneg for both 1G and 10G link */
 	hw->mac.autoneg = true;
 
+	if ((hw->mac.type == ixgbe_mac_82598EB) &&
+	    (hw->phy.media_type == ixgbe_media_type_copper))
+		autoneg = IXGBE_LINK_SPEED_82598_AUTONEG;
+
 	return hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
 }
 
@@ -3877,8 +3909,7 @@
 	pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status);
 	link_speed = link_status & IXGBE_PCI_LINK_SPEED;
 	link_width = link_status & IXGBE_PCI_LINK_WIDTH;
-	dev_info(&pdev->dev, "(PCI Express:%s:%s) "
-	         "%02x:%02x:%02x:%02x:%02x:%02x\n",
+	dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n",
 	        ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" :
 	         (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" :
 	         "Unknown"),
@@ -3887,8 +3918,7 @@
 	         (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" :
 	         (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" :
 	         "Unknown"),
-	        netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-	        netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+	        netdev->dev_addr);
 	ixgbe_read_pba_num_generic(hw, &part_num);
 	dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
 	         hw->mac.type, hw->phy.type,
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 764035a..981e6d8 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -121,6 +121,9 @@
 	enum ixgbe_phy_type phy_type;
 
 	switch (phy_id) {
+	case TN1010_PHY_ID:
+		phy_type = ixgbe_phy_tn;
+		break;
 	case QT2022_PHY_ID:
 		phy_type = ixgbe_phy_qt;
 		break;
@@ -426,3 +429,68 @@
 	return 0;
 }
 
+/**
+ *  ixgbe_check_phy_link_tnx - Determine link and speed status
+ *  @hw: pointer to hardware structure
+ *
+ *  Reads the VS1 register to determine if link is up and the current speed for
+ *  the PHY.
+ **/
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+                             bool *link_up)
+{
+	s32 status = 0;
+	u32 time_out;
+	u32 max_time_out = 10;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+	/*
+	 * Check current speed and link status of the PHY register.
+	 * This is a vendor specific register and may have to
+	 * be changed for other copper PHYs.
+	 */
+	for (time_out = 0; time_out < max_time_out; time_out++) {
+		udelay(10);
+		status = hw->phy.ops.read_reg(hw,
+		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
+		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+		                        &phy_data);
+		phy_link = phy_data &
+		           IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
+		phy_speed = phy_data &
+		            IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
+		if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
+			*link_up = true;
+			if (phy_speed ==
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
+				*speed = IXGBE_LINK_SPEED_1GB_FULL;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+                                       u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
+	                              IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+	                              firmware_version);
+
+	return status;
+}
+
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h
index 9bfe3f2..5cc063d 100644
--- a/drivers/net/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ixgbe/ixgbe_phy.h
@@ -77,4 +77,11 @@
                                        bool autoneg,
                                        bool autoneg_wait_to_complete);
 
+/* PHY specific */
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
+                             ixgbe_link_speed *speed,
+                             bool *link_up);
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+                                       u16 *firmware_version);
+
 #endif /* _IXGBE_PHY_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index c6f8fa1..51df39d 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -36,6 +36,7 @@
 /* Device IDs */
 #define IXGBE_DEV_ID_82598AF_DUAL_PORT   0x10C6
 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
+#define IXGBE_DEV_ID_82598AT             0x10C8
 #define IXGBE_DEV_ID_82598EB_CX4         0x10DD
 #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
 #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
@@ -488,6 +489,8 @@
 #define IXGBE_MAX_PHY_ADDR             32
 
 /* PHY IDs*/
+#define TN1010_PHY_ID    0x00A19410
+#define TNX_FW_REV       0xB
 #define QT2022_PHY_ID    0x0043A400
 
 /* PHY Types */
@@ -1202,6 +1205,7 @@
 
 enum ixgbe_phy_type {
 	ixgbe_phy_unknown = 0,
+	ixgbe_phy_tn,
 	ixgbe_phy_qt,
 	ixgbe_phy_xaui,
 	ixgbe_phy_tw_tyco,
@@ -1396,6 +1400,8 @@
 	s32 (*setup_link)(struct ixgbe_hw *);
 	s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
 	                        bool);
+	s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *);
+	s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *);
 	s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *);
 	s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8);
 	s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 7b70c66..bd96dbc 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -114,8 +114,6 @@
 			skb_put(skb, desc->pkt_length);
 			skb->protocol = eth_type_trans(skb, nds[desc->channel]);
 
-			dev->last_rx = jiffies;
-
 			netif_receive_skb(skb);
 		}
 
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 0794482..334ff9e 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -208,7 +208,6 @@
 	struct sonic_local *lp;
 	struct resource *res;
 	int err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -233,8 +232,7 @@
 	if (err)
 		goto out1;
 
-	printk("%s: MAC %s IRQ %d\n",
-	       dev->name, print_mac(mac, dev->dev_addr), dev->irq);
+	printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq);
 
 	return 0;
 
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 81c6cdc..0796d0b 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -931,7 +931,6 @@
 				RXWBFLAG_DEST_MUL)
 			++(NET_STAT(jme).multicast);
 
-		jme->dev->last_rx = jiffies;
 		NET_STAT(jme).rx_bytes += framesize;
 		++(NET_STAT(jme).rx_packets);
 	}
@@ -2862,18 +2861,10 @@
 		goto err_out_free_shadow;
 	}
 
-	msg_probe(jme,
-		"JMC250 gigabit%s ver:%x rev:%x "
-		"macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+	msg_probe(jme, "JMC250 gigabit%s ver:%x rev:%x macaddr:%pM\n",
 		(jme->fpgaver != 0) ? " (FPGA)" : "",
 		(jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
-		jme->rev,
-		netdev->dev_addr[0],
-		netdev->dev_addr[1],
-		netdev->dev_addr[2],
-		netdev->dev_addr[3],
-		netdev->dev_addr[4],
-		netdev->dev_addr[5]);
+		jme->rev, netdev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index e185763..6362695 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -409,7 +409,6 @@
 
 				/* Pass the packet to upper layers */
 				netif_receive_skb(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 977ed34..f63789a 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -466,7 +466,6 @@
 	unsigned long flags;
 	int err = -ENOMEM;
 	void __iomem *bios;
-	DECLARE_MAC_BUF(mac);
 
 	/* First we look for special cases.
 	   Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
@@ -529,7 +528,7 @@
 	   The first six bytes are the station address. */
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + i);
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 
 	dev->base_addr = ioaddr;
 	/* Make certain the data structures used by the LANCE are aligned and DMAble. */
@@ -1191,7 +1190,6 @@
 					pkt_len);
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				lp->stats.rx_bytes+=pkt_len;
 			}
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index b59f442..7415f51 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -739,7 +739,6 @@
 				skb->len = pkt_len;
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 			}
@@ -1034,12 +1033,8 @@
 
 static void print_eth(unsigned char *add, char *str)
 {
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-
-	printk(KERN_DEBUG "i596 0x%p, %s --> %s %02X%02X, %s\n",
-	       add, print_mac(mac, add + 6), print_mac(mac2, add),
-	       add[12], add[13], str);
+	printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
+	       add, add + 6, add, add[12], add[13], str);
 }
 
 static int __devinit i82596_probe(struct net_device *dev)
@@ -1343,7 +1338,6 @@
 	struct i596_private *lp = netdev_priv(dev);
 	struct i596_dma *dma = lp->dma;
 	int config = 0, cnt;
-	DECLARE_MAC_BUF(mac);
 
 	DEB(DEB_MULTI,
 	    printk(KERN_DEBUG
@@ -1407,8 +1401,8 @@
 			if (i596_debug > 1)
 				DEB(DEB_MULTI,
 				    printk(KERN_DEBUG
-					   "%s: Adding address %s\n",
-					   dev->name, print_mac(mac, cp)));
+					   "%s: Adding address %pM\n",
+					   dev->name, cp));
 		}
 		DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
 		i596_add_cmd(dev, &cmd->cmd);
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index f80dcc1..9430167 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -764,7 +764,6 @@
 				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 				if (pkt_stat & ENRSR_PHY)
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index b369890..bc70d5e 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -169,7 +169,6 @@
 {
 	int i, revision, ret;
 	unsigned long eisa_id;
-	DECLARE_MAC_BUF(mac);
 
 	if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
 
@@ -203,8 +202,8 @@
 
 	for(i = 0; i < ETHER_ADDR_LEN; i++)
 		dev->dev_addr[i] = inb(ioaddr + LNE390_SA_PROM + i);
-	printk("lne390.c: LNE390%X in EISA slot %d, address %s.\n",
-	       0xa+revision, ioaddr/0x1000, print_mac(mac, dev->dev_addr));
+	printk("lne390.c: LNE390%X in EISA slot %d, address %pM.\n",
+	       0xa+revision, ioaddr/0x1000, dev->dev_addr);
 
 	printk("lne390.c: ");
 
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b1ac63a..c4516b5 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -76,8 +76,6 @@
 
 	skb->protocol = eth_type_trans(skb,dev);
 
-	dev->last_rx = jiffies;
-
 	/* it's OK to use per_cpu_ptr() because BHs are off */
 	pcpu_lstats = dev->ml_priv;
 	lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
@@ -206,17 +204,8 @@
 	unregister_netdev(dev);
 }
 
-static struct pernet_operations __net_initdata loopback_net_ops = {
+/* Registered in net/core/dev.c */
+struct pernet_operations __net_initdata loopback_net_ops = {
        .init = loopback_net_init,
        .exit = loopback_net_exit,
 };
-
-static int __init loopback_init(void)
-{
-	return register_pernet_device(&loopback_net_ops);
-}
-
-/* Loopback is special. It should be initialized before any other network
- * device and network subsystem.
- */
-fs_initcall(loopback_init);
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 83fa9d8..d6b0036 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -676,7 +676,6 @@
 
 		skb->protocol = eth_type_trans(skb,dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 	} else {
 #if 0
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index 4ce8afd..2ee477c 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -181,7 +181,6 @@
 	unsigned long ioaddr;
 	unsigned short sig;
 	int err = -ENODEV;
-	DECLARE_MAC_BUF(mac);
 
 	if (!MACH_IS_MAC)
 		return ERR_PTR(-ENODEV);
@@ -279,8 +278,7 @@
 
 	/* print the IRQ and ethernet address. */
 
-	printk(" IRQ %d ADDR %s\n",
-	       dev->irq, print_mac(mac, dev->dev_addr));
+	printk(" IRQ %d ADDR %pM\n", dev->irq, dev->dev_addr);
 
 	dev->open		= net_open;
 	dev->stop		= net_close;
@@ -518,7 +516,6 @@
 
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += length;
 }
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 01f7a31..261b950 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -435,7 +435,6 @@
 
 	bp->stats.rx_packets++;
 	bp->stats.rx_bytes += len;
-	bp->dev->last_rx = jiffies;
 	dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n",
 		skb->len, skb->csum);
 	netif_receive_skb(skb);
@@ -1104,7 +1103,6 @@
 	unsigned long pclk_hz;
 	u32 config;
 	int err = -ENXIO;
-	DECLARE_MAC_BUF(mac);
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
@@ -1223,10 +1221,8 @@
 
 	platform_set_drvdata(pdev, dev);
 
-	printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
-	       "(%s)\n",
-	       dev->name, dev->base_addr, dev->irq,
-	       print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d (%pM)\n",
+	       dev->name, dev->base_addr, dev->irq, dev->dev_addr);
 
 	phydev = bp->phy_dev;
 	printk(KERN_INFO "%s: attached PHY driver [%s] "
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 451acdc..b52f050 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -101,7 +101,6 @@
 	struct mace_data *mp;
 	const unsigned char *addr;
 	int j, rev, rc = -EBUSY;
-	DECLARE_MAC_BUF(mac);
 
 	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
 		printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
@@ -241,8 +240,8 @@
 		goto err_free_rx_irq;
 	}
 
-	printk(KERN_INFO "%s: MACE at %s, chip revision %d.%d\n",
-	       dev->name, print_mac(mac, dev->dev_addr),
+	printk(KERN_INFO "%s: MACE at %pM, chip revision %d.%d\n",
+	       dev->name, dev->dev_addr,
 	       mp->chipid >> 8, mp->chipid & 0xff);
 
 	return 0;
@@ -929,7 +928,6 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		dev->stats.rx_bytes += skb->len;
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		mp->rx_bufs[i] = NULL;
 		++dev->stats.rx_packets;
 	    }
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 85587a66..274e99b 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -194,7 +194,6 @@
 	unsigned char checksum = 0;
 	static int found = 0;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
 		return -ENODEV;
@@ -249,8 +248,8 @@
 	dev->set_multicast_list	= mace_set_multicast;
 	dev->set_mac_address	= mace_set_address;
 
-	printk(KERN_INFO "%s: 68K MACE, hardware address %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n",
+	       dev->name, dev->dev_addr);
 
 	err = register_netdev(dev);
 	if (!err)
@@ -674,7 +673,6 @@
 
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += frame_length;
 	}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index e64c208..205bb05 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -220,7 +220,6 @@
 	struct sonic_local *lp = netdev_priv(dev);
 	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	/* On NuBus boards we can sometimes look in the ROM resources.
 	   No such luck for comm-slot/onboard. */
@@ -264,8 +263,8 @@
 		dev->dev_addr[1] = val >> 8;
 		dev->dev_addr[0] = val & 0xff;
 
-		printk(KERN_INFO "HW Address from CAM 15: %s\n",
-		       print_mac(mac, dev->dev_addr));
+		printk(KERN_INFO "HW Address from CAM 15: %pM\n",
+		       dev->dev_addr);
 	} else return 0;
 
 	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
@@ -560,7 +559,6 @@
 	struct net_device *dev;
 	struct sonic_local *lp;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(sizeof(struct sonic_local));
 	if (!dev)
@@ -584,8 +582,7 @@
 	if (err)
 		goto out;
 
-	printk("%s: MAC %s IRQ %d\n",
-	       dev->name, print_mac(mac, dev->dev_addr), dev->irq);
+	printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq);
 
 	return 0;
 
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 4239450..cabde9a 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -84,7 +84,6 @@
 			dev->stats.rx_bytes += skb->len + ETH_HLEN;
 			dev->stats.rx_packets++;
 			dev->stats.multicast++;
-			dev->last_rx = jiffies;
 
 			nskb->dev = dev;
 			if (!compare_ether_addr(eth->h_dest, dev->broadcast))
@@ -133,7 +132,6 @@
 
 	dev->stats.rx_bytes += skb->len + ETH_HLEN;
 	dev->stats.rx_packets++;
-	dev->last_rx = jiffies;
 
 	skb->dev = dev;
 	skb->pkt_type = PACKET_HOST;
@@ -333,10 +331,34 @@
 	return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
 }
 
+static int macvlan_ethtool_get_settings(struct net_device *dev,
+					struct ethtool_cmd *cmd)
+{
+	const struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	if (!lowerdev->ethtool_ops->get_settings)
+		return -EOPNOTSUPP;
+
+	return lowerdev->ethtool_ops->get_settings(lowerdev, cmd);
+}
+
+static u32 macvlan_ethtool_get_flags(struct net_device *dev)
+{
+	const struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	if (!lowerdev->ethtool_ops->get_flags)
+		return 0;
+	return lowerdev->ethtool_ops->get_flags(lowerdev);
+}
+
 static const struct ethtool_ops macvlan_ethtool_ops = {
 	.get_link		= ethtool_op_get_link,
+	.get_settings		= macvlan_ethtool_get_settings,
 	.get_rx_csum		= macvlan_ethtool_get_rx_csum,
 	.get_drvinfo		= macvlan_ethtool_get_drvinfo,
+	.get_flags		= macvlan_ethtool_get_flags,
 };
 
 static void macvlan_setup(struct net_device *dev)
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index a1e22ed..c336a1f 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -94,10 +94,9 @@
 static inline void load_eaddr(struct net_device *dev)
 {
 	int i;
-	DECLARE_MAC_BUF(mac);
 	u64 macaddr;
 
-	DPRINTK("Loading MAC Address: %s\n", print_mac(mac, dev->dev_addr));
+	DPRINTK("Loading MAC Address: %pM\n", dev->dev_addr);
 	macaddr = 0;
 	for (i = 0; i < 6; i++)
 		macaddr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
@@ -421,7 +420,6 @@
 					skb_put(skb_c, len);
 					priv->rx_skbs[priv->rx_write] = skb;
 					skb_c->protocol = eth_type_trans(skb_c, dev);
-					dev->last_rx = jiffies;
 					dev->stats.rx_packets++;
 					dev->stats.rx_bytes += len;
 					netif_rx(skb_c);
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 6232227..944ad47 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -776,8 +776,6 @@
 		} else
 			netif_receive_skb(skb);
 
-		dev->last_rx = jiffies;
-
 next:
 		++cq->mcq.cons_index;
 		index = (cq->mcq.cons_index) & ring->size_mask;
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 592c01a..b162206 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -118,17 +118,7 @@
 		return err;
 
 	if (0)
-		mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
-			  "%04x:%04x:%04x:%04x is %04x\n",
-			  be16_to_cpu(((__be16 *) gid)[0]),
-			  be16_to_cpu(((__be16 *) gid)[1]),
-			  be16_to_cpu(((__be16 *) gid)[2]),
-			  be16_to_cpu(((__be16 *) gid)[3]),
-			  be16_to_cpu(((__be16 *) gid)[4]),
-			  be16_to_cpu(((__be16 *) gid)[5]),
-			  be16_to_cpu(((__be16 *) gid)[6]),
-			  be16_to_cpu(((__be16 *) gid)[7]),
-			  *hash);
+		mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
 
 	*index = *hash;
 	*prev  = -1;
@@ -277,16 +267,7 @@
 		goto out;
 
 	if (index == -1) {
-		mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
-			  "not found\n",
-			  be16_to_cpu(((__be16 *) gid)[0]),
-			  be16_to_cpu(((__be16 *) gid)[1]),
-			  be16_to_cpu(((__be16 *) gid)[2]),
-			  be16_to_cpu(((__be16 *) gid)[3]),
-			  be16_to_cpu(((__be16 *) gid)[4]),
-			  be16_to_cpu(((__be16 *) gid)[5]),
-			  be16_to_cpu(((__be16 *) gid)[6]),
-			  be16_to_cpu(((__be16 *) gid)[7]));
+		mlx4_err(dev, "MGID %pI6 not found\n", gid);
 		err = -EINVAL;
 		goto out;
 	}
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 11fb17c..cc02219 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -58,17 +58,17 @@
 #define mlx4_dbg(mlevel, priv, format, arg...)	\
 	if (NETIF_MSG_##mlevel & priv->msg_enable) \
 	printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\
-		(&priv->mdev->pdev->dev)->bus_id , ## arg)
+		(dev_name(&priv->mdev->pdev->dev)) , ## arg)
 
 #define mlx4_err(mdev, format, arg...) \
 	printk(KERN_ERR "%s %s: " format , DRV_NAME ,\
-		(&mdev->pdev->dev)->bus_id , ## arg)
+		(dev_name(&mdev->pdev->dev)) , ## arg)
 #define mlx4_info(mdev, format, arg...) \
 	printk(KERN_INFO "%s %s: " format , DRV_NAME ,\
-		(&mdev->pdev->dev)->bus_id , ## arg)
+		(dev_name(&mdev->pdev->dev)) , ## arg)
 #define mlx4_warn(mdev, format, arg...) \
 	printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\
-		(&mdev->pdev->dev)->bus_id , ## arg)
+		(dev_name(&mdev->pdev->dev)) , ## arg)
 
 /*
  * Device constants
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index b9dcdbd..b13fbc4 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -557,8 +557,6 @@
 			skb->protocol = eth_type_trans(skb, mp->dev);
 			netif_receive_skb(skb);
 		}
-
-		mp->dev->last_rx = jiffies;
 	}
 
 	if (rx < budget)
@@ -2592,7 +2590,6 @@
 	struct mv643xx_eth_private *mp;
 	struct net_device *dev;
 	struct resource *res;
-	DECLARE_MAC_BUF(mac);
 	int err;
 
 	pd = pdev->dev.platform_data;
@@ -2686,8 +2683,8 @@
 	if (err)
 		goto out;
 
-	dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %s\n",
-		   mp->port_num, print_mac(mac, dev->dev_addr));
+	dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %pM\n",
+		   mp->port_num, dev->dev_addr);
 
 	if (mp->tx_desc_sram_size > 0)
 		dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n");
diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c
index 06ca425..d30b0d0 100644
--- a/drivers/net/mvme147.c
+++ b/drivers/net/mvme147.c
@@ -67,7 +67,6 @@
 	u_long *addr;
 	u_long address;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	if (!MACH_IS_MVME147 || called)
 		return ERR_PTR(-ENODEV);
@@ -102,9 +101,9 @@
 	dev->dev_addr[3]=address&0xff;
 
 	printk("%s: MVME147 at 0x%08lx, irq %d, "
-	       "Hardware Address %s\n",
+	       "Hardware Address %pM\n",
 	       dev->name, dev->base_addr, MVME147_LANCE_IRQ,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 	lp = (struct m147lance_private *)dev->priv;
 	lp->ram = __get_dma_pages(GFP_ATOMIC, 3);	/* 16K */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index a5f428b..72afe0a 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1334,7 +1334,6 @@
 			myri10ge_vlan_ip_csum(skb, csum);
 	}
 	netif_receive_skb(skb);
-	dev->last_rx = jiffies;
 	return 1;
 }
 
@@ -2983,7 +2982,6 @@
 	struct dev_mc_list *mc_list;
 	__be32 data[2] = { 0, 0 };
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	/* can be called from atomic contexts,
 	 * pass 1 to force atomicity in myri10ge_send_cmd() */
@@ -3030,8 +3028,7 @@
 			printk(KERN_ERR "myri10ge: %s: Failed "
 			       "MXGEFW_JOIN_MULTICAST_GROUP, error status:"
 			       "%d\t", dev->name, err);
-			printk(KERN_ERR "MAC %s\n",
-			       print_mac(mac, mc_list->dmi_addr));
+			printk(KERN_ERR "MAC %pM\n", mc_list->dmi_addr);
 			goto abort;
 		}
 	}
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 3ad7589..a78d4b9 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -318,13 +318,10 @@
 #ifdef DEBUG_HEADER
 static void dump_ehdr(struct ethhdr *ehdr)
 {
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	printk("ehdr[h_dst(%s)"
-	       "h_source(%s)"
+	printk("ehdr[h_dst(%pM)"
+	       "h_source(%pM)"
 	       "h_proto(%04x)]\n",
-	       print_mac(mac, ehdr->h_dest), print_mac(mac2, ehdr->h_source),
-	       ehdr->h_proto);
+	       ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
 }
 
 static void dump_ehdr_and_myripad(unsigned char *stuff)
@@ -528,7 +525,6 @@
 		DRX(("prot[%04x] netif_rx ", skb->protocol));
 		netif_rx(skb);
 
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += len;
 	next:
@@ -905,7 +901,6 @@
 	struct device_node *dp = op->node;
 	static unsigned version_printed;
 	struct net_device *dev;
-	DECLARE_MAC_BUF(mac);
 	struct myri_eth *mp;
 	const void *prop;
 	static int num;
@@ -1088,8 +1083,8 @@
 
 	num++;
 
-	printk("%s: MyriCOM MyriNET Ethernet %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk("%s: MyriCOM MyriNET Ethernet %pM\n",
+	       dev->name, dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index f7fa394..9f81fcb 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -792,7 +792,6 @@
 	const int pcibar = 1; /* PCI base address register */
 	int prev_eedata;
 	u32 tmp;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -948,10 +947,10 @@
 
 	if (netif_msg_drv(np)) {
 		printk(KERN_INFO "natsemi %s: %s at %#08llx "
-		       "(%s), %s, IRQ %d",
+		       "(%s), %pM, IRQ %d",
 		       dev->name, natsemi_pci_info[chip_idx].name,
 		       (unsigned long long)iostart, pci_name(np->pci_dev),
-		       print_mac(mac, dev->dev_addr), irq);
+		       dev->dev_addr, irq);
 		if (dev->if_port == PORT_TP)
 			printk(", port TP.\n");
 		else if (np->ignore_phy)
@@ -2362,7 +2361,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_receive_skb(skb);
-			dev->last_rx = jiffies;
 			np->stats.rx_packets++;
 			np->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index fbc7531..aa99f5e 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -204,7 +204,6 @@
 	static unsigned version_printed;
 	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
 	unsigned char bus_width;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -299,7 +298,7 @@
 
 	for(i = 0; i < ETHER_ADDR_LEN; i++)
 		dev->dev_addr[i] = SA_prom[i];
-	printk(" %s\n", print_mac(mac, dev->dev_addr));
+	printk(" %pM\n", dev->dev_addr);
 
 	printk("%s: %s found at %#x, using IRQ %d.\n",
 		dev->name, name, ioaddr, dev->irq);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index eb681c0..f708712 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -297,7 +297,6 @@
 	int neX000, ctron, copam, bad_card;
 	int reg0, ret;
 	static unsigned version_printed;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -517,7 +516,7 @@
 	}
 #endif
 
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 332df75..6f8f326 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -302,7 +302,6 @@
 static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
 {
 	int len=0;
-	DECLARE_MAC_BUF(mac);
 
 	len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
 	len += sprintf(buf+len, "Driver written by Wim Dumon ");
@@ -313,7 +312,7 @@
 	len += sprintf(buf+len, "Based on the original NE2000 drivers\n" );
 	len += sprintf(buf+len, "Base IO: %#x\n", (unsigned int)dev->base_addr);
 	len += sprintf(buf+len, "IRQ    : %d\n", dev->irq);
-	len += sprintf(buf+len, "HW addr : %s\n", print_mac(mac, dev->dev_addr));
+	len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
 
 	return len;
 }
@@ -326,7 +325,6 @@
 	const char *name = "NE/2";
 	int start_page, stop_page;
 	static unsigned version_printed;
-	DECLARE_MAC_BUF(mac);
 
 	if (ei_debug && version_printed++ == 0)
 		printk(version);
@@ -469,7 +467,7 @@
 	for(i = 0; i < ETHER_ADDR_LEN; i++)
 		dev->dev_addr[i] = SA_prom[i];
 
-	printk(" %s\n", print_mac(mac, dev->dev_addr));
+	printk(" %pM\n", dev->dev_addr);
 
 	printk("%s: %s found at %#x, using IRQ %d.\n",
 			dev->name, name, base_addr, dev->irq);
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index de0de74..12a7d6d 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -212,7 +212,6 @@
 	static unsigned int fnd_cnt;
 	long ioaddr;
 	int flags = pci_clone_list[chip_idx].flags;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -368,9 +367,9 @@
 
 	for(i = 0; i < 6; i++)
 		dev->dev_addr[i] = SA_prom[i];
-	printk("%s: %s found at %#lx, IRQ %d, %s.\n",
+	printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
 	       dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index 425043a..6681ca7 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -99,7 +99,6 @@
 	int i, retval, port_index;
 	struct eisa_device *edev = to_eisa_device (device);
 	struct net_device *dev;
-	DECLARE_MAC_BUF(mac);
 
 	/* Allocate dev->priv and fill in 8390 specific dev fields. */
 	if (!(dev = alloc_ei_netdev ())) {
@@ -131,8 +130,8 @@
 	port_index = inb(ioaddr + NE3210_CFG2) >> 6;
 	for(i = 0; i < ETHER_ADDR_LEN; i++)
 		dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i);
-	printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %s.\n",
-		edev->slot, ifmap[port_index], print_mac(mac, dev->dev_addr));
+	printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %pM.\n",
+		edev->slot, ifmap[port_index], dev->dev_addr);
 
 	/* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
 	dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 9681618..d304d38 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -307,17 +307,14 @@
 static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
 {
 	struct net_device *dev = nt->np.dev;
+	static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-	DECLARE_MAC_BUF(mac);
-	return snprintf(buf, PAGE_SIZE, "%s\n", dev ?
-			print_mac(mac, dev->dev_addr) : "ff:ff:ff:ff:ff:ff");
+	return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
 }
 
 static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
 {
-	DECLARE_MAC_BUF(mac);
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			print_mac(mac, nt->np.remote_mac));
+	return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
 }
 
 /*
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index b9bed82..b418771 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -165,7 +165,6 @@
 	pfifo_push(EMPTY_PTR_FIFO(priv->id),
 		FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
 
-	ndev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, ndev);
 	netif_rx(skb);
 	ndev->stats.rx_packets++;
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 5bba675..d924468 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1285,9 +1285,7 @@
 		}
 		adapter->stats.rxdropped++;
 	} else {
-
 		netif_receive_skb(skb);
-		netdev->last_rx = jiffies;
 
 		adapter->stats.no_rcv++;
 		adapter->stats.rxbytes += length;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 6ef3f0d..33caca9 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -439,7 +439,6 @@
 	int i;
 	unsigned char *p;
 	__le64 mac_addr;
-	DECLARE_MAC_BUF(mac);
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -462,10 +461,9 @@
 
 	/* set station address */
 
-	if (!is_valid_ether_addr(netdev->perm_addr)) {
-		dev_warn(&pdev->dev, "Bad MAC address %s.\n",
-				print_mac(mac, netdev->dev_addr));
-	} else
+	if (!is_valid_ether_addr(netdev->perm_addr))
+		dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr);
+	else
 		adapter->macaddr_set(adapter, netdev->dev_addr);
 
 	return 0;
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 27f07f6..c3b9c83 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -608,7 +608,6 @@
 	int phy = adapter->physical_port;
 	unsigned char mac_addr[6];
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		return 0;
@@ -636,10 +635,8 @@
 	if (i == 10) {
 		printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
 		       netxen_nic_driver_name, adapter->netdev->name);
-		printk(KERN_ERR "MAC address set: %s.\n",
-		       print_mac(mac, addr));
-		printk(KERN_ERR "MAC address get: %s.\n",
-		       print_mac(mac, mac_addr));
+		printk(KERN_ERR "MAC address set: %pM.\n", addr);
+		printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
 	}
 	return 0;
 }
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 8e0ca9f..6c11557 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -203,7 +203,6 @@
 	unsigned int data = 0;
 	int boguscount = 40;
 	int err = -ENODEV;
-	DECLARE_MAC_BUF(mac);
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
@@ -271,7 +270,7 @@
 		outw(i, IE_GP);
 		dev->dev_addr[i] = inb(IE_SAPROM);
 	}
-	printk("%s ", print_mac(mac, dev->dev_addr));
+	printk("%pM ", dev->dev_addr);
 
 	PRINTK2((KERN_DEBUG "%s: I/O #4 passed!\n", dev->name));
 
@@ -570,7 +569,6 @@
 
 	skb->protocol = eth_type_trans(skb,dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += i_pkt_size;
 
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index b9a882d..6d7cf3c9 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -970,7 +970,6 @@
 					memcpy_fromio(skb->data, p->base + readl(&rbd->buffer), totlen);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
-					dev->last_rx = jiffies;
 					p->stats.rx_packets++;
 					p->stats.rx_bytes += totlen;
 				} else
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3edc971..24e393b 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1113,7 +1113,6 @@
 				p->stats.rx_bytes += len;
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 			}
 			else
 			{
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 9acb5d7..2c3bb36 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -3139,8 +3139,6 @@
 	skb->protocol = eth_type_trans(skb, np->dev);
 	netif_receive_skb(skb);
 
-	np->dev->last_rx = jiffies;
-
 	return num_rcr;
 }
 
@@ -8638,10 +8636,8 @@
 static void __devinit niu_device_announce(struct niu *np)
 {
 	struct net_device *dev = np->dev;
-	DECLARE_MAC_BUF(mac);
 
-	pr_info("%s: NIU Ethernet %s\n",
-		dev->name, print_mac(mac, dev->dev_addr));
+	pr_info("%s: NIU Ethernet %pM\n", dev->name, dev->dev_addr);
 
 	if (np->parent->plat_type == PLAT_TYPE_ATCA_CP3220) {
 		pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index ff44961..4bb6441 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1955,7 +1955,6 @@
 	long addr;
 	int err;
 	int using_dac = 0;
-	DECLARE_MAC_BUF(mac);
 
 	/* See if we can set the dma mask early on; failure is fatal. */
 	if (sizeof(dma_addr_t) == 8 &&
@@ -2220,12 +2219,11 @@
 		ndev->features |= NETIF_F_HIGHDMA;
 	}
 
-	printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %s io=0x%08lx irq=%d f=%s\n",
+	printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %pM io=0x%08lx irq=%d f=%s\n",
 		ndev->name,
 		(unsigned)readl(dev->base + SRR) >> 8,
 		(unsigned)readl(dev->base + SRR) & 0xff,
-		print_mac(mac, ndev->dev_addr),
-		addr, pci_dev->irq,
+		ndev->dev_addr, addr, pci_dev->irq,
 		(ndev->features & NETIF_F_HIGHDMA) ? "h,sg" : "sg"
 		);
 
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index edc0fd5..fcbf6cc 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -1105,7 +1105,8 @@
 		goto err;
 
 	phy_id = *prop;
-	snprintf(mac->phy_id, BUS_ID_SIZE, "%x:%02x", (int)r.start, phy_id);
+	snprintf(mac->phy_id, sizeof(mac->phy_id), "%x:%02x",
+		 (int)r.start, phy_id);
 
 	of_node_put(phy_dn);
 
@@ -1742,7 +1743,6 @@
 	struct net_device *dev;
 	struct pasemi_mac *mac;
 	int err;
-	DECLARE_MAC_BUF(mac_buf);
 
 	err = pci_enable_device(pdev);
 	if (err)
@@ -1849,9 +1849,9 @@
 			err);
 		goto out;
 	} else if netif_msg_probe(mac)
-		printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %s\n",
+		printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %pM\n",
 		       dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
-		       mac->dma_if, print_mac(mac_buf, dev->dev_addr));
+		       mac->dma_if, dev->dev_addr);
 
 	return err;
 
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 0a575fe..b23b5c3 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -737,7 +737,6 @@
 	int i, addr_len, option;
 	void *ioaddr = NULL;
 	static int board_idx = -1;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -797,11 +796,11 @@
 
 	tp->phys[0] = 32;
 
-	printk (KERN_INFO "%s: %s at 0x%lx, %sIRQ %d\n",
+	printk (KERN_INFO "%s: %s at 0x%lx, %pM IRQ %d\n",
 		dev->name,
 		board_info[ent->driver_data].name,
 		dev->base_addr,
-		print_mac(mac, dev->dev_addr),
+		dev->dev_addr,
 		dev->irq);
 
 	printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",
@@ -1566,7 +1565,6 @@
 
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_bytes += pkt_size;
 			dev->stats.rx_packets++;
 		} else {
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 08c4dd8..e5cb6b1 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -345,7 +345,6 @@
 	__be16 *phys_addr;
 	char *cardname;
 	__u32 config;
-	DECLARE_MAC_BUF(mac);
 
 	phys_addr = (__be16 *)dev->dev_addr;
 
@@ -463,9 +462,9 @@
 	strcpy(lp->node.dev_name, dev->name);
 
 	printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
-	       "hw_addr %s.\n",
+	       "hw_addr %pM.\n",
 	       dev->name, cardname, dev->base_addr, dev->irq,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 	printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
 		   8 << config & Ram_size,
 		   ram_split[(config & Ram_split) >> Ram_split_shift],
@@ -1062,7 +1061,6 @@
 						((pkt_len+3)>>2));
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 			} else {
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index c235cdb..73ecc65 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -255,7 +255,6 @@
     int last_fn, last_ret, i, j, multi = 0, fifo;
     unsigned int ioaddr;
     char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
-    DECLARE_MAC_BUF(mac);
     
     DEBUG(0, "3c589_config(0x%p)\n", link);
 
@@ -333,9 +332,9 @@
     strcpy(lp->node.dev_name, dev->name);
 
     printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, "
-	   "hw_addr %s\n",
+	   "hw_addr %pM\n",
 	   dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq,
-	   print_mac(mac, dev->dev_addr));
+	   dev->dev_addr);
     printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
 	   (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
 	   if_names[dev->if_port]);
@@ -884,7 +883,6 @@
 			(pkt_len+3)>>2);
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += pkt_len;
 	    } else {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index b37a498..2aca8df 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -321,7 +321,6 @@
     struct net_device *dev = link->priv;
     axnet_dev_t *info = PRIV(dev);
     int i, j, last_ret, last_fn;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "axnet_config(0x%p)\n", link);
 
@@ -397,10 +396,10 @@
     strcpy(info->node.dev_name, dev->name);
 
     printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, "
-	   "hw_addr %s\n",
+	   "hw_addr %pM\n",
 	   dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
 	   dev->base_addr, dev->irq,
-	   print_mac(mac, dev->dev_addr));
+	   dev->dev_addr);
     if (info->phy_id != -1) {
 	DEBUG(0, "  MII transceiver at index %d, status %x.\n", info->phy_id, j);
     } else {
@@ -1493,7 +1492,6 @@
 				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 				if (pkt_stat & ENRSR_PHY)
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 69d916d..69dcfbb 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -125,6 +125,7 @@
     u_short tx_queue_len;
     cardtype_t cardtype;
     u_short sent;
+    u_char __iomem *base;
 } local_info_t;
 
 #define MC_FILTERBREAK 64
@@ -242,6 +243,7 @@
     lp = netdev_priv(dev);
     link->priv = dev;
     lp->p_dev = link;
+    lp->base = NULL;
 
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 32;
@@ -348,7 +350,6 @@
     cardtype_t cardtype;
     char *card_name = "unknown";
     u_char *node_id;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "fmvj18x_config(0x%p)\n", link);
 
@@ -443,8 +444,10 @@
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
-    if (link->io.BasePort2 != 0)
-	fmvj18x_setup_mfc(link);
+    if (link->io.BasePort2 != 0) {
+	ret = fmvj18x_setup_mfc(link);
+	if (ret != 0) goto failed;
+    }
 
     ioaddr = dev->base_addr;
 
@@ -539,9 +542,9 @@
 
     /* print current configuration */
     printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
-	   "hw_addr %s\n",
+	   "hw_addr %pM\n",
 	   dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", 
-	   dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr));
+	   dev->base_addr, dev->irq, dev->dev_addr);
 
     return 0;
     
@@ -611,10 +614,10 @@
 {
     win_req_t req;
     memreq_t mem;
-    u_char __iomem *base;
-    int i, j;
+    int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
+    local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,25 +629,32 @@
 	return -1;
     }
 
-    base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(req.Base, req.Size);
+    if (lp->base == NULL) {
+	printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+	return -1;
+    }
+
     mem.Page = 0;
     mem.CardOffset = 0;
-    pcmcia_map_mem_page(link->win, &mem);
-
+    i = pcmcia_map_mem_page(link->win, &mem);
+    if (i != 0) {
+	iounmap(lp->base);
+	lp->base = NULL;
+	cs_error(link, MapMemPage, i);
+	return -1;
+    }
+    
     ioaddr = dev->base_addr;
-    writeb(0x47, base+0x800);	/* Config Option Register of LAN */
-    writeb(0x0, base+0x802);	/* Config and Status Register */
+    writeb(0x47, lp->base+0x800);	/* Config Option Register of LAN */
+    writeb(0x0,  lp->base+0x802);	/* Config and Status Register */
 
-    writeb(ioaddr & 0xff, base+0x80a);		/* I/O Base(Low) of LAN */
-    writeb((ioaddr >> 8) & 0xff, base+0x80c);	/* I/O Base(High) of LAN */
+    writeb(ioaddr & 0xff, lp->base+0x80a);	  /* I/O Base(Low) of LAN */
+    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
    
-    writeb(0x45, base+0x820);	/* Config Option Register of Modem */
-    writeb(0x8, base+0x822);	/* Config and Status Register */
+    writeb(0x45, lp->base+0x820);	/* Config Option Register of Modem */
+    writeb(0x8,  lp->base+0x822);	/* Config and Status Register */
 
-    iounmap(base);
-    j = pcmcia_release_window(link->win);
-    if (j != 0)
-	cs_error(link, ReleaseWindow, j);
     return 0;
 
 }
@@ -652,8 +662,25 @@
 
 static void fmvj18x_release(struct pcmcia_device *link)
 {
-	DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-	pcmcia_disable_device(link);
+
+    struct net_device *dev = link->priv;
+    local_info_t *lp = netdev_priv(dev);
+    u_char __iomem *tmp;
+    int j;
+
+    DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+
+    if (lp->base != NULL) {
+	tmp = lp->base;
+	lp->base = NULL;    /* set NULL before iounmap */
+	iounmap(tmp);
+	j = pcmcia_release_window(link->win);
+	if (j != 0)
+	    cs_error(link, ReleaseWindow, j);
+    }
+
+    pcmcia_disable_device(link);
+
 }
 
 static int fmvj18x_suspend(struct pcmcia_device *link)
@@ -784,6 +811,13 @@
 
     outb(D_TX_INTR, ioaddr + TX_INTR);
     outb(D_RX_INTR, ioaddr + RX_INTR);
+
+    if (lp->base != NULL) {
+	/* Ack interrupt for multifunction card */
+	writeb(0x01, lp->base+0x802);
+	writeb(0x09, lp->base+0x822);
+    }
+
     return IRQ_HANDLED;
 
 } /* fjn_interrupt */
@@ -1036,7 +1070,6 @@
 #endif
 
 	    netif_rx(skb);
-	    dev->last_rx = jiffies;
 	    lp->stats.rx_packets++;
 	    lp->stats.rx_bytes += pkt_len;
 	}
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 448cd40..ec7c588 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -659,7 +659,6 @@
   u_char buf[64];
   int i, last_ret, last_fn;
   unsigned int ioaddr;
-  DECLARE_MAC_BUF(mac);
 
   DEBUG(0, "nmclan_config(0x%p)\n", link);
 
@@ -719,9 +718,9 @@
   strcpy(lp->node.dev_name, dev->name);
 
   printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port,"
-	 " hw_addr %s\n",
+	 " hw_addr %pM\n",
 	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port],
-	 print_mac(mac, dev->dev_addr));
+	 dev->dev_addr);
   return 0;
 
 cs_failed:
@@ -1193,7 +1192,6 @@
 	
 	netif_rx(skb); /* Send the packet to the upper (protocol) layers. */
 
-	dev->last_rx = jiffies;
 	lp->linux_stats.rx_packets++;
 	lp->linux_stats.rx_bytes += pkt_len;
 	outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index e40d630..6962537 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -554,7 +554,6 @@
     int last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
     hw_info_t *local_hw_info;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "pcnet_config(0x%p)\n", link);
 
@@ -675,7 +674,7 @@
 	printk (" mem %#5lx,", dev->mem_start);
     if (info->flags & HAS_MISC_REG)
 	printk(" %s xcvr,", if_names[dev->if_port]);
-    printk(" hw_addr %s\n", print_mac(mac, dev->dev_addr));
+    printk(" hw_addr %pM\n", dev->dev_addr);
     return 0;
 
 cs_failed:
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index c74d665..fccd53e 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -949,7 +949,6 @@
     int i, j, rev;
     unsigned int ioaddr;
     u_long mir;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "smc91c92_config(0x%p)\n", link);
 
@@ -1062,9 +1061,9 @@
     strcpy(smc->node.dev_name, dev->name);
 
     printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
-	   "hw_addr %s\n",
+	   "hw_addr %pM\n",
 	   dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
-	   print_mac(mac, dev->dev_addr));
+	   dev->dev_addr);
 
     if (rev > 0) {
 	if (mir & 0x3ff)
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index e1fd585..fef7e18 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -772,7 +772,6 @@
     int err, i;
     u_char buf[64];
     cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
-    DECLARE_MAC_BUF(mac);
 
     local->dingo_ccr = NULL;
 
@@ -1051,9 +1050,9 @@
     strcpy(local->node.dev_name, dev->name);
 
     /* give some infos about the hardware */
-    printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %s\n",
+    printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n",
 	   dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq,
-	   print_mac(mac, dev->dev_addr));
+	   dev->dev_addr);
 
     return 0;
 
@@ -1243,7 +1242,6 @@
 		}
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		lp->stats.rx_packets++;
 		lp->stats.rx_bytes += pktlen;
 		if (!(rsr & PhyPkt))
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ca8c0e0..f2b192c 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1246,7 +1246,6 @@
 	dev->stats.rx_bytes += skb->len;
 	skb->protocol = eth_type_trans(skb, dev);
 	netif_receive_skb(skb);
-	dev->last_rx = jiffies;
 	dev->stats.rx_packets++;
 	return;
 }
@@ -1747,8 +1746,7 @@
 		memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
 
 	if (pcnet32_debug & NETIF_MSG_PROBE) {
-		DECLARE_MAC_BUF(mac);
-		printk(" %s", print_mac(mac, dev->dev_addr));
+		printk(" %pM", dev->dev_addr);
 
 		/* Version 0x2623 and 0x2624 */
 		if (((chip_version + 1) & 0xfffe) == 0x2624) {
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 4b4dc98..fd4fc66 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 
+#define PHY_ID_BCM50610		0x0143bd60
+
 #define MII_BCM54XX_ECR		0x10	/* BCM54xx extended control register */
 #define MII_BCM54XX_ECR_IM	0x1000	/* Interrupt mask */
 #define MII_BCM54XX_ECR_IF	0x0800	/* Interrupt force */
@@ -54,6 +56,21 @@
 #define MII_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
 
 /*
+ * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
+ */
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
+#define MII_BCM54XX_AUXCTL_ACTL_TX_6DB		0x0400
+#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA	0x0800
+
+#define MII_BCM54XX_AUXCTL_MISC_WREN	0x8000
+#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
+#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
+
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
+
+
+/*
  * Broadcom LED source encodings.  These are used in BCM5461, BCM5481,
  * BCM5482, and possibly some others.
  */
@@ -88,6 +105,24 @@
 #define BCM5482_SHD_MODE_1000BX	0x0001	/* Enable 1000BASE-X registers */
 
 /*
+ * EXPANSION SHADOW ACCESS REGISTERS.  (PHY REG 0x15, 0x16, and 0x17)
+ */
+#define MII_BCM54XX_EXP_AADJ1CH0		0x001f
+#define  MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN	0x0200
+#define  MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF	0x0100
+#define MII_BCM54XX_EXP_AADJ1CH3		0x601f
+#define  MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ	0x0002
+#define MII_BCM54XX_EXP_EXP08			0x0F08
+#define  MII_BCM54XX_EXP_EXP08_RJCT_2MHZ	0x0001
+#define  MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE	0x0200
+#define MII_BCM54XX_EXP_EXP75			0x0f75
+#define  MII_BCM54XX_EXP_EXP75_VDACCTRL		0x003c
+#define MII_BCM54XX_EXP_EXP96			0x0f96
+#define  MII_BCM54XX_EXP_EXP96_MYST		0x0010
+#define MII_BCM54XX_EXP_EXP97			0x0f97
+#define  MII_BCM54XX_EXP_EXP97_MYST		0x0c0c
+
+/*
  * BCM5482: Secondary SerDes registers
  */
 #define BCM5482_SSD_1000BX_CTL		0x00	/* 1000BASE-X Control */
@@ -128,40 +163,93 @@
 			 MII_BCM54XX_SHD_DATA(val));
 }
 
-/*
- * Indirect register access functions for the Expansion Registers
- * and Secondary SerDes registers (when sec_serdes=1).
- */
-static int bcm54xx_exp_read(struct phy_device *phydev,
-			    int sec_serdes, u8 regnum)
+/* Indirect register access functions for the Expansion Registers */
+static int bcm54xx_exp_read(struct phy_device *phydev, u8 regnum)
 {
 	int val;
 
-	phy_write(phydev, MII_BCM54XX_EXP_SEL,
-		  (sec_serdes ? MII_BCM54XX_EXP_SEL_SSD :
-				MII_BCM54XX_EXP_SEL_ER) |
-		  regnum);
+	val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+	if (val < 0)
+		return val;
+
 	val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+
+	/* Restore default value.  It's O.K. if this write fails. */
+	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
 
 	return val;
 }
 
-static int bcm54xx_exp_write(struct phy_device *phydev,
-			     int sec_serdes, u8 regnum, u16 val)
+static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
 {
 	int ret;
 
-	phy_write(phydev, MII_BCM54XX_EXP_SEL,
-		  (sec_serdes ? MII_BCM54XX_EXP_SEL_SSD :
-				MII_BCM54XX_EXP_SEL_ER) |
-		  regnum);
+	ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+	if (ret < 0)
+		return ret;
+
 	ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+
+	/* Restore default value.  It's O.K. if this write fails. */
+	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
 
 	return ret;
 }
 
+static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
+}
+
+static int bcm50610_a0_workaround(struct phy_device *phydev)
+{
+	int err;
+
+	err = bcm54xx_auxctl_write(phydev,
+				   MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
+				   MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
+				   MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
+	if (err < 0)
+		return err;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
+				MII_BCM54XX_EXP_EXP08_RJCT_2MHZ	|
+				MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
+	if (err < 0)
+		goto error;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
+				MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
+				MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
+	if (err < 0)
+		goto error;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
+					MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
+	if (err < 0)
+		goto error;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
+				MII_BCM54XX_EXP_EXP75_VDACCTRL);
+	if (err < 0)
+		goto error;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
+				MII_BCM54XX_EXP_EXP96_MYST);
+	if (err < 0)
+		goto error;
+
+	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
+				MII_BCM54XX_EXP_EXP97_MYST);
+
+error:
+	bcm54xx_auxctl_write(phydev,
+			     MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
+			     MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
+
+	return err;
+}
+
 static int bcm54xx_config_init(struct phy_device *phydev)
 {
 	int reg, err;
@@ -183,6 +271,13 @@
 	err = phy_write(phydev, MII_BCM54XX_IMR, reg);
 	if (err < 0)
 		return err;
+
+	if (phydev->drv->phy_id == PHY_ID_BCM50610) {
+		err = bcm50610_a0_workaround(phydev);
+		if (err < 0)
+			return err;
+	}
+
 	return 0;
 }
 
@@ -205,18 +300,27 @@
 		/*
 		 * Enable SGMII slave mode and auto-detection
 		 */
-		reg = bcm54xx_exp_read(phydev, 1, BCM5482_SSD_SGMII_SLAVE);
-		bcm54xx_exp_write(phydev, 1, BCM5482_SSD_SGMII_SLAVE,
-				  reg |
-				  BCM5482_SSD_SGMII_SLAVE_EN |
-				  BCM5482_SSD_SGMII_SLAVE_AD);
+		reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
+		err = bcm54xx_exp_read(phydev, reg);
+		if (err < 0)
+			return err;
+		err = bcm54xx_exp_write(phydev, reg, err |
+					BCM5482_SSD_SGMII_SLAVE_EN |
+					BCM5482_SSD_SGMII_SLAVE_AD);
+		if (err < 0)
+			return err;
 
 		/*
 		 * Disable secondary SerDes powerdown
 		 */
-		reg = bcm54xx_exp_read(phydev, 1, BCM5482_SSD_1000BX_CTL);
-		bcm54xx_exp_write(phydev, 1, BCM5482_SSD_1000BX_CTL,
-				  reg & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
+		reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
+		err = bcm54xx_exp_read(phydev, reg);
+		if (err < 0)
+			return err;
+		err = bcm54xx_exp_write(phydev, reg,
+					err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
+		if (err < 0)
+			return err;
 
 		/*
 		 * Select 1000BASE-X register set (primary SerDes)
@@ -335,7 +439,8 @@
 	.phy_id		= 0x00206070,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5411",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
@@ -349,7 +454,8 @@
 	.phy_id		= 0x002060e0,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5421",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
@@ -363,7 +469,8 @@
 	.phy_id		= 0x002060c0,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5461",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
@@ -377,7 +484,8 @@
 	.phy_id		= 0x002060b0,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5464",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
@@ -391,7 +499,8 @@
 	.phy_id		= 0x0143bca0,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5481",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= bcm5481_config_aneg,
@@ -405,7 +514,8 @@
 	.phy_id		= 0x0143bcb0,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5482",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm5482_config_init,
 	.config_aneg	= genphy_config_aneg,
@@ -415,6 +525,21 @@
 	.driver 	= { .owner = THIS_MODULE },
 };
 
+static struct phy_driver bcm50610_driver = {
+	.phy_id		= PHY_ID_BCM50610,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Broadcom BCM50610",
+	.features	= PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+	.config_init	= bcm54xx_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.ack_interrupt	= bcm54xx_ack_interrupt,
+	.config_intr	= bcm54xx_config_intr,
+	.driver 	= { .owner = THIS_MODULE },
+};
+
 static int __init broadcom_init(void)
 {
 	int ret;
@@ -437,8 +562,13 @@
 	ret = phy_driver_register(&bcm5482_driver);
 	if (ret)
 		goto out_5482;
+	ret = phy_driver_register(&bcm50610_driver);
+	if (ret)
+		goto out_50610;
 	return ret;
 
+out_50610:
+	phy_driver_unregister(&bcm5482_driver);
 out_5482:
 	phy_driver_unregister(&bcm5481_driver);
 out_5481:
@@ -455,6 +585,7 @@
 
 static void __exit broadcom_exit(void)
 {
+	phy_driver_unregister(&bcm50610_driver);
 	phy_driver_unregister(&bcm5482_driver);
 	phy_driver_unregister(&bcm5481_driver);
 	phy_driver_unregister(&bcm5464_driver);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d0ed1ef..6afd35f 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -97,7 +97,7 @@
 	bus->dev.parent = bus->parent;
 	bus->dev.class = &mdio_bus_class;
 	bus->dev.groups = NULL;
-	memcpy(bus->dev.bus_id, bus->id, MII_BUS_ID_SIZE);
+	dev_set_name(&bus->dev, bus->id);
 
 	err = device_register(&bus->dev);
 	if (err) {
@@ -191,7 +191,7 @@
 
 	phydev->dev.parent = bus->parent;
 	phydev->dev.bus = &mdio_bus_type;
-	snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr);
+	dev_set_name(&phydev->dev, PHY_ID_FMT, bus->id, addr);
 
 	phydev->bus = bus;
 
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index df4e625..e4ede60 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -45,7 +45,7 @@
  */
 void phy_print_status(struct phy_device *phydev)
 {
-	pr_info("PHY: %s - Link is %s", phydev->dev.bus_id,
+	pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev),
 			phydev->link ? "Up" : "Down");
 	if (phydev->link)
 		printk(" - %d/%s", phydev->speed,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e11b03b..e976c1c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -74,7 +74,7 @@
 	if (!fixup)
 		return -ENOMEM;
 
-	strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
+	strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
 	fixup->phy_uid = phy_uid;
 	fixup->phy_uid_mask = phy_uid_mask;
 	fixup->run = run;
@@ -109,7 +109,7 @@
  */
 static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
 {
-	if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
+	if (strcmp(fixup->bus_id, dev_name(&phydev->dev)) != 0)
 		if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
 			return 0;
 
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 73baa7a..c05d38d 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -126,6 +126,27 @@
 	.driver		= { .owner = THIS_MODULE, }
 };
 
+static struct phy_driver lan911x_int_driver = {
+	.phy_id		= 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "SMSC LAN911x Internal PHY",
+
+	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
+				| SUPPORTED_Asym_Pause),
+	.flags		= PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+	/* basic functions */
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.config_init	= smsc_phy_config_init,
+
+	/* IRQ related */
+	.ack_interrupt	= smsc_phy_ack_interrupt,
+	.config_intr	= smsc_phy_config_intr,
+
+	.driver		= { .owner = THIS_MODULE, }
+};
+
 static int __init smsc_init(void)
 {
 	int ret;
@@ -142,8 +163,14 @@
 	if (ret)
 		goto err3;
 
+	ret = phy_driver_register (&lan911x_int_driver);
+	if (ret)
+		goto err4;
+
 	return 0;
 
+err4:
+	phy_driver_unregister (&lan8700_driver);
 err3:
 	phy_driver_unregister (&lan8187_driver);
 err2:
@@ -154,6 +181,7 @@
 
 static void __exit smsc_exit(void)
 {
+	phy_driver_unregister (&lan911x_int_driver);
 	phy_driver_unregister (&lan8700_driver);
 	phy_driver_unregister (&lan8187_driver);
 	phy_driver_unregister (&lan83c185_driver);
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 1e96542..2ea78e6 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -664,7 +664,6 @@
 		/* Inform the upper layer for the arrival of a packet. */
 		rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
 		netif_rx_ni(rcv->skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_bytes += rcv->length.h;
 		dev->stats.rx_packets++;
 		rcv->skb = NULL;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 7e857e9..274d495 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1684,7 +1684,6 @@
 			skb->protocol = htons(npindex_to_ethertype[npi]);
 			skb_reset_mac_header(skb);
 			netif_rx(skb);
-			ppp->dev->last_rx = jiffies;
 		}
 	}
 	return;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index b646e92..c22b305 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -958,7 +958,6 @@
 {
 	struct pppox_sock *po;
 	char *dev_name;
-	DECLARE_MAC_BUF(mac);
 
 	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, "Id       Address              Device\n");
@@ -968,8 +967,8 @@
 	po = v;
 	dev_name = po->pppoe_pa.dev;
 
-	seq_printf(seq, "%08X %s %8s\n",
-		   po->pppoe_pa.sid, print_mac(mac, po->pppoe_pa.remote), dev_name);
+	seq_printf(seq, "%08X %pM %8s\n",
+		   po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
 out:
 	return 0;
 }
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 2eb54fd..4b564ed 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -1443,7 +1443,6 @@
 {
 	int status;
 	u64 v1, v2;
-	DECLARE_MAC_BUF(mac);
 
 	netdev->features = NETIF_F_IP_CSUM;
 
@@ -1474,9 +1473,8 @@
 			__func__, netdev->name, status);
 		return status;
 	}
-	dev_info(ctodev(card), "%s: MAC addr %s\n",
-		 netdev->name,
-		 print_mac(mac, netdev->dev_addr));
+	dev_info(ctodev(card), "%s: MAC addr %pM\n",
+		 netdev->name, netdev->dev_addr);
 
 	return 0;
 }
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index a834b52..ec23142 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -30,10 +30,11 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 
 #include <linux/dma-mapping.h>
 #include <net/checksum.h>
@@ -449,9 +450,9 @@
 
 	/* element id */
 	if (rsn)
-		*buf++ = MFIE_TYPE_RSN;
+		*buf++ = WLAN_EID_RSN;
 	else
-		*buf++ = MFIE_TYPE_GENERIC;
+		*buf++ = WLAN_EID_GENERIC;
 
 	/* length filed; set later */
 	buf++;
@@ -539,7 +540,7 @@
 			break;
 
 		switch (item_id) {
-		case MFIE_TYPE_GENERIC:
+		case WLAN_EID_GENERIC:
 			if ((OUI_LEN + 1 <= item_len) &&
 			    !memcmp(pos, wpa_oui, OUI_LEN) &&
 			    pos[OUI_LEN] == 0x01) {
@@ -547,7 +548,7 @@
 				ie_info->wpa.len = item_len + 2;
 			}
 			break;
-		case MFIE_TYPE_RSN:
+		case WLAN_EID_RSN:
 			ie_info->rsn.data = pos - 2;
 			/* length includes the header */
 			ie_info->rsn.len = item_len + 2;
@@ -581,7 +582,7 @@
 	char *tmp;
 	u8 rate;
 	unsigned int i, j, len;
-	u8 buf[MAX_WPA_IE_LEN];
+	u8 buf[64]; /* arbitrary size large enough */
 
 	pr_debug("%s: <-\n", __func__);
 
@@ -763,7 +764,6 @@
 {
 	struct gelic_wl_scan_info *scan_info;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	i = 0;
 	list_for_each_entry(scan_info, &wl->network_list, list) {
@@ -775,8 +775,7 @@
 			 scan_info->rate_len, scan_info->rate_ext_len,
 			 scan_info->essid_len);
 		/* -- */
-		pr_debug("bssid=%s\n",
-			 print_mac(mac, &scan_info->hwinfo->bssid[2]));
+		pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]);
 		pr_debug("essid=%s\n", scan_info->hwinfo->essid);
 	}
 }
@@ -1167,11 +1166,7 @@
 		       ETH_ALEN);
 		set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
 		set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
-		pr_debug("%s: bss=%02x:%02x:%02x:%02x:%02x:%02x\n",
-			 __func__,
-			 wl->bssid[0], wl->bssid[1],
-			 wl->bssid[2], wl->bssid[3],
-			 wl->bssid[4], wl->bssid[5]);
+		pr_debug("%s: bss=%pM\n", __func__, wl->bssid);
 	} else {
 		pr_debug("%s: clear bssid\n", __func__);
 		clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
@@ -1632,7 +1627,6 @@
 	unsigned long this_time = jiffies;
 	unsigned int data_len, i, found, r;
 	void *buf;
-	DECLARE_MAC_BUF(mac);
 
 	pr_debug("%s:start\n", __func__);
 	mutex_lock(&wl->scan_lock);
@@ -1684,9 +1678,9 @@
 	     scan_info_size < data_len;
 	     i++, scan_info_size += be16_to_cpu(scan_info->size),
 	     scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) {
-		pr_debug("%s:size=%d bssid=%s scan_info=%p\n", __func__,
+		pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__,
 			 be16_to_cpu(scan_info->size),
-			 print_mac(mac, &scan_info->bssid[2]), scan_info);
+			 &scan_info->bssid[2], scan_info);
 
 		/*
 		 * The wireless firmware may return invalid channel 0 and/or
@@ -1741,14 +1735,14 @@
 		target->essid_len = strnlen(scan_info->essid,
 					    sizeof(scan_info->essid));
 		target->rate_len = 0;
-		for (r = 0; r < MAX_RATES_LENGTH; r++)
+		for (r = 0; r < 12; r++)
 			if (scan_info->rate[r])
 				target->rate_len++;
 		if (8 < target->rate_len)
 			pr_info("%s: AP returns %d rates\n", __func__,
 				target->rate_len);
 		target->rate_ext_len = 0;
-		for (r = 0; r < MAX_RATES_EX_LENGTH; r++)
+		for (r = 0; r < 16; r++)
 			if (scan_info->ext_rate[r])
 				target->rate_ext_len++;
 		list_move_tail(&target->list, &wl->network_list);
@@ -1787,7 +1781,6 @@
 	struct gelic_wl_scan_info *best_bss;
 	int weight, best_weight;
 	u16 security;
-	DECLARE_MAC_BUF(mac);
 
 	pr_debug("%s: <-\n", __func__);
 
@@ -1857,8 +1850,8 @@
 #ifdef DEBUG
 	pr_debug("%s: -> bss=%p\n", __func__, best_bss);
 	if (best_bss) {
-		pr_debug("%s:addr=%s\n", __func__,
-			 print_mac(mac, &best_bss->hwinfo->bssid[2]));
+		pr_debug("%s:addr=%pM\n", __func__,
+			 &best_bss->hwinfo->bssid[2]);
 	}
 #endif
 	return best_bss;
diff --git a/drivers/net/ps3_gelic_wireless.h b/drivers/net/ps3_gelic_wireless.h
index 5339e00..5b631c6 100644
--- a/drivers/net/ps3_gelic_wireless.h
+++ b/drivers/net/ps3_gelic_wireless.h
@@ -164,8 +164,8 @@
 	__be16 security;
 	u8  bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */
 	u8  essid[32]; /* IW_ESSID_MAX_SIZE */
-	u8  rate[16]; /* first MAX_RATES_LENGTH(12) are valid */
-	u8  ext_rate[16]; /* first MAX_RATES_EX_LENGTH(16) are valid */
+	u8  rate[16]; /* first 12 are valid */
+	u8  ext_rate[16]; /* first 16 are valid */
 	__be32 reserved1;
 	__be32 reserved2;
 	__be32 reserved3;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 3cdd07c..8b41242 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2136,7 +2136,6 @@
 	skb->protocol = eth_type_trans(skb, qdev->ndev);
 
 	netif_receive_skb(skb);
-	qdev->ndev->last_rx = jiffies;
 	lrg_buf_cb2->skb = NULL;
 
 	if (qdev->device_id == QL3022_DEVICE_ID)
@@ -2210,7 +2209,6 @@
 	netif_receive_skb(skb2);
 	ndev->stats.rx_packets++;
 	ndev->stats.rx_bytes += length;
-	ndev->last_rx = jiffies;
 	lrg_buf_cb2->skb = NULL;
 
 	if (qdev->device_id == QL3022_DEVICE_ID)
@@ -3529,7 +3527,6 @@
 {
 	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
 	struct pci_dev *pdev = qdev->pdev;
-	DECLARE_MAC_BUF(mac);
 
 	printk(KERN_INFO PFX
 	       "\n%s Adapter %d RevisionID %d found %s on PCI slot %d.\n",
@@ -3555,8 +3552,8 @@
 
 	if (netif_msg_probe(qdev))
 		printk(KERN_INFO PFX
-		       "%s: MAC address %s\n",
-		       ndev->name, print_mac(mac, ndev->dev_addr));
+		       "%s: MAC address %pM\n",
+		       ndev->name, ndev->dev_addr);
 }
 
 static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset)
@@ -3978,9 +3975,7 @@
 	if (qdev->device_id == QL3032_DEVICE_ID)
 		ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 
-	qdev->mem_map_registers =
-	    ioremap_nocache(pci_resource_start(pdev, 1),
-			    pci_resource_len(qdev->pdev, 1));
+	qdev->mem_map_registers = pci_ioremap_bar(pdev, 1);
 	if (!qdev->mem_map_registers) {
 		printk(KERN_ERR PFX "%s: cannot map device registers\n",
 		       pci_name(pdev));
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index b83a9c9..3a6d3ac 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -336,12 +336,11 @@
 			    (addr[5]);
 
 			QPRINTK(qdev, IFUP, INFO,
-				"Adding %s address %02x:%02x:%02x:%02x:%02x:%02x"
+				"Adding %s address %pM"
 				" at index %d in the CAM.\n",
 				((type ==
 				  MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" :
-				 "UNICAST"), addr[0], addr[1], addr[2], addr[3],
-				addr[4], addr[5], index);
+				 "UNICAST"), addr, index);
 
 			status =
 			    ql_wait_reg_rdy(qdev,
@@ -1452,7 +1451,6 @@
 			"Passing a normal packet upstream.\n");
 		netif_rx(skb);
 	}
-	ndev->last_rx = jiffies;
 }
 
 /* Process an outbound completion from an rx ring. */
@@ -3127,11 +3125,7 @@
 		qdev->chip_rev_id >> 4 & 0x0000000f,
 		qdev->chip_rev_id >> 8 & 0x0000000f,
 		qdev->chip_rev_id >> 12 & 0x0000000f);
-	QPRINTK(qdev, PROBE, INFO,
-		"MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
-		ndev->dev_addr[0], ndev->dev_addr[1],
-		ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
-		ndev->dev_addr[5]);
+	QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr);
 }
 
 static int ql_adapter_down(struct ql_adapter *qdev)
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 34fe7ef..d9a6e92 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -598,7 +598,6 @@
 		
 		/* Send to upper layer */
 		netif_receive_skb(skb_ptr);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += descptr->len - 4;
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 4b7cb38..cb5042e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -3484,7 +3484,6 @@
 			if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0)
 				netif_receive_skb(skb);
 
-			dev->last_rx = jiffies;
 			dev->stats.rx_bytes += pkt_size;
 			dev->stats.rx_packets++;
 		}
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 2b8fd68..bd4f4ad 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -435,7 +435,6 @@
 	struct net_device *ndev = NULL;
 	struct rionet_private *rnet;
 	u16 device_id;
-	DECLARE_MAC_BUF(mac);
 
 	/* Allocate our net_device structure */
 	ndev = alloc_etherdev(sizeof(struct rionet_private));
@@ -485,12 +484,12 @@
 	if (rc != 0)
 		goto out;
 
-	printk("%s: %s %s Version %s, MAC %s\n",
+	printk("%s: %s %s Version %s, MAC %pM\n",
 	       ndev->name,
 	       DRV_NAME,
 	       DRV_DESC,
 	       DRV_VERSION,
-	       print_mac(mac, ndev->dev_addr));
+	       ndev->dev_addr);
 
       out:
 	return rc;
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 3dd8f13..6e4131f 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -511,7 +511,6 @@
 	struct rr_private *rrpriv;
 	struct rr_regs __iomem *regs;
 	u32 sram_size, rev;
-	DECLARE_MAC_BUF(mac);
 
 	rrpriv = netdev_priv(dev);
 	regs = rrpriv->regs;
@@ -549,7 +548,7 @@
 	*(__be32 *)(dev->dev_addr+2) =
 	  htonl(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA[4])));
 
-	printk("  MAC: %s\n", print_mac(mac, dev->dev_addr));
+	printk("  MAC: %pM\n", dev->dev_addr);
 
 	sram_size = rr_read_eeprom_word(rrpriv, 8);
 	printk("  SRAM size 0x%06x\n", sram_size);
@@ -1006,7 +1005,6 @@
 
 			netif_rx(skb);		/* send it up */
 
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 6a1375f..cec9fe0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -7544,7 +7544,6 @@
 	sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
 send_up:
 	queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
-	dev->last_rx = jiffies;
 aggregate:
 	sp->mac_control.rings[ring_no].rx_bufs_left -= 1;
 	return SUCCESS;
@@ -7748,7 +7747,6 @@
 	int mode;
 	u8 dev_intr_type = intr_type;
 	u8 dev_multiq = 0;
-	DECLARE_MAC_BUF(mac);
 
 	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
 	if (ret)
@@ -7918,8 +7916,7 @@
 		goto mem_alloc_failed;
 	}
 
-	sp->bar0 = ioremap(pci_resource_start(pdev, 0),
-				     pci_resource_len(pdev, 0));
+	sp->bar0 = pci_ioremap_bar(pdev, 0);
 	if (!sp->bar0) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n",
 			  dev->name);
@@ -7927,8 +7924,7 @@
 		goto bar0_remap_failed;
 	}
 
-	sp->bar1 = ioremap(pci_resource_start(pdev, 2),
-				     pci_resource_len(pdev, 2));
+	sp->bar1 = pci_ioremap_bar(pdev, 2);
 	if (!sp->bar1) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n",
 			  dev->name);
@@ -8125,8 +8121,7 @@
 		  sp->product_name, pdev->revision);
 	DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
 		  s2io_driver_version);
-	DBG_PRINT(ERR_DBG, "%s: MAC ADDR: %s\n",
-		  dev->name, print_mac(mac, dev->dev_addr));
+	DBG_PRINT(ERR_DBG, "%s: MAC ADDR: %pM\n", dev->name, dev->dev_addr);
 	DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num);
 	if (sp->device_type & XFRAME_II_DEVICE) {
 		mode = s2io_print_pci_mode(sp);
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 5986cec..be30253 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -869,7 +869,6 @@
 	/* datagram completed: send to upper level */
 	skb_trim(skb, dlen);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 	stats->rx_bytes+=dlen;
 	stats->rx_packets++;
 	lp->rx_skb[ns] = NULL;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 2615d46..480caec 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2292,7 +2292,6 @@
 	uint64_t ea_reg;
 	int i;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	sc->sbm_dev = dev;
 	sc->sbe_idx = idx;
@@ -2373,8 +2372,8 @@
 	 * process so we need to finish off the config message that
 	 * was being displayed)
 	 */
-	pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %s\n",
-	       dev->name, base, print_mac(mac, eaddr));
+	pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n",
+	       dev->name, base, eaddr);
 
 	sc->mii_bus->name = sbmac_mdio_string;
 	snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 61955f8..590f217 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -816,7 +816,6 @@
 		}
 
 		skb->protocol = eth_type_trans(skb, dev);
-		dev->last_rx = jiffies;
 		netif_rx(skb);
 
 		dev->stats.rx_bytes += pkt_size;
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index 48c64fb..2fbc8f1 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -158,7 +158,6 @@
 	int old_dmaar;
 	int old_rear;
 	int retval;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005"))
 		return -ENODEV;
@@ -303,7 +302,7 @@
 	/* Retrieve and print the ethernet address. */
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = SA_prom[i+6];
-	printk("%s", print_mac(mac, dev->dev_addr));
+	printk("%pM", dev->dev_addr);
 
 	if (dev->irq == 0xff)
 		;			/* Do nothing: a user-level program will set it. */
@@ -564,7 +563,6 @@
 
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
index 3be13b5..3e25fb3 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/sfc/Kconfig
@@ -12,3 +12,11 @@
 
 	  To compile this driver as a module, choose M here.  The module
 	  will be called sfc.
+config SFC_MTD
+	bool "Solarflare Solarstorm SFC4000 flash MTD support"
+	depends on SFC && MTD
+	default y
+	help
+	  This exposes the on-board flash memory as an MTD device (e.g.
+          /dev/mtd1).  This makes it possible to upload new boot code
+          to the NIC.
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index c8f5704..e507daa 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,5 +1,6 @@
 sfc-y			+= efx.o falcon.o tx.o rx.o falcon_xmac.o \
 			   selftest.o ethtool.o xfp_phy.o \
 			   mdio_10g.o tenxpress.o boards.o sfe4001.o
+sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 
 obj-$(CONFIG_SFC)	+= sfc.o
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c
index 99e6023..edf0262 100644
--- a/drivers/net/sfc/boards.c
+++ b/drivers/net/sfc/boards.c
@@ -11,6 +11,7 @@
 #include "phy.h"
 #include "boards.h"
 #include "efx.h"
+#include "workarounds.h"
 
 /* Macros for unpacking the board revision */
 /* The revision info is in host byte order. */
@@ -52,9 +53,128 @@
 }
 
 /*****************************************************************************
+ * Support for LM87 sensor chip used on several boards
+ */
+#define LM87_REG_ALARMS1		0x41
+#define LM87_REG_ALARMS2		0x42
+#define LM87_IN_LIMITS(nr, _min, _max)			\
+	0x2B + (nr) * 2, _max, 0x2C + (nr) * 2, _min
+#define LM87_AIN_LIMITS(nr, _min, _max)			\
+	0x3B + (nr), _max, 0x1A + (nr), _min
+#define LM87_TEMP_INT_LIMITS(_min, _max)		\
+	0x39, _max, 0x3A, _min
+#define LM87_TEMP_EXT1_LIMITS(_min, _max)		\
+	0x37, _max, 0x38, _min
+
+#define LM87_ALARM_TEMP_INT		0x10
+#define LM87_ALARM_TEMP_EXT1		0x20
+
+#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
+
+static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+			 const u8 *reg_values)
+{
+	struct i2c_client *client = i2c_new_device(&efx->i2c_adap, info);
+	int rc;
+
+	if (!client)
+		return -EIO;
+
+	while (*reg_values) {
+		u8 reg = *reg_values++;
+		u8 value = *reg_values++;
+		rc = i2c_smbus_write_byte_data(client, reg, value);
+		if (rc)
+			goto err;
+	}
+
+	efx->board_info.hwmon_client = client;
+	return 0;
+
+err:
+	i2c_unregister_device(client);
+	return rc;
+}
+
+static void efx_fini_lm87(struct efx_nic *efx)
+{
+	i2c_unregister_device(efx->board_info.hwmon_client);
+}
+
+static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+	struct i2c_client *client = efx->board_info.hwmon_client;
+	s32 alarms1, alarms2;
+
+	/* If link is up then do not monitor temperature */
+	if (EFX_WORKAROUND_7884(efx) && efx->link_up)
+		return 0;
+
+	alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+	alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+	if (alarms1 < 0)
+		return alarms1;
+	if (alarms2 < 0)
+		return alarms2;
+	alarms1 &= mask;
+	alarms2 &= mask >> 8;
+	if (alarms1 || alarms2) {
+		EFX_ERR(efx,
+			"LM87 detected a hardware failure (status %02x:%02x)"
+			"%s%s\n",
+			alarms1, alarms2,
+			(alarms1 & LM87_ALARM_TEMP_INT) ? " INTERNAL" : "",
+			(alarms1 & LM87_ALARM_TEMP_EXT1) ? " EXTERNAL" : "");
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+#else /* !CONFIG_SENSORS_LM87 */
+
+static inline int
+efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+	      const u8 *reg_values)
+{
+	return 0;
+}
+static inline void efx_fini_lm87(struct efx_nic *efx)
+{
+}
+static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SENSORS_LM87 */
+
+/*****************************************************************************
  * Support for the SFE4002
  *
  */
+static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4002_lm87_regs[] = {
+	LM87_IN_LIMITS(0, 0x83, 0x91),		/* 2.5V:  1.8V +/- 5% */
+	LM87_IN_LIMITS(1, 0x51, 0x5a),		/* Vccp1: 1.2V +/- 5% */
+	LM87_IN_LIMITS(2, 0xb6, 0xca),		/* 3.3V:  3.3V +/- 5% */
+	LM87_IN_LIMITS(3, 0xb0, 0xc9),		/* 5V:    4.6-5.2V */
+	LM87_IN_LIMITS(4, 0xb0, 0xe0),		/* 12V:   11-14V */
+	LM87_IN_LIMITS(5, 0x44, 0x4b),		/* Vccp2: 1.0V +/- 5% */
+	LM87_AIN_LIMITS(0, 0xa0, 0xb2),		/* AIN1:  1.66V +/- 5% */
+	LM87_AIN_LIMITS(1, 0x91, 0xa1),		/* AIN2:  1.5V +/- 5% */
+	LM87_TEMP_INT_LIMITS(10, 60),		/* board */
+	LM87_TEMP_EXT1_LIMITS(10, 70),		/* Falcon */
+	0
+};
+
+static struct i2c_board_info sfe4002_hwmon_info = {
+	I2C_BOARD_INFO("lm87", 0x2e),
+	.platform_data	= &sfe4002_lm87_channel,
+	.irq		= -1,
+};
+
 /****************************************************************************/
 /* LED allocations. Note that on rev A0 boards the schematic and the reality
  * differ: red and green are swapped. Below is the fixed (A1) layout (there
@@ -84,11 +204,27 @@
 			QUAKE_LED_OFF);
 }
 
+static int sfe4002_check_hw(struct efx_nic *efx)
+{
+	/* A0 board rev. 4002s report a temperature fault the whole time
+	 * (bad sensor) so we mask it out. */
+	unsigned alarm_mask =
+		(efx->board_info.major == 0 && efx->board_info.minor == 0) ?
+		~LM87_ALARM_TEMP_EXT1 : ~0;
+
+	return efx_check_lm87(efx, alarm_mask);
+}
+
 static int sfe4002_init(struct efx_nic *efx)
 {
+	int rc = efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
+	if (rc)
+		return rc;
+	efx->board_info.monitor = sfe4002_check_hw;
 	efx->board_info.init_leds = sfe4002_init_leds;
 	efx->board_info.set_fault_led = sfe4002_fault_led;
 	efx->board_info.blink = board_blink;
+	efx->board_info.fini = efx_fini_lm87;
 	return 0;
 }
 
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 06ea71c..ac7bdbf 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -77,11 +77,6 @@
  */
 unsigned int efx_monitor_interval = 1 * HZ;
 
-/* This controls whether or not the hardware monitor will trigger a
- * reset when it detects an error condition.
- */
-static unsigned int monitor_reset = true;
-
 /* This controls whether or not the driver will initialise devices
  * with invalid MAC addresses stored in the EEPROM or flash.  If true,
  * such devices will be initialised with a random locally-generated
@@ -612,17 +607,15 @@
 	if (is_valid_ether_addr(efx->mac_address)) {
 		memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
 	} else {
-		DECLARE_MAC_BUF(mac);
-
-		EFX_ERR(efx, "invalid MAC address %s\n",
-			print_mac(mac, efx->mac_address));
+		EFX_ERR(efx, "invalid MAC address %pM\n",
+			efx->mac_address);
 		if (!allow_bad_hwaddr) {
 			rc = -EINVAL;
 			goto err;
 		}
 		random_ether_addr(efx->net_dev->dev_addr);
-		EFX_INFO(efx, "using locally-generated MAC %s\n",
-			 print_mac(mac, efx->net_dev->dev_addr));
+		EFX_INFO(efx, "using locally-generated MAC %pM\n",
+			 efx->net_dev->dev_addr);
 	}
 
 	return 0;
@@ -1178,17 +1171,6 @@
 		rc = falcon_check_xmac(efx);
 	mutex_unlock(&efx->mac_lock);
 
-	if (rc) {
-		if (monitor_reset) {
-			EFX_ERR(efx, "hardware monitor detected a fault: "
-				"triggering reset\n");
-			efx_schedule_reset(efx, RESET_TYPE_MONITOR);
-		} else {
-			EFX_ERR(efx, "hardware monitor detected a fault, "
-				"skipping reset\n");
-		}
-	}
-
 	queue_delayed_work(efx->workqueue, &efx->monitor_work,
 			   efx_monitor_interval);
 }
@@ -1360,12 +1342,11 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
-	EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
-		atomic_read(&efx->netif_stop_count), efx->port_enabled,
-		monitor_reset ? "resetting channels" : "skipping reset");
+	EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d:"
+		" resetting channels\n",
+		atomic_read(&efx->netif_stop_count), efx->port_enabled);
 
-	if (monitor_reset)
-		efx_schedule_reset(efx, RESET_TYPE_MONITOR);
+	efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
 }
 
 
@@ -1401,9 +1382,8 @@
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
 	if (!is_valid_ether_addr(new_addr)) {
-		DECLARE_MAC_BUF(mac);
-		EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
-			print_mac(mac, new_addr));
+		EFX_ERR(efx, "invalid ethernet MAC address requested: %pM\n",
+			new_addr);
 		return -EINVAL;
 	}
 
@@ -1462,6 +1442,7 @@
 		struct efx_nic *efx = netdev_priv(net_dev);
 
 		strcpy(efx->name, net_dev->name);
+		efx_mtd_rename(efx);
 	}
 
 	return NOTIFY_DONE;
@@ -1553,6 +1534,7 @@
 
 	efx_stop_all(efx);
 	mutex_lock(&efx->mac_lock);
+	mutex_lock(&efx->spi_lock);
 
 	rc = falcon_xmac_get_settings(efx, ecmd);
 	if (rc)
@@ -1585,6 +1567,7 @@
 			EFX_ERR(efx, "could not restore PHY settings\n");
 	}
 
+	mutex_unlock(&efx->spi_lock);
 	mutex_unlock(&efx->mac_lock);
 
 	if (ok) {
@@ -1780,6 +1763,7 @@
 	memset(efx, 0, sizeof(*efx));
 	spin_lock_init(&efx->biu_lock);
 	spin_lock_init(&efx->phy_lock);
+	mutex_init(&efx->spi_lock);
 	INIT_WORK(&efx->reset_work, efx_reset_work);
 	INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
 	efx->pci_dev = pci_dev;
@@ -1914,6 +1898,8 @@
 	if (!efx)
 		return;
 
+	efx_mtd_remove(efx);
+
 	/* Mark the NIC as fini, then stop the interface */
 	rtnl_lock();
 	efx->state = STATE_FINI;
@@ -2080,6 +2066,7 @@
 
 	EFX_LOG(efx, "initialisation successful\n");
 
+	efx_mtd_probe(efx); /* allowed to fail */
 	return 0;
 
  fail5:
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index d02937b..dd0d45b 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -58,6 +58,16 @@
 extern void efx_port_dummy_op_void(struct efx_nic *efx);
 extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink);
 
+/* MTD */
+#ifdef CONFIG_SFC_MTD
+extern int efx_mtd_probe(struct efx_nic *efx);
+extern void efx_mtd_rename(struct efx_nic *efx);
+extern void efx_mtd_remove(struct efx_nic *efx);
+#else
+static inline int efx_mtd_probe(struct efx_nic *efx) { return 0; }
+static inline void efx_mtd_rename(struct efx_nic *efx) {}
+static inline void efx_mtd_remove(struct efx_nic *efx) {}
+#endif
 
 extern unsigned int efx_monitor_interval;
 
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index cec15db..41e758e 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -72,7 +72,7 @@
  * @RESET_TYPE_ALL: reset everything but PCI core blocks
  * @RESET_TYPE_WORLD: reset everything, save & restore PCI config
  * @RESET_TYPE_DISABLE: disable NIC
- * @RESET_TYPE_MONITOR: reset due to hardware monitor
+ * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
  * @RESET_TYPE_INT_ERROR: reset due to internal error
  * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
  * @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch
@@ -86,7 +86,7 @@
 	RESET_TYPE_WORLD = 2,
 	RESET_TYPE_DISABLE = 3,
 	RESET_TYPE_MAX_METHOD,
-	RESET_TYPE_MONITOR,
+	RESET_TYPE_TX_WATCHDOG,
 	RESET_TYPE_INT_ERROR,
 	RESET_TYPE_RX_RECOVERY,
 	RESET_TYPE_RX_DESC_FETCH,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index cd0d087..abd8fcd 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -172,10 +172,7 @@
 /* Number of ethtool statistics */
 #define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
 
-/* EEPROM range with gPXE configuration */
 #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
-#define EFX_ETHTOOL_EEPROM_MIN 0x800U
-#define EFX_ETHTOOL_EEPROM_MAX 0x1800U
 
 /**************************************************************************
  *
@@ -545,8 +542,8 @@
 
 	if (!spi)
 		return 0;
-	return min(spi->size, EFX_ETHTOOL_EEPROM_MAX) -
-		min(spi->size, EFX_ETHTOOL_EEPROM_MIN);
+	return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
+		min(spi->size, EFX_EEPROM_BOOTCONFIG_START);
 }
 
 static int efx_ethtool_get_eeprom(struct net_device *net_dev,
@@ -557,8 +554,10 @@
 	size_t len;
 	int rc;
 
-	rc = falcon_spi_read(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+	mutex_lock(&efx->spi_lock);
+	rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			     eeprom->len, &len, buf);
+	mutex_unlock(&efx->spi_lock);
 	eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
 	eeprom->len = len;
 	return rc;
@@ -575,8 +574,10 @@
 	if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
 		return -EINVAL;
 
-	rc = falcon_spi_write(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+	mutex_lock(&efx->spi_lock);
+	rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			      eeprom->len, &len, buf);
+	mutex_unlock(&efx->spi_lock);
 	eeprom->len = len;
 	return rc;
 }
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 31ed1f4..71e0bed 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1628,9 +1628,9 @@
 	}
 }
 
-static int falcon_spi_cmd(const struct efx_spi_device *spi,
-			  unsigned int command, int address,
-			  const void *in, void *out, unsigned int len)
+int falcon_spi_cmd(const struct efx_spi_device *spi,
+		   unsigned int command, int address,
+		   const void *in, void *out, unsigned int len)
 {
 	struct efx_nic *efx = spi->efx;
 	bool addressed = (address >= 0);
@@ -1641,6 +1641,7 @@
 	/* Input validation */
 	if (len > FALCON_SPI_MAX_LEN)
 		return -EINVAL;
+	BUG_ON(!mutex_is_locked(&efx->spi_lock));
 
 	/* Check SPI not currently being accessed */
 	rc = falcon_spi_wait(efx);
@@ -1699,8 +1700,7 @@
 	return command | (((address >> 8) & spi->munge_address) << 3);
 }
 
-
-static int falcon_spi_fast_wait(const struct efx_spi_device *spi)
+int falcon_spi_fast_wait(const struct efx_spi_device *spi)
 {
 	u8 status;
 	int i, rc;
@@ -2253,13 +2253,15 @@
 	__le16 *word, *limit;
 	u32 csum;
 
-	region = kmalloc(NVCONFIG_END, GFP_KERNEL);
+	region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
 	if (!region)
 		return -ENOMEM;
 	nvconfig = region + NVCONFIG_OFFSET;
 
 	spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
-	rc = falcon_spi_read(spi, 0, NVCONFIG_END, NULL, region);
+	mutex_lock(&efx->spi_lock);
+	rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
+	mutex_unlock(&efx->spi_lock);
 	if (rc) {
 		EFX_ERR(efx, "Failed to read %s\n",
 			efx->spi_flash ? "flash" : "EEPROM");
@@ -2283,7 +2285,7 @@
 		limit = (__le16 *) (nvconfig + 1);
 	} else {
 		word = region;
-		limit = region + NVCONFIG_END;
+		limit = region + FALCON_NVCONFIG_END;
 	}
 	for (csum = 0; word < limit; ++word)
 		csum += le16_to_cpu(*word);
@@ -2555,6 +2557,11 @@
 			SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
 		spi_device->munge_address = (spi_device->size == 1 << 9 &&
 					     spi_device->addr_len == 1);
+		spi_device->erase_command =
+			SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD);
+		spi_device->erase_size =
+			1 << SPI_DEV_TYPE_FIELD(device_type,
+						SPI_DEV_TYPE_ERASE_SIZE);
 		spi_device->block_size =
 			1 << SPI_DEV_TYPE_FIELD(device_type,
 						SPI_DEV_TYPE_BLOCK_SIZE);
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 5d584b0..040e70e 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -1150,7 +1150,6 @@
 	(((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(EFX_WIDTH(field)))
 
 #define NVCONFIG_OFFSET 0x300
-#define NVCONFIG_END 0x400
 
 #define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
 struct falcon_nvconfig {
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 003e48d..19e2521 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -260,6 +260,41 @@
 				    MDIO_MMDREG_CTRL1, ctrl2);
 }
 
+static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
+					 int lpower, int mmd)
+{
+	int phy = efx->mii.phy_id;
+	int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1);
+	int ctrl1, ctrl2;
+
+	EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n",
+		  mmd, lpower);
+
+	if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) {
+		ctrl1 = ctrl2 = mdio_clause45_read(efx, phy,
+						   mmd, MDIO_MMDREG_CTRL1);
+		if (lpower)
+			ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
+		else
+			ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
+		if (ctrl1 != ctrl2)
+			mdio_clause45_write(efx, phy, mmd,
+					    MDIO_MMDREG_CTRL1, ctrl2);
+	}
+}
+
+void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
+				   int low_power, unsigned int mmd_mask)
+{
+	int mmd = 0;
+	while (mmd_mask) {
+		if (mmd_mask & 1)
+			mdio_clause45_set_mmd_lpower(efx, low_power, mmd);
+		mmd_mask = (mmd_mask >> 1);
+		mmd++;
+	}
+}
+
 /**
  * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
  * @efx:		Efx NIC
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 19c42ea..db9f358 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -54,6 +54,9 @@
 /* Loopback bit for WIS, PCS, PHYSX and DTEXS */
 #define MDIO_MMDREG_CTRL1_LBACK_LBN	(14)
 #define MDIO_MMDREG_CTRL1_LBACK_WIDTH	(1)
+/* Low power */
+#define MDIO_MMDREG_CTRL1_LPOWER_LBN	(11)
+#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH	(1)
 
 /* Bits in MMDREG_STAT1 */
 #define MDIO_MMDREG_STAT1_FAULT_LBN	(7)
@@ -240,6 +243,10 @@
 /* Generic part of reconfigure: set/clear loopback bits */
 extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx);
 
+/* Set the power state of the specified MMDs */
+extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
+					  int low_power, unsigned int mmd_mask);
+
 /* Read (some of) the PHY settings over MDIO */
 extern void mdio_clause45_get_settings(struct efx_nic *efx,
 				       struct ethtool_cmd *ecmd);
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
new file mode 100644
index 0000000..a1e6c28
--- /dev/null
+++ b/drivers/net/sfc/mtd.c
@@ -0,0 +1,268 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2008 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/delay.h>
+
+#define EFX_DRIVER_NAME "sfc_mtd"
+#include "net_driver.h"
+#include "spi.h"
+
+#define EFX_SPI_VERIFY_BUF_LEN 16
+
+struct efx_mtd {
+	const struct efx_spi_device *spi;
+	struct mtd_info mtd;
+	char name[IFNAMSIZ + 20];
+};
+
+/* SPI utilities */
+
+static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
+{
+	const struct efx_spi_device *spi = efx_mtd->spi;
+	struct efx_nic *efx = spi->efx;
+	u8 status;
+	int rc, i;
+
+	/* Wait up to 4s for flash/EEPROM to finish a slow operation. */
+	for (i = 0; i < 40; i++) {
+		__set_current_state(uninterruptible ?
+				    TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 10);
+		rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
+				    &status, sizeof(status));
+		if (rc)
+			return rc;
+		if (!(status & SPI_STATUS_NRDY))
+			return 0;
+		if (signal_pending(current))
+			return -EINTR;
+	}
+	EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name);
+	return -ETIMEDOUT;
+}
+
+static int efx_spi_unlock(const struct efx_spi_device *spi)
+{
+	const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
+				SPI_STATUS_BP0);
+	u8 status;
+	int rc;
+
+	rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status));
+	if (rc)
+		return rc;
+
+	if (!(status & unlock_mask))
+		return 0; /* already unlocked */
+
+	rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+	if (rc)
+		return rc;
+	rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
+	if (rc)
+		return rc;
+
+	status &= ~unlock_mask;
+	rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status));
+	if (rc)
+		return rc;
+	rc = falcon_spi_fast_wait(spi);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
+{
+	const struct efx_spi_device *spi = efx_mtd->spi;
+	unsigned pos, block_len;
+	u8 empty[EFX_SPI_VERIFY_BUF_LEN];
+	u8 buffer[EFX_SPI_VERIFY_BUF_LEN];
+	int rc;
+
+	if (len != spi->erase_size)
+		return -EINVAL;
+
+	if (spi->erase_command == 0)
+		return -EOPNOTSUPP;
+
+	rc = efx_spi_unlock(spi);
+	if (rc)
+		return rc;
+	rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+	if (rc)
+		return rc;
+	rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0);
+	if (rc)
+		return rc;
+	rc = efx_spi_slow_wait(efx_mtd, false);
+
+	/* Verify the entire region has been wiped */
+	memset(empty, 0xff, sizeof(empty));
+	for (pos = 0; pos < len; pos += block_len) {
+		block_len = min(len - pos, sizeof(buffer));
+		rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer);
+		if (rc)
+			return rc;
+		if (memcmp(empty, buffer, block_len))
+			return -EIO;
+
+		/* Avoid locking up the system */
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+	}
+
+	return rc;
+}
+
+/* MTD interface */
+
+static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
+			size_t *retlen, u8 *buffer)
+{
+	struct efx_mtd *efx_mtd = mtd->priv;
+	const struct efx_spi_device *spi = efx_mtd->spi;
+	struct efx_nic *efx = spi->efx;
+	int rc;
+
+	rc = mutex_lock_interruptible(&efx->spi_lock);
+	if (rc)
+		return rc;
+	rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start,
+			     len, retlen, buffer);
+	mutex_unlock(&efx->spi_lock);
+	return rc;
+}
+
+static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->spi->efx;
+	int rc;
+
+	rc = mutex_lock_interruptible(&efx->spi_lock);
+	if (rc)
+		return rc;
+	rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr,
+			   erase->len);
+	mutex_unlock(&efx->spi_lock);
+
+	if (rc == 0) {
+		erase->state = MTD_ERASE_DONE;
+	} else {
+		erase->state = MTD_ERASE_FAILED;
+		erase->fail_addr = 0xffffffff;
+	}
+	mtd_erase_callback(erase);
+	return rc;
+}
+
+static int efx_mtd_write(struct mtd_info *mtd, loff_t start,
+			 size_t len, size_t *retlen, const u8 *buffer)
+{
+	struct efx_mtd *efx_mtd = mtd->priv;
+	const struct efx_spi_device *spi = efx_mtd->spi;
+	struct efx_nic *efx = spi->efx;
+	int rc;
+
+	rc = mutex_lock_interruptible(&efx->spi_lock);
+	if (rc)
+		return rc;
+	rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start,
+			      len, retlen, buffer);
+	mutex_unlock(&efx->spi_lock);
+	return rc;
+}
+
+static void efx_mtd_sync(struct mtd_info *mtd)
+{
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->spi->efx;
+	int rc;
+
+	mutex_lock(&efx->spi_lock);
+	rc = efx_spi_slow_wait(efx_mtd, true);
+	mutex_unlock(&efx->spi_lock);
+
+	if (rc)
+		EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
+	return;
+}
+
+void efx_mtd_remove(struct efx_nic *efx)
+{
+	if (efx->spi_flash && efx->spi_flash->mtd) {
+		struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
+		int rc;
+
+		for (;;) {
+			rc = del_mtd_device(&efx_mtd->mtd);
+			if (rc != -EBUSY)
+				break;
+			ssleep(1);
+		}
+		WARN_ON(rc);
+		kfree(efx_mtd);
+	}
+}
+
+void efx_mtd_rename(struct efx_nic *efx)
+{
+	if (efx->spi_flash && efx->spi_flash->mtd) {
+		struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
+		snprintf(efx_mtd->name, sizeof(efx_mtd->name),
+			 "%s sfc_flash_bootrom", efx->name);
+	}
+}
+
+int efx_mtd_probe(struct efx_nic *efx)
+{
+	struct efx_spi_device *spi = efx->spi_flash;
+	struct efx_mtd *efx_mtd;
+
+	if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
+		return -ENODEV;
+
+	efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
+	if (!efx_mtd)
+		return -ENOMEM;
+
+	efx_mtd->spi = spi;
+	spi->mtd = efx_mtd;
+
+	efx_mtd->mtd.type = MTD_NORFLASH;
+	efx_mtd->mtd.flags = MTD_CAP_NORFLASH;
+	efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
+	efx_mtd->mtd.erasesize = spi->erase_size;
+	efx_mtd->mtd.writesize = 1;
+	efx_mtd_rename(efx);
+
+	efx_mtd->mtd.owner = THIS_MODULE;
+	efx_mtd->mtd.priv = efx_mtd;
+	efx_mtd->mtd.name = efx_mtd->name;
+	efx_mtd->mtd.erase = efx_mtd_erase;
+	efx_mtd->mtd.read = efx_mtd_read;
+	efx_mtd->mtd.write = efx_mtd_write;
+	efx_mtd->mtd.sync = efx_mtd_sync;
+
+	if (add_mtd_device(&efx_mtd->mtd)) {
+		kfree(efx_mtd);
+		spi->mtd = NULL;
+		/* add_mtd_device() returns 1 if the MTD table is full */
+		return -ENOMEM;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index cdb11fa..e596c9a 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -414,6 +414,7 @@
  * @init_leds: Sets up board LEDs
  * @set_fault_led: Turns the fault LED on or off
  * @blink: Starts/stops blinking
+ * @monitor: Board-specific health check function
  * @fini: Cleanup function
  * @blinker: used to blink LEDs in software
  * @hwmon_client: I2C client for hardware monitor
@@ -428,6 +429,7 @@
 	 * have a separate init callback that happens later than
 	 * board init. */
 	int (*init_leds)(struct efx_nic *efx);
+	int (*monitor) (struct efx_nic *nic);
 	void (*set_fault_led) (struct efx_nic *efx, bool state);
 	void (*blink) (struct efx_nic *efx, bool start);
 	void (*fini) (struct efx_nic *nic);
@@ -525,11 +527,15 @@
  * @enum efx_phy_mode - PHY operating mode flags
  * @PHY_MODE_NORMAL: on and should pass traffic
  * @PHY_MODE_TX_DISABLED: on with TX disabled
+ * @PHY_MODE_LOW_POWER: set to low power through MDIO
+ * @PHY_MODE_OFF: switched off through external control
  * @PHY_MODE_SPECIAL: on but will not pass traffic
  */
 enum efx_phy_mode {
 	PHY_MODE_NORMAL		= 0,
 	PHY_MODE_TX_DISABLED	= 1,
+	PHY_MODE_LOW_POWER	= 2,
+	PHY_MODE_OFF		= 4,
 	PHY_MODE_SPECIAL	= 8,
 };
 
@@ -655,6 +661,7 @@
  *	This field will be %NULL if no flash device is present.
  * @spi_eeprom: SPI EEPROM device
  *	This field will be %NULL if no EEPROM device is present.
+ * @spi_lock: SPI bus lock
  * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
  * @nic_data: Hardware dependant state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
@@ -731,6 +738,7 @@
 
 	struct efx_spi_device *spi_flash;
 	struct efx_spi_device *spi_eeprom;
+	struct mutex spi_lock;
 
 	unsigned n_rx_nodesc_drop_cnt;
 
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 0f805da..b8ba4bb 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -752,7 +752,7 @@
 	channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
 
 done:
-	efx->net_dev->last_rx = jiffies;
+	;
 }
 
 void efx_rx_strategy(struct efx_channel *channel)
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index fe4e3fd..aa576c5 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -21,6 +21,7 @@
 #include "falcon_hwdefs.h"
 #include "falcon_io.h"
 #include "mac.h"
+#include "workarounds.h"
 
 /**************************************************************************
  *
@@ -65,48 +66,9 @@
 #define	P1_SPARE_LBN 4
 #define	P1_SPARE_WIDTH 4
 
-
-/**************************************************************************
- *
- * Temperature Sensor
- *
- **************************************************************************/
-#define	MAX6647	0x4e
-
-#define	RLTS	0x00
-#define	RLTE	0x01
-#define	RSL	0x02
-#define	RCL	0x03
-#define	RCRA	0x04
-#define	RLHN	0x05
-#define	RLLI	0x06
-#define	RRHI	0x07
-#define	RRLS	0x08
-#define	WCRW	0x0a
-#define	WLHO	0x0b
-#define	WRHA	0x0c
-#define	WRLN	0x0e
-#define	OSHT	0x0f
-#define	REET	0x10
-#define	RIET	0x11
-#define	RWOE	0x19
-#define	RWOI	0x20
-#define	HYS	0x21
-#define	QUEUE	0x22
-#define	MFID	0xfe
-#define	REVID	0xff
-
-/* Status bits */
-#define MAX6647_BUSY	(1 << 7)	/* ADC is converting */
-#define MAX6647_LHIGH	(1 << 6)	/* Local high temp. alarm */
-#define MAX6647_LLOW	(1 << 5)	/* Local low temp. alarm */
-#define MAX6647_RHIGH	(1 << 4)	/* Remote high temp. alarm */
-#define MAX6647_RLOW	(1 << 3)	/* Remote low temp. alarm */
-#define MAX6647_FAULT	(1 << 2)	/* DXN/DXP short/open circuit */
-#define MAX6647_EOT	(1 << 1)	/* Remote junction overtemp. */
-#define MAX6647_IOT	(1 << 0)	/* Local junction overtemp. */
-
-static const u8 xgphy_max_temperature = 90;
+/* Temperature Sensor */
+#define MAX664X_REG_RSL		0x02
+#define MAX664X_REG_WLHO	0x0B
 
 static void sfe4001_poweroff(struct efx_nic *efx)
 {
@@ -119,7 +81,7 @@
 	i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff);
 
 	/* Clear any over-temperature alert */
-	i2c_smbus_read_byte_data(hwmon_client, RSL);
+	i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
 }
 
 static int sfe4001_poweron(struct efx_nic *efx)
@@ -131,7 +93,7 @@
 	u8 out;
 
 	/* Clear any previous over-temperature alert */
-	rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
+	rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
 	if (rc < 0)
 		return rc;
 
@@ -209,6 +171,34 @@
 	return rc;
 }
 
+static int sfe4001_check_hw(struct efx_nic *efx)
+{
+	s32 status;
+
+	/* If XAUI link is up then do not monitor */
+	if (EFX_WORKAROUND_7884(efx) && falcon_xaui_link_ok(efx))
+		return 0;
+
+	/* Check the powered status of the PHY. Lack of power implies that
+	 * the MAX6647 has shut down power to it, probably due to a temp.
+	 * alarm. Reading the power status rather than the MAX6647 status
+	 * directly because the later is read-to-clear and would thus
+	 * start to power up the PHY again when polled, causing us to blip
+	 * the power undesirably.
+	 * We know we can read from the IO expander because we did
+	 * it during power-on. Assume failure now is bad news. */
+	status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN);
+	if (status >= 0 &&
+	    (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0)
+		return 0;
+
+	/* Use board power control, not PHY power control */
+	sfe4001_poweroff(efx);
+	efx->phy_mode = PHY_MODE_OFF;
+
+	return (status < 0) ? -EIO : -ERANGE;
+}
+
 /* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
  * using the 3V3X output of the IO-expander.  Allow the user to set
  * this when the device is stopped, and keep it stopped then.
@@ -261,35 +251,34 @@
 	i2c_unregister_device(efx->board_info.hwmon_client);
 }
 
+static struct i2c_board_info sfe4001_hwmon_info = {
+	I2C_BOARD_INFO("max6647", 0x4e),
+	.irq		= -1,
+};
+
 /* This board uses an I2C expander to provider power to the PHY, which needs to
  * be turned on before the PHY can be used.
  * Context: Process context, rtnl lock held
  */
 int sfe4001_init(struct efx_nic *efx)
 {
-	struct i2c_client *hwmon_client;
 	int rc;
 
-	hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647);
-	if (!hwmon_client)
+#if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE)
+	efx->board_info.hwmon_client =
+		i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
+#else
+	efx->board_info.hwmon_client =
+		i2c_new_dummy(&efx->i2c_adap, sfe4001_hwmon_info.addr);
+#endif
+	if (!efx->board_info.hwmon_client)
 		return -EIO;
-	efx->board_info.hwmon_client = hwmon_client;
 
-	/* Set DSP over-temperature alert threshold */
-	EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
-	rc = i2c_smbus_write_byte_data(hwmon_client, WLHO,
-				       xgphy_max_temperature);
+	/* Raise board/PHY high limit from 85 to 90 degrees Celsius */
+	rc = i2c_smbus_write_byte_data(efx->board_info.hwmon_client,
+				       MAX664X_REG_WLHO, 90);
 	if (rc)
-		goto fail_ioexp;
-
-	/* Read it back and verify */
-	rc = i2c_smbus_read_byte_data(hwmon_client, RLHN);
-	if (rc < 0)
-		goto fail_ioexp;
-	if (rc != xgphy_max_temperature) {
-		rc = -EFAULT;
-		goto fail_ioexp;
-	}
+		goto fail_hwmon;
 
 	efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
 	if (!efx->board_info.ioexp_client) {
@@ -301,6 +290,7 @@
 	 * blink code. */
 	efx->board_info.blink = tenxpress_phy_blink;
 
+	efx->board_info.monitor = sfe4001_check_hw;
 	efx->board_info.fini = sfe4001_fini;
 
 	rc = sfe4001_poweron(efx);
@@ -319,6 +309,6 @@
 fail_ioexp:
 	i2c_unregister_device(efx->board_info.ioexp_client);
 fail_hwmon:
-	i2c_unregister_device(hwmon_client);
+	i2c_unregister_device(efx->board_info.hwmon_client);
 	return rc;
 }
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
index feef619..c4aca13 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/sfc/spi.h
@@ -25,6 +25,7 @@
 #define SPI_WRDI 0x04		/* Reset write enable latch */
 #define SPI_RDSR 0x05		/* Read status register */
 #define SPI_WREN 0x06		/* Set write enable latch */
+#define SPI_SST_EWSR 0x50	/* SST: Enable write to status register */
 
 #define SPI_STATUS_WPEN 0x80	/* Write-protect pin enabled */
 #define SPI_STATUS_BP2 0x10	/* Block protection bit 2 */
@@ -36,6 +37,7 @@
 /**
  * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
  * @efx:		The Efx controller that owns this device
+ * @mtd:		MTD state
  * @device_id:		Controller's id for the device
  * @size:		Size (in bytes)
  * @addr_len:		Number of address bytes in read/write commands
@@ -44,23 +46,51 @@
  *	use bit 3 of the command byte as address bit A8, rather
  *	than having a two-byte address.  If this flag is set, then
  *	commands should be munged in this way.
+ * @erase_command:	Erase command (or 0 if sector erase not needed).
+ * @erase_size:		Erase sector size (in bytes)
+ *	Erase commands affect sectors with this size and alignment.
+ *	This must be a power of two.
  * @block_size:		Write block size (in bytes).
  *	Write commands are limited to blocks with this size and alignment.
- * @read:		Read function for the device
- * @write:		Write function for the device
  */
 struct efx_spi_device {
 	struct efx_nic *efx;
+#ifdef CONFIG_SFC_MTD
+	void *mtd;
+#endif
 	int device_id;
 	unsigned int size;
 	unsigned int addr_len;
 	unsigned int munge_address:1;
+	u8 erase_command;
+	unsigned int erase_size;
 	unsigned int block_size;
 };
 
+int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command,
+		   int address, const void* in, void *out, unsigned int len);
+int falcon_spi_fast_wait(const struct efx_spi_device *spi);
 int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
 		    size_t len, size_t *retlen, u8 *buffer);
 int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
 		     size_t len, size_t *retlen, const u8 *buffer);
 
+/*
+ * SFC4000 flash is partitioned into:
+ *     0-0x400       chip and board config (see falcon_hwdefs.h)
+ *     0x400-0x8000  unused (or may contain VPD if EEPROM not present)
+ *     0x8000-end    boot code (mapped to PCI expansion ROM)
+ * SFC4000 small EEPROM (size < 0x400) is used for VPD only.
+ * SFC4000 large EEPROM (size >= 0x400) is partitioned into:
+ *     0-0x400       chip and board config
+ *     configurable  VPD
+ *     0x800-0x1800  boot config
+ * Aside from the chip and board config, all of these are optional and may
+ * be absent or truncated depending on the devices used.
+ */
+#define FALCON_NVCONFIG_END 0x400U
+#define FALCON_FLASH_BOOTCODE_START 0x8000U
+#define EFX_EEPROM_BOOTCONFIG_START 0x800U
+#define EFX_EEPROM_BOOTCONFIG_END 0x1800U
+
 #endif /* EFX_SPI_H */
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index d507c93..8d41c29 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -376,6 +376,7 @@
 {
 	struct tenxpress_phy_data *phy_data = efx->phy_data;
 	bool link_ok;
+	int rc = 0;
 
 	link_ok = tenxpress_link_ok(efx, true);
 
@@ -391,7 +392,22 @@
 		atomic_set(&phy_data->bad_crc_count, 0);
 	}
 
-	return 0;
+	rc = efx->board_info.monitor(efx);
+	if (rc) {
+		EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
+			(rc == -ERANGE) ? "reported fault" : "failed");
+		if (efx->phy_mode & PHY_MODE_OFF) {
+			/* Assume that board has shut PHY off */
+			phy_data->phy_mode = PHY_MODE_OFF;
+		} else {
+			efx->phy_mode |= PHY_MODE_LOW_POWER;
+			mdio_clause45_set_mmds_lpower(efx, true,
+						      efx->phy_op->mmds);
+			phy_data->phy_mode |= PHY_MODE_LOW_POWER;
+		}
+	}
+
+	return rc;
 }
 
 static void tenxpress_phy_fini(struct efx_nic *efx)
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index fa7b49d..ec50b90 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -22,6 +22,8 @@
 #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
 /* RX PCIe double split performance issue */
 #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
+/* Bit-bashed I2C reads cause performance drop */
+#define EFX_WORKAROUND_7884 EFX_WORKAROUND_ALWAYS
 /* TX pkt parser problem with <= 16 byte TXes */
 #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
 /* Low rate CRC errors require XAUI reset */
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index 276151d..91f0246 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -128,6 +128,15 @@
 	if (link_up != efx->link_up)
 		falcon_xmac_sim_phy_event(efx);
 
+	rc = efx->board_info.monitor(efx);
+	if (rc) {
+		struct xfp_phy_data *phy_data = efx->phy_data;
+		EFX_ERR(efx, "XFP sensor alert; putting PHY into low power\n");
+		efx->phy_mode |= PHY_MODE_LOW_POWER;
+		mdio_clause45_set_mmds_lpower(efx, 1, XFP_REQUIRED_DEVS);
+		phy_data->phy_mode |= PHY_MODE_LOW_POWER;
+	}
+
 	return rc;
 }
 
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 6261201..cdffea6 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -377,7 +377,6 @@
 					skb_put(skb, len);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
-					dev->last_rx = jiffies;
 					dev->stats.rx_packets++;
 					dev->stats.rx_bytes += len;
 				} else {
@@ -719,7 +718,6 @@
 	struct sgiseeq_private *sp;
 	struct net_device *dev;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	dev = alloc_etherdev(sizeof (struct sgiseeq_private));
 	if (!dev) {
@@ -793,8 +791,7 @@
 		goto err_out_free_page;
 	}
 
-	printk(KERN_INFO "%s: %s %s\n",
-	       dev->name, sgiseeqstr, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a24bb68..077d796 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -540,7 +540,6 @@
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, ndev);
 			netif_rx(skb);
-			ndev->last_rx = jiffies;
 			mdp->stats.rx_packets++;
 			mdp->stats.rx_bytes += pkt_len;
 		}
@@ -800,7 +799,7 @@
 	char phy_id[BUS_ID_SIZE];
 	struct phy_device *phydev = NULL;
 
-	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
+	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
 		mdp->mii_bus->id , mdp->phy_id);
 
 	mdp->link = PHY_DOWN;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index e6e3bf5..83cc3c5 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -627,7 +627,6 @@
 
 			sis190_rx_skb(skb);
 
-			dev->last_rx = jiffies;
 			stats->rx_packets++;
 			stats->rx_bytes += pkt_size;
 			if ((status & BCAST) == MCAST)
@@ -1791,7 +1790,6 @@
 	struct net_device *dev;
 	void __iomem *ioaddr;
 	int rc;
-	DECLARE_MAC_BUF(mac);
 
 	if (!printed_version) {
 		net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
@@ -1841,10 +1839,9 @@
 	if (rc < 0)
 		goto err_remove_mii;
 
-	net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
-		  "%s\n",
+	net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), %pM\n",
 		  pci_name(pdev), sis_chip_info[ent->driver_data].name,
-		  ioaddr, dev->irq, print_mac(mac, dev->dev_addr));
+		  ioaddr, dev->irq, dev->dev_addr);
 
 	net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
 		  (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index fa3a460..28f6c04 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -404,7 +404,6 @@
 	int i, ret;
 	const char *card_name = card_names[pci_id->driver_data];
 	const char *dev_name = pci_name(pci_dev);
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -534,9 +533,9 @@
 		goto err_unmap_rx;
 
 	/* print some information about our NIC */
-	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %s\n",
+	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
 	       net_dev->name, card_name, ioaddr, net_dev->irq,
-	       print_mac(mac, net_dev->dev_addr));
+	       net_dev->dev_addr);
 
 	/* Detect Wake on Lan support */
 	ret = (inl(net_dev->base_addr + CFGPMC) & PMESP) >> 27;
@@ -1790,7 +1789,6 @@
 			/* some network statistics */
 			if ((rx_status & BCAST) == MCAST)
 				net_dev->stats.multicast++;
-			net_dev->last_rx = jiffies;
 			net_dev->stats.rx_bytes += rx_size;
 			net_dev->stats.rx_packets++;
 			sis_priv->dirty_rx++;
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index a2b092b..282bb47 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -1680,7 +1680,6 @@
 	skb->protocol = fddi_type_trans(skb, bp->dev);
 
 	netif_rx(skb);
-	bp->dev->last_rx = jiffies;
 
 	HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
 	return;
@@ -1939,7 +1938,6 @@
 
 	// deliver frame to system
 	skb->protocol = fddi_type_trans(skb, smc->os.dev);
-	skb->dev->last_rx = jiffies;
 	netif_rx(skb);
 
 	return (0);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 43f4c73..05f9d50 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -149,24 +149,6 @@
 	return WAKE_MAGIC | WAKE_PHY;
 }
 
-static u32 pci_wake_enabled(struct pci_dev *dev)
-{
-	int pm = pci_find_capability(dev, PCI_CAP_ID_PM);
-	u16 value;
-
-	/* If device doesn't support PM Capabilities, but request is to disable
-	 * wake events, it's a nop; otherwise fail */
-	if (!pm)
-		return 0;
-
-	pci_read_config_word(dev, pm + PCI_PM_PMC, &value);
-
-	value &= PCI_PM_CAP_PME_MASK;
-	value >>= ffs(PCI_PM_CAP_PME_MASK) - 1;   /* First bit of mask */
-
-	return value != 0;
-}
-
 static void skge_wol_init(struct skge_port *skge)
 {
 	struct skge_hw *hw = skge->hw;
@@ -254,10 +236,14 @@
 	struct skge_port *skge = netdev_priv(dev);
 	struct skge_hw *hw = skge->hw;
 
-	if (wol->wolopts & ~wol_supported(hw))
+	if ((wol->wolopts & ~wol_supported(hw))
+	    || !device_can_wakeup(&hw->pdev->dev))
 		return -EOPNOTSUPP;
 
 	skge->wol = wol->wolopts;
+
+	device_set_wakeup_enable(&hw->pdev->dev, skge->wol);
+
 	return 0;
 }
 
@@ -3200,7 +3186,6 @@
 
 		skb = skge_rx_get(dev, e, control, rd->status, rd->csum2);
 		if (likely(skb)) {
-			dev->last_rx = jiffies;
 			netif_receive_skb(skb);
 
 			++work_done;
@@ -3856,7 +3841,7 @@
 	skge->speed = -1;
 	skge->advertising = skge_supported_modes(hw);
 
-	if (pci_wake_enabled(hw->pdev))
+	if (device_may_wakeup(&hw->pdev->dev))
 		skge->wol = wol_supported(hw) & WAKE_MAGIC;
 
 	hw->dev[port] = dev;
@@ -3885,11 +3870,10 @@
 static void __devinit skge_show_addr(struct net_device *dev)
 {
 	const struct skge_port *skge = netdev_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	if (netif_msg_probe(skge))
-		printk(KERN_INFO PFX "%s: addr %s\n",
-		       dev->name, print_mac(mac, dev->dev_addr));
+		printk(KERN_INFO PFX "%s: addr %pM\n",
+		       dev->name, dev->dev_addr);
 }
 
 static int __devinit skge_probe(struct pci_dev *pdev,
@@ -4082,8 +4066,8 @@
 	}
 
 	skge_write32(hw, B0_IMSK, 0);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	pci_prepare_to_sleep(pdev);
 
 	return 0;
 }
@@ -4096,7 +4080,7 @@
 	if (!hw)
 		return 0;
 
-	err = pci_set_power_state(pdev, PCI_D0);
+	err = pci_back_from_sleep(pdev);
 	if (err)
 		goto out;
 
@@ -4104,8 +4088,6 @@
 	if (err)
 		goto out;
 
-	pci_enable_wake(pdev, PCI_D0, 0);
-
 	err = skge_reset(hw);
 	if (err)
 		goto out;
@@ -4146,8 +4128,8 @@
 		wol |= skge->wol;
 	}
 
-	pci_enable_wake(pdev, PCI_D3hot, wol);
-	pci_enable_wake(pdev, PCI_D3cold, wol);
+	if (pci_enable_wake(pdev, PCI_D3cold, wol))
+		pci_enable_wake(pdev, PCI_D3hot, wol);
 
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3813d15..4dcd1a6 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4118,11 +4118,10 @@
 static void __devinit sky2_show_addr(struct net_device *dev)
 {
 	const struct sky2_port *sky2 = netdev_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	if (netif_msg_probe(sky2))
-		printk(KERN_INFO PFX "%s: addr %s\n",
-		       dev->name, print_mac(mac, dev->dev_addr));
+		printk(KERN_INFO PFX "%s: addr %pM\n",
+		       dev->name, dev->dev_addr);
 }
 
 /* Handle software interrupt used during MSI test */
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 1d58991..25cec06 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -365,7 +365,6 @@
 	skb_reset_mac_header(skb);
 	skb->protocol = htons(ETH_P_IP);
 	netif_rx(skb);
-	sl->dev->last_rx = jiffies;
 	sl->rx_packets++;
 }
 
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index d6abb68..58a0e0a 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -196,7 +196,6 @@
 	int tirq = 0;
 	int base_addr = ultra_io[ultra_found];
 	int irq = ultra_irq[ultra_found];
-	DECLARE_MAC_BUF(mac);
 
 	if (base_addr || irq) {
 		printk(KERN_INFO "Probing for SMC MCA adapter");
@@ -334,8 +333,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-	printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %s",
-	       slot + 1, ioaddr, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM",
+	       slot + 1, ioaddr, dev->dev_addr);
 
 	/* Switch from the station address to the alternate register set
 	 * and read the useful registers there.
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 00d6cf1..0fe0251 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -198,7 +198,6 @@
 	unsigned char num_pages, irqreg, addr, piomode;
 	unsigned char idreg = inb(ioaddr + 7);
 	unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -228,8 +227,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-	printk("%s: %s at %#3x, %s", dev->name, model_name,
-	       ioaddr, print_mac(mac, dev->dev_addr));
+	printk("%s: %s at %#3x, %pM", dev->name, model_name,
+	       ioaddr, dev->dev_addr);
 
 	/* Switch from the station address to the alternate register set and
 	   read the useful registers there. */
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index a5a91ac..cb6c097 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -163,7 +163,6 @@
 	unsigned char idreg;
 	unsigned char reg4;
 	const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
-	DECLARE_MAC_BUF(mac);
 
 	if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -207,8 +206,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-	printk("%s: %s at 0x%X, %s",
-	       dev->name, model_name, ioaddr, print_mac(mac, dev->dev_addr));
+	printk("%s: %s at 0x%X, %pM",
+	       dev->name, model_name, ioaddr, dev->dev_addr);
 
 	/* Switch from the station address to the alternate register set and
 	   read the useful registers there. */
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 5051554..e0b972d 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -439,7 +439,6 @@
 
 		DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name);
 		PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
-		dev->last_rx = jiffies;
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
 		dev->stats.rx_packets++;
@@ -1231,7 +1230,6 @@
 	BUG_ON(skb == NULL);
 	lp->current_rx_skb = NULL;
 	PRINT_PKT(skb->data, skb->len);
-	dev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, dev);
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += skb->len;
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index de67744..e35fab1 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -876,8 +876,6 @@
 	word memory_info_register;
 	word memory_cfg_register;
 
-	DECLARE_MAC_BUF(mac);
-
 	/* Grab the region so that no one else tries to probe our ioports. */
 	if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
@@ -1033,7 +1031,7 @@
 	/*
 	 . Print the Ethernet address
 	*/
-	printk("ADDR: %s\n", print_mac(mac, dev->dev_addr));
+	printk("ADDR: %pM\n", dev->dev_addr);
 
 	/* set the private data to zero by default */
 	memset(dev->priv, 0, sizeof(struct smc_local));
@@ -1272,7 +1270,6 @@
 
 		skb->protocol = eth_type_trans(skb, dev );
 		netif_rx(skb);
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += packet_length;
 	} else {
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index fc80f25..5879c71 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -518,7 +518,6 @@
 
 		PRINT_PKT(data, packet_len - 4);
 
-		dev->last_rx = jiffies;
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
 		dev->stats.rx_packets++;
@@ -1778,7 +1777,6 @@
 	int retval;
 	unsigned int val, revision_register;
 	const char *version_string;
-	DECLARE_MAC_BUF(mac);
 
 	DBG(2, "%s: %s\n", CARDNAME, __func__);
 
@@ -1972,8 +1970,8 @@
 			       "set using ifconfig\n", dev->name);
 		} else {
 			/* Print the Ethernet address */
-			printk("%s: Ethernet addr: %s\n",
-			       dev->name, print_mac(mac, dev->dev_addr));
+			printk("%s: Ethernet addr: %pM\n",
+			       dev->name, dev->dev_addr);
 		}
 
 		if (lp->phy_type == 0) {
@@ -2126,7 +2124,7 @@
  *	0 --> there is a device
  *	anything else, error
  */
-static int smc_drv_probe(struct platform_device *pdev)
+static int __init smc_drv_probe(struct platform_device *pdev)
 {
 	struct smc91x_platdata *pd = pdev->dev.platform_data;
 	struct smc_local *lp;
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
new file mode 100644
index 0000000..fe51788
--- /dev/null
+++ b/drivers/net/smsc911x.c
@@ -0,0 +1,2091 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2004-2008 SMSC
+ * Copyright (C) 2005-2008 ARM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ ***************************************************************************
+ * Rewritten, heavily based on smsc911x simple driver by SMSC.
+ * Partly uses io macros from smc91x.c by Nicolas Pitre
+ *
+ * Supported devices:
+ *   LAN9115, LAN9116, LAN9117, LAN9118
+ *   LAN9215, LAN9216, LAN9217, LAN9218
+ *   LAN9210, LAN9211
+ *   LAN9220, LAN9221
+ *
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <linux/bug.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/smsc911x.h>
+#include "smsc911x.h"
+
+#define SMSC_CHIPNAME		"smsc911x"
+#define SMSC_MDIONAME		"smsc911x-mdio"
+#define SMSC_DRV_VERSION	"2008-10-21"
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SMSC_DRV_VERSION);
+
+#if USE_DEBUG > 0
+static int debug = 16;
+#else
+static int debug = 3;
+#endif
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+struct smsc911x_data {
+	void __iomem *ioaddr;
+
+	unsigned int idrev;
+
+	/* used to decide which workarounds apply */
+	unsigned int generation;
+
+	/* device configuration (copied from platform_data during probe) */
+	unsigned int irq_polarity;
+	unsigned int irq_type;
+	phy_interface_t phy_interface;
+
+	/* This needs to be acquired before calling any of below:
+	 * smsc911x_mac_read(), smsc911x_mac_write()
+	 */
+	spinlock_t mac_lock;
+
+#if (!SMSC_CAN_USE_32BIT)
+	/* spinlock to ensure 16-bit accesses are serialised */
+	spinlock_t dev_lock;
+#endif
+
+	struct phy_device *phy_dev;
+	struct mii_bus *mii_bus;
+	int phy_irq[PHY_MAX_ADDR];
+	unsigned int using_extphy;
+	int last_duplex;
+	int last_carrier;
+
+	u32 msg_enable;
+	unsigned int gpio_setting;
+	unsigned int gpio_orig_setting;
+	struct net_device *dev;
+	struct napi_struct napi;
+
+	unsigned int software_irq_signal;
+
+#ifdef USE_PHY_WORK_AROUND
+#define MIN_PACKET_SIZE (64)
+	char loopback_tx_pkt[MIN_PACKET_SIZE];
+	char loopback_rx_pkt[MIN_PACKET_SIZE];
+	unsigned int resetcount;
+#endif
+
+	/* Members for Multicast filter workaround */
+	unsigned int multicast_update_pending;
+	unsigned int set_bits_mask;
+	unsigned int clear_bits_mask;
+	unsigned int hashhi;
+	unsigned int hashlo;
+};
+
+#if SMSC_CAN_USE_32BIT
+
+static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
+{
+	return readl(pdata->ioaddr + reg);
+}
+
+static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
+				      u32 val)
+{
+	writel(val, pdata->ioaddr + reg);
+}
+
+/* Writes a packet to the TX_DATA_FIFO */
+static inline void
+smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
+		      unsigned int wordcount)
+{
+	writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
+}
+
+/* Reads a packet out of the RX_DATA_FIFO */
+static inline void
+smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
+		     unsigned int wordcount)
+{
+	readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
+}
+
+#else				/* SMSC_CAN_USE_32BIT */
+
+/* These 16-bit access functions are significantly slower, due to the locking
+ * necessary.  If your bus hardware can be configured to do this for you
+ * (in response to a single 32-bit operation from software), you should use
+ * the 32-bit access functions instead. */
+
+static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
+{
+	unsigned long flags;
+	u32 data;
+
+	/* these two 16-bit reads must be performed consecutively, so must
+	 * not be interrupted by our own ISR (which would start another
+	 * read operation) */
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+	data = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
+		((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
+
+	return data;
+}
+
+static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
+				      u32 val)
+{
+	unsigned long flags;
+
+	/* these two 16-bit writes must be performed consecutively, so must
+	 * not be interrupted by our own ISR (which would start another
+	 * read operation) */
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+	writew(val & 0xFFFF, pdata->ioaddr + reg);
+	writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
+}
+
+/* Writes a packet to the TX_DATA_FIFO */
+static inline void
+smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
+		      unsigned int wordcount)
+{
+	while (wordcount--)
+		smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
+}
+
+/* Reads a packet out of the RX_DATA_FIFO */
+static inline void
+smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
+		     unsigned int wordcount)
+{
+	while (wordcount--)
+		*buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
+}
+
+#endif				/* SMSC_CAN_USE_32BIT */
+
+/* waits for MAC not busy, with timeout.  Only called by smsc911x_mac_read
+ * and smsc911x_mac_write, so assumes mac_lock is held */
+static int smsc911x_mac_complete(struct smsc911x_data *pdata)
+{
+	int i;
+	u32 val;
+
+	SMSC_ASSERT_MAC_LOCK(pdata);
+
+	for (i = 0; i < 40; i++) {
+		val = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+		if (!(val & MAC_CSR_CMD_CSR_BUSY_))
+			return 0;
+	}
+	SMSC_WARNING(HW, "Timed out waiting for MAC not BUSY. "
+		"MAC_CSR_CMD: 0x%08X", val);
+	return -EIO;
+}
+
+/* Fetches a MAC register value. Assumes mac_lock is acquired */
+static u32 smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset)
+{
+	unsigned int temp;
+
+	SMSC_ASSERT_MAC_LOCK(pdata);
+
+	temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+	if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
+		SMSC_WARNING(HW, "MAC busy at entry");
+		return 0xFFFFFFFF;
+	}
+
+	/* Send the MAC cmd */
+	smsc911x_reg_write(pdata, MAC_CSR_CMD, ((offset & 0xFF) |
+		MAC_CSR_CMD_CSR_BUSY_ | MAC_CSR_CMD_R_NOT_W_));
+
+	/* Workaround for hardware read-after-write restriction */
+	temp = smsc911x_reg_read(pdata, BYTE_TEST);
+
+	/* Wait for the read to complete */
+	if (likely(smsc911x_mac_complete(pdata) == 0))
+		return smsc911x_reg_read(pdata, MAC_CSR_DATA);
+
+	SMSC_WARNING(HW, "MAC busy after read");
+	return 0xFFFFFFFF;
+}
+
+/* Set a mac register, mac_lock must be acquired before calling */
+static void smsc911x_mac_write(struct smsc911x_data *pdata,
+			       unsigned int offset, u32 val)
+{
+	unsigned int temp;
+
+	SMSC_ASSERT_MAC_LOCK(pdata);
+
+	temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+	if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
+		SMSC_WARNING(HW,
+			"smsc911x_mac_write failed, MAC busy at entry");
+		return;
+	}
+
+	/* Send data to write */
+	smsc911x_reg_write(pdata, MAC_CSR_DATA, val);
+
+	/* Write the actual data */
+	smsc911x_reg_write(pdata, MAC_CSR_CMD, ((offset & 0xFF) |
+		MAC_CSR_CMD_CSR_BUSY_));
+
+	/* Workaround for hardware read-after-write restriction */
+	temp = smsc911x_reg_read(pdata, BYTE_TEST);
+
+	/* Wait for the write to complete */
+	if (likely(smsc911x_mac_complete(pdata) == 0))
+		return;
+
+	SMSC_WARNING(HW,
+		"smsc911x_mac_write failed, MAC busy after write");
+}
+
+/* Get a phy register */
+static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
+{
+	struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv;
+	unsigned long flags;
+	unsigned int addr;
+	int i, reg;
+
+	spin_lock_irqsave(&pdata->mac_lock, flags);
+
+	/* Confirm MII not busy */
+	if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+		SMSC_WARNING(HW,
+			"MII is busy in smsc911x_mii_read???");
+		reg = -EIO;
+		goto out;
+	}
+
+	/* Set the address, index & direction (read from PHY) */
+	addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6);
+	smsc911x_mac_write(pdata, MII_ACC, addr);
+
+	/* Wait for read to complete w/ timeout */
+	for (i = 0; i < 100; i++)
+		if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+			reg = smsc911x_mac_read(pdata, MII_DATA);
+			goto out;
+		}
+
+	SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
+	reg = -EIO;
+
+out:
+	spin_unlock_irqrestore(&pdata->mac_lock, flags);
+	return reg;
+}
+
+/* Set a phy register */
+static int smsc911x_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+			   u16 val)
+{
+	struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv;
+	unsigned long flags;
+	unsigned int addr;
+	int i, reg;
+
+	spin_lock_irqsave(&pdata->mac_lock, flags);
+
+	/* Confirm MII not busy */
+	if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+		SMSC_WARNING(HW,
+			"MII is busy in smsc911x_mii_write???");
+		reg = -EIO;
+		goto out;
+	}
+
+	/* Put the data to write in the MAC */
+	smsc911x_mac_write(pdata, MII_DATA, val);
+
+	/* Set the address, index & direction (write to PHY) */
+	addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6) |
+		MII_ACC_MII_WRITE_;
+	smsc911x_mac_write(pdata, MII_ACC, addr);
+
+	/* Wait for write to complete w/ timeout */
+	for (i = 0; i < 100; i++)
+		if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+			reg = 0;
+			goto out;
+		}
+
+	SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
+	reg = -EIO;
+
+out:
+	spin_unlock_irqrestore(&pdata->mac_lock, flags);
+	return reg;
+}
+
+/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors.
+ * If something goes wrong, returns -ENODEV to revert back to internal phy.
+ * Performed at initialisation only, so interrupts are enabled */
+static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata)
+{
+	unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG);
+
+	/* External phy is requested, supported, and detected */
+	if (hwcfg & HW_CFG_EXT_PHY_DET_) {
+
+		/* Switch to external phy. Assuming tx and rx are stopped
+		 * because smsc911x_phy_initialise is called before
+		 * smsc911x_rx_initialise and tx_initialise. */
+
+		/* Disable phy clocks to the MAC */
+		hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
+		hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
+		smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+		udelay(10);	/* Enough time for clocks to stop */
+
+		/* Switch to external phy */
+		hwcfg |= HW_CFG_EXT_PHY_EN_;
+		smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+
+		/* Enable phy clocks to the MAC */
+		hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
+		hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
+		smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+		udelay(10);	/* Enough time for clocks to restart */
+
+		hwcfg |= HW_CFG_SMI_SEL_;
+		smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+
+		SMSC_TRACE(HW, "Successfully switched to external PHY");
+		pdata->using_extphy = 1;
+	} else {
+		SMSC_WARNING(HW, "No external PHY detected, "
+			"Using internal PHY instead.");
+		/* Use internal phy */
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/* Fetches a tx status out of the status fifo */
+static unsigned int smsc911x_tx_get_txstatus(struct smsc911x_data *pdata)
+{
+	unsigned int result =
+	    smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TSUSED_;
+
+	if (result != 0)
+		result = smsc911x_reg_read(pdata, TX_STATUS_FIFO);
+
+	return result;
+}
+
+/* Fetches the next rx status */
+static unsigned int smsc911x_rx_get_rxstatus(struct smsc911x_data *pdata)
+{
+	unsigned int result =
+	    smsc911x_reg_read(pdata, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED_;
+
+	if (result != 0)
+		result = smsc911x_reg_read(pdata, RX_STATUS_FIFO);
+
+	return result;
+}
+
+#ifdef USE_PHY_WORK_AROUND
+static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata)
+{
+	unsigned int tries;
+	u32 wrsz;
+	u32 rdsz;
+	ulong bufp;
+
+	for (tries = 0; tries < 10; tries++) {
+		unsigned int txcmd_a;
+		unsigned int txcmd_b;
+		unsigned int status;
+		unsigned int pktlength;
+		unsigned int i;
+
+		/* Zero-out rx packet memory */
+		memset(pdata->loopback_rx_pkt, 0, MIN_PACKET_SIZE);
+
+		/* Write tx packet to 118 */
+		txcmd_a = (u32)((ulong)pdata->loopback_tx_pkt & 0x03) << 16;
+		txcmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
+		txcmd_a |= MIN_PACKET_SIZE;
+
+		txcmd_b = MIN_PACKET_SIZE << 16 | MIN_PACKET_SIZE;
+
+		smsc911x_reg_write(pdata, TX_DATA_FIFO, txcmd_a);
+		smsc911x_reg_write(pdata, TX_DATA_FIFO, txcmd_b);
+
+		bufp = (ulong)pdata->loopback_tx_pkt & (~0x3);
+		wrsz = MIN_PACKET_SIZE + 3;
+		wrsz += (u32)((ulong)pdata->loopback_tx_pkt & 0x3);
+		wrsz >>= 2;
+
+		smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
+
+		/* Wait till transmit is done */
+		i = 60;
+		do {
+			udelay(5);
+			status = smsc911x_tx_get_txstatus(pdata);
+		} while ((i--) && (!status));
+
+		if (!status) {
+			SMSC_WARNING(HW, "Failed to transmit "
+				"during loopback test");
+			continue;
+		}
+		if (status & TX_STS_ES_) {
+			SMSC_WARNING(HW, "Transmit encountered "
+				"errors during loopback test");
+			continue;
+		}
+
+		/* Wait till receive is done */
+		i = 60;
+		do {
+			udelay(5);
+			status = smsc911x_rx_get_rxstatus(pdata);
+		} while ((i--) && (!status));
+
+		if (!status) {
+			SMSC_WARNING(HW,
+				"Failed to receive during loopback test");
+			continue;
+		}
+		if (status & RX_STS_ES_) {
+			SMSC_WARNING(HW, "Receive encountered "
+				"errors during loopback test");
+			continue;
+		}
+
+		pktlength = ((status & 0x3FFF0000UL) >> 16);
+		bufp = (ulong)pdata->loopback_rx_pkt;
+		rdsz = pktlength + 3;
+		rdsz += (u32)((ulong)pdata->loopback_rx_pkt & 0x3);
+		rdsz >>= 2;
+
+		smsc911x_rx_readfifo(pdata, (unsigned int *)bufp, rdsz);
+
+		if (pktlength != (MIN_PACKET_SIZE + 4)) {
+			SMSC_WARNING(HW, "Unexpected packet size "
+				"during loop back test, size=%d, will retry",
+				pktlength);
+		} else {
+			unsigned int j;
+			int mismatch = 0;
+			for (j = 0; j < MIN_PACKET_SIZE; j++) {
+				if (pdata->loopback_tx_pkt[j]
+				    != pdata->loopback_rx_pkt[j]) {
+					mismatch = 1;
+					break;
+				}
+			}
+			if (!mismatch) {
+				SMSC_TRACE(HW, "Successfully verified "
+					   "loopback packet");
+				return 0;
+			} else {
+				SMSC_WARNING(HW, "Data mismatch "
+					"during loop back test, will retry");
+			}
+		}
+	}
+
+	return -EIO;
+}
+
+static int smsc911x_phy_reset(struct smsc911x_data *pdata)
+{
+	struct phy_device *phy_dev = pdata->phy_dev;
+	unsigned int temp;
+	unsigned int i = 100000;
+
+	BUG_ON(!phy_dev);
+	BUG_ON(!phy_dev->bus);
+
+	SMSC_TRACE(HW, "Performing PHY BCR Reset");
+	smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET);
+	do {
+		msleep(1);
+		temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr,
+			MII_BMCR);
+	} while ((i--) && (temp & BMCR_RESET));
+
+	if (temp & BMCR_RESET) {
+		SMSC_WARNING(HW, "PHY reset failed to complete.");
+		return -EIO;
+	}
+	/* Extra delay required because the phy may not be completed with
+	* its reset when BMCR_RESET is cleared. Specs say 256 uS is
+	* enough delay but using 1ms here to be safe */
+	msleep(1);
+
+	return 0;
+}
+
+static int smsc911x_phy_loopbacktest(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	struct phy_device *phy_dev = pdata->phy_dev;
+	int result = -EIO;
+	unsigned int i, val;
+	unsigned long flags;
+
+	/* Initialise tx packet using broadcast destination address */
+	memset(pdata->loopback_tx_pkt, 0xff, ETH_ALEN);
+
+	/* Use incrementing source address */
+	for (i = 6; i < 12; i++)
+		pdata->loopback_tx_pkt[i] = (char)i;
+
+	/* Set length type field */
+	pdata->loopback_tx_pkt[12] = 0x00;
+	pdata->loopback_tx_pkt[13] = 0x00;
+
+	for (i = 14; i < MIN_PACKET_SIZE; i++)
+		pdata->loopback_tx_pkt[i] = (char)i;
+
+	val = smsc911x_reg_read(pdata, HW_CFG);
+	val &= HW_CFG_TX_FIF_SZ_;
+	val |= HW_CFG_SF_;
+	smsc911x_reg_write(pdata, HW_CFG, val);
+
+	smsc911x_reg_write(pdata, TX_CFG, TX_CFG_TX_ON_);
+	smsc911x_reg_write(pdata, RX_CFG,
+		(u32)((ulong)pdata->loopback_rx_pkt & 0x03) << 8);
+
+	for (i = 0; i < 10; i++) {
+		/* Set PHY to 10/FD, no ANEG, and loopback mode */
+		smsc911x_mii_write(phy_dev->bus, phy_dev->addr,	MII_BMCR,
+			BMCR_LOOPBACK | BMCR_FULLDPLX);
+
+		/* Enable MAC tx/rx, FD */
+		spin_lock_irqsave(&pdata->mac_lock, flags);
+		smsc911x_mac_write(pdata, MAC_CR, MAC_CR_FDPX_
+				   | MAC_CR_TXEN_ | MAC_CR_RXEN_);
+		spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+		if (smsc911x_phy_check_loopbackpkt(pdata) == 0) {
+			result = 0;
+			break;
+		}
+		pdata->resetcount++;
+
+		/* Disable MAC rx */
+		spin_lock_irqsave(&pdata->mac_lock, flags);
+		smsc911x_mac_write(pdata, MAC_CR, 0);
+		spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+		smsc911x_phy_reset(pdata);
+	}
+
+	/* Disable MAC */
+	spin_lock_irqsave(&pdata->mac_lock, flags);
+	smsc911x_mac_write(pdata, MAC_CR, 0);
+	spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+	/* Cancel PHY loopback mode */
+	smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, 0);
+
+	smsc911x_reg_write(pdata, TX_CFG, 0);
+	smsc911x_reg_write(pdata, RX_CFG, 0);
+
+	return result;
+}
+#endif				/* USE_PHY_WORK_AROUND */
+
+static u8 smsc95xx_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv)
+{
+	u8 cap = 0;
+
+	if (lcladv & ADVERTISE_PAUSE_CAP) {
+		if (lcladv & ADVERTISE_PAUSE_ASYM) {
+			if (rmtadv & LPA_PAUSE_CAP)
+				cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+			else if (rmtadv & LPA_PAUSE_ASYM)
+				cap = FLOW_CTRL_RX;
+		} else {
+			if (rmtadv & LPA_PAUSE_CAP)
+				cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+		}
+	} else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+		if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+			cap = FLOW_CTRL_TX;
+	}
+
+	return cap;
+}
+
+static void smsc911x_phy_update_flowcontrol(struct smsc911x_data *pdata)
+{
+	struct phy_device *phy_dev = pdata->phy_dev;
+	u32 afc = smsc911x_reg_read(pdata, AFC_CFG);
+	u32 flow;
+	unsigned long flags;
+
+	if (phy_dev->duplex == DUPLEX_FULL) {
+		u16 lcladv = phy_read(phy_dev, MII_ADVERTISE);
+		u16 rmtadv = phy_read(phy_dev, MII_LPA);
+		u8 cap = smsc95xx_resolve_flowctrl_fulldplx(lcladv, rmtadv);
+
+		if (cap & FLOW_CTRL_RX)
+			flow = 0xFFFF0002;
+		else
+			flow = 0;
+
+		if (cap & FLOW_CTRL_TX)
+			afc |= 0xF;
+		else
+			afc &= ~0xF;
+
+		SMSC_TRACE(HW, "rx pause %s, tx pause %s",
+			(cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+			(cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+	} else {
+		SMSC_TRACE(HW, "half duplex");
+		flow = 0;
+		afc |= 0xF;
+	}
+
+	spin_lock_irqsave(&pdata->mac_lock, flags);
+	smsc911x_mac_write(pdata, FLOW, flow);
+	spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+	smsc911x_reg_write(pdata, AFC_CFG, afc);
+}
+
+/* Update link mode if anything has changed.  Called periodically when the
+ * PHY is in polling mode, even if nothing has changed. */
+static void smsc911x_phy_adjust_link(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	struct phy_device *phy_dev = pdata->phy_dev;
+	unsigned long flags;
+	int carrier;
+
+	if (phy_dev->duplex != pdata->last_duplex) {
+		unsigned int mac_cr;
+		SMSC_TRACE(HW, "duplex state has changed");
+
+		spin_lock_irqsave(&pdata->mac_lock, flags);
+		mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+		if (phy_dev->duplex) {
+			SMSC_TRACE(HW,
+				"configuring for full duplex mode");
+			mac_cr |= MAC_CR_FDPX_;
+		} else {
+			SMSC_TRACE(HW,
+				"configuring for half duplex mode");
+			mac_cr &= ~MAC_CR_FDPX_;
+		}
+		smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+		spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+		smsc911x_phy_update_flowcontrol(pdata);
+		pdata->last_duplex = phy_dev->duplex;
+	}
+
+	carrier = netif_carrier_ok(dev);
+	if (carrier != pdata->last_carrier) {
+		SMSC_TRACE(HW, "carrier state has changed");
+		if (carrier) {
+			SMSC_TRACE(HW, "configuring for carrier OK");
+			if ((pdata->gpio_orig_setting & GPIO_CFG_LED1_EN_) &&
+			    (!pdata->using_extphy)) {
+				/* Restore orginal GPIO configuration */
+				pdata->gpio_setting = pdata->gpio_orig_setting;
+				smsc911x_reg_write(pdata, GPIO_CFG,
+					pdata->gpio_setting);
+			}
+		} else {
+			SMSC_TRACE(HW, "configuring for no carrier");
+			/* Check global setting that LED1
+			 * usage is 10/100 indicator */
+			pdata->gpio_setting = smsc911x_reg_read(pdata,
+				GPIO_CFG);
+			if ((pdata->gpio_setting & GPIO_CFG_LED1_EN_)
+			    && (!pdata->using_extphy)) {
+				/* Force 10/100 LED off, after saving
+				 * orginal GPIO configuration */
+				pdata->gpio_orig_setting = pdata->gpio_setting;
+
+				pdata->gpio_setting &= ~GPIO_CFG_LED1_EN_;
+				pdata->gpio_setting |= (GPIO_CFG_GPIOBUF0_
+							| GPIO_CFG_GPIODIR0_
+							| GPIO_CFG_GPIOD0_);
+				smsc911x_reg_write(pdata, GPIO_CFG,
+					pdata->gpio_setting);
+			}
+		}
+		pdata->last_carrier = carrier;
+	}
+}
+
+static int smsc911x_mii_probe(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	int phy_addr;
+
+	/* find the first phy */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (pdata->mii_bus->phy_map[phy_addr]) {
+			phydev = pdata->mii_bus->phy_map[phy_addr];
+			SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X",
+				phy_addr, phydev->addr, phydev->phy_id);
+			break;
+		}
+	}
+
+	if (!phydev) {
+		pr_err("%s: no PHY found\n", dev->name);
+		return -ENODEV;
+	}
+
+	phydev = phy_connect(dev, phydev->dev.bus_id,
+		&smsc911x_phy_adjust_link, 0, pdata->phy_interface);
+
+	if (IS_ERR(phydev)) {
+		pr_err("%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
+
+	pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+		dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
+	/* mask with MAC supported features */
+	phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+			      SUPPORTED_Asym_Pause);
+	phydev->advertising = phydev->supported;
+
+	pdata->phy_dev = phydev;
+	pdata->last_duplex = -1;
+	pdata->last_carrier = -1;
+
+#ifdef USE_PHY_WORK_AROUND
+	if (smsc911x_phy_loopbacktest(dev) < 0) {
+		SMSC_WARNING(HW, "Failed Loop Back Test");
+		return -ENODEV;
+	}
+	SMSC_TRACE(HW, "Passed Loop Back Test");
+#endif				/* USE_PHY_WORK_AROUND */
+
+	SMSC_TRACE(HW, "phy initialised succesfully");
+	return 0;
+}
+
+static int __devinit smsc911x_mii_init(struct platform_device *pdev,
+				       struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	int err = -ENXIO, i;
+
+	pdata->mii_bus = mdiobus_alloc();
+	if (!pdata->mii_bus) {
+		err = -ENOMEM;
+		goto err_out_1;
+	}
+
+	pdata->mii_bus->name = SMSC_MDIONAME;
+	snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+	pdata->mii_bus->priv = pdata;
+	pdata->mii_bus->read = smsc911x_mii_read;
+	pdata->mii_bus->write = smsc911x_mii_write;
+	pdata->mii_bus->irq = pdata->phy_irq;
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		pdata->mii_bus->irq[i] = PHY_POLL;
+
+	pdata->mii_bus->parent = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, &pdata->mii_bus);
+
+	pdata->using_extphy = 0;
+
+	switch (pdata->idrev & 0xFFFF0000) {
+	case 0x01170000:
+	case 0x01150000:
+	case 0x117A0000:
+	case 0x115A0000:
+		/* External PHY supported, try to autodetect */
+		if (smsc911x_phy_initialise_external(pdata) < 0) {
+			SMSC_TRACE(HW, "No external PHY detected, "
+				"using internal PHY");
+		}
+		break;
+	default:
+		SMSC_TRACE(HW, "External PHY is not supported, "
+			"using internal PHY");
+		break;
+	}
+
+	if (!pdata->using_extphy) {
+		/* Mask all PHYs except ID 1 (internal) */
+		pdata->mii_bus->phy_mask = ~(1 << 1);
+	}
+
+	if (mdiobus_register(pdata->mii_bus)) {
+		SMSC_WARNING(PROBE, "Error registering mii bus");
+		goto err_out_free_bus_2;
+	}
+
+	if (smsc911x_mii_probe(dev) < 0) {
+		SMSC_WARNING(PROBE, "Error registering mii bus");
+		goto err_out_unregister_bus_3;
+	}
+
+	return 0;
+
+err_out_unregister_bus_3:
+	mdiobus_unregister(pdata->mii_bus);
+err_out_free_bus_2:
+	mdiobus_free(pdata->mii_bus);
+err_out_1:
+	return err;
+}
+
+/* Gets the number of tx statuses in the fifo */
+static unsigned int smsc911x_tx_get_txstatcount(struct smsc911x_data *pdata)
+{
+	return (smsc911x_reg_read(pdata, TX_FIFO_INF)
+		& TX_FIFO_INF_TSUSED_) >> 16;
+}
+
+/* Reads tx statuses and increments counters where necessary */
+static void smsc911x_tx_update_txcounters(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int tx_stat;
+
+	while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
+		if (unlikely(tx_stat & 0x80000000)) {
+			/* In this driver the packet tag is used as the packet
+			 * length. Since a packet length can never reach the
+			 * size of 0x8000, this bit is reserved. It is worth
+			 * noting that the "reserved bit" in the warning above
+			 * does not reference a hardware defined reserved bit
+			 * but rather a driver defined one.
+			 */
+			SMSC_WARNING(HW,
+				"Packet tag reserved bit is high");
+		} else {
+			if (unlikely(tx_stat & 0x00008000)) {
+				dev->stats.tx_errors++;
+			} else {
+				dev->stats.tx_packets++;
+				dev->stats.tx_bytes += (tx_stat >> 16);
+			}
+			if (unlikely(tx_stat & 0x00000100)) {
+				dev->stats.collisions += 16;
+				dev->stats.tx_aborted_errors += 1;
+			} else {
+				dev->stats.collisions +=
+				    ((tx_stat >> 3) & 0xF);
+			}
+			if (unlikely(tx_stat & 0x00000800))
+				dev->stats.tx_carrier_errors += 1;
+			if (unlikely(tx_stat & 0x00000200)) {
+				dev->stats.collisions++;
+				dev->stats.tx_aborted_errors++;
+			}
+		}
+	}
+}
+
+/* Increments the Rx error counters */
+static void
+smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
+{
+	int crc_err = 0;
+
+	if (unlikely(rxstat & 0x00008000)) {
+		dev->stats.rx_errors++;
+		if (unlikely(rxstat & 0x00000002)) {
+			dev->stats.rx_crc_errors++;
+			crc_err = 1;
+		}
+	}
+	if (likely(!crc_err)) {
+		if (unlikely((rxstat & 0x00001020) == 0x00001020)) {
+			/* Frame type indicates length,
+			 * and length error is set */
+			dev->stats.rx_length_errors++;
+		}
+		if (rxstat & RX_STS_MCAST_)
+			dev->stats.multicast++;
+	}
+}
+
+/* Quickly dumps bad packets */
+static void
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+{
+	unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
+
+	if (likely(pktwords >= 4)) {
+		unsigned int timeout = 500;
+		unsigned int val;
+		smsc911x_reg_write(pdata, RX_DP_CTRL, RX_DP_CTRL_RX_FFWD_);
+		do {
+			udelay(1);
+			val = smsc911x_reg_read(pdata, RX_DP_CTRL);
+		} while (timeout-- && (val & RX_DP_CTRL_RX_FFWD_));
+
+		if (unlikely(timeout == 0))
+			SMSC_WARNING(HW, "Timed out waiting for "
+				"RX FFWD to finish, RX_DP_CTRL: 0x%08X", val);
+	} else {
+		unsigned int temp;
+		while (pktwords--)
+			temp = smsc911x_reg_read(pdata, RX_DATA_FIFO);
+	}
+}
+
+/* NAPI poll function */
+static int smsc911x_poll(struct napi_struct *napi, int budget)
+{
+	struct smsc911x_data *pdata =
+		container_of(napi, struct smsc911x_data, napi);
+	struct net_device *dev = pdata->dev;
+	int npackets = 0;
+
+	while (likely(netif_running(dev)) && (npackets < budget)) {
+		unsigned int pktlength;
+		unsigned int pktwords;
+		struct sk_buff *skb;
+		unsigned int rxstat = smsc911x_rx_get_rxstatus(pdata);
+
+		if (!rxstat) {
+			unsigned int temp;
+			/* We processed all packets available.  Tell NAPI it can
+			 * stop polling then re-enable rx interrupts */
+			smsc911x_reg_write(pdata, INT_STS, INT_STS_RSFL_);
+			netif_rx_complete(dev, napi);
+			temp = smsc911x_reg_read(pdata, INT_EN);
+			temp |= INT_EN_RSFL_EN_;
+			smsc911x_reg_write(pdata, INT_EN, temp);
+			break;
+		}
+
+		/* Count packet for NAPI scheduling, even if it has an error.
+		 * Error packets still require cycles to discard */
+		npackets++;
+
+		pktlength = ((rxstat & 0x3FFF0000) >> 16);
+		pktwords = (pktlength + NET_IP_ALIGN + 3) >> 2;
+		smsc911x_rx_counterrors(dev, rxstat);
+
+		if (unlikely(rxstat & RX_STS_ES_)) {
+			SMSC_WARNING(RX_ERR,
+				"Discarding packet with error bit set");
+			/* Packet has an error, discard it and continue with
+			 * the next */
+			smsc911x_rx_fastforward(pdata, pktwords);
+			dev->stats.rx_dropped++;
+			continue;
+		}
+
+		skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+		if (unlikely(!skb)) {
+			SMSC_WARNING(RX_ERR,
+				"Unable to allocate skb for rx packet");
+			/* Drop the packet and stop this polling iteration */
+			smsc911x_rx_fastforward(pdata, pktwords);
+			dev->stats.rx_dropped++;
+			break;
+		}
+
+		skb->data = skb->head;
+		skb_reset_tail_pointer(skb);
+
+		/* Align IP on 16B boundary */
+		skb_reserve(skb, NET_IP_ALIGN);
+		skb_put(skb, pktlength - 4);
+		smsc911x_rx_readfifo(pdata, (unsigned int *)skb->head,
+				     pktwords);
+		skb->protocol = eth_type_trans(skb, dev);
+		skb->ip_summed = CHECKSUM_NONE;
+		netif_receive_skb(skb);
+
+		/* Update counters */
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += (pktlength - 4);
+		dev->last_rx = jiffies;
+	}
+
+	/* Return total received packets */
+	return npackets;
+}
+
+/* Returns hash bit number for given MAC address
+ * Example:
+ * 01 00 5E 00 00 01 -> returns bit number 31 */
+static unsigned int smsc911x_hash(char addr[ETH_ALEN])
+{
+	return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
+}
+
+static void smsc911x_rx_multicast_update(struct smsc911x_data *pdata)
+{
+	/* Performs the multicast & mac_cr update.  This is called when
+	 * safe on the current hardware, and with the mac_lock held */
+	unsigned int mac_cr;
+
+	SMSC_ASSERT_MAC_LOCK(pdata);
+
+	mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+	mac_cr |= pdata->set_bits_mask;
+	mac_cr &= ~(pdata->clear_bits_mask);
+	smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+	smsc911x_mac_write(pdata, HASHH, pdata->hashhi);
+	smsc911x_mac_write(pdata, HASHL, pdata->hashlo);
+	SMSC_TRACE(HW, "maccr 0x%08X, HASHH 0x%08X, HASHL 0x%08X",
+		mac_cr, pdata->hashhi, pdata->hashlo);
+}
+
+static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata)
+{
+	unsigned int mac_cr;
+
+	/* This function is only called for older LAN911x devices
+	 * (revA or revB), where MAC_CR, HASHH and HASHL should not
+	 * be modified during Rx - newer devices immediately update the
+	 * registers.
+	 *
+	 * This is called from interrupt context */
+
+	spin_lock(&pdata->mac_lock);
+
+	/* Check Rx has stopped */
+	if (smsc911x_mac_read(pdata, MAC_CR) & MAC_CR_RXEN_)
+		SMSC_WARNING(DRV, "Rx not stopped");
+
+	/* Perform the update - safe to do now Rx has stopped */
+	smsc911x_rx_multicast_update(pdata);
+
+	/* Re-enable Rx */
+	mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+	mac_cr |= MAC_CR_RXEN_;
+	smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+
+	pdata->multicast_update_pending = 0;
+
+	spin_unlock(&pdata->mac_lock);
+}
+
+static int smsc911x_soft_reset(struct smsc911x_data *pdata)
+{
+	unsigned int timeout;
+	unsigned int temp;
+
+	/* Reset the LAN911x */
+	smsc911x_reg_write(pdata, HW_CFG, HW_CFG_SRST_);
+	timeout = 10;
+	do {
+		udelay(10);
+		temp = smsc911x_reg_read(pdata, HW_CFG);
+	} while ((--timeout) && (temp & HW_CFG_SRST_));
+
+	if (unlikely(temp & HW_CFG_SRST_)) {
+		SMSC_WARNING(DRV, "Failed to complete reset");
+		return -EIO;
+	}
+	return 0;
+}
+
+/* Sets the device MAC address to dev_addr, called with mac_lock held */
+static void
+smsc911x_set_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6])
+{
+	u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4];
+	u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+	    (dev_addr[1] << 8) | dev_addr[0];
+
+	SMSC_ASSERT_MAC_LOCK(pdata);
+
+	smsc911x_mac_write(pdata, ADDRH, mac_high16);
+	smsc911x_mac_write(pdata, ADDRL, mac_low32);
+}
+
+static int smsc911x_open(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int timeout;
+	unsigned int temp;
+	unsigned int intcfg;
+
+	/* if the phy is not yet registered, retry later*/
+	if (!pdata->phy_dev) {
+		SMSC_WARNING(HW, "phy_dev is NULL");
+		return -EAGAIN;
+	}
+
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		SMSC_WARNING(HW, "dev_addr is not a valid MAC address");
+		return -EADDRNOTAVAIL;
+	}
+
+	/* Reset the LAN911x */
+	if (smsc911x_soft_reset(pdata)) {
+		SMSC_WARNING(HW, "soft reset failed");
+		return -EIO;
+	}
+
+	smsc911x_reg_write(pdata, HW_CFG, 0x00050000);
+	smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740);
+
+	/* Make sure EEPROM has finished loading before setting GPIO_CFG */
+	timeout = 50;
+	while ((timeout--) &&
+	       (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
+		udelay(10);
+	}
+
+	if (unlikely(timeout == 0))
+		SMSC_WARNING(IFUP,
+			"Timed out waiting for EEPROM busy bit to clear");
+
+	smsc911x_reg_write(pdata, GPIO_CFG, 0x70070000);
+
+	/* The soft reset above cleared the device's MAC address,
+	 * restore it from local copy (set in probe) */
+	spin_lock_irq(&pdata->mac_lock);
+	smsc911x_set_mac_address(pdata, dev->dev_addr);
+	spin_unlock_irq(&pdata->mac_lock);
+
+	/* Initialise irqs, but leave all sources disabled */
+	smsc911x_reg_write(pdata, INT_EN, 0);
+	smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
+
+	/* Set interrupt deassertion to 100uS */
+	intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
+
+	if (pdata->irq_polarity) {
+		SMSC_TRACE(IFUP, "irq polarity: active high");
+		intcfg |= INT_CFG_IRQ_POL_;
+	} else {
+		SMSC_TRACE(IFUP, "irq polarity: active low");
+	}
+
+	if (pdata->irq_type) {
+		SMSC_TRACE(IFUP, "irq type: push-pull");
+		intcfg |= INT_CFG_IRQ_TYPE_;
+	} else {
+		SMSC_TRACE(IFUP, "irq type: open drain");
+	}
+
+	smsc911x_reg_write(pdata, INT_CFG, intcfg);
+
+	SMSC_TRACE(IFUP, "Testing irq handler using IRQ %d", dev->irq);
+	pdata->software_irq_signal = 0;
+	smp_wmb();
+
+	temp = smsc911x_reg_read(pdata, INT_EN);
+	temp |= INT_EN_SW_INT_EN_;
+	smsc911x_reg_write(pdata, INT_EN, temp);
+
+	timeout = 1000;
+	while (timeout--) {
+		if (pdata->software_irq_signal)
+			break;
+		msleep(1);
+	}
+
+	if (!pdata->software_irq_signal) {
+		dev_warn(&dev->dev, "ISR failed signaling test (IRQ %d)\n",
+			 dev->irq);
+		return -ENODEV;
+	}
+	SMSC_TRACE(IFUP, "IRQ handler passed test using IRQ %d", dev->irq);
+
+	dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n",
+		 (unsigned long)pdata->ioaddr, dev->irq);
+
+	/* Bring the PHY up */
+	phy_start(pdata->phy_dev);
+
+	temp = smsc911x_reg_read(pdata, HW_CFG);
+	/* Preserve TX FIFO size and external PHY configuration */
+	temp &= (HW_CFG_TX_FIF_SZ_|0x00000FFF);
+	temp |= HW_CFG_SF_;
+	smsc911x_reg_write(pdata, HW_CFG, temp);
+
+	temp = smsc911x_reg_read(pdata, FIFO_INT);
+	temp |= FIFO_INT_TX_AVAIL_LEVEL_;
+	temp &= ~(FIFO_INT_RX_STS_LEVEL_);
+	smsc911x_reg_write(pdata, FIFO_INT, temp);
+
+	/* set RX Data offset to 2 bytes for alignment */
+	smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+
+	/* enable NAPI polling before enabling RX interrupts */
+	napi_enable(&pdata->napi);
+
+	temp = smsc911x_reg_read(pdata, INT_EN);
+	temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_);
+	smsc911x_reg_write(pdata, INT_EN, temp);
+
+	spin_lock_irq(&pdata->mac_lock);
+	temp = smsc911x_mac_read(pdata, MAC_CR);
+	temp |= (MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
+	smsc911x_mac_write(pdata, MAC_CR, temp);
+	spin_unlock_irq(&pdata->mac_lock);
+
+	smsc911x_reg_write(pdata, TX_CFG, TX_CFG_TX_ON_);
+
+	netif_start_queue(dev);
+	return 0;
+}
+
+/* Entry point for stopping the interface */
+static int smsc911x_stop(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int temp;
+
+	BUG_ON(!pdata->phy_dev);
+
+	/* Disable all device interrupts */
+	temp = smsc911x_reg_read(pdata, INT_CFG);
+	temp &= ~INT_CFG_IRQ_EN_;
+	smsc911x_reg_write(pdata, INT_CFG, temp);
+
+	/* Stop Tx and Rx polling */
+	netif_stop_queue(dev);
+	napi_disable(&pdata->napi);
+
+	/* At this point all Rx and Tx activity is stopped */
+	dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+	smsc911x_tx_update_txcounters(dev);
+
+	/* Bring the PHY down */
+	phy_stop(pdata->phy_dev);
+
+	SMSC_TRACE(IFDOWN, "Interface stopped");
+	return 0;
+}
+
+/* Entry point for transmitting a packet */
+static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int freespace;
+	unsigned int tx_cmd_a;
+	unsigned int tx_cmd_b;
+	unsigned int temp;
+	u32 wrsz;
+	ulong bufp;
+
+	freespace = smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TDFREE_;
+
+	if (unlikely(freespace < TX_FIFO_LOW_THRESHOLD))
+		SMSC_WARNING(TX_ERR,
+			"Tx data fifo low, space available: %d", freespace);
+
+	/* Word alignment adjustment */
+	tx_cmd_a = (u32)((ulong)skb->data & 0x03) << 16;
+	tx_cmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
+	tx_cmd_a |= (unsigned int)skb->len;
+
+	tx_cmd_b = ((unsigned int)skb->len) << 16;
+	tx_cmd_b |= (unsigned int)skb->len;
+
+	smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_a);
+	smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_b);
+
+	bufp = (ulong)skb->data & (~0x3);
+	wrsz = (u32)skb->len + 3;
+	wrsz += (u32)((ulong)skb->data & 0x3);
+	wrsz >>= 2;
+
+	smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
+	freespace -= (skb->len + 32);
+	dev_kfree_skb(skb);
+	dev->trans_start = jiffies;
+
+	if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
+		smsc911x_tx_update_txcounters(dev);
+
+	if (freespace < TX_FIFO_LOW_THRESHOLD) {
+		netif_stop_queue(dev);
+		temp = smsc911x_reg_read(pdata, FIFO_INT);
+		temp &= 0x00FFFFFF;
+		temp |= 0x32000000;
+		smsc911x_reg_write(pdata, FIFO_INT, temp);
+	}
+
+	return NETDEV_TX_OK;
+}
+
+/* Entry point for getting status counters */
+static struct net_device_stats *smsc911x_get_stats(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	smsc911x_tx_update_txcounters(dev);
+	dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+	return &dev->stats;
+}
+
+/* Entry point for setting addressing modes */
+static void smsc911x_set_multicast_list(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned long flags;
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Enabling promiscuous mode */
+		pdata->set_bits_mask = MAC_CR_PRMS_;
+		pdata->clear_bits_mask = (MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+		pdata->hashhi = 0;
+		pdata->hashlo = 0;
+	} else if (dev->flags & IFF_ALLMULTI) {
+		/* Enabling all multicast mode */
+		pdata->set_bits_mask = MAC_CR_MCPAS_;
+		pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_HPFILT_);
+		pdata->hashhi = 0;
+		pdata->hashlo = 0;
+	} else if (dev->mc_count > 0) {
+		/* Enabling specific multicast addresses */
+		unsigned int hash_high = 0;
+		unsigned int hash_low = 0;
+		unsigned int count = 0;
+		struct dev_mc_list *mc_list = dev->mc_list;
+
+		pdata->set_bits_mask = MAC_CR_HPFILT_;
+		pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+		while (mc_list) {
+			count++;
+			if ((mc_list->dmi_addrlen) == ETH_ALEN) {
+				unsigned int bitnum =
+				    smsc911x_hash(mc_list->dmi_addr);
+				unsigned int mask = 0x01 << (bitnum & 0x1F);
+				if (bitnum & 0x20)
+					hash_high |= mask;
+				else
+					hash_low |= mask;
+			} else {
+				SMSC_WARNING(DRV, "dmi_addrlen != 6");
+			}
+			mc_list = mc_list->next;
+		}
+		if (count != (unsigned int)dev->mc_count)
+			SMSC_WARNING(DRV, "mc_count != dev->mc_count");
+
+		pdata->hashhi = hash_high;
+		pdata->hashlo = hash_low;
+	} else {
+		/* Enabling local MAC address only */
+		pdata->set_bits_mask = 0;
+		pdata->clear_bits_mask =
+		    (MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+		pdata->hashhi = 0;
+		pdata->hashlo = 0;
+	}
+
+	spin_lock_irqsave(&pdata->mac_lock, flags);
+
+	if (pdata->generation <= 1) {
+		/* Older hardware revision - cannot change these flags while
+		 * receiving data */
+		if (!pdata->multicast_update_pending) {
+			unsigned int temp;
+			SMSC_TRACE(HW, "scheduling mcast update");
+			pdata->multicast_update_pending = 1;
+
+			/* Request the hardware to stop, then perform the
+			 * update when we get an RX_STOP interrupt */
+			smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_);
+			temp = smsc911x_reg_read(pdata, INT_EN);
+			temp |= INT_EN_RXSTOP_INT_EN_;
+			smsc911x_reg_write(pdata, INT_EN, temp);
+
+			temp = smsc911x_mac_read(pdata, MAC_CR);
+			temp &= ~(MAC_CR_RXEN_);
+			smsc911x_mac_write(pdata, MAC_CR, temp);
+		} else {
+			/* There is another update pending, this should now
+			 * use the newer values */
+		}
+	} else {
+		/* Newer hardware revision - can write immediately */
+		smsc911x_rx_multicast_update(pdata);
+	}
+
+	spin_unlock_irqrestore(&pdata->mac_lock, flags);
+}
+
+static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	u32 intsts = smsc911x_reg_read(pdata, INT_STS);
+	u32 inten = smsc911x_reg_read(pdata, INT_EN);
+	int serviced = IRQ_NONE;
+	u32 temp;
+
+	if (unlikely(intsts & inten & INT_STS_SW_INT_)) {
+		temp = smsc911x_reg_read(pdata, INT_EN);
+		temp &= (~INT_EN_SW_INT_EN_);
+		smsc911x_reg_write(pdata, INT_EN, temp);
+		smsc911x_reg_write(pdata, INT_STS, INT_STS_SW_INT_);
+		pdata->software_irq_signal = 1;
+		smp_wmb();
+		serviced = IRQ_HANDLED;
+	}
+
+	if (unlikely(intsts & inten & INT_STS_RXSTOP_INT_)) {
+		/* Called when there is a multicast update scheduled and
+		 * it is now safe to complete the update */
+		SMSC_TRACE(INTR, "RX Stop interrupt");
+		temp = smsc911x_reg_read(pdata, INT_EN);
+		temp &= (~INT_EN_RXSTOP_INT_EN_);
+		smsc911x_reg_write(pdata, INT_EN, temp);
+		smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_);
+		smsc911x_rx_multicast_update_workaround(pdata);
+		serviced = IRQ_HANDLED;
+	}
+
+	if (intsts & inten & INT_STS_TDFA_) {
+		temp = smsc911x_reg_read(pdata, FIFO_INT);
+		temp |= FIFO_INT_TX_AVAIL_LEVEL_;
+		smsc911x_reg_write(pdata, FIFO_INT, temp);
+		smsc911x_reg_write(pdata, INT_STS, INT_STS_TDFA_);
+		netif_wake_queue(dev);
+		serviced = IRQ_HANDLED;
+	}
+
+	if (unlikely(intsts & inten & INT_STS_RXE_)) {
+		SMSC_TRACE(INTR, "RX Error interrupt");
+		smsc911x_reg_write(pdata, INT_STS, INT_STS_RXE_);
+		serviced = IRQ_HANDLED;
+	}
+
+	if (likely(intsts & inten & INT_STS_RSFL_)) {
+		if (likely(netif_rx_schedule_prep(dev, &pdata->napi))) {
+			/* Disable Rx interrupts */
+			temp = smsc911x_reg_read(pdata, INT_EN);
+			temp &= (~INT_EN_RSFL_EN_);
+			smsc911x_reg_write(pdata, INT_EN, temp);
+			/* Schedule a NAPI poll */
+			__netif_rx_schedule(dev, &pdata->napi);
+		} else {
+			SMSC_WARNING(RX_ERR,
+				"netif_rx_schedule_prep failed");
+		}
+		serviced = IRQ_HANDLED;
+	}
+
+	return serviced;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void smsc911x_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	smsc911x_irqhandler(0, dev);
+	enable_irq(dev->irq);
+}
+#endif				/* CONFIG_NET_POLL_CONTROLLER */
+
+/* Standard ioctls for mii-tool */
+static int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	if (!netif_running(dev) || !pdata->phy_dev)
+		return -EINVAL;
+
+	return phy_mii_ioctl(pdata->phy_dev, if_mii(ifr), cmd);
+}
+
+static int
+smsc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	cmd->maxtxpkt = 1;
+	cmd->maxrxpkt = 1;
+	return phy_ethtool_gset(pdata->phy_dev, cmd);
+}
+
+static int
+smsc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	return phy_ethtool_sset(pdata->phy_dev, cmd);
+}
+
+static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
+					struct ethtool_drvinfo *info)
+{
+	strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver));
+	strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version));
+	strlcpy(info->bus_info, dev->dev.parent->bus_id,
+		sizeof(info->bus_info));
+}
+
+static int smsc911x_ethtool_nwayreset(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	return phy_start_aneg(pdata->phy_dev);
+}
+
+static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	return pdata->msg_enable;
+}
+
+static void smsc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	pdata->msg_enable = level;
+}
+
+static int smsc911x_ethtool_getregslen(struct net_device *dev)
+{
+	return (((E2P_DATA - ID_REV) / 4 + 1) + (WUCSR - MAC_CR) + 1 + 32) *
+	    sizeof(u32);
+}
+
+static void
+smsc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
+			 void *buf)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	struct phy_device *phy_dev = pdata->phy_dev;
+	unsigned long flags;
+	unsigned int i;
+	unsigned int j = 0;
+	u32 *data = buf;
+
+	regs->version = pdata->idrev;
+	for (i = ID_REV; i <= E2P_DATA; i += (sizeof(u32)))
+		data[j++] = smsc911x_reg_read(pdata, i);
+
+	for (i = MAC_CR; i <= WUCSR; i++) {
+		spin_lock_irqsave(&pdata->mac_lock, flags);
+		data[j++] = smsc911x_mac_read(pdata, i);
+		spin_unlock_irqrestore(&pdata->mac_lock, flags);
+	}
+
+	for (i = 0; i <= 31; i++)
+		data[j++] = smsc911x_mii_read(phy_dev->bus, phy_dev->addr, i);
+}
+
+static void smsc911x_eeprom_enable_access(struct smsc911x_data *pdata)
+{
+	unsigned int temp = smsc911x_reg_read(pdata, GPIO_CFG);
+	temp &= ~GPIO_CFG_EEPR_EN_;
+	smsc911x_reg_write(pdata, GPIO_CFG, temp);
+	msleep(1);
+}
+
+static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op)
+{
+	int timeout = 100;
+	u32 e2cmd;
+
+	SMSC_TRACE(DRV, "op 0x%08x", op);
+	if (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) {
+		SMSC_WARNING(DRV, "Busy at start");
+		return -EBUSY;
+	}
+
+	e2cmd = op | E2P_CMD_EPC_BUSY_;
+	smsc911x_reg_write(pdata, E2P_CMD, e2cmd);
+
+	do {
+		msleep(1);
+		e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
+	} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+
+	if (!timeout) {
+		SMSC_TRACE(DRV, "TIMED OUT");
+		return -EAGAIN;
+	}
+
+	if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
+		SMSC_TRACE(DRV, "Error occured during eeprom operation");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smsc911x_eeprom_read_location(struct smsc911x_data *pdata,
+					 u8 address, u8 *data)
+{
+	u32 op = E2P_CMD_EPC_CMD_READ_ | address;
+	int ret;
+
+	SMSC_TRACE(DRV, "address 0x%x", address);
+	ret = smsc911x_eeprom_send_cmd(pdata, op);
+
+	if (!ret)
+		data[address] = smsc911x_reg_read(pdata, E2P_DATA);
+
+	return ret;
+}
+
+static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata,
+					  u8 address, u8 data)
+{
+	u32 op = E2P_CMD_EPC_CMD_ERASE_ | address;
+	int ret;
+
+	SMSC_TRACE(DRV, "address 0x%x, data 0x%x", address, data);
+	ret = smsc911x_eeprom_send_cmd(pdata, op);
+
+	if (!ret) {
+		op = E2P_CMD_EPC_CMD_WRITE_ | address;
+		smsc911x_reg_write(pdata, E2P_DATA, (u32)data);
+		ret = smsc911x_eeprom_send_cmd(pdata, op);
+	}
+
+	return ret;
+}
+
+static int smsc911x_ethtool_get_eeprom_len(struct net_device *dev)
+{
+	return SMSC911X_EEPROM_SIZE;
+}
+
+static int smsc911x_ethtool_get_eeprom(struct net_device *dev,
+				       struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	u8 eeprom_data[SMSC911X_EEPROM_SIZE];
+	int len;
+	int i;
+
+	smsc911x_eeprom_enable_access(pdata);
+
+	len = min(eeprom->len, SMSC911X_EEPROM_SIZE);
+	for (i = 0; i < len; i++) {
+		int ret = smsc911x_eeprom_read_location(pdata, i, eeprom_data);
+		if (ret < 0) {
+			eeprom->len = 0;
+			return ret;
+		}
+	}
+
+	memcpy(data, &eeprom_data[eeprom->offset], len);
+	eeprom->len = len;
+	return 0;
+}
+
+static int smsc911x_ethtool_set_eeprom(struct net_device *dev,
+				       struct ethtool_eeprom *eeprom, u8 *data)
+{
+	int ret;
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	smsc911x_eeprom_enable_access(pdata);
+	smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWEN_);
+	ret = smsc911x_eeprom_write_location(pdata, eeprom->offset, *data);
+	smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWDS_);
+
+	/* Single byte write, according to man page */
+	eeprom->len = 1;
+
+	return ret;
+}
+
+static struct ethtool_ops smsc911x_ethtool_ops = {
+	.get_settings = smsc911x_ethtool_getsettings,
+	.set_settings = smsc911x_ethtool_setsettings,
+	.get_link = ethtool_op_get_link,
+	.get_drvinfo = smsc911x_ethtool_getdrvinfo,
+	.nway_reset = smsc911x_ethtool_nwayreset,
+	.get_msglevel = smsc911x_ethtool_getmsglevel,
+	.set_msglevel = smsc911x_ethtool_setmsglevel,
+	.get_regs_len = smsc911x_ethtool_getregslen,
+	.get_regs = smsc911x_ethtool_getregs,
+	.get_eeprom_len = smsc911x_ethtool_get_eeprom_len,
+	.get_eeprom = smsc911x_ethtool_get_eeprom,
+	.set_eeprom = smsc911x_ethtool_set_eeprom,
+};
+
+/* Initializing private device structures, only called from probe */
+static int __devinit smsc911x_init(struct net_device *dev)
+{
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int byte_test;
+
+	SMSC_TRACE(PROBE, "Driver Parameters:");
+	SMSC_TRACE(PROBE, "LAN base: 0x%08lX",
+		(unsigned long)pdata->ioaddr);
+	SMSC_TRACE(PROBE, "IRQ: %d", dev->irq);
+	SMSC_TRACE(PROBE, "PHY will be autodetected.");
+
+#if (!SMSC_CAN_USE_32BIT)
+	spin_lock_init(&pdata->dev_lock);
+#endif
+
+	if (pdata->ioaddr == 0) {
+		SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000");
+		return -ENODEV;
+	}
+
+	/* Check byte ordering */
+	byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+	SMSC_TRACE(PROBE, "BYTE_TEST: 0x%08X", byte_test);
+	if (byte_test == 0x43218765) {
+		SMSC_TRACE(PROBE, "BYTE_TEST looks swapped, "
+			"applying WORD_SWAP");
+		smsc911x_reg_write(pdata, WORD_SWAP, 0xffffffff);
+
+		/* 1 dummy read of BYTE_TEST is needed after a write to
+		 * WORD_SWAP before its contents are valid */
+		byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+
+		byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+	}
+
+	if (byte_test != 0x87654321) {
+		SMSC_WARNING(DRV, "BYTE_TEST: 0x%08X", byte_test);
+		if (((byte_test >> 16) & 0xFFFF) == (byte_test & 0xFFFF)) {
+			SMSC_WARNING(PROBE,
+				"top 16 bits equal to bottom 16 bits");
+			SMSC_TRACE(PROBE, "This may mean the chip is set "
+				"for 32 bit while the bus is reading 16 bit");
+		}
+		return -ENODEV;
+	}
+
+	/* Default generation to zero (all workarounds apply) */
+	pdata->generation = 0;
+
+	pdata->idrev = smsc911x_reg_read(pdata, ID_REV);
+	switch (pdata->idrev & 0xFFFF0000) {
+	case 0x01180000:
+	case 0x01170000:
+	case 0x01160000:
+	case 0x01150000:
+		/* LAN911[5678] family */
+		pdata->generation = pdata->idrev & 0x0000FFFF;
+		break;
+
+	case 0x118A0000:
+	case 0x117A0000:
+	case 0x116A0000:
+	case 0x115A0000:
+		/* LAN921[5678] family */
+		pdata->generation = 3;
+		break;
+
+	case 0x92100000:
+	case 0x92110000:
+	case 0x92200000:
+	case 0x92210000:
+		/* LAN9210/LAN9211/LAN9220/LAN9221 */
+		pdata->generation = 4;
+		break;
+
+	default:
+		SMSC_WARNING(PROBE, "LAN911x not identified, idrev: 0x%08X",
+			pdata->idrev);
+		return -ENODEV;
+	}
+
+	SMSC_TRACE(PROBE, "LAN911x identified, idrev: 0x%08X, generation: %d",
+		pdata->idrev, pdata->generation);
+
+	if (pdata->generation == 0)
+		SMSC_WARNING(PROBE,
+			"This driver is not intended for this chip revision");
+
+	/* Reset the LAN911x */
+	if (smsc911x_soft_reset(pdata))
+		return -ENODEV;
+
+	/* Disable all interrupt sources until we bring the device up */
+	smsc911x_reg_write(pdata, INT_EN, 0);
+
+	ether_setup(dev);
+	dev->open = smsc911x_open;
+	dev->stop = smsc911x_stop;
+	dev->hard_start_xmit = smsc911x_hard_start_xmit;
+	dev->get_stats = smsc911x_get_stats;
+	dev->set_multicast_list = smsc911x_set_multicast_list;
+	dev->flags |= IFF_MULTICAST;
+	dev->do_ioctl = smsc911x_do_ioctl;
+	netif_napi_add(dev, &pdata->napi, smsc911x_poll, SMSC_NAPI_WEIGHT);
+	dev->ethtool_ops = &smsc911x_ethtool_ops;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = smsc911x_poll_controller;
+#endif				/* CONFIG_NET_POLL_CONTROLLER */
+
+	return 0;
+}
+
+static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct smsc911x_data *pdata;
+	struct resource *res;
+
+	dev = platform_get_drvdata(pdev);
+	BUG_ON(!dev);
+	pdata = netdev_priv(dev);
+	BUG_ON(!pdata);
+	BUG_ON(!pdata->ioaddr);
+	BUG_ON(!pdata->phy_dev);
+
+	SMSC_TRACE(IFDOWN, "Stopping driver.");
+
+	phy_disconnect(pdata->phy_dev);
+	pdata->phy_dev = NULL;
+	mdiobus_unregister(pdata->mii_bus);
+	mdiobus_free(pdata->mii_bus);
+
+	platform_set_drvdata(pdev, NULL);
+	unregister_netdev(dev);
+	free_irq(dev->irq, dev);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "smsc911x-memory");
+	if (!res)
+		platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	release_mem_region(res->start, res->end - res->start);
+
+	iounmap(pdata->ioaddr);
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct smsc911x_data *pdata;
+	struct resource *res;
+	unsigned int intcfg = 0;
+	int res_size;
+	int retval;
+	DECLARE_MAC_BUF(mac);
+
+	pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "smsc911x-memory");
+	if (!res)
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		pr_warning("%s: Could not allocate resource.\n",
+			SMSC_CHIPNAME);
+		retval = -ENODEV;
+		goto out_0;
+	}
+	res_size = res->end - res->start;
+
+	if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) {
+		retval = -EBUSY;
+		goto out_0;
+	}
+
+	dev = alloc_etherdev(sizeof(struct smsc911x_data));
+	if (!dev) {
+		pr_warning("%s: Could not allocate device.\n", SMSC_CHIPNAME);
+		retval = -ENOMEM;
+		goto out_release_io_1;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	pdata = netdev_priv(dev);
+
+	dev->irq = platform_get_irq(pdev, 0);
+	pdata->ioaddr = ioremap_nocache(res->start, res_size);
+
+	/* copy config parameters across if present, otherwise pdata
+	 * defaults to zeros */
+	if (pdev->dev.platform_data) {
+		struct smsc911x_platform_config *config =
+			pdev->dev.platform_data;
+		pdata->irq_polarity = config->irq_polarity;
+		pdata->irq_type  = config->irq_type;
+		pdata->phy_interface = config->phy_interface;
+	}
+
+	pdata->dev = dev;
+	pdata->msg_enable = ((1 << debug) - 1);
+
+	if (pdata->ioaddr == NULL) {
+		SMSC_WARNING(PROBE,
+			"Error smsc911x base address invalid");
+		retval = -ENOMEM;
+		goto out_free_netdev_2;
+	}
+
+	retval = smsc911x_init(dev);
+	if (retval < 0)
+		goto out_unmap_io_3;
+
+	/* configure irq polarity and type before connecting isr */
+	if (pdata->irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
+		intcfg |= INT_CFG_IRQ_POL_;
+
+	if (pdata->irq_type == SMSC911X_IRQ_TYPE_PUSH_PULL)
+		intcfg |= INT_CFG_IRQ_TYPE_;
+
+	smsc911x_reg_write(pdata, INT_CFG, intcfg);
+
+	/* Ensure interrupts are globally disabled before connecting ISR */
+	smsc911x_reg_write(pdata, INT_EN, 0);
+	smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
+
+	retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED,
+			     SMSC_CHIPNAME, dev);
+	if (retval) {
+		SMSC_WARNING(PROBE,
+			"Unable to claim requested irq: %d", dev->irq);
+		goto out_unmap_io_3;
+	}
+
+	platform_set_drvdata(pdev, dev);
+
+	retval = register_netdev(dev);
+	if (retval) {
+		SMSC_WARNING(PROBE,
+			"Error %i registering device", retval);
+		goto out_unset_drvdata_4;
+	} else {
+		SMSC_TRACE(PROBE, "Network interface: \"%s\"", dev->name);
+	}
+
+	spin_lock_init(&pdata->mac_lock);
+
+	retval = smsc911x_mii_init(pdev, dev);
+	if (retval) {
+		SMSC_WARNING(PROBE,
+			"Error %i initialising mii", retval);
+		goto out_unregister_netdev_5;
+	}
+
+	spin_lock_irq(&pdata->mac_lock);
+
+	/* Check if mac address has been specified when bringing interface up */
+	if (is_valid_ether_addr(dev->dev_addr)) {
+		smsc911x_set_mac_address(pdata, dev->dev_addr);
+		SMSC_TRACE(PROBE, "MAC Address is specified by configuration");
+	} else {
+		/* Try reading mac address from device. if EEPROM is present
+		 * it will already have been set */
+		u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
+		u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL);
+		dev->dev_addr[0] = (u8)(mac_low32);
+		dev->dev_addr[1] = (u8)(mac_low32 >> 8);
+		dev->dev_addr[2] = (u8)(mac_low32 >> 16);
+		dev->dev_addr[3] = (u8)(mac_low32 >> 24);
+		dev->dev_addr[4] = (u8)(mac_high16);
+		dev->dev_addr[5] = (u8)(mac_high16 >> 8);
+
+		if (is_valid_ether_addr(dev->dev_addr)) {
+			/* eeprom values are valid  so use them */
+			SMSC_TRACE(PROBE,
+				"Mac Address is read from LAN911x EEPROM");
+		} else {
+			/* eeprom values are invalid, generate random MAC */
+			random_ether_addr(dev->dev_addr);
+			smsc911x_set_mac_address(pdata, dev->dev_addr);
+			SMSC_TRACE(PROBE,
+				"MAC Address is set to random_ether_addr");
+		}
+	}
+
+	spin_unlock_irq(&pdata->mac_lock);
+
+	dev_info(&dev->dev, "MAC Address: %s\n",
+		 print_mac(mac, dev->dev_addr));
+
+	return 0;
+
+out_unregister_netdev_5:
+	unregister_netdev(dev);
+out_unset_drvdata_4:
+	platform_set_drvdata(pdev, NULL);
+	free_irq(dev->irq, dev);
+out_unmap_io_3:
+	iounmap(pdata->ioaddr);
+out_free_netdev_2:
+	free_netdev(dev);
+out_release_io_1:
+	release_mem_region(res->start, res->end - res->start);
+out_0:
+	return retval;
+}
+
+static struct platform_driver smsc911x_driver = {
+	.probe = smsc911x_drv_probe,
+	.remove = smsc911x_drv_remove,
+	.driver = {
+		.name = SMSC_CHIPNAME,
+	},
+};
+
+/* Entry point for loading the module */
+static int __init smsc911x_init_module(void)
+{
+	return platform_driver_register(&smsc911x_driver);
+}
+
+/* entry point for unloading the module */
+static void __exit smsc911x_cleanup_module(void)
+{
+	platform_driver_unregister(&smsc911x_driver);
+}
+
+module_init(smsc911x_init_module);
+module_exit(smsc911x_cleanup_module);
diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h
new file mode 100644
index 0000000..feb36de
--- /dev/null
+++ b/drivers/net/smsc911x.h
@@ -0,0 +1,394 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2004-2008 SMSC
+ * Copyright (C) 2005-2008 ARM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ ***************************************************************************/
+#ifndef __SMSC911X_H__
+#define __SMSC911X_H__
+
+#define SMSC_CAN_USE_32BIT	1
+#define TX_FIFO_LOW_THRESHOLD	((u32)1600)
+#define SMSC911X_EEPROM_SIZE	((u32)7)
+#define USE_DEBUG		0
+
+/* This is the maximum number of packets to be received every
+ * NAPI poll */
+#define SMSC_NAPI_WEIGHT	16
+
+/* implements a PHY loopback test at initialisation time, to ensure a packet
+ * can be succesfully looped back */
+#define USE_PHY_WORK_AROUND
+
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+	((void)((NETIF_MSG_##nlevel & pdata->msg_enable) && \
+	printk(KERN_##klevel "%s: %s: " fmt "\n", \
+	pdata->dev->name, __func__, ## args)))
+
+#if USE_DEBUG >= 1
+#define SMSC_WARNING(nlevel, fmt, args...) \
+	DPRINTK(nlevel, WARNING, fmt, ## args)
+#else
+#define SMSC_WARNING(nlevel, fmt, args...) \
+	({ do {} while (0); 0; })
+#endif
+
+#if USE_DEBUG >= 2
+#define SMSC_TRACE(nlevel, fmt, args...) \
+	DPRINTK(nlevel, INFO, fmt, ## args)
+#else
+#define SMSC_TRACE(nlevel, fmt, args...) \
+	({ do {} while (0); 0; })
+#endif
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define SMSC_ASSERT_MAC_LOCK(pdata) \
+		WARN_ON(!spin_is_locked(&pdata->mac_lock))
+#else
+#define SMSC_ASSERT_MAC_LOCK(pdata) do {} while (0)
+#endif				/* CONFIG_DEBUG_SPINLOCK */
+
+#define FLOW_CTRL_TX		(1)
+#define FLOW_CTRL_RX		(2)
+
+/* SMSC911x registers and bitfields */
+#define RX_DATA_FIFO			0x00
+
+#define TX_DATA_FIFO			0x20
+#define TX_CMD_A_ON_COMP_		0x80000000
+#define TX_CMD_A_BUF_END_ALGN_		0x03000000
+#define TX_CMD_A_4_BYTE_ALGN_		0x00000000
+#define TX_CMD_A_16_BYTE_ALGN_		0x01000000
+#define TX_CMD_A_32_BYTE_ALGN_		0x02000000
+#define TX_CMD_A_DATA_OFFSET_		0x001F0000
+#define TX_CMD_A_FIRST_SEG_		0x00002000
+#define TX_CMD_A_LAST_SEG_		0x00001000
+#define TX_CMD_A_BUF_SIZE_		0x000007FF
+#define TX_CMD_B_PKT_TAG_		0xFFFF0000
+#define TX_CMD_B_ADD_CRC_DISABLE_	0x00002000
+#define TX_CMD_B_DISABLE_PADDING_	0x00001000
+#define TX_CMD_B_PKT_BYTE_LENGTH_	0x000007FF
+
+#define RX_STATUS_FIFO			0x40
+#define RX_STS_ES_			0x00008000
+#define RX_STS_MCAST_			0x00000400
+
+#define RX_STATUS_FIFO_PEEK		0x44
+
+#define TX_STATUS_FIFO			0x48
+#define TX_STS_ES_			0x00008000
+
+#define TX_STATUS_FIFO_PEEK		0x4C
+
+#define ID_REV				0x50
+#define ID_REV_CHIP_ID_			0xFFFF0000
+#define ID_REV_REV_ID_			0x0000FFFF
+
+#define INT_CFG				0x54
+#define INT_CFG_INT_DEAS_		0xFF000000
+#define INT_CFG_INT_DEAS_CLR_		0x00004000
+#define INT_CFG_INT_DEAS_STS_		0x00002000
+#define INT_CFG_IRQ_INT_		0x00001000
+#define INT_CFG_IRQ_EN_			0x00000100
+#define INT_CFG_IRQ_POL_		0x00000010
+#define INT_CFG_IRQ_TYPE_		0x00000001
+
+#define INT_STS				0x58
+#define INT_STS_SW_INT_			0x80000000
+#define INT_STS_TXSTOP_INT_		0x02000000
+#define INT_STS_RXSTOP_INT_		0x01000000
+#define INT_STS_RXDFH_INT_		0x00800000
+#define INT_STS_RXDF_INT_		0x00400000
+#define INT_STS_TX_IOC_			0x00200000
+#define INT_STS_RXD_INT_		0x00100000
+#define INT_STS_GPT_INT_		0x00080000
+#define INT_STS_PHY_INT_		0x00040000
+#define INT_STS_PME_INT_		0x00020000
+#define INT_STS_TXSO_			0x00010000
+#define INT_STS_RWT_			0x00008000
+#define INT_STS_RXE_			0x00004000
+#define INT_STS_TXE_			0x00002000
+#define INT_STS_TDFU_			0x00000800
+#define INT_STS_TDFO_			0x00000400
+#define INT_STS_TDFA_			0x00000200
+#define INT_STS_TSFF_			0x00000100
+#define INT_STS_TSFL_			0x00000080
+#define INT_STS_RXDF_			0x00000040
+#define INT_STS_RDFL_			0x00000020
+#define INT_STS_RSFF_			0x00000010
+#define INT_STS_RSFL_			0x00000008
+#define INT_STS_GPIO2_INT_		0x00000004
+#define INT_STS_GPIO1_INT_		0x00000002
+#define INT_STS_GPIO0_INT_		0x00000001
+
+#define INT_EN				0x5C
+#define INT_EN_SW_INT_EN_		0x80000000
+#define INT_EN_TXSTOP_INT_EN_		0x02000000
+#define INT_EN_RXSTOP_INT_EN_		0x01000000
+#define INT_EN_RXDFH_INT_EN_		0x00800000
+#define INT_EN_TIOC_INT_EN_		0x00200000
+#define INT_EN_RXD_INT_EN_		0x00100000
+#define INT_EN_GPT_INT_EN_		0x00080000
+#define INT_EN_PHY_INT_EN_		0x00040000
+#define INT_EN_PME_INT_EN_		0x00020000
+#define INT_EN_TXSO_EN_			0x00010000
+#define INT_EN_RWT_EN_			0x00008000
+#define INT_EN_RXE_EN_			0x00004000
+#define INT_EN_TXE_EN_			0x00002000
+#define INT_EN_TDFU_EN_			0x00000800
+#define INT_EN_TDFO_EN_			0x00000400
+#define INT_EN_TDFA_EN_			0x00000200
+#define INT_EN_TSFF_EN_			0x00000100
+#define INT_EN_TSFL_EN_			0x00000080
+#define INT_EN_RXDF_EN_			0x00000040
+#define INT_EN_RDFL_EN_			0x00000020
+#define INT_EN_RSFF_EN_			0x00000010
+#define INT_EN_RSFL_EN_			0x00000008
+#define INT_EN_GPIO2_INT_		0x00000004
+#define INT_EN_GPIO1_INT_		0x00000002
+#define INT_EN_GPIO0_INT_		0x00000001
+
+#define BYTE_TEST			0x64
+
+#define FIFO_INT			0x68
+#define FIFO_INT_TX_AVAIL_LEVEL_	0xFF000000
+#define FIFO_INT_TX_STS_LEVEL_		0x00FF0000
+#define FIFO_INT_RX_AVAIL_LEVEL_	0x0000FF00
+#define FIFO_INT_RX_STS_LEVEL_		0x000000FF
+
+#define RX_CFG				0x6C
+#define RX_CFG_RX_END_ALGN_		0xC0000000
+#define RX_CFG_RX_END_ALGN4_		0x00000000
+#define RX_CFG_RX_END_ALGN16_		0x40000000
+#define RX_CFG_RX_END_ALGN32_		0x80000000
+#define RX_CFG_RX_DMA_CNT_		0x0FFF0000
+#define RX_CFG_RX_DUMP_			0x00008000
+#define RX_CFG_RXDOFF_			0x00001F00
+
+#define TX_CFG				0x70
+#define TX_CFG_TXS_DUMP_		0x00008000
+#define TX_CFG_TXD_DUMP_		0x00004000
+#define TX_CFG_TXSAO_			0x00000004
+#define TX_CFG_TX_ON_			0x00000002
+#define TX_CFG_STOP_TX_			0x00000001
+
+#define HW_CFG				0x74
+#define HW_CFG_TTM_			0x00200000
+#define HW_CFG_SF_			0x00100000
+#define HW_CFG_TX_FIF_SZ_		0x000F0000
+#define HW_CFG_TR_			0x00003000
+#define HW_CFG_SRST_			0x00000001
+
+/* only available on 115/117 */
+#define HW_CFG_PHY_CLK_SEL_		0x00000060
+#define HW_CFG_PHY_CLK_SEL_INT_PHY_	0x00000000
+#define HW_CFG_PHY_CLK_SEL_EXT_PHY_	0x00000020
+#define HW_CFG_PHY_CLK_SEL_CLK_DIS_	0x00000040
+#define HW_CFG_SMI_SEL_		 	0x00000010
+#define HW_CFG_EXT_PHY_DET_		0x00000008
+#define HW_CFG_EXT_PHY_EN_		0x00000004
+#define HW_CFG_SRST_TO_			0x00000002
+
+/* only available  on 116/118 */
+#define HW_CFG_32_16_BIT_MODE_		0x00000004
+
+#define RX_DP_CTRL			0x78
+#define RX_DP_CTRL_RX_FFWD_		0x80000000
+
+#define RX_FIFO_INF			0x7C
+#define RX_FIFO_INF_RXSUSED_		0x00FF0000
+#define RX_FIFO_INF_RXDUSED_		0x0000FFFF
+
+#define TX_FIFO_INF			0x80
+#define TX_FIFO_INF_TSUSED_		0x00FF0000
+#define TX_FIFO_INF_TDFREE_		0x0000FFFF
+
+#define PMT_CTRL			0x84
+#define PMT_CTRL_PM_MODE_		0x00003000
+#define PMT_CTRL_PM_MODE_D0_		0x00000000
+#define PMT_CTRL_PM_MODE_D1_		0x00001000
+#define PMT_CTRL_PM_MODE_D2_		0x00002000
+#define PMT_CTRL_PM_MODE_D3_		0x00003000
+#define PMT_CTRL_PHY_RST_		0x00000400
+#define PMT_CTRL_WOL_EN_		0x00000200
+#define PMT_CTRL_ED_EN_			0x00000100
+#define PMT_CTRL_PME_TYPE_		0x00000040
+#define PMT_CTRL_WUPS_			0x00000030
+#define PMT_CTRL_WUPS_NOWAKE_		0x00000000
+#define PMT_CTRL_WUPS_ED_		0x00000010
+#define PMT_CTRL_WUPS_WOL_		0x00000020
+#define PMT_CTRL_WUPS_MULTI_		0x00000030
+#define PMT_CTRL_PME_IND_		0x00000008
+#define PMT_CTRL_PME_POL_		0x00000004
+#define PMT_CTRL_PME_EN_		0x00000002
+#define PMT_CTRL_READY_			0x00000001
+
+#define GPIO_CFG			0x88
+#define GPIO_CFG_LED3_EN_		0x40000000
+#define GPIO_CFG_LED2_EN_		0x20000000
+#define GPIO_CFG_LED1_EN_		0x10000000
+#define GPIO_CFG_GPIO2_INT_POL_		0x04000000
+#define GPIO_CFG_GPIO1_INT_POL_		0x02000000
+#define GPIO_CFG_GPIO0_INT_POL_		0x01000000
+#define GPIO_CFG_EEPR_EN_		0x00700000
+#define GPIO_CFG_GPIOBUF2_		0x00040000
+#define GPIO_CFG_GPIOBUF1_		0x00020000
+#define GPIO_CFG_GPIOBUF0_		0x00010000
+#define GPIO_CFG_GPIODIR2_		0x00000400
+#define GPIO_CFG_GPIODIR1_		0x00000200
+#define GPIO_CFG_GPIODIR0_		0x00000100
+#define GPIO_CFG_GPIOD4_		0x00000020
+#define GPIO_CFG_GPIOD3_		0x00000010
+#define GPIO_CFG_GPIOD2_		0x00000004
+#define GPIO_CFG_GPIOD1_		0x00000002
+#define GPIO_CFG_GPIOD0_		0x00000001
+
+#define GPT_CFG				0x8C
+#define GPT_CFG_TIMER_EN_		0x20000000
+#define GPT_CFG_GPT_LOAD_		0x0000FFFF
+
+#define GPT_CNT				0x90
+#define GPT_CNT_GPT_CNT_		0x0000FFFF
+
+#define WORD_SWAP			0x98
+
+#define FREE_RUN			0x9C
+
+#define RX_DROP				0xA0
+
+#define MAC_CSR_CMD			0xA4
+#define MAC_CSR_CMD_CSR_BUSY_		0x80000000
+#define MAC_CSR_CMD_R_NOT_W_		0x40000000
+#define MAC_CSR_CMD_CSR_ADDR_		0x000000FF
+
+#define MAC_CSR_DATA			0xA8
+
+#define AFC_CFG				0xAC
+#define AFC_CFG_AFC_HI_			0x00FF0000
+#define AFC_CFG_AFC_LO_			0x0000FF00
+#define AFC_CFG_BACK_DUR_		0x000000F0
+#define AFC_CFG_FCMULT_			0x00000008
+#define AFC_CFG_FCBRD_			0x00000004
+#define AFC_CFG_FCADD_			0x00000002
+#define AFC_CFG_FCANY_			0x00000001
+
+#define E2P_CMD				0xB0
+#define E2P_CMD_EPC_BUSY_		0x80000000
+#define E2P_CMD_EPC_CMD_		0x70000000
+#define E2P_CMD_EPC_CMD_READ_		0x00000000
+#define E2P_CMD_EPC_CMD_EWDS_		0x10000000
+#define E2P_CMD_EPC_CMD_EWEN_		0x20000000
+#define E2P_CMD_EPC_CMD_WRITE_		0x30000000
+#define E2P_CMD_EPC_CMD_WRAL_		0x40000000
+#define E2P_CMD_EPC_CMD_ERASE_		0x50000000
+#define E2P_CMD_EPC_CMD_ERAL_		0x60000000
+#define E2P_CMD_EPC_CMD_RELOAD_		0x70000000
+#define E2P_CMD_EPC_TIMEOUT_		0x00000200
+#define E2P_CMD_MAC_ADDR_LOADED_	0x00000100
+#define E2P_CMD_EPC_ADDR_		0x000000FF
+
+#define E2P_DATA			0xB4
+#define E2P_DATA_EEPROM_DATA_		0x000000FF
+#define LAN_REGISTER_EXTENT		0x00000100
+
+/*
+ * MAC Control and Status Register (Indirect Address)
+ * Offset (through the MAC_CSR CMD and DATA port)
+ */
+#define MAC_CR				0x01
+#define MAC_CR_RXALL_			0x80000000
+#define MAC_CR_HBDIS_			0x10000000
+#define MAC_CR_RCVOWN_			0x00800000
+#define MAC_CR_LOOPBK_			0x00200000
+#define MAC_CR_FDPX_			0x00100000
+#define MAC_CR_MCPAS_			0x00080000
+#define MAC_CR_PRMS_			0x00040000
+#define MAC_CR_INVFILT_			0x00020000
+#define MAC_CR_PASSBAD_			0x00010000
+#define MAC_CR_HFILT_			0x00008000
+#define MAC_CR_HPFILT_			0x00002000
+#define MAC_CR_LCOLL_			0x00001000
+#define MAC_CR_BCAST_			0x00000800
+#define MAC_CR_DISRTY_			0x00000400
+#define MAC_CR_PADSTR_			0x00000100
+#define MAC_CR_BOLMT_MASK_		0x000000C0
+#define MAC_CR_DFCHK_			0x00000020
+#define MAC_CR_TXEN_			0x00000008
+#define MAC_CR_RXEN_			0x00000004
+
+#define ADDRH				0x02
+
+#define ADDRL				0x03
+
+#define HASHH				0x04
+
+#define HASHL				0x05
+
+#define MII_ACC				0x06
+#define MII_ACC_PHY_ADDR_		0x0000F800
+#define MII_ACC_MIIRINDA_		0x000007C0
+#define MII_ACC_MII_WRITE_		0x00000002
+#define MII_ACC_MII_BUSY_		0x00000001
+
+#define MII_DATA			0x07
+
+#define FLOW				0x08
+#define FLOW_FCPT_			0xFFFF0000
+#define FLOW_FCPASS_			0x00000004
+#define FLOW_FCEN_			0x00000002
+#define FLOW_FCBSY_			0x00000001
+
+#define VLAN1				0x09
+
+#define VLAN2				0x0A
+
+#define WUFF				0x0B
+
+#define WUCSR				0x0C
+#define WUCSR_GUE_			0x00000200
+#define WUCSR_WUFR_			0x00000040
+#define WUCSR_MPR_			0x00000020
+#define WUCSR_WAKE_EN_			0x00000004
+#define WUCSR_MPEN_			0x00000002
+
+/*
+ * Phy definitions (vendor-specific)
+ */
+#define LAN9118_PHY_ID			0x00C0001C
+
+#define MII_INTSTS			0x1D
+
+#define MII_INTMSK			0x1E
+#define PHY_INTMSK_AN_RCV_		(1 << 1)
+#define PHY_INTMSK_PDFAULT_		(1 << 2)
+#define PHY_INTMSK_AN_ACK_		(1 << 3)
+#define PHY_INTMSK_LNKDOWN_		(1 << 4)
+#define PHY_INTMSK_RFAULT_		(1 << 5)
+#define PHY_INTMSK_AN_COMP_		(1 << 6)
+#define PHY_INTMSK_ENERGYON_		(1 << 7)
+#define PHY_INTMSK_DEFAULT_		(PHY_INTMSK_ENERGYON_ | \
+					 PHY_INTMSK_AN_COMP_ | \
+					 PHY_INTMSK_RFAULT_ | \
+					 PHY_INTMSK_LNKDOWN_)
+
+#define ADVERTISE_PAUSE_ALL		(ADVERTISE_PAUSE_CAP | \
+					 ADVERTISE_PAUSE_ASYM)
+
+#define LPA_PAUSE_ALL			(LPA_PAUSE_CAP | \
+					 LPA_PAUSE_ASYM)
+
+#endif				/* __SMSC911X_H__ */
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 8069f3e..211e805 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -450,7 +450,6 @@
 			skb_trim(used_skb, pkt_len);
 			used_skb->protocol = eth_type_trans(used_skb, dev);
 			netif_rx(used_skb);
-			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes += pkt_len;
 
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 1d2ef8f..0358809 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -653,7 +653,6 @@
 	void __iomem *base;
 	int drv_flags, io_size;
 	int boguscnt;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -823,9 +822,9 @@
 	if (register_netdev(dev))
 		goto err_out_cleardev;
 
-	printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
 	       dev->name, netdrv_tbl[chip_idx].name, base,
-	       print_mac(mac, dev->dev_addr), irq);
+	       dev->dev_addr, irq);
 
 	if (drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
@@ -1452,12 +1451,8 @@
 #ifndef final_version			/* Remove after testing. */
 		/* You will want this info for the initial debug. */
 		if (debug > 5) {
-			printk(KERN_DEBUG "  Rx data " MAC_FMT " " MAC_FMT
-			       " %2.2x%2.2x.\n",
-			       skb->data[0], skb->data[1], skb->data[2],
-			       skb->data[3], skb->data[4], skb->data[5],
-			       skb->data[6], skb->data[7], skb->data[8],
-			       skb->data[9], skb->data[10], skb->data[11],
+			printk(KERN_DEBUG "  Rx data %pM %pM %2.2x%2.2x.\n",
+			       skb->data, skb->data + 6,
 			       skb->data[12], skb->data[13]);
 		}
 #endif
@@ -1501,7 +1496,6 @@
 		} else
 #endif /* VLAN_SUPPORT */
 			netif_receive_skb(skb);
-		dev->last_rx = jiffies;
 		np->stats.rx_packets++;
 
 	next_rx:
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 359452a..4bb8f72 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -303,7 +303,6 @@
 	static int 		did_version;
 	volatile unsigned short *ioaddr_probe;
 	unsigned short tmp1, tmp2;
-	DECLARE_MAC_BUF(mac);
 
 #ifdef CONFIG_SUN3
 	ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE);
@@ -379,7 +378,7 @@
 	MEM->init.hwaddr[4] = dev->dev_addr[5];
 	MEM->init.hwaddr[5] = dev->dev_addr[4];
 
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 
 	MEM->init.mode = 0x0000;
 	MEM->init.filter[0] = 0x00000000;
@@ -824,12 +823,10 @@
 #if 0
 				if (lance_debug >= 3) {
 					u_char *data = PKTBUF_ADDR(head);
-					DECLARE_MAC_BUF(mac);
-					DECLARE_MAC_BUF(mac2)
 					printk("%s: RX pkt %d type 0x%04x"
-					       " from %s to %s",
+					       " from %pM to %pM",
 					       dev->name, lp->new_tx, ((u_short *)data)[6],
-					       print_mac(mac, &data[6]), print_mac(mac2, data));
+					       &data[6], data);
 
 					printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
 					       "len %d at %08x\n",
@@ -852,7 +849,6 @@
 
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
-				dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 			}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 018d0fc..3f57ba0 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -878,7 +878,6 @@
 		/* No checksums done by the BigMAC ;-( */
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		netif_rx(skb);
-		bp->dev->last_rx = jiffies;
 		bp->enet_stats.rx_packets++;
 		bp->enet_stats.rx_bytes += len;
 	next:
@@ -1081,7 +1080,6 @@
 	static int version_printed;
 	struct net_device *dev;
 	u8 bsizes, bsizes_more;
-	DECLARE_MAC_BUF(mac);
 	struct bigmac *bp;
 	int i;
 
@@ -1212,8 +1210,8 @@
 
 	dev_set_drvdata(&bp->bigmac_op->dev, bp);
 
-	printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %pM\n",
+	       dev->name, dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index f860ea1..698893b 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -468,7 +468,6 @@
 	int bar = 1;
 #endif
 	int phy, phy_end, phy_idx = 0;
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -547,9 +546,9 @@
 	if (i)
 		goto err_out_unmap_rx;
 
-	printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
 	       dev->name, pci_id_tbl[chip_idx].name, ioaddr,
-	       print_mac(mac, dev->dev_addr), irq);
+	       dev->dev_addr, irq);
 
 	np->phys[0] = 1;		/* Default setting */
 	np->mii_preamble_required++;
@@ -1351,7 +1350,6 @@
 			skb->protocol = eth_type_trans(skb, dev);
 			/* Note: checksum -> skb->ip_summed = CHECKSUM_UNNECESSARY; */
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 		}
 		entry = (entry + 1) % RX_RING_SIZE;
 		received++;
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 4291458..deb1148 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -863,7 +863,6 @@
 
 		gp->net_stats.rx_packets++;
 		gp->net_stats.rx_bytes += len;
-		gp->dev->last_rx = jiffies;
 
 	next:
 		entry = NEXT_RX(entry);
@@ -2966,7 +2965,6 @@
 	struct net_device *dev;
 	struct gem *gp;
 	int err, pci_using_dac;
-	DECLARE_MAC_BUF(mac);
 
 	if (gem_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -3150,9 +3148,8 @@
 		goto err_out_free_consistent;
 	}
 
-	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet "
-	       "%s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
+	       dev->name, dev->dev_addr);
 
 	if (gp->phy_type == phy_mii_mdio0 ||
      	    gp->phy_type == phy_mii_mdio1)
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index f1ebeb5..e55db66 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2072,7 +2072,6 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
 
-		dev->last_rx = jiffies;
 		hp->net_stats.rx_packets++;
 		hp->net_stats.rx_bytes += len;
 	next:
@@ -2617,7 +2616,6 @@
 	struct net_device *dev;
 	int i, qfe_slot = -1;
 	int err = -ENODEV;
-	DECLARE_MAC_BUF(mac);
 
 	if (is_qfe) {
 		qp = quattro_sbus_find(op);
@@ -2797,7 +2795,7 @@
 		printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
 		       dev->name);
 
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 
 	return 0;
 
@@ -2932,7 +2930,6 @@
 	int i, qfe_slot = -1;
 	char prom_name[64];
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	/* Now make sure pci_dev cookie is there. */
 #ifdef CONFIG_SPARC
@@ -3141,7 +3138,7 @@
 		printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
 		       dev->name);
 
-	printk("%s\n", print_mac(mac, dev->dev_addr));
+	printk("%pM\n", dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 704301a..2813732 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -555,7 +555,6 @@
 					 len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 
@@ -726,7 +725,6 @@
 			lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 		}
 
@@ -1321,7 +1319,6 @@
 	static unsigned version_printed;
 	struct lance_private *lp;
 	struct net_device *dev;
-	DECLARE_MAC_BUF(mac);
 	int    i;
 
 	dev = alloc_etherdev(sizeof(struct lance_private) + 8);
@@ -1491,8 +1488,8 @@
 
 	dev_set_drvdata(&op->dev, lp);
 
-	printk(KERN_INFO "%s: LANCE %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: LANCE %pM\n",
+	       dev->name, dev->dev_addr);
 
 	return 0;
 
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index f636447..8f1e7ff 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -446,7 +446,6 @@
 						 len);
 				skb->protocol = eth_type_trans(skb, qep->dev);
 				netif_rx(skb);
-				qep->dev->last_rx = jiffies;
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += len;
 			}
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index a720065..233f1cd 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -1149,7 +1149,6 @@
 	struct vnet *vp;
 	const u64 *rmac;
 	int len, i, err, switch_port;
-	DECLARE_MAC_BUF(mac);
 
 	print_version();
 
@@ -1214,8 +1213,8 @@
 
 	dev_set_drvdata(&vdev->dev, port);
 
-	printk(KERN_INFO "%s: PORT ( remote-mac %s%s )\n",
-	       vp->dev->name, print_mac(mac, port->raddr),
+	printk(KERN_INFO "%s: PORT ( remote-mac %pM%s )\n",
+	       vp->dev->name, port->raddr,
 	       switch_port ? " switch-port" : "");
 
 	vio_port_up(&port->vio);
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index df20caf..44126c4 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -236,7 +236,7 @@
 #define Rx_Halted	       0x00008000 /* Rx Halted			     */
 #define Rx_Good		       0x00004000 /* Rx Good			     */
 #define Rx_RxPar	       0x00002000 /* Rx Parity Error		     */
-			    /* 0x00001000    not use			     */
+#define Rx_TypePkt	       0x00001000 /* Rx Type Packet		     */
 #define Rx_LongErr	       0x00000800 /* Rx Long Error		     */
 #define Rx_Over		       0x00000400 /* Rx Overflow		     */
 #define Rx_CRCErr	       0x00000200 /* Rx CRC Error		     */
@@ -244,8 +244,9 @@
 #define Rx_10Stat	       0x00000080 /* Rx 10Mbps Status		     */
 #define Rx_IntRx	       0x00000040 /* Rx Interrupt		     */
 #define Rx_CtlRecd	       0x00000020 /* Rx Control Receive		     */
+#define Rx_InLenErr	       0x00000010 /* Rx In Range Frame Length Error  */
 
-#define Rx_Stat_Mask	       0x0000EFC0 /* Rx All Status Mask		     */
+#define Rx_Stat_Mask	       0x0000FFF0 /* Rx All Status Mask		     */
 
 /* Int_En bit asign -------------------------------------------------------- */
 #define Int_NRAbtEn	       0x00000800 /* 1:Non-recoverable Abort Enable  */
@@ -865,7 +866,6 @@
 	struct net_device *dev;
 	struct tc35815_local *lp;
 	int rc;
-	DECLARE_MAC_BUF(mac);
 
 	static int printed_version;
 	if (!printed_version++) {
@@ -942,11 +942,11 @@
 		goto err_out;
 
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-	printk(KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+	printk(KERN_INFO "%s: %s at 0x%lx, %pM, IRQ %d\n",
 		dev->name,
 		chip_info[ent->driver_data].name,
 		dev->base_addr,
-		print_mac(mac, dev->dev_addr),
+		dev->dev_addr,
 		dev->irq);
 
 	rc = tc_mii_init(dev);
@@ -1288,12 +1288,9 @@
 
 static void print_eth(const u8 *add)
 {
-	DECLARE_MAC_BUF(mac);
-
 	printk(KERN_DEBUG "print_eth(%p)\n", add);
-	printk(KERN_DEBUG " %s =>", print_mac(mac, add + 6));
-	printk(KERN_CONT " %s : %02x%02x\n",
-		print_mac(mac, add), add[12], add[13]);
+	printk(KERN_DEBUG " %pM => %pM : %02x%02x\n",
+		add + 6, add, add[12], add[13]);
 }
 
 static int tc35815_tx_full(struct net_device *dev)
@@ -1760,7 +1757,6 @@
 #else
 			netif_rx(skb);
 #endif
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		} else {
@@ -2153,13 +2149,12 @@
 	int cam_index = index * 6;
 	u32 cam_data;
 	u32 saved_addr;
-	DECLARE_MAC_BUF(mac);
 
 	saved_addr = tc_readl(&tr->CAM_Adr);
 
 	if (netif_msg_hw(lp))
-		printk(KERN_DEBUG "%s: CAM %d: %s\n",
-			dev->name, index, print_mac(mac, addr));
+		printk(KERN_DEBUG "%s: CAM %d: %pM\n",
+			dev->name, index, addr);
 	if (index & 1) {
 		/* read modify write */
 		tc_writel(cam_index - 2, &tr->CAM_Adr);
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 91f9054..30d5065 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -1237,7 +1237,6 @@
 	ENTER;
 	max_done = budget;
 
-	priv->ndev->last_rx = jiffies;
 	f->m.wptr = READ_REG(priv, f->m.reg_WPTR) & TXF_WPTR_WR_PTR;
 
 	size = f->m.wptr - f->m.rptr;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index eb9f8f3..e05849e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -54,6 +54,9 @@
 #include <asm/prom.h>
 #endif
 
+#define BAR_0	0
+#define BAR_2	2
+
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define TG3_VLAN_TAG_USED 1
 #else
@@ -66,8 +69,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.94"
-#define DRV_MODULE_RELDATE	"August 14, 2008"
+#define DRV_MODULE_VERSION	"3.95"
+#define DRV_MODULE_RELDATE	"November 3, 2008"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -205,6 +208,8 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5785)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
@@ -872,13 +877,48 @@
 	return 0;
 }
 
-static void tg3_mdio_config(struct tg3 *tp)
+static void tg3_mdio_config_5785(struct tg3 *tp)
 {
 	u32 val;
+	struct phy_device *phydev;
 
-	if (tp->mdio_bus->phy_map[PHY_ADDR]->interface !=
-	    PHY_INTERFACE_MODE_RGMII)
+	phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+	switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+	case TG3_PHY_ID_BCM50610:
+		val = MAC_PHYCFG2_50610_LED_MODES;
+		break;
+	case TG3_PHY_ID_BCMAC131:
+		val = MAC_PHYCFG2_AC131_LED_MODES;
+		break;
+	case TG3_PHY_ID_RTL8211C:
+		val = MAC_PHYCFG2_RTL8211C_LED_MODES;
+		break;
+	case TG3_PHY_ID_RTL8201E:
+		val = MAC_PHYCFG2_RTL8201E_LED_MODES;
+		break;
+	default:
 		return;
+	}
+
+	if (phydev->interface != PHY_INTERFACE_MODE_RGMII) {
+		tw32(MAC_PHYCFG2, val);
+
+		val = tr32(MAC_PHYCFG1);
+		val &= ~MAC_PHYCFG1_RGMII_INT;
+		tw32(MAC_PHYCFG1, val);
+
+		return;
+	}
+
+	if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
+		val |= MAC_PHYCFG2_EMODE_MASK_MASK |
+		       MAC_PHYCFG2_FMODE_MASK_MASK |
+		       MAC_PHYCFG2_GMODE_MASK_MASK |
+		       MAC_PHYCFG2_ACT_MASK_MASK   |
+		       MAC_PHYCFG2_QUAL_MASK_MASK |
+		       MAC_PHYCFG2_INBAND_ENABLE;
+
+	tw32(MAC_PHYCFG2, val);
 
 	val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC |
 				    MAC_PHYCFG1_RGMII_SND_STAT_EN);
@@ -890,11 +930,6 @@
 	}
 	tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV);
 
-	val = tr32(MAC_PHYCFG2) & ~(MAC_PHYCFG2_INBAND_ENABLE);
-	if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
-		val |= MAC_PHYCFG2_INBAND_ENABLE;
-	tw32(MAC_PHYCFG2, val);
-
 	val = tr32(MAC_EXT_RGMII_MODE);
 	val &= ~(MAC_RGMII_MODE_RX_INT_B |
 		 MAC_RGMII_MODE_RX_QUALITY |
@@ -903,7 +938,7 @@
 		 MAC_RGMII_MODE_TX_ENABLE |
 		 MAC_RGMII_MODE_TX_LOWPWR |
 		 MAC_RGMII_MODE_TX_RESET);
-	if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) {
+	if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) {
 		if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
 			val |= MAC_RGMII_MODE_RX_INT_B |
 			       MAC_RGMII_MODE_RX_QUALITY |
@@ -929,8 +964,9 @@
 	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(80);
 
-	if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)
-		tg3_mdio_config(tp);
+	if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+		tg3_mdio_config_5785(tp);
 }
 
 static void tg3_mdio_stop(struct tg3 *tp)
@@ -984,29 +1020,41 @@
 	if (i) {
 		printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n",
 			tp->dev->name, i);
+		mdiobus_free(tp->mdio_bus);
 		return i;
 	}
 
-	tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
-
 	phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
-	switch (phydev->phy_id) {
+	if (!phydev || !phydev->drv) {
+		printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name);
+		mdiobus_unregister(tp->mdio_bus);
+		mdiobus_free(tp->mdio_bus);
+		return -ENODEV;
+	}
+
+	switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
 	case TG3_PHY_ID_BCM50610:
-		phydev->interface = PHY_INTERFACE_MODE_RGMII;
 		if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)
 			phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE;
 		if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
 			phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE;
 		if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN)
 			phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE;
+		/* fallthru */
+	case TG3_PHY_ID_RTL8211C:
+		phydev->interface = PHY_INTERFACE_MODE_RGMII;
 		break;
+	case TG3_PHY_ID_RTL8201E:
 	case TG3_PHY_ID_BCMAC131:
 		phydev->interface = PHY_INTERFACE_MODE_MII;
 		break;
 	}
 
-	tg3_mdio_config(tp);
+	tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+		tg3_mdio_config_5785(tp);
 
 	return 0;
 }
@@ -1299,6 +1347,15 @@
 		udelay(40);
 	}
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+		if (phydev->speed == SPEED_10)
+			tw32(MAC_MI_STAT,
+			     MAC_MI_STAT_10MBPS_MODE |
+			     MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+		else
+			tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+	}
+
 	if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF)
 		tw32(MAC_TX_LENGTHS,
 		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
@@ -1339,26 +1396,35 @@
 	phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
 	/* Attach the MAC to the PHY. */
-	phydev = phy_connect(tp->dev, phydev->dev.bus_id, tg3_adjust_link,
+	phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link,
 			     phydev->dev_flags, phydev->interface);
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name);
 		return PTR_ERR(phydev);
 	}
 
+	/* Mask with MAC supported features. */
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_GMII:
+	case PHY_INTERFACE_MODE_RGMII:
+		phydev->supported &= (PHY_GBIT_FEATURES |
+				      SUPPORTED_Pause |
+				      SUPPORTED_Asym_Pause);
+		break;
+	case PHY_INTERFACE_MODE_MII:
+		phydev->supported &= (PHY_BASIC_FEATURES |
+				      SUPPORTED_Pause |
+				      SUPPORTED_Asym_Pause);
+		break;
+	default:
+		phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+		return -EINVAL;
+	}
+
 	tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED;
 
-	/* Mask with MAC supported features. */
-	phydev->supported &= (PHY_GBIT_FEATURES |
-			      SUPPORTED_Pause |
-			      SUPPORTED_Asym_Pause);
-
 	phydev->advertising = phydev->supported;
 
-	printk(KERN_INFO
-	       "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
-	       tp->dev->name, phydev->drv->name, phydev->dev.bus_id);
-
 	return 0;
 }
 
@@ -1737,7 +1803,8 @@
 		tw32(TG3_CPMU_CTRL, cpmuctrl);
 	}
 
-	if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
 		u32 val;
 
 		val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
@@ -1961,7 +2028,7 @@
 static int tg3_nvram_lock(struct tg3 *);
 static void tg3_nvram_unlock(struct tg3 *);
 
-static void tg3_power_down_phy(struct tg3 *tp)
+static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
 	u32 val;
 
@@ -1984,10 +2051,15 @@
 		tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
 		udelay(40);
 		return;
-	} else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
+	} else if (do_low_power) {
 		tg3_writephy(tp, MII_TG3_EXT_CTRL,
 			     MII_TG3_EXT_CTRL_FORCE_LED_OFF);
-		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+
+		tg3_writephy(tp, MII_TG3_AUX_CTRL,
+			     MII_TG3_AUXCTL_SHDWSEL_PWRCTL |
+			     MII_TG3_AUXCTL_PCTL_100TX_LPWR |
+			     MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
+			     MII_TG3_AUXCTL_PCTL_VREG_11V);
 	}
 
 	/* The PHY should not be powered down on some chips because
@@ -1999,7 +2071,8 @@
 	     (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
 		return;
 
-	if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
 		val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
 		val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
 		val |= CPMU_LSPD_1000MB_MACCLK_12_5;
@@ -2009,9 +2082,47 @@
 	tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
 }
 
+/* tp->lock is held. */
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{
+	u32 addr_high, addr_low;
+	int i;
+
+	addr_high = ((tp->dev->dev_addr[0] << 8) |
+		     tp->dev->dev_addr[1]);
+	addr_low = ((tp->dev->dev_addr[2] << 24) |
+		    (tp->dev->dev_addr[3] << 16) |
+		    (tp->dev->dev_addr[4] <<  8) |
+		    (tp->dev->dev_addr[5] <<  0));
+	for (i = 0; i < 4; i++) {
+		if (i == 1 && skip_mac_1)
+			continue;
+		tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+	}
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+		for (i = 0; i < 12; i++) {
+			tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+			tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+		}
+	}
+
+	addr_high = (tp->dev->dev_addr[0] +
+		     tp->dev->dev_addr[1] +
+		     tp->dev->dev_addr[2] +
+		     tp->dev->dev_addr[3] +
+		     tp->dev->dev_addr[4] +
+		     tp->dev->dev_addr[5]) &
+		TX_BACKOFF_SEED_MASK;
+	tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
 static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 {
 	u32 misc_host_ctrl;
+	bool device_should_wake, do_low_power;
 
 	/* Make sure register accesses (indirect or otherwise)
 	 * will function correctly.
@@ -2045,11 +2156,16 @@
 	tw32(TG3PCI_MISC_HOST_CTRL,
 	     misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 
+	device_should_wake = pci_pme_capable(tp->pdev, state) &&
+			     device_may_wakeup(&tp->pdev->dev) &&
+			     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+
 	if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+		do_low_power = false;
 		if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) &&
 		    !tp->link_config.phy_is_low_power) {
 			struct phy_device *phydev;
-			u32 advertising;
+			u32 phyid, advertising;
 
 			phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
@@ -2066,7 +2182,7 @@
 				      ADVERTISED_10baseT_Half;
 
 			if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
-			    (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) {
+			    device_should_wake) {
 				if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)
 					advertising |=
 						ADVERTISED_100baseT_Half |
@@ -2079,8 +2195,19 @@
 			phydev->advertising = advertising;
 
 			phy_start_aneg(phydev);
+
+			phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
+			if (phyid != TG3_PHY_ID_BCMAC131) {
+				phyid &= TG3_PHY_OUI_MASK;
+				if (phyid == TG3_PHY_OUI_1 &&
+				    phyid == TG3_PHY_OUI_2 &&
+				    phyid == TG3_PHY_OUI_3)
+					do_low_power = true;
+			}
 		}
 	} else {
+		do_low_power = false;
+
 		if (tp->link_config.phy_is_low_power == 0) {
 			tp->link_config.phy_is_low_power = 1;
 			tp->link_config.orig_speed = tp->link_config.speed;
@@ -2096,6 +2223,8 @@
 		}
 	}
 
+	__tg3_set_mac_addr(tp, 0);
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		u32 val;
 
@@ -2118,11 +2247,11 @@
 						     WOL_DRV_WOL |
 						     WOL_SET_MAGIC_PKT);
 
-	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
+	if (device_should_wake) {
 		u32 mac_mode;
 
 		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
-			if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
+			if (do_low_power) {
 				tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
 				udelay(40);
 			}
@@ -2150,9 +2279,12 @@
 		if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
 			tw32(MAC_LED_CTRL, tp->led_ctrl);
 
-		if (pci_pme_capable(tp->pdev, state) &&
-		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))
-			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+		mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+		if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+		    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) &&
+		    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+		     (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
+			mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
 
 		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
 			mac_mode |= tp->mac_mode &
@@ -2224,10 +2356,10 @@
 		}
 	}
 
-	if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+	if (!(device_should_wake) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
 	    !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
-		tg3_power_down_phy(tp);
+		tg3_power_down_phy(tp, do_low_power);
 
 	tg3_frob_aux_power(tp);
 
@@ -2250,7 +2382,7 @@
 
 	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
-	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+	if (device_should_wake)
 		pci_enable_wake(tp->pdev, state, true);
 
 	/* Finally, set the new power state. */
@@ -3765,8 +3897,7 @@
 		err = tg3_setup_copper_phy(tp, force_reset);
 	}
 
-	if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-	    tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
 		u32 val, scale;
 
 		val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
@@ -4157,7 +4288,6 @@
 #endif
 			netif_receive_skb(skb);
 
-		tp->dev->last_rx = jiffies;
 		received++;
 		budget--;
 
@@ -5557,6 +5687,13 @@
 			event = APE_EVENT_STATUS_STATE_START;
 			break;
 		case RESET_KIND_SHUTDOWN:
+			/* With the interface we are currently using,
+			 * APE does not track driver state.  Wiping
+			 * out the HOST SEGMENT SIGNATURE forces
+			 * the APE to assume OS absent status.
+			 */
+			tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+
 			event = APE_EVENT_STATUS_STATE_UNLOAD;
 			break;
 		case RESET_KIND_SUSPEND:
@@ -5721,13 +5858,15 @@
 
 	pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
-	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
-		pcie_set_readrq(tp->pdev, 4096);
-	else {
-		pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
-				      tp->pci_cacheline_sz);
-		pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
-				      tp->pci_lat_timer);
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+		if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+			pcie_set_readrq(tp->pdev, 4096);
+		else {
+			pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+					      tp->pci_cacheline_sz);
+			pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+					      tp->pci_lat_timer);
+		}
 	}
 
 	/* Make sure PCI-X relaxed ordering bit is clear. */
@@ -5884,8 +6023,9 @@
 			pci_write_config_dword(tp->pdev, 0xc4,
 					       cfg_val | (1 << 15));
 		}
-		/* Set PCIE max payload size and clear error status.  */
-		pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785)
+			/* Set PCIE max payload size and clear error status.  */
+			pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
 	}
 
 	tg3_restore_pci_state(tp);
@@ -6883,43 +7023,6 @@
 }
 
 
-/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
-{
-	u32 addr_high, addr_low;
-	int i;
-
-	addr_high = ((tp->dev->dev_addr[0] << 8) |
-		     tp->dev->dev_addr[1]);
-	addr_low = ((tp->dev->dev_addr[2] << 24) |
-		    (tp->dev->dev_addr[3] << 16) |
-		    (tp->dev->dev_addr[4] <<  8) |
-		    (tp->dev->dev_addr[5] <<  0));
-	for (i = 0; i < 4; i++) {
-		if (i == 1 && skip_mac_1)
-			continue;
-		tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
-		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
-	}
-
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-		for (i = 0; i < 12; i++) {
-			tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
-			tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
-		}
-	}
-
-	addr_high = (tp->dev->dev_addr[0] +
-		     tp->dev->dev_addr[1] +
-		     tp->dev->dev_addr[2] +
-		     tp->dev->dev_addr[3] +
-		     tp->dev->dev_addr[4] +
-		     tp->dev->dev_addr[5]) &
-		TX_BACKOFF_SEED_MASK;
-	tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
 static int tg3_set_mac_addr(struct net_device *dev, void *p)
 {
 	struct tg3 *tp = netdev_priv(dev);
@@ -7024,8 +7127,7 @@
 
 	tg3_write_sig_legacy(tp, RESET_KIND_INIT);
 
-	if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-	    tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
 		val = tr32(TG3_CPMU_CTRL);
 		val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
 		tw32(TG3_CPMU_CTRL, val);
@@ -7091,8 +7193,7 @@
 		return err;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
 		/* This value is determined during the probe time DMA
 		 * engine test, tg3_test_dma.
 		 */
@@ -9066,7 +9167,8 @@
 	else
 		wol->supported = 0;
 	wol->wolopts = 0;
-	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+	    device_can_wakeup(&tp->pdev->dev))
 		wol->wolopts = WAKE_MAGIC;
 	memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
@@ -11299,7 +11401,7 @@
 		    (val & VCPU_CFGSHDW_WOL_MAGPKT) &&
 		    device_may_wakeup(&tp->pdev->dev))
 			tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
-		return;
+		goto done;
 	}
 
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
@@ -11421,15 +11523,17 @@
 			if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
 		}
-		if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE)
+
+		if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+			(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
 			tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE;
+
 		if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
 		    !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
 			tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
 		if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
-		    (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE) &&
-		    device_may_wakeup(&tp->pdev->dev))
+		    (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
 			tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
 
 		if (cfg2 & (1 << 17))
@@ -11455,6 +11559,10 @@
 		if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
 			tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN;
 	}
+done:
+	device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
+	device_set_wakeup_enable(&tp->pdev->dev,
+				 tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
 }
 
 static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
@@ -12091,7 +12199,8 @@
 			if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
 				tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
 		}
-	}
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
 	/* If we have an AMD 762 or VIA K8T800 chipset, write
 	 * reordering to the mailbox registers done by the host
@@ -12263,16 +12372,9 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
 		tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
-		if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-		    tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
-		    tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
-		    tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
-			tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
-	}
-
 	/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
 	 * GPIO1 driven high will bring 5700's external PHY out of reset.
 	 * It is also used as eeprom write protect on LOMs.
@@ -13245,14 +13347,12 @@
 				  const struct pci_device_id *ent)
 {
 	static int tg3_version_printed = 0;
-	resource_size_t tg3reg_base;
-	unsigned long tg3reg_len;
+	resource_size_t tg3reg_len;
 	struct net_device *dev;
 	struct tg3 *tp;
 	int err, pm_cap;
 	char str[40];
 	u64 dma_mask, persist_dma_mask;
-	DECLARE_MAC_BUF(mac);
 
 	if (tg3_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -13264,7 +13364,7 @@
 		return err;
 	}
 
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+	if (!(pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM)) {
 		printk(KERN_ERR PFX "Cannot find proper PCI device "
 		       "base address, aborting.\n");
 		err = -ENODEV;
@@ -13289,9 +13389,6 @@
 		goto err_out_free_res;
 	}
 
-	tg3reg_base = pci_resource_start(pdev, 0);
-	tg3reg_len = pci_resource_len(pdev, 0);
-
 	dev = alloc_etherdev(sizeof(*tp));
 	if (!dev) {
 		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
@@ -13343,7 +13440,11 @@
 	spin_lock_init(&tp->indirect_lock);
 	INIT_WORK(&tp->reset_task, tg3_reset_task);
 
-	tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
+	dev->mem_start = pci_resource_start(pdev, BAR_0);
+	tg3reg_len = pci_resource_len(pdev, BAR_0);
+	dev->mem_end = dev->mem_start + tg3reg_len;
+
+	tp->regs = ioremap_nocache(dev->mem_start, tg3reg_len);
 	if (!tp->regs) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -13466,17 +13567,14 @@
 	}
 
 	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
-		if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+		if (!(pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM)) {
 			printk(KERN_ERR PFX "Cannot find proper PCI device "
 			       "base address for APE, aborting.\n");
 			err = -ENODEV;
 			goto err_out_iounmap;
 		}
 
-		tg3reg_base = pci_resource_start(pdev, 2);
-		tg3reg_len = pci_resource_len(pdev, 2);
-
-		tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+		tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
 		if (!tp->aperegs) {
 			printk(KERN_ERR PFX "Cannot map APE registers, "
 			       "aborting.\n");
@@ -13535,26 +13633,34 @@
 		goto err_out_apeunmap;
 	}
 
-	printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] "
-	       "(%s) %s Ethernet %s\n",
+	printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n",
 	       dev->name,
 	       tp->board_part_number,
 	       tp->pci_chip_rev_id,
-	       tg3_phy_string(tp),
 	       tg3_bus_string(tp, str),
-	       ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
-		((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
-		 "10/100/1000Base-T")),
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
-	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
-	       "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
+	if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)
+		printk(KERN_INFO
+		       "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+		       tp->dev->name,
+		       tp->mdio_bus->phy_map[PHY_ADDR]->drv->name,
+		       dev_name(&tp->mdio_bus->phy_map[PHY_ADDR]->dev));
+	else
+		printk(KERN_INFO
+		       "%s: attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n",
+		       tp->dev->name, tg3_phy_string(tp),
+		       ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+			((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+			 "10/100/1000Base-T")),
+		       (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0);
+
+	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
 	       dev->name,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
 	       (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
-	       (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
 	       (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
 	printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
 	       dev->name, tp->dma_rwctrl,
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index be252ab..599e490 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -38,6 +38,8 @@
 #define  TG3PCI_DEVICE_TIGON3_2		 0x1645 /* BCM5701 */
 #define  TG3PCI_DEVICE_TIGON3_3		 0x1646 /* BCM5702 */
 #define  TG3PCI_DEVICE_TIGON3_4		 0x1647 /* BCM5703 */
+#define  TG3PCI_DEVICE_TIGON3_5761S	 0x1688
+#define  TG3PCI_DEVICE_TIGON3_5761SE	 0x1689
 #define TG3PCI_COMMAND			0x00000004
 #define TG3PCI_STATUS			0x00000006
 #define TG3PCI_CCREVID			0x00000008
@@ -325,6 +327,7 @@
 #define  MAC_MODE_TDE_ENABLE		 0x00200000
 #define  MAC_MODE_RDE_ENABLE		 0x00400000
 #define  MAC_MODE_FHDE_ENABLE		 0x00800000
+#define  MAC_MODE_KEEP_FRAME_IN_WOL	 0x01000000
 #define  MAC_MODE_APE_RX_EN		 0x08000000
 #define  MAC_MODE_APE_TX_EN		 0x10000000
 #define MAC_STATUS			0x00000404
@@ -414,6 +417,7 @@
 #define  MI_COM_DATA_MASK		 0x0000ffff
 #define MAC_MI_STAT			0x00000450
 #define  MAC_MI_STAT_LNKSTAT_ATTN_ENAB	 0x00000001
+#define  MAC_MI_STAT_10MBPS_MODE	 0x00000002
 #define MAC_MI_MODE			0x00000454
 #define  MAC_MI_MODE_CLK_10MHZ		 0x00000001
 #define  MAC_MI_MODE_SHORT_PREAMBLE	 0x00000002
@@ -539,6 +543,100 @@
 #define  MAC_PHYCFG1_TXC_DRV		 0x20000000
 #define MAC_PHYCFG2			0x000005a4
 #define  MAC_PHYCFG2_INBAND_ENABLE	 0x00000001
+#define  MAC_PHYCFG2_EMODE_MASK_MASK	 0x000001c0
+#define  MAC_PHYCFG2_EMODE_MASK_AC131	 0x000000c0
+#define  MAC_PHYCFG2_EMODE_MASK_50610	 0x00000100
+#define  MAC_PHYCFG2_EMODE_MASK_RT8211	 0x00000000
+#define  MAC_PHYCFG2_EMODE_MASK_RT8201	 0x000001c0
+#define  MAC_PHYCFG2_EMODE_COMP_MASK	 0x00000e00
+#define  MAC_PHYCFG2_EMODE_COMP_AC131	 0x00000600
+#define  MAC_PHYCFG2_EMODE_COMP_50610	 0x00000400
+#define  MAC_PHYCFG2_EMODE_COMP_RT8211	 0x00000800
+#define  MAC_PHYCFG2_EMODE_COMP_RT8201	 0x00000000
+#define  MAC_PHYCFG2_FMODE_MASK_MASK	 0x00007000
+#define  MAC_PHYCFG2_FMODE_MASK_AC131	 0x00006000
+#define  MAC_PHYCFG2_FMODE_MASK_50610	 0x00004000
+#define  MAC_PHYCFG2_FMODE_MASK_RT8211	 0x00000000
+#define  MAC_PHYCFG2_FMODE_MASK_RT8201	 0x00007000
+#define  MAC_PHYCFG2_FMODE_COMP_MASK	 0x00038000
+#define  MAC_PHYCFG2_FMODE_COMP_AC131	 0x00030000
+#define  MAC_PHYCFG2_FMODE_COMP_50610	 0x00008000
+#define  MAC_PHYCFG2_FMODE_COMP_RT8211	 0x00038000
+#define  MAC_PHYCFG2_FMODE_COMP_RT8201	 0x00000000
+#define  MAC_PHYCFG2_GMODE_MASK_MASK	 0x001c0000
+#define  MAC_PHYCFG2_GMODE_MASK_AC131	 0x001c0000
+#define  MAC_PHYCFG2_GMODE_MASK_50610	 0x00100000
+#define  MAC_PHYCFG2_GMODE_MASK_RT8211	 0x00000000
+#define  MAC_PHYCFG2_GMODE_MASK_RT8201	 0x001c0000
+#define  MAC_PHYCFG2_GMODE_COMP_MASK	 0x00e00000
+#define  MAC_PHYCFG2_GMODE_COMP_AC131	 0x00e00000
+#define  MAC_PHYCFG2_GMODE_COMP_50610	 0x00000000
+#define  MAC_PHYCFG2_GMODE_COMP_RT8211	 0x00200000
+#define  MAC_PHYCFG2_GMODE_COMP_RT8201	 0x00000000
+#define  MAC_PHYCFG2_ACT_MASK_MASK	 0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_AC131	 0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_50610	 0x01000000
+#define  MAC_PHYCFG2_ACT_MASK_RT8211	 0x03000000
+#define  MAC_PHYCFG2_ACT_MASK_RT8201	 0x01000000
+#define  MAC_PHYCFG2_ACT_COMP_MASK	 0x0c000000
+#define  MAC_PHYCFG2_ACT_COMP_AC131	 0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_50610	 0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_RT8211	 0x00000000
+#define  MAC_PHYCFG2_ACT_COMP_RT8201	 0x08000000
+#define  MAC_PHYCFG2_QUAL_MASK_MASK	 0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_AC131	 0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_50610	 0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_RT8211	 0x30000000
+#define  MAC_PHYCFG2_QUAL_MASK_RT8201	 0x30000000
+#define  MAC_PHYCFG2_QUAL_COMP_MASK	 0xc0000000
+#define  MAC_PHYCFG2_QUAL_COMP_AC131	 0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_50610	 0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_RT8211	 0x00000000
+#define  MAC_PHYCFG2_QUAL_COMP_RT8201	 0x00000000
+#define MAC_PHYCFG2_50610_LED_MODES \
+	(MAC_PHYCFG2_EMODE_MASK_50610 | \
+	 MAC_PHYCFG2_EMODE_COMP_50610 | \
+	 MAC_PHYCFG2_FMODE_MASK_50610 | \
+	 MAC_PHYCFG2_FMODE_COMP_50610 | \
+	 MAC_PHYCFG2_GMODE_MASK_50610 | \
+	 MAC_PHYCFG2_GMODE_COMP_50610 | \
+	 MAC_PHYCFG2_ACT_MASK_50610 | \
+	 MAC_PHYCFG2_ACT_COMP_50610 | \
+	 MAC_PHYCFG2_QUAL_MASK_50610 | \
+	 MAC_PHYCFG2_QUAL_COMP_50610)
+#define MAC_PHYCFG2_AC131_LED_MODES \
+	(MAC_PHYCFG2_EMODE_MASK_AC131 | \
+	 MAC_PHYCFG2_EMODE_COMP_AC131 | \
+	 MAC_PHYCFG2_FMODE_MASK_AC131 | \
+	 MAC_PHYCFG2_FMODE_COMP_AC131 | \
+	 MAC_PHYCFG2_GMODE_MASK_AC131 | \
+	 MAC_PHYCFG2_GMODE_COMP_AC131 | \
+	 MAC_PHYCFG2_ACT_MASK_AC131 | \
+	 MAC_PHYCFG2_ACT_COMP_AC131 | \
+	 MAC_PHYCFG2_QUAL_MASK_AC131 | \
+	 MAC_PHYCFG2_QUAL_COMP_AC131)
+#define MAC_PHYCFG2_RTL8211C_LED_MODES \
+	(MAC_PHYCFG2_EMODE_MASK_RT8211 | \
+	 MAC_PHYCFG2_EMODE_COMP_RT8211 | \
+	 MAC_PHYCFG2_FMODE_MASK_RT8211 | \
+	 MAC_PHYCFG2_FMODE_COMP_RT8211 | \
+	 MAC_PHYCFG2_GMODE_MASK_RT8211 | \
+	 MAC_PHYCFG2_GMODE_COMP_RT8211 | \
+	 MAC_PHYCFG2_ACT_MASK_RT8211 | \
+	 MAC_PHYCFG2_ACT_COMP_RT8211 | \
+	 MAC_PHYCFG2_QUAL_MASK_RT8211 | \
+	 MAC_PHYCFG2_QUAL_COMP_RT8211)
+#define MAC_PHYCFG2_RTL8201E_LED_MODES \
+	(MAC_PHYCFG2_EMODE_MASK_RT8201 | \
+	 MAC_PHYCFG2_EMODE_COMP_RT8201 | \
+	 MAC_PHYCFG2_FMODE_MASK_RT8201 | \
+	 MAC_PHYCFG2_FMODE_COMP_RT8201 | \
+	 MAC_PHYCFG2_GMODE_MASK_RT8201 | \
+	 MAC_PHYCFG2_GMODE_COMP_RT8201 | \
+	 MAC_PHYCFG2_ACT_MASK_RT8201 | \
+	 MAC_PHYCFG2_ACT_COMP_RT8201 | \
+	 MAC_PHYCFG2_QUAL_MASK_RT8201 | \
+	 MAC_PHYCFG2_QUAL_COMP_RT8201)
 #define MAC_EXT_RGMII_MODE		0x000005a8
 #define  MAC_RGMII_MODE_TX_ENABLE	 0x00000001
 #define  MAC_RGMII_MODE_TX_LOWPWR	 0x00000002
@@ -1792,6 +1890,11 @@
 
 #define MII_TG3_AUX_CTRL		0x18 /* auxilliary control register */
 
+#define MII_TG3_AUXCTL_PCTL_100TX_LPWR	0x0010
+#define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE	0x0020
+#define MII_TG3_AUXCTL_PCTL_VREG_11V	0x0180
+#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL	0x0002
+
 #define MII_TG3_AUXCTL_MISC_WREN	0x8000
 #define MII_TG3_AUXCTL_MISC_FORCE_AMDIX	0x0200
 #define MII_TG3_AUXCTL_MISC_RDSEL_MISC	0x7000
@@ -2507,7 +2610,6 @@
 	u32				tg3_flags3;
 #define TG3_FLG3_NO_NVRAM_ADDR_TRANS	0x00000001
 #define TG3_FLG3_ENABLE_APE		0x00000002
-#define TG3_FLG3_5761_5784_AX_FIXES	0x00000004
 #define TG3_FLG3_5701_DMA_BUG		0x00000008
 #define TG3_FLG3_USE_PHYLIB		0x00000010
 #define TG3_FLG3_MDIOBUS_INITED		0x00000020
@@ -2588,7 +2690,12 @@
 #define PHY_REV_BCM5411_X0		0x1 /* Found on Netgear GA302T */
 #define TG3_PHY_ID_BCM50610		0x143bd60
 #define TG3_PHY_ID_BCMAC131		0x143bc70
-
+#define TG3_PHY_ID_RTL8211C		0x001cc910
+#define TG3_PHY_ID_RTL8201E		0x00008200
+#define TG3_PHY_OUI_MASK		0xfffffc00
+#define TG3_PHY_OUI_1			0x00206000
+#define TG3_PHY_OUI_2			0x0143bc00
+#define TG3_PHY_OUI_3			0x03625c00
 
 	u32				led_ctrl;
 	u32				phy_otp;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index c41d687..055d342 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -1649,8 +1649,6 @@
 		}
 	}
 
-	dev->last_rx = jiffies;
-
 	return ack;
 
 } /* TLan_HandleRxEOF */
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index bf62132..87509a6 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -974,7 +974,6 @@
 
 			netif_rx(skb2) ; 		
 		 } /* if multiple buffers */
-		dev->last_rx = jiffies ; 	
 	} /* while packet to do */
 
 	/* Clear the updComplete interrupt */
@@ -1571,7 +1570,6 @@
 		 * anyway.
 		 */
 
-		dev->last_rx = jiffies ; 
 		/* Acknowledge interrupt, this tells nic we are done with the arb */
 		writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
 
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 7a7de04..b566d6d 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -99,7 +99,6 @@
 	struct net_local *tp;
 	int ret, pci_irq_line;
 	unsigned long pci_ioaddr;
-	DECLARE_MAC_BUF(mac);
 	
 	if (versionprinted++ == 0)
 		printk("%s", version);
@@ -147,8 +146,7 @@
 
 	abyss_read_eeprom(dev);
 
-	printk("%s:    Ring Station Address: %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk("%s:    Ring Station Address: %pM\n", dev->name, dev->dev_addr);
 
 	tp = netdev_priv(dev);
 	tp->setnselout = abyss_setnselout_pins;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index e494c63..9fd0993 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -389,7 +389,6 @@
         unsigned long timeout;
 	static int version_printed;
 #endif
-	DECLARE_MAC_BUF(mac);
 
 	/*    Query the adapter PIO base port which will return
 	 *    indication of where MMIO was placed. We also have a
@@ -703,8 +702,7 @@
 		channel_def[cardpresent - 1], adapter_def(ti->adapter_type));
 	DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n",
 			irq, PIOaddr, ti->mapped_ram_size / 2);
-	DPRINTK("Hardware address : %s\n",
-		print_mac(mac, dev->dev_addr));
+	DPRINTK("Hardware address : %pM\n", dev->dev_addr);
 	if (ti->page_mask)
 		DPRINTK("Shared RAM paging enabled. "
 			"Page size: %uK Shared Ram size %dK\n",
@@ -1741,8 +1739,6 @@
 		void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
 		u8 saddr[6];
 		u8 daddr[6];
-		DECLARE_MAC_BUF(mac);
-		DECLARE_MAC_BUF(mac2);
 		int i;
 		for (i = 0 ; i < 6 ; i++)
 			saddr[i] = readb(trhhdr + SADDR_OFST + i);
@@ -1750,9 +1746,9 @@
 			daddr[i] = readb(trhhdr + DADDR_OFST + i);
 		DPRINTK("Probably non-IP frame received.\n");
 		DPRINTK("ssap: %02X dsap: %02X "
-			"saddr: %s daddr: %$s\n",
+			"saddr: %pM daddr: %pM\n",
 			readb(llc + SSAP_OFST), readb(llc + DSAP_OFST),
-			print_mac(mac, saddr), print_mac(mac2, daddr));
+			saddr, daddr);
 	}
 #endif
 
@@ -1826,7 +1822,6 @@
 		skb->ip_summed = CHECKSUM_COMPLETE;
 	}
 	netif_rx(skb);
-	dev->last_rx = jiffies;
 }				/*tr_rx */
 
 /*****************************************************************************/
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 59d1673..239c752 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -446,9 +446,6 @@
 	unsigned int uaa_addr;
 	struct sk_buff *skb = NULL;
 	__u16 misr;
-#if STREAMER_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
 
 	streamer_priv = netdev_priv(dev);
 	streamer_mmio = streamer_priv->streamer_mmio;
@@ -577,8 +574,7 @@
 			dev->dev_addr[i+1]= addr & 0xff;
 		}
 #if STREAMER_DEBUG
-		printk("Adapter address: %s\n",
-		       print_mac(mac, dev->dev_addr));
+		printk("Adapter address: %pM\n", dev->dev_addr);
 #endif
 	}
 	return 0;
@@ -1013,7 +1009,6 @@
 					/* send up to the protocol */
 					netif_rx(skb);
 				}
-				dev->last_rx = jiffies;
 				streamer_priv->streamer_stats.rx_packets++;
 				streamer_priv->streamer_stats.rx_bytes += length;
 			}	/* if skb == null */
@@ -1538,7 +1533,6 @@
 
 #if STREAMER_NETWORK_MONITOR
 	struct trh_hdr *mac_hdr;
-	DECLARE_MAC_BUF(mac);
 #endif
 
 	writew(streamer_priv->arb, streamer_mmio + LAPA);
@@ -1611,11 +1605,11 @@
 		       dev->name);
 		mac_hdr = tr_hdr(mac_frame);
 		printk(KERN_WARNING
-		       "%s: MAC Frame Dest. Addr: %s\n",
-		       dev->name, print_mac(mac, mac_hdr->daddr));
+		       "%s: MAC Frame Dest. Addr: %pM\n",
+		       dev->name, mac_hdr->daddr);
 		printk(KERN_WARNING
-		       "%s: MAC Frame Srce. Addr: %s\n",
-		       dev->name, DEV->ADDR6(mac_hdr->saddr));
+		       "%s: MAC Frame Srce. Addr: %pM\n",
+		       dev->name, mac_hdr->saddr);
 #endif
 		netif_rx(mac_frame);
 
@@ -1850,8 +1844,6 @@
 	struct streamer_parameters_table spt;
 	int size = 0;
 	int i;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA);
 	for (i = 0; i < 14; i += 2) {
@@ -1873,9 +1865,8 @@
 	size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n", dev->name);
 
 	size += sprintf(buffer + size,
-			"%6s: %s : %s : %02x:%02x:%02x:%02x\n",
-			dev->name, print_mac(mac, dev->dev_addr),
-			print_mac(mac2, sat.node_addr),
+			"%6s: %pM : %pM : %02x:%02x:%02x:%02x\n",
+			dev->name, dev->dev_addr, sat.node_addr,
 			sat.func_addr[0], sat.func_addr[1],
 			sat.func_addr[2], sat.func_addr[3]);
 
@@ -1884,19 +1875,18 @@
 	size += sprintf(buffer + size, "%6s: Physical Addr : Up Node Address   : Poll Address      : AccPri : Auth Src : Att Code :\n", dev->name);
 
 	size += sprintf(buffer + size,
-		    "%6s: %02x:%02x:%02x:%02x   : %s : %s : %04x   : %04x     :  %04x    :\n",
+		    "%6s: %02x:%02x:%02x:%02x   : %pM : %pM : %04x   : %04x     :  %04x    :\n",
 		    dev->name, spt.phys_addr[0], spt.phys_addr[1],
 		    spt.phys_addr[2], spt.phys_addr[3],
-		    print_mac(mac, spt.up_node_addr),
-		    print_mac(mac2, spt.poll_addr),
+		    spt.up_node_addr, spt.poll_addr,
 		    ntohs(spt.acc_priority), ntohs(spt.auth_source_class),
 		    ntohs(spt.att_code));
 
 	size += sprintf(buffer + size, "%6s: Source Address    : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name);
 
 	size += sprintf(buffer + size,
-		    "%6s: %s : %04x  : %04x   : %04x   : %04x   : %04x    :     %04x     : \n",
-		    dev->name, print_mac(mac, spt.source_addr),
+		    "%6s: %pM : %04x  : %04x   : %04x   : %04x   : %04x    :     %04x     : \n",
+		    dev->name, spt.source_addr,
 		    ntohs(spt.beacon_type), ntohs(spt.major_vector),
 		    ntohs(spt.lan_status), ntohs(spt.local_ring),
 		    ntohs(spt.mon_error), ntohs(spt.frame_correl));
@@ -1905,10 +1895,10 @@
 		    dev->name);
 
 	size += sprintf(buffer + size,
-		    "%6s:                :  %02x  :  %02x  : %s : %02x:%02x:%02x:%02x    : \n",
+		    "%6s:                :  %02x  :  %02x  : %pM : %02x:%02x:%02x:%02x    : \n",
 		    dev->name, ntohs(spt.beacon_transmit),
 		    ntohs(spt.beacon_receive),
-		    print_mac(mac, spt.beacon_naun),
+		    spt.beacon_naun,
 		    spt.beacon_phys[0], spt.beacon_phys[1],
 		    spt.beacon_phys[2], spt.beacon_phys[3]);
 	return size;
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index c9c5a2b..0ba6f0b 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -152,7 +152,6 @@
 	struct card_info *card;
 	struct mca_device *mdev = to_mca_device(device);
 	int ret = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (versionprinted++ == 0)
 		printk("%s", version);
@@ -323,8 +322,8 @@
 	mca_device_set_name(mdev, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
 	mca_set_adapter_procfn(mdev->slot, madgemc_mcaproc, dev);
 
-	printk("%s:     Ring Station Address: %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk("%s:     Ring Station Address: %pM\n",
+	       dev->name, dev->dev_addr);
 
 	if (tmsdev_init(dev, device)) {
 		printk("%s: unable to get memory for dev->priv.\n", 
@@ -690,7 +689,6 @@
 	struct net_local *tp = netdev_priv(dev);
 	struct card_info *curcard = tp->tmspriv;
 	int len = 0;
-	DECLARE_MAC_BUF(mac);
 	
 	len += sprintf(buf+len, "-------\n");
 	if (curcard) {
@@ -714,8 +712,8 @@
 		}
 		len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair");
 		
-		len += sprintf(buf+len, "Ring Station Address: %s\n",
-			       print_mac(mac, dev->dev_addr));
+		len += sprintf(buf+len, "Ring Station Address: %pM\n",
+			       dev->dev_addr);
 	} else 
 		len += sprintf(buf+len, "Card not configured\n");
 
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 0ab51a0..ecb5c7c 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -421,10 +421,7 @@
 	memcpy_fromio(&dev->dev_addr[0], adapter_addr,6);
 
 #if OLYMPIC_DEBUG
- {
-	DECLARE_MAC_BUF(mac);
-	printk("adapter address: %s\n", print_mac(mac, dev->dev_addr));
- }
+	printk("adapter address: %pM\n", dev->dev_addr);
 #endif
 
 	olympic_priv->olympic_addr_table_addr = swab16(readw(init_srb + 12)); 
@@ -441,7 +438,6 @@
 	unsigned long flags, t;
 	int i, open_finished = 1 ;
 	u8 resp, err;
-	DECLARE_MAC_BUF(mac);
 
 	DECLARE_WAITQUEUE(wait,current) ; 
 
@@ -569,8 +565,8 @@
 			goto out;
 
 		case 0x32:
-			printk(KERN_WARNING "%s: Invalid LAA: %s\n",
-			       dev->name, print_mac(mac, olympic_priv->olympic_laa));
+			printk(KERN_WARNING "%s: Invalid LAA: %pM\n",
+			       dev->name, olympic_priv->olympic_laa);
 			goto out;
 
 		default:
@@ -704,13 +700,12 @@
 		u8 __iomem *opt;
 		int i;
 		u8 addr[6];
-		DECLARE_MAC_BUF(mac);
 		oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr);
 		opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr);
 
 		for (i = 0; i < 6; i++)
 			addr[i] = readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+i);
-		printk("%s: Node Address: %s\n",dev->name, print_mac(mac, addr));
+		printk("%s: Node Address: %pM\n", dev->name, addr);
 		printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name, 
 			readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), 
 			readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
@@ -719,7 +714,7 @@
 
 		for (i = 0; i < 6; i++)
 			addr[i] = readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+i);
-		printk("%s: NAUN Address: %s\n",dev->name, print_mac(mac, addr));
+		printk("%s: NAUN Address: %pM\n", dev->name, addr);
 	}
 	
 	netif_start_queue(dev);
@@ -867,7 +862,6 @@
 						skb->protocol = tr_type_trans(skb,dev);
 						netif_rx(skb) ; 
 					} 
-					dev->last_rx = jiffies ; 
 					olympic_priv->olympic_stats.rx_packets++ ; 
 					olympic_priv->olympic_stats.rx_bytes += length ; 
 				} /* if skb == null */
@@ -1440,19 +1434,12 @@
 			struct trh_hdr *mac_hdr;
 			printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name);
 			mac_hdr = tr_hdr(mac_frame);
-			printk(KERN_WARNING "%s: MAC Frame Dest. Addr: "
-			       MAC_FMT " \n", dev->name,
-			       mac_hdr->daddr[0], mac_hdr->daddr[1],
-			       mac_hdr->daddr[2], mac_hdr->daddr[3],
-			       mac_hdr->daddr[4], mac_hdr->daddr[5]);
-			printk(KERN_WARNING "%s: MAC Frame Srce. Addr: "
-			       MAC_FMT " \n", dev->name,
-			       mac_hdr->saddr[0], mac_hdr->saddr[1],
-			       mac_hdr->saddr[2], mac_hdr->saddr[3],
-			       mac_hdr->saddr[4], mac_hdr->saddr[5]);
+			printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %pM\n",
+			       dev->name, mac_hdr->daddr);
+			printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %pM\n",
+			       dev->name, mac_hdr->saddr);
 		}
 		netif_rx(mac_frame);
-		dev->last_rx = jiffies;
 
 drop_frame:
 		/* Now tell the card we have dealt with the received frame */
@@ -1647,8 +1634,6 @@
 	u8 addr[6];
 	u8 addr2[6];
 	int i;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	size = sprintf(buffer, 
 		"IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapter %s\n",dev->name);
@@ -1658,10 +1643,9 @@
 	for (i = 0 ; i < 6 ; i++)
 		addr[i] = readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr) + i);
 
-	size += sprintf(buffer+size, "%6s: %s : %s : %02x:%02x:%02x:%02x\n",
+	size += sprintf(buffer+size, "%6s: %pM : %pM : %02x:%02x:%02x:%02x\n",
 	   dev->name,
-	   print_mac(mac, dev->dev_addr),
-	   print_mac(mac2, addr),
+	   dev->dev_addr, addr,
 	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), 
 	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
 	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
@@ -1677,14 +1661,13 @@
 	for (i = 0 ; i < 6 ; i++)
 		addr2[i] =  readb(opt+offsetof(struct olympic_parameters_table, poll_addr) + i);
 
-	size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x   : %s : %s : %04x   : %04x     :  %04x    :\n",
+	size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x   : %pM : %pM : %04x   : %04x     :  %04x    :\n",
 	  dev->name,
 	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)),
 	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1),
 	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2),
 	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3),
-	  print_mac(mac, addr),
-	  print_mac(mac2, addr2),
+	  addr, addr2,
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))),
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))),
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code))));
@@ -1694,9 +1677,8 @@
 	
 	for (i = 0 ; i < 6 ; i++)
 		addr[i] = readb(opt+offsetof(struct olympic_parameters_table, source_addr) + i);
-	size += sprintf(buffer+size, "%6s: %s : %04x  : %04x   : %04x   : %04x   : %04x    :     %04x     : \n",
-	  dev->name,
-	  print_mac(mac, addr),
+	size += sprintf(buffer+size, "%6s: %pM : %04x  : %04x   : %04x   : %04x   : %04x    :     %04x     : \n",
+	  dev->name, addr,
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))),
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))),
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, lan_status))),
@@ -1709,11 +1691,11 @@
 
 	for (i = 0 ; i < 6 ; i++)
 		addr[i] = readb(opt+offsetof(struct olympic_parameters_table, beacon_naun) + i);
-	size += sprintf(buffer+size, "%6s:                :  %02x  :  %02x  : %s : %02x:%02x:%02x:%02x    : \n",
+	size += sprintf(buffer+size, "%6s:                :  %02x  :  %02x  : %pM : %02x:%02x:%02x:%02x    : \n",
 	  dev->name,
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))),
 	  swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))),
-	  print_mac(mac, addr),
+	  addr,
 	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)),
 	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1),
 	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2),
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 00ea945..cd2d62f 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -122,7 +122,6 @@
         static int versionprinted;
 	const unsigned *port;
 	int j,err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (!dev)
 		return -ENOMEM;
@@ -153,8 +152,8 @@
 		
 	proteon_read_eeprom(dev);
 
-	printk(KERN_DEBUG "proteon.c:    Ring Station Address: %s\n",
-	       print_mac(mac, dev->dev_addr));
+	printk(KERN_DEBUG "proteon.c:    Ring Station Address: %pM\n",
+	       dev->dev_addr);
 		
 	tp = netdev_priv(dev);
 	tp->setnselout = proteon_setnselout_pins;
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index 41b6999..b578744 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -139,7 +139,6 @@
         static int versionprinted;
 	const unsigned *port;
 	int j, err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (!dev)
 		return -ENOMEM;
@@ -170,8 +169,8 @@
 		
 	sk_isa_read_eeprom(dev);
 
-	printk(KERN_DEBUG "skisa.c:    Ring Station Address: %s\n",
-	       print_mac(mac, dev->dev_addr));
+	printk(KERN_DEBUG "skisa.c:    Ring Station Address: %pM\n",
+	       dev->dev_addr);
 		
 	tp = netdev_priv(dev);
 	tp->setnselout = sk_isa_setnselout_pins;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index ed50d28..a011666 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3910,7 +3910,6 @@
                 /* Kick the packet on up. */
                 skb->protocol = tr_type_trans(skb, dev);
                 netif_rx(skb);
-		dev->last_rx = jiffies;
                 err = 0;
         }
 
@@ -4496,7 +4495,6 @@
                                 	/* Kick the packet on up. */
                                 	skb->protocol = tr_type_trans(skb, dev);
                                 	netif_rx(skb);
-					dev->last_rx = jiffies;
 				} else {
 				}
                         }
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index d07c452..b408397 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -2186,7 +2186,6 @@
 				skb_trim(skb,Length);
 				skb->protocol = tr_type_trans(skb,dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 			}
 		}
 		else	/* Invalid frame */
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 5f0ee88..5f60177 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -100,7 +100,6 @@
 	unsigned int pci_irq_line;
 	unsigned long pci_ioaddr;
 	struct card_info *cardinfo = &card_info_table[ent->driver_data];
-	DECLARE_MAC_BUF(mac);
 
 	if (versionprinted++ == 0)
 		printk("%s", version);
@@ -137,8 +136,8 @@
 		
 	tms_pci_read_eeprom(dev);
 
-	printk("%s:    Ring Station Address: %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk("%s:    Ring Station Address: %pM\n",
+	       dev->name, dev->dev_addr);
 		
 	ret = tmsdev_init(dev, &pdev->dev);
 	if (ret) {
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index eb1da6f..271bc23 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -788,7 +788,6 @@
 		skb_put(skb, data->rxring[rx].len);
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_receive_skb(skb);
-		dev->last_rx = jiffies;
 	}
 
 	return done;
@@ -1569,7 +1568,6 @@
 	struct tsi108_prv_data *data = NULL;
 	hw_info *einfo;
 	int err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	einfo = pdev->dev.platform_data;
 
@@ -1659,8 +1657,8 @@
 	}
 
 	platform_set_drvdata(pdev, dev);
-	printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %pM\n",
+	       dev->name, dev->dev_addr);
 #ifdef DEBUG
 	data->msg_enable = DEBUG;
 	dump_eth_one(dev);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 124d5d6..e23a508 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -459,7 +459,6 @@
 
 		de->net_stats.rx_packets++;
 		de->net_stats.rx_bytes += skb->len;
-		de->dev->last_rx = jiffies;
 		rc = netif_rx (skb);
 		if (rc == NET_RX_DROP)
 			drop = 1;
@@ -1932,7 +1931,6 @@
 	void __iomem *regs;
 	unsigned long pciaddr;
 	static int board_idx = -1;
-	DECLARE_MAC_BUF(mac);
 
 	board_idx++;
 
@@ -2046,11 +2044,11 @@
 		goto err_out_iomap;
 
 	/* print info about board and interface just registered */
-	printk (KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+	printk (KERN_INFO "%s: %s at 0x%lx, %pM, IRQ %d\n",
 		dev->name,
 		de->de21040 ? "21040" : "21041",
 		dev->base_addr,
-		print_mac(mac, dev->dev_addr),
+		dev->dev_addr,
 		dev->irq);
 
 	pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 6444cbe..67bfd6f 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1085,7 +1085,6 @@
     struct de4x5_private *lp = netdev_priv(dev);
     struct pci_dev *pdev = NULL;
     int i, status=0;
-    DECLARE_MAC_BUF(mac);
 
     gendev->driver_data = dev;
 
@@ -1119,10 +1118,10 @@
     }
 
     dev->base_addr = iobase;
-    printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase);
+    printk ("%s: %s at 0x%04lx", dev_name(gendev), name, iobase);
 
     status = get_hw_addr(dev);
-    printk(", h/w address %s\n", print_mac(mac, dev->dev_addr));
+    printk(", h/w address %pM\n", dev->dev_addr);
 
     if (status != 0) {
 	printk("      which has an Ethernet PROM CRC error.\n");
@@ -1154,7 +1153,7 @@
             }
         }
 	lp->fdx = lp->params.fdx;
-	sprintf(lp->adapter_name,"%s (%s)", name, gendev->bus_id);
+	sprintf(lp->adapter_name,"%s (%s)", name, dev_name(gendev));
 
 	lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);
 #if defined(__alpha__) || defined(__powerpc__) || defined(CONFIG_SPARC) || defined(DE4X5_DO_MEMCPY)
@@ -1647,7 +1646,6 @@
 		    netif_rx(skb);
 
 		    /* Update stats */
-		    dev->last_rx = jiffies;
 		    lp->stats.rx_packets++;
  		    lp->stats.rx_bytes += pkt_len;
 		}
@@ -5401,7 +5399,6 @@
 de4x5_dbg_srom(struct de4x5_srom *p)
 {
     int i;
-    DECLARE_MAC_BUF(mac);
 
     if (de4x5_debug & DEBUG_SROM) {
 	printk("Sub-system Vendor ID: %04x\n", *((u_short *)p->sub_vendor_id));
@@ -5410,7 +5407,7 @@
 	printk("SROM version:         %02x\n", (u_char)(p->version));
 	printk("# controllers:        %02x\n", (u_char)(p->num_controllers));
 
-	printk("Hardware Address:     %s\n", print_mac(mac, p->ieee_addr));
+	printk("Hardware Address:     %pM\n", p->ieee_addr);
 	printk("CRC checksum:         %04x\n", (u_short)(p->chksum));
 	for (i=0; i<64; i++) {
 	    printk("%3d %04x\n", i<<1, (u_short)*((u_short *)p+i));
@@ -5424,12 +5421,10 @@
 de4x5_dbg_rx(struct sk_buff *skb, int len)
 {
     int i, j;
-    DECLARE_MAC_BUF(mac);
-    DECLARE_MAC_BUF(mac2);
 
     if (de4x5_debug & DEBUG_RX) {
-	printk("R: %s <- %s len/SAP:%02x%02x [%d]\n",
-	       print_mac(mac, skb->data), print_mac(mac2, &skb->data[6]),
+	printk("R: %pM <- %pM len/SAP:%02x%02x [%d]\n",
+	       skb->data, &skb->data[6],
 	       (u_char)skb->data[12],
 	       (u_char)skb->data[13],
 	       len);
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index c91852f..28a5c51 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -362,7 +362,6 @@
 	struct net_device *dev;
 	u32 pci_pmr;
 	int i, err;
-	DECLARE_MAC_BUF(mac);
 
 	DMFE_DBUG(0, "dmfe_init_one()", 0);
 
@@ -475,12 +474,11 @@
 	if (err)
 		goto err_out_free_buf;
 
-	printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, "
-	       "%s, irq %d.\n",
+	printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, %pM, irq %d.\n",
 	       dev->name,
 	       ent->driver_data >> 16,
 	       pci_name(pdev),
-	       print_mac(mac, dev->dev_addr),
+	       dev->dev_addr,
 	       dev->irq);
 
 	pci_set_master(pdev);
@@ -1010,7 +1008,6 @@
 
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
-					dev->last_rx = jiffies;
 					db->stats.rx_packets++;
 					db->stats.rx_bytes += rxlen;
 				}
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index c6bad98..739d610 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -231,7 +231,6 @@
 
                                netif_receive_skb(skb);
 
-                               dev->last_rx = jiffies;
                                tp->stats.rx_packets++;
                                tp->stats.rx_bytes += pkt_len;
                        }
@@ -444,7 +443,6 @@
 
 			netif_rx(skb);
 
-			dev->last_rx = jiffies;
 			tp->stats.rx_packets++;
 			tp->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index cafa89e..1c5ef23 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1050,13 +1050,11 @@
 					filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 				filterbit &= 0x3f;
 				mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
-				if (tulip_debug > 2) {
-					DECLARE_MAC_BUF(mac);
-					printk(KERN_INFO "%s: Added filter for %s"
+				if (tulip_debug > 2)
+					printk(KERN_INFO "%s: Added filter for %pM"
 					       "  %8.8x bit %d.\n",
-					       dev->name, print_mac(mac, mclist->dmi_addr),
+					       dev->name, mclist->dmi_addr,
 					       ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit);
-				}
 			}
 			if (mc_filter[0] == tp->mc_filter[0]  &&
 				mc_filter[1] == tp->mc_filter[1])
@@ -1250,7 +1248,6 @@
 	const char *chip_name = tulip_tbl[chip_idx].chip_name;
 	unsigned int eeprom_missing = 0;
 	unsigned int force_csr0 = 0;
-	DECLARE_MAC_BUF(mac);
 
 #ifndef MODULE
 	static int did_version;		/* Already printed version info. */
@@ -1635,7 +1632,7 @@
 
 	if (eeprom_missing)
 		printk(" EEPROM not present,");
-	printk(" %s", print_mac(mac, dev->dev_addr));
+	printk(" %pM", dev->dev_addr);
 	printk(", IRQ %d.\n", irq);
 
         if (tp->chip_id == PNIC2)
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index e9e62862..35c57f6 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -261,7 +261,6 @@
 	struct uli526x_board_info *db;	/* board information structure */
 	struct net_device *dev;
 	int i, err;
-	DECLARE_MAC_BUF(mac);
 
 	ULI526X_DBUG(0, "uli526x_init_one()", 0);
 
@@ -379,9 +378,9 @@
 	if (err)
 		goto err_out_res;
 
-	printk(KERN_INFO "%s: ULi M%04lx at pci%s, %s, irq %d.\n",
+	printk(KERN_INFO "%s: ULi M%04lx at pci%s, %pM, irq %d.\n",
 	       dev->name,ent->driver_data >> 16,pci_name(pdev),
-	       print_mac(mac, dev->dev_addr), dev->irq);
+	       dev->dev_addr, dev->irq);
 
 	pci_set_master(pdev);
 
@@ -855,7 +854,6 @@
 
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				db->stats.rx_packets++;
 				db->stats.rx_bytes += rxlen;
 
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 5006819..022d99a 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -355,7 +355,6 @@
 	int irq;
 	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
 	void __iomem *ioaddr;
-	DECLARE_MAC_BUF(mac);
 
 	i = pci_enable_device(pdev);
 	if (i) return i;
@@ -435,9 +434,9 @@
 	if (i)
 		goto err_out_cleardev;
 
-	printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
 	       dev->name, pci_id_tbl[chip_idx].name, ioaddr,
-	       print_mac(mac, dev->dev_addr), irq);
+	       dev->dev_addr, irq);
 
 	if (np->drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
@@ -1245,20 +1244,15 @@
 			}
 #ifndef final_version				/* Remove after testing. */
 			/* You will want this info for the initial debug. */
-			if (debug > 5) {
-				DECLARE_MAC_BUF(mac);
-				DECLARE_MAC_BUF(mac2);
-
-				printk(KERN_DEBUG "  Rx data %s %s"
+			if (debug > 5)
+				printk(KERN_DEBUG "  Rx data %pM %pM"
 				       " %2.2x%2.2x %d.%d.%d.%d.\n",
-				       print_mac(mac, &skb->data[0]), print_mac(mac2, &skb->data[6]),
+				       &skb->data[0], &skb->data[6],
 				       skb->data[12], skb->data[13],
 				       skb->data[14], skb->data[15], skb->data[16], skb->data[17]);
-			}
 #endif
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			np->stats.rx_packets++;
 			np->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 6b93d016..13c8703 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -1072,7 +1072,6 @@
 	unsigned char j, tuple, link, data_id, data_count;
 	unsigned long flags;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	enter("read_mac_address");
 
@@ -1102,7 +1101,7 @@
 		}
 	}
 	spin_unlock_irqrestore(&card->lock, flags);
-	pr_debug(" %s\n", print_mac(mac, card->dev->dev_addr));
+	pr_debug(" %pM\n", card->dev->dev_addr);
 	leave("read_mac_address");
 }
 
@@ -1202,7 +1201,6 @@
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			card->stats.rx_packets++;
 			card->stats.rx_bytes += pkt_len;
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 33b6d1b..5a62030 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -529,7 +529,6 @@
 	}
 
 	netif_rx_ni(skb);
-	tun->dev->last_rx = jiffies;
 
 	tun->dev->stats.rx_packets++;
 	tun->dev->stats.rx_bytes += len;
@@ -883,7 +882,6 @@
 	void __user* argp = (void __user*)arg;
 	struct ifreq ifr;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
 		if (copy_from_user(&ifr, argp, sizeof ifr))
@@ -1011,8 +1009,8 @@
 
 	case SIOCSIFHWADDR:
 		/* Set hw address */
-		DBG(KERN_DEBUG "%s: set hw address: %s\n",
-			tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+		DBG(KERN_DEBUG "%s: set hw address: %pM\n",
+			tun->dev->name, ifr.ifr_hwaddr.sa_data);
 
 		rtnl_lock();
 		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 734ce09..8763987 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1729,7 +1729,6 @@
 			netif_receive_skb(new_skb);
 		spin_unlock(&tp->state_lock);
 
-		tp->dev->last_rx = jiffies;
 		received++;
 		budget--;
 	}
@@ -2311,7 +2310,6 @@
 	struct cmd_desc xp_cmd;
 	struct resp_desc xp_resp[3];
 	int err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if(!did_version++)
 		printk(KERN_INFO "%s", version);
@@ -2526,11 +2524,11 @@
 
 	pci_set_drvdata(pdev, dev);
 
-	printk(KERN_INFO "%s: %s at %s 0x%llx, %s\n",
+	printk(KERN_INFO "%s: %s at %s 0x%llx, %pM\n",
 	       dev->name, typhoon_card_info[card_id].name,
 	       use_mmio ? "MMIO" : "IO",
 	       (unsigned long long)pci_resource_start(pdev, use_mmio),
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 
 	/* xp_resp still contains the response to the READ_VERSIONS command.
 	 * For debugging, let the user know what version he has.
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index c87747b..0a5b817 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1615,8 +1615,8 @@
 	priv->oldspeed = 0;
 	priv->oldduplex = -1;
 
-	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus,
-			priv->ug_info->phy_address);
+	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->ug_info->mdio_bus,
+		 priv->ug_info->phy_address);
 
 	phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface);
 
@@ -3502,8 +3502,6 @@
 			netif_receive_skb(skb);
 		}
 
-		ugeth->dev->last_rx = jiffies;
-
 		skb = get_new_skb(ugeth, bd);
 		if (!skb) {
 			if (netif_msg_rx_err(ugeth))
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 466a89e..d762123 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -271,8 +271,6 @@
 
 	} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
 
-	catc->netdev->last_rx = jiffies;
-
 	if (catc->is_f5u011) {
 		if (atomic_read(&catc->recq_sz)) {
 			int status;
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 7914867..c073929 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1309,7 +1309,6 @@
 	pegasus_t *pegasus;
 	int dev_index = id - pegasus_ids;
 	int res = -ENOMEM;
-	DECLARE_MAC_BUF(mac);
 
 	usb_get_dev(dev);
 
@@ -1386,10 +1385,10 @@
 	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
 				CARRIER_CHECK_DELAY);
 
-	dev_info(&intf->dev, "%s, %s, %s\n",
+	dev_info(&intf->dev, "%s, %s, %pM\n",
 		 net->name,
 		 usb_dev_id[dev_index].name,
-		 print_mac(mac, net->dev_addr));
+		 net->dev_addr);
 	return 0;
 
 out3:
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 51e2f5d..e0d349f 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -759,7 +759,6 @@
 	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
 	u32 read_buf, write_buf, burst_cap;
 	int ret = 0, timeout;
-	DECLARE_MAC_BUF(mac);
 
 	if (netif_msg_ifup(dev))
 		devdbg(dev, "entering smsc95xx_reset");
@@ -818,8 +817,7 @@
 		return ret;
 
 	if (netif_msg_ifup(dev))
-		devdbg(dev, "MAC Address: %s",
-			print_mac(mac, dev->net->dev_addr));
+		devdbg(dev, "MAC Address: %pM", dev->net->dev_addr);
 
 	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
 	if (ret < 0) {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 02d25c7..aa31490 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1125,7 +1125,6 @@
 	struct usb_device		*xdev;
 	int				status;
 	const char			*name;
-	DECLARE_MAC_BUF(mac);
 
 	name = udev->dev.driver->name;
 	info = (struct driver_info *) prod->driver_info;
@@ -1236,11 +1235,11 @@
 	if (status)
 		goto out3;
 	if (netif_msg_probe (dev))
-		devinfo (dev, "register '%s' at usb-%s-%s, %s, %s",
+		devinfo (dev, "register '%s' at usb-%s-%s, %s, %pM",
 			udev->dev.driver->name,
 			xdev->bus->bus_name, xdev->devpath,
 			dev->driver_info->description,
-			print_mac(mac, net->dev_addr));
+			net->dev_addr);
 
 	// ok, it's ready to go.
 	usb_set_intfdata (udev, dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 31cd817..75b40fe 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -8,7 +8,6 @@
  *
  */
 
-#include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
@@ -30,14 +29,10 @@
 
 struct veth_priv {
 	struct net_device *peer;
-	struct net_device *dev;
-	struct list_head list;
 	struct veth_net_stats *stats;
 	unsigned ip_summed;
 };
 
-static LIST_HEAD(veth_list);
-
 /*
  * ethtool interface
  */
@@ -420,14 +415,10 @@
 	 */
 
 	priv = netdev_priv(dev);
-	priv->dev = dev;
 	priv->peer = peer;
-	list_add(&priv->list, &veth_list);
 
 	priv = netdev_priv(peer);
-	priv->dev = peer;
 	priv->peer = dev;
-	INIT_LIST_HEAD(&priv->list);
 	return 0;
 
 err_register_dev:
@@ -449,13 +440,6 @@
 	priv = netdev_priv(dev);
 	peer = priv->peer;
 
-	if (!list_empty(&priv->list))
-		list_del(&priv->list);
-
-	priv = netdev_priv(peer);
-	if (!list_empty(&priv->list))
-		list_del(&priv->list);
-
 	unregister_netdevice(dev);
 	unregister_netdevice(peer);
 }
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 5b78700..9a650d0 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -631,7 +631,6 @@
 #else
 	int bar = 0;
 #endif
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -787,14 +786,14 @@
 	if (rc)
 		goto err_out_unmap;
 
-	printk(KERN_INFO "%s: VIA %s at 0x%lx, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: VIA %s at 0x%lx, %pM, IRQ %d.\n",
 	       dev->name, name,
 #ifdef USE_MMIO
 	       memaddr,
 #else
 	       (long)ioaddr,
 #endif
-	       print_mac(mac, dev->dev_addr), pdev->irq);
+	       dev->dev_addr, pdev->irq);
 
 	pci_set_drvdata(pdev, dev);
 
@@ -1505,7 +1504,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_receive_skb(skb);
-			dev->last_rx = jiffies;
 			rp->stats.rx_bytes += pkt_len;
 			rp->stats.rx_packets++;
 		}
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 3590ea5..448772f 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1412,8 +1412,6 @@
 
 		rd->size |= RX_INTEN;
 
-		vptr->dev->last_rx = jiffies;
-
 		rd_curr++;
 		if (rd_curr >= vptr->options.numrx)
 			rd_curr = 0;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 0196a0d..68f908a 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -325,9 +325,7 @@
 
 	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 
-	pr_debug("%s: xmit %p " MAC_FMT "\n", vi->dev->name, skb,
-		 dest[0], dest[1], dest[2],
-		 dest[3], dest[4], dest[5]);
+	pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
 
 	/* Encode metadata header at front. */
 	hdr = skb_vnet_hdr(skb);
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7f97f8d..d80b72e 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -754,7 +754,6 @@
 	chan->netdev->stats.rx_bytes += chan->cosa->rxsize;
 	netif_rx(chan->rx_skb);
 	chan->rx_skb = NULL;
-	chan->netdev->last_rx = jiffies;
 	return 0;
 }
 
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 5a7303d..aeea321 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -843,7 +843,6 @@
 
 	skb_reset_mac_header(skb);
 	netif_rx(skb);
-	dev->last_rx = jiffies;		/* timestamp */
 }
 
 /* Connect interrupt handler. */
@@ -1494,7 +1493,6 @@
 
 	skb->protocol = x25_type_trans(skb, dev);
 	netif_rx(skb);
-	dev->last_rx = jiffies;		/* timestamp */
 }
 
 /* Convert line speed in bps to a number used by cyclom 2x code. */
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index b142427..5d13832 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -181,7 +181,6 @@
 		dlp->stats.rx_bytes += skb->len;
 		netif_rx(skb);
 		dlp->stats.rx_packets++;
-		dev->last_rx = jiffies;
 	}
 	else
 		dev_kfree_skb(skb);
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 5f1ccb2..888025d 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -659,7 +659,6 @@
 		skb_put(skb, pkt_len);
 		if (netif_running(dev))
 			skb->protocol = hdlc_type_trans(skb, dev);
-		skb->dev->last_rx = jiffies;
 		netif_rx(skb);
 	} else {
 		if (skb->data[pkt_len] & FrameRdo)
@@ -730,8 +729,7 @@
 	        goto err_free_mmio_region_1;
 	}
 
-	ioaddr = ioremap(pci_resource_start(pdev, 0),
-					pci_resource_len(pdev, 0));
+	ioaddr = pci_ioremap_bar(pdev, 0);
 	if (!ioaddr) {
 		printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
 			DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 9557ad0..48a2c9d 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -896,7 +896,6 @@
 	fst_process_rx_status(rx_status, port_to_dev(port)->name);
 	if (rx_status == NET_RX_DROP)
 		dev->stats.rx_dropped++;
-	dev->last_rx = jiffies;
 }
 
 /*
@@ -1322,7 +1321,6 @@
 		fst_process_rx_status(rx_status, port_to_dev(port)->name);
 		if (rx_status == NET_RX_DROP)
 			dev->stats.rx_dropped++;
-		dev->last_rx = jiffies;
 	} else {
 		card->dma_skb_rx = skb;
 		card->dma_port_rx = port;
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
index 591fb45..434583a 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd6457x.c
@@ -328,7 +328,6 @@
 #endif
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += skb->len;
-	dev->last_rx = jiffies;
 	skb->protocol = hdlc_type_trans(skb, dev);
 	netif_rx(skb);
 }
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e299313..af54f0c 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -66,7 +66,6 @@
 	 *	it right now.
 	 */
 	netif_rx(skb);
-	c->netdevice->last_rx = jiffies;
 }
 
 /*
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 24fd613..5b61b3e 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -143,7 +143,6 @@
 	*ptr = 0x00;
 
 	skb->protocol = x25_type_trans(skb, dev);
-	skb->dev->last_rx = jiffies;
 	return netif_rx(skb);
 }
 
@@ -235,7 +234,6 @@
 	*ptr = 0x01;
 
 	skb->protocol = x25_type_trans(skb, dev);
-	skb->dev->last_rx = jiffies;
 	netif_rx(skb);
 }
 
@@ -253,7 +251,6 @@
 	*ptr = 0x02;
 
 	skb->protocol = x25_type_trans(skb, dev);
-	skb->dev->last_rx = jiffies;
 	netif_rx(skb);
 }
 
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index d7bb63e..feac3b9 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1594,7 +1594,6 @@
             goto skip_packet;
         }
         
-        dev->last_rx = jiffies;
 	sc->lmc_device->stats.rx_packets++;
 	sc->lmc_device->stats.rx_bytes += len;
 
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c
index be9877f..94b4c20 100644
--- a/drivers/net/wan/lmc/lmc_proto.c
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -142,7 +142,6 @@
     case LMC_PPP:
     case LMC_NET:
     default:
-        skb->dev->last_rx = jiffies;
         netif_rx(skb);
         break;
     case LMC_RAW:
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index bf1b015..2226711 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -379,7 +379,7 @@
 	card->scabase = ioremap(scaphys, PC300_SCA_SIZE);
 
 	ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK;
-	card->rambase = ioremap(ramphys, pci_resource_len(pdev,3));
+	card->rambase = pci_ioremap_bar(pdev, 3);
 
 	if (card->plxbase == NULL ||
 	    card->scabase == NULL ||
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index b595b64..bba111c 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -343,7 +343,7 @@
 	card->scabase = ioremap(scaphys, PCI200SYN_SCA_SIZE);
 
 	ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK;
-	card->rambase = ioremap(ramphys, pci_resource_len(pdev,3));
+	card->rambase = pci_ioremap_bar(pdev, 3);
 
 	if (card->plxbase == NULL ||
 	    card->scabase == NULL ||
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index ee51b6a..6db063e 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -1013,13 +1013,11 @@
 #ifdef CONFIG_SBNI_MULTILINE
 	skb->protocol = eth_type_trans( skb, nl->master );
 	netif_rx( skb );
-	dev->last_rx = jiffies;
 	++((struct net_local *) nl->master->priv)->stats.rx_packets;
 	((struct net_local *) nl->master->priv)->stats.rx_bytes += nl->inppos;
 #else
 	skb->protocol = eth_type_trans( skb, dev );
 	netif_rx( skb );
-	dev->last_rx = jiffies;
 	++nl->stats.rx_packets;
 	nl->stats.rx_bytes += nl->inppos;
 #endif
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index c023584..0941a26 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -68,7 +68,6 @@
 	skb_reset_mac_header(skb);
 	skb->dev = c->netdevice;
 	netif_rx(skb);
-	c->netdevice->last_rx = jiffies;
 }
 
 /*
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 6e92f7b..58ae8a2 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -284,7 +284,6 @@
 					printk(KERN_DEBUG "Yow an IP frame.\n");
 				skb->protocol=htons(ETH_P_IP);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				goto done;
 			}
 			break;
@@ -294,7 +293,6 @@
 			if (sp->lcp.state == LCP_STATE_OPENED) {
 				skb->protocol=htons(ETH_P_IPX);
 				netif_rx(skb);
-				dev->last_rx = jiffies;
 				goto done;
 			}
 			break;
@@ -321,14 +319,12 @@
 		case ETH_P_IP:
 			skb->protocol=htons(ETH_P_IP);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			goto done;
 #endif
 #ifdef CONFIG_IPX
 		case ETH_P_IPX:
 			skb->protocol=htons(ETH_P_IPX);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			goto done;
 #endif
 		}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index a8a5ca0..8845949 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -220,7 +220,6 @@
 #endif
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += skb->len;
-				dev->last_rx = jiffies;
 				skb->protocol = hdlc_type_trans(skb, dev);
 				netif_rx(skb);
 				skb = NULL;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 2a6c7a6..3b7bdfd 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -211,7 +211,6 @@
 		printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
 	} else {
 		netif_rx(skb);
-		sl->dev->last_rx = jiffies;
 		sl->stats.rx_packets++;
 	}
 }
@@ -361,7 +360,6 @@
 
 static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	skb->dev->last_rx = jiffies;
 	return netif_rx(skb);
 }
 
@@ -413,7 +411,6 @@
 
 	skb->protocol = x25_type_trans(skb, sl->dev);
 	netif_rx(skb);
-	sl->dev->last_rx = jiffies;
 }
 
 static void x25_asy_disconnected(struct net_device *dev, int reason)
@@ -433,7 +430,6 @@
 
 	skb->protocol = x25_type_trans(skb, sl->dev);
 	netif_rx(skb);
-	sl->dev->last_rx = jiffies;
 }
 
 static struct lapb_register_struct x25_asy_callbacks = {
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index fa14255..6d96ed4 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -156,7 +156,6 @@
 	int word16 = 0;				/* 0 = 8 bit, 1 = 16 bit */
 	const char *model_name;
 	static unsigned version_printed;
-	DECLARE_MAC_BUF(mac);
 
 	for (i = 0; i < 8; i++)
 		checksum += inb(ioaddr + 8 + i);
@@ -178,8 +177,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-	printk("%s: WD80x3 at %#3x, %s",
-	       dev->name, ioaddr, print_mac(mac, dev->dev_addr));
+	printk("%s: WD80x3 at %#3x, %pM",
+	       dev->name, ioaddr, dev->dev_addr);
 
 	/* The following PureData probe code was contributed by
 	   Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 45bdf0b..42afaed 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -271,6 +271,7 @@
 	tristate "Marvell 8xxx Libertas WLAN driver support"
 	depends on WLAN_80211
 	select WIRELESS_EXT
+	select LIB80211
 	select FW_LOADER
 	---help---
 	  A library for Marvell Libertas 8xxx devices.
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 59d2d80..7882084 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -16,14 +16,7 @@
 obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave_cs.o
 obj-$(CONFIG_PCMCIA_WAVELAN)	+= wavelan_cs.o
 
-obj-$(CONFIG_HERMES)		+= orinoco.o hermes.o hermes_dld.o
-obj-$(CONFIG_PCMCIA_HERMES)	+= orinoco_cs.o
-obj-$(CONFIG_APPLE_AIRPORT)	+= airport.o
-obj-$(CONFIG_PLX_HERMES)	+= orinoco_plx.o
-obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.o
-obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o
-obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o
-obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o
+obj-$(CONFIG_HERMES)		+= orinoco/
 
 obj-$(CONFIG_AIRO)		+= airo.o
 obj-$(CONFIG_AIRO_CS)		+= airo_cs.o airo.o
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index b2c050b..fc0897f 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -341,15 +341,14 @@
 		pci_unmap_single(priv->pdev, info->mapping,
 				 info->skb->len, PCI_DMA_TODEVICE);
 
-		memset(&txi->status, 0, sizeof(txi->status));
+		ieee80211_tx_info_clear_status(txi);
+
 		skb_pull(skb, sizeof(struct adm8211_tx_hdr));
 		memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen);
-		if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
-			if (status & TDES0_STATUS_ES)
-				txi->status.excessive_retries = 1;
-			else
-				txi->flags |= IEEE80211_TX_STAT_ACK;
-		}
+		if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) &&
+		    !(status & TDES0_STATUS_ES))
+			txi->flags |= IEEE80211_TX_STAT_ACK;
+
 		ieee80211_tx_status_irqsafe(dev, skb);
 
 		info->skb = NULL;
@@ -1298,25 +1297,10 @@
 	ADM8211_CSR_WRITE(ABDA1, reg);
 }
 
-static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
+static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
 {
 	struct adm8211_priv *priv = dev->priv;
-	u8 buf[36];
-
-	if (ssid_len > 32)
-		return -EINVAL;
-
-	memset(buf, 0, sizeof(buf));
-	buf[0] = ssid_len;
-	memcpy(buf + 1, ssid, ssid_len);
-	adm8211_write_sram_bytes(dev, ADM8211_SRAM_SSID, buf, 33);
-	/* TODO: configure beacon for adhoc? */
-	return 0;
-}
-
-static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
-{
-	struct adm8211_priv *priv = dev->priv;
+	struct ieee80211_conf *conf = &dev->conf;
 	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
 	if (channel != priv->channel) {
@@ -1338,13 +1322,6 @@
 		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 	}
 
-	if (conf->ssid_len != priv->ssid_len ||
-	    memcmp(conf->ssid, priv->ssid, conf->ssid_len)) {
-		adm8211_set_ssid(dev, conf->ssid, conf->ssid_len);
-		priv->ssid_len = conf->ssid_len;
-		memcpy(priv->ssid, conf->ssid, conf->ssid_len);
-	}
-
 	return 0;
 }
 
@@ -1690,8 +1667,10 @@
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info);
+	u8 rc_flags;
 
-	short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE);
+	rc_flags = info->control.rates[0].flags;
+	short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
 	plcp_signal = txrate->bitrate;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -1723,10 +1702,10 @@
 	if (short_preamble)
 		txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE);
 
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS);
 
-	txhdr->retry_limit = info->control.retry_limit;
+	txhdr->retry_limit = info->control.rates[0].count;
 
 	adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);
 
@@ -1791,7 +1770,6 @@
 	int err;
 	u32 reg;
 	u8 perm_addr[ETH_ALEN];
-	DECLARE_MAC_BUF(mac);
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -1925,8 +1903,8 @@
 		goto err_free_desc;
 	}
 
-	printk(KERN_INFO "%s: hwaddr %s, Rev 0x%02x\n",
-	       wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+	printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n",
+	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
 	       pdev->revision);
 
 	return 0;
diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
index 9b190ee..4f6ab13 100644
--- a/drivers/net/wireless/adm8211.h
+++ b/drivers/net/wireless/adm8211.h
@@ -553,8 +553,6 @@
 
 	int channel;
 	u8 bssid[ETH_ALEN];
-	u8 ssid[32];
-	size_t ssid_len;
 
 	u8 soft_rx_crc;
 	u8 retry_limit;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 370133e..67d504e 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -47,10 +47,11 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
-#include <net/ieee80211.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+#include <linux/ieee80211.h>
+
 #include "airo.h"
 
 #define DRV_NAME "airo"
@@ -1270,6 +1271,7 @@
 #define airo_print_err(name, fmt, args...) \
 	airo_print(KERN_ERR, name, fmt, ##args)
 
+#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash)
 
 /***********************************************************************
  *                              MIC ROUTINES                           *
@@ -1865,7 +1867,7 @@
 }
 
 static int airo_open(struct net_device *dev) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int rc = 0;
 
 	if (test_bit(FLAG_FLASHING, &ai->flags))
@@ -1912,7 +1914,7 @@
 static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
 	int npacks, pending;
 	unsigned long flags;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	if (!skb) {
 		airo_print_err(dev->name, "%s: skb == NULL!",__func__);
@@ -1956,7 +1958,7 @@
 	unsigned char *buffer;
 	s16 len;
 	__le16 *payloadLen;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	u8 *sendbuf;
 
 	/* get a packet to send */
@@ -2085,7 +2087,7 @@
 static void airo_end_xmit(struct net_device *dev) {
 	u16 status;
 	int i;
-	struct airo_info *priv = dev->priv;
+	struct airo_info *priv = dev->ml_priv;
 	struct sk_buff *skb = priv->xmit.skb;
 	int fid = priv->xmit.fid;
 	u32 *fids = priv->fids;
@@ -2111,7 +2113,7 @@
 static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
 	s16 len;
 	int i, j;
-	struct airo_info *priv = dev->priv;
+	struct airo_info *priv = dev->ml_priv;
 	u32 *fids = priv->fids;
 
 	if ( skb == NULL ) {
@@ -2150,7 +2152,7 @@
 static void airo_end_xmit11(struct net_device *dev) {
 	u16 status;
 	int i;
-	struct airo_info *priv = dev->priv;
+	struct airo_info *priv = dev->ml_priv;
 	struct sk_buff *skb = priv->xmit11.skb;
 	int fid = priv->xmit11.fid;
 	u32 *fids = priv->fids;
@@ -2176,7 +2178,7 @@
 static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
 	s16 len;
 	int i, j;
-	struct airo_info *priv = dev->priv;
+	struct airo_info *priv = dev->ml_priv;
 	u32 *fids = priv->fids;
 
 	if (test_bit(FLAG_MPI, &priv->flags)) {
@@ -2220,7 +2222,7 @@
 
 static void airo_read_stats(struct net_device *dev)
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	StatsRid stats_rid;
 	__le32 *vals = stats_rid.vals;
 
@@ -2254,7 +2256,7 @@
 
 static struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
-	struct airo_info *local =  dev->priv;
+	struct airo_info *local =  dev->ml_priv;
 
 	if (!test_bit(JOB_STATS, &local->jobs)) {
 		/* Get stats out of the card if available */
@@ -2281,7 +2283,7 @@
 }
 
 static void airo_set_multicast_list(struct net_device *dev) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
 		change_bit(FLAG_PROMISC, &ai->flags);
@@ -2299,7 +2301,7 @@
 
 static int airo_set_mac_address(struct net_device *dev, void *p)
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	struct sockaddr *addr = p;
 
 	readConfigRid(ai, 1);
@@ -2339,7 +2341,7 @@
 }
 
 static int airo_close(struct net_device *dev) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	netif_stop_queue(dev);
 
@@ -2365,7 +2367,7 @@
 
 void stop_airo_card( struct net_device *dev, int freeres )
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	set_bit(FLAG_RADIO_DOWN, &ai->flags);
 	disable_MAC(ai, 1);
@@ -2665,7 +2667,7 @@
 	struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
 	if (!dev)
 		return NULL;
-	dev->priv = ethdev->priv;
+	dev->ml_priv = ethdev->ml_priv;
 	dev->irq = ethdev->irq;
 	dev->base_addr = ethdev->base_addr;
 	dev->wireless_data = ethdev->wireless_data;
@@ -2680,7 +2682,7 @@
 }
 
 static int reset_card( struct net_device *dev , int lock) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	if (lock && down_interruptible(&ai->sem))
 		return -1;
@@ -2757,7 +2759,6 @@
 	struct net_device *dev;
 	struct airo_info *ai;
 	int i, rc;
-	DECLARE_MAC_BUF(mac);
 
 	/* Create the network device object. */
 	dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2766,7 +2767,7 @@
 		return NULL;
 	}
 
-	ai = dev->priv;
+	ai = dev->ml_priv = netdev_priv(dev);
 	ai->wifidev = NULL;
 	ai->flags = 1 << FLAG_RADIO_DOWN;
 	ai->jobs = 0;
@@ -2860,15 +2861,14 @@
 		goto err_out_reg;
 
 	set_bit(FLAG_REGISTERED,&ai->flags);
-	airo_print_info(dev->name, "MAC enabled %s",
-			print_mac(mac, dev->dev_addr));
+	airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
 
 	/* Allocate the transmit buffers */
 	if (probe && !test_bit(FLAG_MPI,&ai->flags))
 		for( i = 0; i < MAX_FIDS; i++ )
 			ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
-	if (setup_proc_entry(dev, dev->priv) < 0)
+	if (setup_proc_entry(dev, dev->ml_priv) < 0)
 		goto err_out_wifi;
 
 	return dev;
@@ -2917,8 +2917,7 @@
 int reset_airo_card( struct net_device *dev )
 {
 	int i;
-	struct airo_info *ai = dev->priv;
-	DECLARE_MAC_BUF(mac);
+	struct airo_info *ai = dev->ml_priv;
 
 	if (reset_card (dev, 1))
 		return -1;
@@ -2927,8 +2926,7 @@
 		airo_print_err(dev->name, "MAC could not be enabled");
 		return -1;
 	}
-	airo_print_info(dev->name, "MAC enabled %s",
-			print_mac(mac, dev->dev_addr));
+	airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
 	/* Allocate the transmit buffers if needed */
 	if (!test_bit(FLAG_MPI,&ai->flags))
 		for( i = 0; i < MAX_FIDS; i++ )
@@ -2942,7 +2940,7 @@
 EXPORT_SYMBOL(reset_airo_card);
 
 static void airo_send_event(struct net_device *dev) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	union iwreq_data wrqu;
 	StatusRid status_rid;
 
@@ -3019,7 +3017,7 @@
 
 static int airo_thread(void *data) {
 	struct net_device *dev = data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int locked;
 
 	set_freezable();
@@ -3134,7 +3132,7 @@
 	struct net_device *dev = dev_id;
 	u16 status;
 	u16 fid;
-	struct airo_info *apriv = dev->priv;
+	struct airo_info *apriv = dev->ml_priv;
 	u16 savedInterrupts = 0;
 	int handled = 0;
 
@@ -3369,7 +3367,6 @@
 				skb->protocol = htons(ETH_P_802_2);
 			} else
 				skb->protocol = eth_type_trans(skb,dev);
-			skb->dev->last_rx = jiffies;
 			skb->ip_summed = CHECKSUM_NONE;
 
 			netif_rx( skb );
@@ -3599,7 +3596,6 @@
 
 		skb->ip_summed = CHECKSUM_NONE;
 		skb->protocol = eth_type_trans(skb, ai->dev);
-		skb->dev->last_rx = jiffies;
 		netif_rx(skb);
 	}
 badrx:
@@ -3693,7 +3689,6 @@
 	skb->pkt_type = PACKET_OTHERHOST;
 	skb->dev = ai->wifidev;
 	skb->protocol = htons(ETH_P_802_2);
-	skb->dev->last_rx = jiffies;
 	skb->ip_summed = CHECKSUM_NONE;
 	netif_rx( skb );
 badrx:
@@ -4604,7 +4599,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *apriv = dev->priv;
+	struct airo_info *apriv = dev->ml_priv;
 	CapabilityRid cap_rid;
 	StatusRid status_rid;
 	u16 mode;
@@ -4687,7 +4682,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *apriv = dev->priv;
+	struct airo_info *apriv = dev->ml_priv;
 	StatsRid stats;
 	int i, j;
 	__le32 *vals = stats.vals;
@@ -4750,7 +4745,7 @@
 	struct proc_data *data = file->private_data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	char *line;
 
 	if ( !data->writelen ) return;
@@ -4962,7 +4957,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int i;
 	__le16 mode;
 
@@ -5053,7 +5048,7 @@
 	struct proc_data *data = (struct proc_data *)file->private_data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	SsidRid SSID_rid;
 	int i;
 	char *p = data->wbuffer;
@@ -5096,7 +5091,7 @@
 	struct proc_data *data = (struct proc_data *)file->private_data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	APListRid APList_rid;
 	int i;
 
@@ -5191,7 +5186,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char key[16];
 	u16 index = 0;
@@ -5233,7 +5228,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	WepKeyRid wkr;
 	__le16 lastindex;
@@ -5282,7 +5277,7 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
 	SsidRid SSID_rid;
@@ -5326,11 +5321,10 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
 	APListRid APList_rid;
-	DECLARE_MAC_BUF(mac);
 
 	if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -5354,8 +5348,7 @@
 // We end when we find a zero MAC
 		if ( !*(int*)APList_rid.ap[i] &&
 		     !*(int*)&APList_rid.ap[i][2]) break;
-		ptr += sprintf(ptr, "%s\n",
-			       print_mac(mac, APList_rid.ap[i]));
+		ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
 	}
 	if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
 
@@ -5368,13 +5361,12 @@
 	struct proc_data *data;
 	struct proc_dir_entry *dp = PDE(inode);
 	struct net_device *dev = dp->data;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	BSSListRid BSSList_rid;
 	int rc;
 	/* If doLoseSync is not 1, we won't do a Lose Sync */
 	int doLoseSync = -1;
-	DECLARE_MAC_BUF(mac);
 
 	if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -5411,8 +5403,8 @@
            we have to add a spin lock... */
 	rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
 	while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
-		ptr += sprintf(ptr, "%s %*s rssi = %d",
-			       print_mac(mac, BSSList_rid.bssid),
+		ptr += sprintf(ptr, "%pM %*s rssi = %d",
+			       BSSList_rid.bssid,
 				(int)BSSList_rid.ssidLen,
 				BSSList_rid.ssid,
 				le16_to_cpu(BSSList_rid.dBm));
@@ -5447,7 +5439,7 @@
    associated we will check every minute to see if anything has
    changed. */
 static void timer_func( struct net_device *dev ) {
-	struct airo_info *apriv = dev->priv;
+	struct airo_info *apriv = dev->ml_priv;
 
 /* We don't have a link so try changing the authtype */
 	readConfigRid(apriv, 0);
@@ -5518,7 +5510,7 @@
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	Cmd cmd;
 	Resp rsp;
 
@@ -5550,7 +5542,7 @@
 static int airo_pci_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	pci_power_t prev_state = pdev->current_state;
 
 	pci_set_power_state(pdev, PCI_D0);
@@ -5729,7 +5721,7 @@
 			 struct iw_freq *fwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int rc = -EINPROGRESS;		/* Call commit handler */
 
 	/* If setting by frequency, convert to a channel */
@@ -5774,7 +5766,7 @@
 			 struct iw_freq *fwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	StatusRid status_rid;		/* Card status info */
 	int ch;
 
@@ -5805,7 +5797,7 @@
 			  struct iw_point *dwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	SsidRid SSID_rid;		/* SSIDs */
 
 	/* Reload the list of current SSID */
@@ -5851,7 +5843,7 @@
 			  struct iw_point *dwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	StatusRid status_rid;		/* Card status info */
 
 	readStatusRid(local, &status_rid, 1);
@@ -5879,7 +5871,7 @@
 			struct sockaddr *awrq,
 			char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	Cmd cmd;
 	Resp rsp;
 	APListRid APList_rid;
@@ -5916,7 +5908,7 @@
 			struct sockaddr *awrq,
 			char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	StatusRid status_rid;		/* Card status info */
 
 	readStatusRid(local, &status_rid, 1);
@@ -5937,7 +5929,7 @@
 			 struct iw_point *dwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	/* Check the size of the string */
 	if(dwrq->length > 16) {
@@ -5960,7 +5952,7 @@
 			 struct iw_point *dwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	strncpy(extra, local->config.nodeName, 16);
@@ -5979,7 +5971,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	CapabilityRid cap_rid;		/* Card capability info */
 	u8	brate = 0;
 	int	i;
@@ -6049,7 +6041,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	StatusRid status_rid;		/* Card status info */
 
 	readStatusRid(local, &status_rid, 1);
@@ -6071,7 +6063,7 @@
 			struct iw_param *vwrq,
 			char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int rthr = vwrq->value;
 
 	if(vwrq->disabled)
@@ -6095,7 +6087,7 @@
 			struct iw_param *vwrq,
 			char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	vwrq->value = le16_to_cpu(local->config.rtsThres);
@@ -6114,7 +6106,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int fthr = vwrq->value;
 
 	if(vwrq->disabled)
@@ -6139,7 +6131,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	vwrq->value = le16_to_cpu(local->config.fragThresh);
@@ -6158,7 +6150,7 @@
 			 __u32 *uwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int reset = 0;
 
 	readConfigRid(local, 1);
@@ -6221,7 +6213,7 @@
 			 __u32 *uwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	/* If not managed, assume it's ad-hoc */
@@ -6258,7 +6250,7 @@
 			   struct iw_point *dwrq,
 			   char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	CapabilityRid cap_rid;		/* Card capability info */
 	int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
 	__le16 currentAuthType = local->config.authType;
@@ -6345,7 +6337,7 @@
 			   struct iw_point *dwrq,
 			   char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 	CapabilityRid cap_rid;		/* Card capability info */
 
@@ -6393,7 +6385,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct iw_point *encoding = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	CapabilityRid cap_rid;		/* Card capability info */
@@ -6479,7 +6471,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct iw_point *encoding = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	CapabilityRid cap_rid;		/* Card capability info */
@@ -6542,7 +6534,7 @@
 			       struct iw_request_info *info,
 			       union iwreq_data *wrqu, char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct iw_param *param = &wrqu->param;
 	__le16 currentAuthType = local->config.authType;
 
@@ -6610,7 +6602,7 @@
 			       struct iw_request_info *info,
 			       union iwreq_data *wrqu, char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct iw_param *param = &wrqu->param;
 	__le16 currentAuthType = local->config.authType;
 
@@ -6659,7 +6651,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	CapabilityRid cap_rid;		/* Card capability info */
 	int i;
 	int rc = -EINVAL;
@@ -6696,7 +6688,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	vwrq->value = le16_to_cpu(local->config.txPower);
@@ -6716,7 +6708,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	int rc = -EINVAL;
 
 	if(vwrq->disabled) {
@@ -6754,7 +6746,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	vwrq->disabled = 0;      /* Can't be disabled */
 
@@ -6785,7 +6777,7 @@
 			  struct iw_point *dwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct iw_range *range = (struct iw_range *) extra;
 	CapabilityRid cap_rid;		/* Card capability info */
 	int		i;
@@ -6910,7 +6902,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	if (vwrq->disabled) {
@@ -6967,7 +6959,7 @@
 			  struct iw_param *vwrq,
 			  char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	__le16 mode;
 
 	readConfigRid(local, 1);
@@ -6998,7 +6990,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	local->config.rssiThreshold =
@@ -7017,7 +7009,7 @@
 			 struct iw_param *vwrq,
 			 char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	readConfigRid(local, 1);
 	vwrq->value = le16_to_cpu(local->config.rssiThreshold);
@@ -7037,7 +7029,7 @@
 			   struct iw_point *dwrq,
 			   char *extra)
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 	struct sockaddr *address = (struct sockaddr *) extra;
 	struct iw_quality qual[IW_MAX_AP];
 	BSSListRid BSSList;
@@ -7110,7 +7102,7 @@
 			 struct iw_point *dwrq,
 			 char *extra)
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	Cmd cmd;
 	Resp rsp;
 	int wake = 0;
@@ -7156,7 +7148,7 @@
 					char *end_buf,
 					BSSListRid *bss)
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	struct iw_event		iwe;		/* Temporary buffer */
 	__le16			capabilities;
 	char *			current_val;	/* For rates */
@@ -7274,56 +7266,53 @@
 	if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
 		unsigned int num_null_ies = 0;
 		u16 length = sizeof (bss->extra.iep);
-		struct ieee80211_info_element *info_element =
-			(struct ieee80211_info_element *) &bss->extra.iep;
+		u8 *ie = (void *)&bss->extra.iep;
 
-		while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
-			if (sizeof(*info_element) + info_element->len > length) {
+		while ((length >= 2) && (num_null_ies < 2)) {
+			if (2 + ie[1] > length) {
 				/* Invalid element, don't continue parsing IE */
 				break;
 			}
 
-			switch (info_element->id) {
-			case MFIE_TYPE_SSID:
+			switch (ie[0]) {
+			case WLAN_EID_SSID:
 				/* Two zero-length SSID elements
 				 * mean we're done parsing elements */
-				if (!info_element->len)
+				if (!ie[1])
 					num_null_ies++;
 				break;
 
-			case MFIE_TYPE_GENERIC:
-				if (info_element->len >= 4 &&
-				    info_element->data[0] == 0x00 &&
-				    info_element->data[1] == 0x50 &&
-				    info_element->data[2] == 0xf2 &&
-				    info_element->data[3] == 0x01) {
+			case WLAN_EID_GENERIC:
+				if (ie[1] >= 4 &&
+				    ie[2] == 0x00 &&
+				    ie[3] == 0x50 &&
+				    ie[4] == 0xf2 &&
+				    ie[5] == 0x01) {
 					iwe.cmd = IWEVGENIE;
-					iwe.u.data.length = min(info_element->len + 2,
-								  MAX_WPA_IE_LEN);
+					/* 64 is an arbitrary cut-off */
+					iwe.u.data.length = min(ie[1] + 2,
+								64);
 					current_ev = iwe_stream_add_point(
 							info, current_ev,
-							end_buf, &iwe,
-							(char *) info_element);
+							end_buf, &iwe, ie);
 				}
 				break;
 
-			case MFIE_TYPE_RSN:
+			case WLAN_EID_RSN:
 				iwe.cmd = IWEVGENIE;
-				iwe.u.data.length = min(info_element->len + 2,
-							  MAX_WPA_IE_LEN);
+				/* 64 is an arbitrary cut-off */
+				iwe.u.data.length = min(ie[1] + 2, 64);
 				current_ev = iwe_stream_add_point(
 					info, current_ev, end_buf,
-					&iwe, (char *) info_element);
+					&iwe, ie);
 				break;
 
 			default:
 				break;
 			}
 
-			length -= sizeof(*info_element) + info_element->len;
-			info_element =
-			    (struct ieee80211_info_element *)&info_element->
-			    data[info_element->len];
+			length -= 2 + ie[1];
+			ie += 2 + ie[1];
 		}
 	}
 	return current_ev;
@@ -7338,7 +7327,7 @@
 			 struct iw_point *dwrq,
 			 char *extra)
 {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	BSSListElement *net;
 	int err = 0;
 	char *current_ev = extra;
@@ -7382,7 +7371,7 @@
 			      void *zwrq,			/* NULL */
 			      char *extra)			/* NULL */
 {
-	struct airo_info *local = dev->priv;
+	struct airo_info *local = dev->ml_priv;
 
 	if (!test_bit (FLAG_COMMIT, &local->flags))
 		return 0;
@@ -7527,7 +7516,7 @@
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	int rc = 0;
-	struct airo_info *ai = (struct airo_info *)dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	if (ai->power.event)
 		return 0;
@@ -7655,7 +7644,7 @@
 
 static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
-	struct airo_info *local =  dev->priv;
+	struct airo_info *local =  dev->ml_priv;
 
 	if (!test_bit(JOB_WSTATS, &local->jobs)) {
 		/* Get stats out of the card if available */
@@ -7680,7 +7669,7 @@
 	unsigned short ridcode;
 	unsigned char *iobuf;
 	int len;
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 
 	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
@@ -7746,7 +7735,7 @@
  */
 
 static int writerids(struct net_device *dev, aironet_ioctl *comp) {
-	struct airo_info *ai = dev->priv;
+	struct airo_info *ai = dev->ml_priv;
 	int  ridcode;
         int  enabled;
 	static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
@@ -7869,41 +7858,41 @@
 	switch(comp->command)
 	{
 	case AIROFLSHRST:
-		return cmdreset((struct airo_info *)dev->priv);
+		return cmdreset((struct airo_info *)dev->ml_priv);
 
 	case AIROFLSHSTFL:
-		if (!((struct airo_info *)dev->priv)->flash &&
-			(((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+		if (!AIRO_FLASH(dev) &&
+		    (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
-		return setflashmode((struct airo_info *)dev->priv);
+		return setflashmode((struct airo_info *)dev->ml_priv);
 
 	case AIROFLSHGCHR: /* Get char from aux */
 		if(comp->len != sizeof(int))
 			return -EINVAL;
 		if (copy_from_user(&z,comp->data,comp->len))
 			return -EFAULT;
-		return flashgchar((struct airo_info *)dev->priv,z,8000);
+		return flashgchar((struct airo_info *)dev->ml_priv, z, 8000);
 
 	case AIROFLSHPCHR: /* Send char to card. */
 		if(comp->len != sizeof(int))
 			return -EINVAL;
 		if (copy_from_user(&z,comp->data,comp->len))
 			return -EFAULT;
-		return flashpchar((struct airo_info *)dev->priv,z,8000);
+		return flashpchar((struct airo_info *)dev->ml_priv, z, 8000);
 
 	case AIROFLPUTBUF: /* Send 32k to card */
-		if (!((struct airo_info *)dev->priv)->flash)
+		if (!AIRO_FLASH(dev))
 			return -ENOMEM;
 		if(comp->len > FLASHSIZE)
 			return -EINVAL;
-		if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+		if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len))
 			return -EFAULT;
 
-		flashputbuf((struct airo_info *)dev->priv);
+		flashputbuf((struct airo_info *)dev->ml_priv);
 		return 0;
 
 	case AIRORESTART:
-		if(flashrestart((struct airo_info *)dev->priv,dev))
+		if (flashrestart((struct airo_info *)dev->ml_priv, dev))
 			return -EIO;
 		return 0;
 	}
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index dec5e87..bfca15d 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -1467,19 +1467,17 @@
 						else if (hw_dst_addr[1] == 0x40)
 							printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name);
 					while (dmi)
-					{							if (dmi->dmi_addrlen == 6)
-						{
-							DECLARE_MAC_BUF(mac);
+					{
+						if (dmi->dmi_addrlen == 6) {
 							if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP)
-								printk(KERN_ERR "%s mcl %s\n",
-								       dev->name, print_mac(mac, dmi->dmi_addr));
+								printk(KERN_ERR "%s mcl %pM\n",
+								       dev->name, dmi->dmi_addr);
 							for (i = 0; i < 6; i++)
 								if (dmi->dmi_addr[i] != hw_dst_addr[i])
 									break;
 							if (i == 6)
 								break;
-						}
-						else
+						} else
 							printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name);
 						dmi = dmi->next;
 					}
@@ -1512,18 +1510,14 @@
 			{
 				char immedDestAddress[6];
 				char immedSrcAddress[6];
-				DECLARE_MAC_BUF(mac);
-				DECLARE_MAC_BUF(mac2);
-				DECLARE_MAC_BUF(mac3);
-				DECLARE_MAC_BUF(mac4);
 				memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6);
 				memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6);
 
-				printk(KERN_WARNING "%s t %s f %s imd %s ims %s\n",
-				       dev->name, print_mac(mac, skbtmp),
-				       print_mac(mac2, &skbtmp[6]),
-				       print_mac(mac3, immedDestAddress),
-				       print_mac(mac4, immedSrcAddress));
+				printk(KERN_WARNING "%s t %pM f %pM imd %pM ims %pM\n",
+				       dev->name, skbtmp,
+				       &skbtmp[6],
+				       immedDestAddress,
+				       immedSrcAddress);
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
@@ -1535,7 +1529,6 @@
 					printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol);
 				}
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 53ea439..a725bb9 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -507,11 +507,15 @@
 #define AR5K_TXQ_FLAG_TXEOLINT_ENABLE		0x0004	/* Enable TXEOL interrupt -not used- */
 #define AR5K_TXQ_FLAG_TXDESCINT_ENABLE		0x0008	/* Enable TXDESC interrupt -not used- */
 #define AR5K_TXQ_FLAG_TXURNINT_ENABLE		0x0010	/* Enable TXURN interrupt */
-#define AR5K_TXQ_FLAG_BACKOFF_DISABLE		0x0020	/* Disable random post-backoff */
-#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE	0x0040	/* Enable ready time expiry policy (?)*/
-#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE	0x0080	/* Enable backoff while bursting */
-#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS		0x0100	/* Disable backoff while bursting */
-#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE	0x0200	/* Enable hw compression -not implemented-*/
+#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE		0x0020	/* Enable CBRORN interrupt */
+#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE		0x0040	/* Enable CBRURN interrupt */
+#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE		0x0080	/* Enable QTRIG interrupt */
+#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE		0x0100	/* Enable TXNOFRM interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE		0x0200	/* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE	0x0300	/* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE	0x0800	/* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS		0x1000	/* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE	0x2000	/* Enable hw compression -not implemented-*/
 
 /*
  * A struct to hold tx queue's parameters
@@ -853,7 +857,7 @@
  * 	checked. We should do this with ath5k_hw_update_mib_counters() but
  * 	it seems we should also then do some noise immunity work.
  * @AR5K_INT_RXPHY: RX PHY Error
- * @AR5K_INT_RXKCM: ??
+ * @AR5K_INT_RXKCM: RX Key cache miss
  * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
  * 	beacon that must be handled in software. The alternative is if you
  * 	have VEOL support, in that case you let the hardware deal with things.
@@ -869,7 +873,7 @@
  * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
  * 	errors. These types of errors we can enable seem to be of type
  * 	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
- * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER
+ * @AR5K_INT_GLOBAL: Used to clear and set the IER
  * @AR5K_INT_NOCARD: signals the card has been removed
  * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
  * 	bit value
@@ -881,36 +885,61 @@
  * MACs.
  */
 enum ath5k_int {
-	AR5K_INT_RX	= 0x00000001, /* Not common */
+	AR5K_INT_RXOK	= 0x00000001,
 	AR5K_INT_RXDESC	= 0x00000002,
+	AR5K_INT_RXERR	= 0x00000004,
 	AR5K_INT_RXNOFRM = 0x00000008,
 	AR5K_INT_RXEOL	= 0x00000010,
 	AR5K_INT_RXORN	= 0x00000020,
-	AR5K_INT_TX	= 0x00000040, /* Not common */
+	AR5K_INT_TXOK	= 0x00000040,
 	AR5K_INT_TXDESC	= 0x00000080,
+	AR5K_INT_TXERR	= 0x00000100,
+	AR5K_INT_TXNOFRM = 0x00000200,
+	AR5K_INT_TXEOL	= 0x00000400,
 	AR5K_INT_TXURN	= 0x00000800,
 	AR5K_INT_MIB	= 0x00001000,
+	AR5K_INT_SWI	= 0x00002000,
 	AR5K_INT_RXPHY	= 0x00004000,
 	AR5K_INT_RXKCM	= 0x00008000,
 	AR5K_INT_SWBA	= 0x00010000,
+	AR5K_INT_BRSSI	= 0x00020000,
 	AR5K_INT_BMISS	= 0x00040000,
-	AR5K_INT_BNR	= 0x00100000, /* Not common */
-	AR5K_INT_GPIO	= 0x01000000,
-	AR5K_INT_FATAL	= 0x40000000, /* Not common */
-	AR5K_INT_GLOBAL	= 0x80000000,
+	AR5K_INT_FATAL	= 0x00080000, /* Non common */
+	AR5K_INT_BNR	= 0x00100000, /* Non common */
+	AR5K_INT_TIM	= 0x00200000, /* Non common */
+	AR5K_INT_DTIM	= 0x00400000, /* Non common */
+	AR5K_INT_DTIM_SYNC =	0x00800000, /* Non common */
+	AR5K_INT_GPIO	=	0x01000000,
+	AR5K_INT_BCN_TIMEOUT =	0x02000000, /* Non common */
+	AR5K_INT_CAB_TIMEOUT =	0x04000000, /* Non common */
+	AR5K_INT_RX_DOPPLER =	0x08000000, /* Non common */
+	AR5K_INT_QCBRORN =	0x10000000, /* Non common */
+	AR5K_INT_QCBRURN =	0x20000000, /* Non common */
+	AR5K_INT_QTRIG	=	0x40000000, /* Non common */
+	AR5K_INT_GLOBAL =	0x80000000,
 
-	AR5K_INT_COMMON  = AR5K_INT_RXNOFRM
-			| AR5K_INT_RXDESC
-			| AR5K_INT_RXEOL
-			| AR5K_INT_RXORN
-			| AR5K_INT_TXURN
-			| AR5K_INT_TXDESC
-			| AR5K_INT_MIB
-			| AR5K_INT_RXPHY
-			| AR5K_INT_RXKCM
-			| AR5K_INT_SWBA
-			| AR5K_INT_BMISS
-			| AR5K_INT_GPIO,
+	AR5K_INT_COMMON  = AR5K_INT_RXOK
+		| AR5K_INT_RXDESC
+		| AR5K_INT_RXERR
+		| AR5K_INT_RXNOFRM
+		| AR5K_INT_RXEOL
+		| AR5K_INT_RXORN
+		| AR5K_INT_TXOK
+		| AR5K_INT_TXDESC
+		| AR5K_INT_TXERR
+		| AR5K_INT_TXNOFRM
+		| AR5K_INT_TXEOL
+		| AR5K_INT_TXURN
+		| AR5K_INT_MIB
+		| AR5K_INT_SWI
+		| AR5K_INT_RXPHY
+		| AR5K_INT_RXKCM
+		| AR5K_INT_SWBA
+		| AR5K_INT_BRSSI
+		| AR5K_INT_BMISS
+		| AR5K_INT_GPIO
+		| AR5K_INT_GLOBAL,
+
 	AR5K_INT_NOCARD	= 0xffffffff
 };
 
@@ -1064,10 +1093,11 @@
 
 	u8			ah_sta_id[ETH_ALEN];
 
-	/* Current BSSID we are trying to assoc to / creating.
+	/* Current BSSID we are trying to assoc to / create.
 	 * This is passed by mac80211 on config_interface() and cached here for
 	 * use in resets */
 	u8			ah_bssid[ETH_ALEN];
+	u8			ah_bssid_mask[ETH_ALEN];
 
 	u32			ah_gpio[AR5K_MAX_GPIO];
 	int			ah_gpio_npins;
@@ -1081,6 +1111,11 @@
 	u32			ah_txq_imr_txurn;
 	u32			ah_txq_imr_txdesc;
 	u32			ah_txq_imr_txeol;
+	u32			ah_txq_imr_cbrorn;
+	u32			ah_txq_imr_cbrurn;
+	u32			ah_txq_imr_qtrig;
+	u32			ah_txq_imr_nofrm;
+	u32			ah_txq_isr;
 	u32			*ah_rf_banks;
 	size_t			ah_rf_banks_size;
 	struct ath5k_gain	ah_gain;
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index cfd4d05..c7ffcbb 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -60,6 +60,9 @@
 #include "debug.h"
 
 static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
 
 /******************\
@@ -219,8 +222,7 @@
 		struct ieee80211_if_init_conf *conf);
 static void ath5k_remove_interface(struct ieee80211_hw *hw,
 		struct ieee80211_if_init_conf *conf);
-static int ath5k_config(struct ieee80211_hw *hw,
-		struct ieee80211_conf *conf);
+static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
 static int ath5k_config_interface(struct ieee80211_hw *hw,
 		struct ieee80211_vif *vif,
 		struct ieee80211_if_conf *conf);
@@ -238,8 +240,7 @@
 		struct ieee80211_tx_queue_stats *stats);
 static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
 static void ath5k_reset_tsf(struct ieee80211_hw *hw);
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
-		struct sk_buff *skb);
+static int ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb);
 
 static struct ieee80211_ops ath5k_hw_ops = {
 	.tx 		= ath5k_tx,
@@ -543,8 +544,8 @@
 
 	/* set up multi-rate retry capabilities */
 	if (sc->ah->ah_version == AR5K_AR5212) {
-		hw->max_altrates = 3;
-		hw->max_altrate_tries = 11;
+		hw->max_rates = 4;
+		hw->max_rate_tries = 11;
 	}
 
 	/* Finish private driver data initialization */
@@ -1183,7 +1184,7 @@
 		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
 		(sc->power_level * 2),
 		ieee80211_get_tx_rate(sc->hw, info)->hw_value,
-		info->control.retry_limit, keyidx, 0, flags, 0, 0);
+		info->control.rates[0].count, keyidx, 0, flags, 0, 0);
 	if (ret)
 		goto err_unmap;
 
@@ -1195,7 +1196,7 @@
 			break;
 
 		mrr_rate[i] = rate->hw_value;
-		mrr_tries[i] = info->control.retries[i].limit;
+		mrr_tries[i] = info->control.rates[i + 1].count;
 	}
 
 	ah->ah_setup_mrr_tx_desc(ah, ds,
@@ -1780,7 +1781,17 @@
 
 		rxs.noise = sc->ah->ah_noise_floor;
 		rxs.signal = rxs.noise + rs.rs_rssi;
-		rxs.qual = rs.rs_rssi * 100 / 64;
+
+		/* An rssi of 35 indicates you should be able use
+		 * 54 Mbps reliably. A more elaborate scheme can be used
+		 * here but it requires a map of SNR/throughput for each
+		 * possible mode used */
+		rxs.qual = rs.rs_rssi * 100 / 35;
+
+		/* rssi can be more than 35 though, anything above that
+		 * should be considered at 100% */
+		if (rxs.qual > 100)
+			rxs.qual = 100;
 
 		rxs.antenna = rs.rs_antenna;
 		rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
@@ -1841,30 +1852,26 @@
 		pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
 				PCI_DMA_TODEVICE);
 
-		memset(&info->status, 0, sizeof(info->status));
-		info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
-				ts.ts_rate[ts.ts_final_idx]);
-		info->status.retry_count = ts.ts_longretry;
-
+		ieee80211_tx_info_clear_status(info);
 		for (i = 0; i < 4; i++) {
-			struct ieee80211_tx_altrate *r =
-				&info->status.retries[i];
+			struct ieee80211_tx_rate *r =
+				&info->status.rates[i];
 
 			if (ts.ts_rate[i]) {
-				r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
-				r->limit = ts.ts_retry[i];
+				r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
+				r->count = ts.ts_retry[i];
 			} else {
-				r->rate_idx = -1;
-				r->limit = 0;
+				r->idx = -1;
+				r->count = 0;
 			}
 		}
 
-		info->status.excessive_retries = 0;
+		/* count the successful attempt as well */
+		info->status.rates[ts.ts_final_idx].count++;
+
 		if (unlikely(ts.ts_status)) {
 			sc->ll_stats.dot11ACKFailureCount++;
-			if (ts.ts_status & AR5K_TXERR_XRETRY)
-				info->status.excessive_retries = 1;
-			else if (ts.ts_status & AR5K_TXERR_FILT)
+			if (ts.ts_status & AR5K_TXERR_FILT)
 				info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 		} else {
 			info->flags |= IEEE80211_TX_STAT_ACK;
@@ -2138,8 +2145,6 @@
  *
  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
  * interrupts to detect TSF updates only.
- *
- * AP mode is missing.
  */
 static void
 ath5k_beacon_config(struct ath5k_softc *sc)
@@ -2152,7 +2157,9 @@
 
 	if (sc->opmode == NL80211_IFTYPE_STATION) {
 		sc->imask |= AR5K_INT_BMISS;
-	} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+	} else if (sc->opmode == NL80211_IFTYPE_ADHOC ||
+			sc->opmode == NL80211_IFTYPE_MESH_POINT ||
+			sc->opmode == NL80211_IFTYPE_AP) {
 		/*
 		 * In IBSS mode we use a self-linked tx descriptor and let the
 		 * hardware send the beacons automatically. We have to load it
@@ -2164,13 +2171,15 @@
 
 		sc->imask |= AR5K_INT_SWBA;
 
-		if (ath5k_hw_hasveol(ah)) {
-			spin_lock(&sc->block);
-			ath5k_beacon_send(sc);
-			spin_unlock(&sc->block);
-		}
+		if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+			if (ath5k_hw_hasveol(ah)) {
+				spin_lock(&sc->block);
+				ath5k_beacon_send(sc);
+				spin_unlock(&sc->block);
+			}
+		} else
+			ath5k_beacon_update_timers(sc, -1);
 	}
-	/* TODO else AP */
 
 	ath5k_hw_set_imr(ah, sc->imask);
 }
@@ -2210,7 +2219,7 @@
 	 */
 	sc->curchan = sc->hw->conf.channel;
 	sc->curband = &sc->sbands[sc->curchan->band];
-	sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
+	sc->imask = AR5K_INT_RXOK | AR5K_INT_TXOK | AR5K_INT_RXEOL |
 		AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
 		AR5K_INT_MIB;
 	ret = ath5k_reset(sc, false, false);
@@ -2404,9 +2413,10 @@
 				/* bump tx trigger level */
 				ath5k_hw_update_tx_triglevel(ah, true);
 			}
-			if (status & AR5K_INT_RX)
+			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
 				tasklet_schedule(&sc->rxtq);
-			if (status & AR5K_INT_TX)
+			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+					| AR5K_INT_TXERR | AR5K_INT_TXEOL))
 				tasklet_schedule(&sc->txtq);
 			if (status & AR5K_INT_BMISS) {
 			}
@@ -2522,8 +2532,7 @@
 	led->led_dev.brightness_set = ath5k_led_brightness_set;
 
 	err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
-	if (err)
-	{
+	if (err) {
 		ATH5K_WARN(sc, "could not register LED %s\n", name);
 		led->sc = NULL;
 	}
@@ -2741,8 +2750,10 @@
 	sc->vif = conf->vif;
 
 	switch (conf->type) {
+	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
 	case NL80211_IFTYPE_MONITOR:
 		sc->opmode = conf->type;
 		break;
@@ -2780,10 +2791,10 @@
  * TODO: Phy disable/diversity etc
  */
 static int
-ath5k_config(struct ieee80211_hw *hw,
-			struct ieee80211_conf *conf)
+ath5k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath5k_softc *sc = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
 
 	sc->bintval = conf->beacon_int;
 	sc->power_level = conf->power_level;
@@ -2804,7 +2815,7 @@
 		ret = -EIO;
 		goto unlock;
 	}
-	if (conf->bssid) {
+	if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
 		/* Cache for later use during resets */
 		memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
 		/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
@@ -2812,18 +2823,17 @@
 		ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
 		mmiowb();
 	}
-
 	if (conf->changed & IEEE80211_IFCC_BEACON &&
-	    vif->type == NL80211_IFTYPE_ADHOC) {
+			(vif->type == NL80211_IFTYPE_ADHOC ||
+			 vif->type == NL80211_IFTYPE_MESH_POINT ||
+			 vif->type == NL80211_IFTYPE_AP)) {
 		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
 		if (!beacon) {
 			ret = -ENOMEM;
 			goto unlock;
 		}
-		/* call old handler for now */
-		ath5k_beacon_update(hw, beacon);
+		ath5k_beacon_update(sc, beacon);
 	}
-
 	mutex_unlock(&sc->lock);
 
 	return ath5k_reset_wake(sc);
@@ -2883,9 +2893,9 @@
 		if (*new_flags & FIF_PROMISC_IN_BSS) {
 			rfilt |= AR5K_RX_FILTER_PROM;
 			__set_bit(ATH_STAT_PROMISC, sc->status);
-		}
-		else
+		} else {
 			__clear_bit(ATH_STAT_PROMISC, sc->status);
+		}
 	}
 
 	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
@@ -2946,9 +2956,12 @@
 		sc->opmode == NL80211_IFTYPE_ADHOC) {
 		rfilt |= AR5K_RX_FILTER_BEACON;
 	}
+	if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
+		rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
+			AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
 
 	/* Set filters */
-	ath5k_hw_set_rx_filter(ah,rfilt);
+	ath5k_hw_set_rx_filter(ah, rfilt);
 
 	/* Set multicast bits */
 	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
@@ -2965,12 +2978,13 @@
 	struct ath5k_softc *sc = hw->priv;
 	int ret = 0;
 
-	switch(key->alg) {
+	if (modparam_nohwcrypt)
+		return -EOPNOTSUPP;
+
+	switch (key->alg) {
 	case ALG_WEP:
-	/* XXX: fix hardware encryption, its not working. For now
-	 * allow software encryption */
-		/* break; */
 	case ALG_TKIP:
+		break;
 	case ALG_CCMP:
 		return -EOPNOTSUPP;
 	default:
@@ -2989,6 +3003,8 @@
 		}
 		__set_bit(key->keyidx, sc->keymap);
 		key->hw_key_idx = key->keyidx;
+		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
+			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
 		break;
 	case DISABLE_KEY:
 		ath5k_hw_reset_key(sc->ah, key->keyidx);
@@ -3055,19 +3071,13 @@
 }
 
 static int
-ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb)
 {
-	struct ath5k_softc *sc = hw->priv;
 	unsigned long flags;
 	int ret;
 
 	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
 
-	if (sc->opmode != NL80211_IFTYPE_ADHOC) {
-		ret = -EIO;
-		goto end;
-	}
-
 	spin_lock_irqsave(&sc->block, flags);
 	ath5k_txbuf_free(sc, sc->bbuf);
 	sc->bbuf->skb = skb;
@@ -3080,7 +3090,6 @@
 		mmiowb();
 	}
 
-end:
 	return ret;
 }
 
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c
index 7adceb2..7e2b1a6 100644
--- a/drivers/net/wireless/ath5k/dma.c
+++ b/drivers/net/wireless/ath5k/dma.c
@@ -472,9 +472,6 @@
  *
  * NOTE: We use read-and-clear register, so after this function is called ISR
  * is zeroed.
- *
- * XXX: Why filter interrupts in sw with interrupt_mask ? No benefit at all
- * plus it can be misleading (one might thing that we save interrupts this way)
  */
 int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
 {
@@ -494,11 +491,16 @@
 		}
 	} else {
 		/*
-		 * Read interrupt status from the Read-And-Clear
-		 * shadow register.
+		 * Read interrupt status from Interrupt
+		 * Status Register shadow copy (Read And Clear)
+		 *
 		 * Note: PISR/SISR Not available on 5210
 		 */
 		data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+		if (unlikely(data == AR5K_INT_NOCARD)) {
+			*interrupt_mask = data;
+			return -ENODEV;
+		}
 	}
 
 	/*
@@ -506,17 +508,9 @@
 	 */
 	*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
 
-	if (unlikely(data == AR5K_INT_NOCARD))
-		return -ENODEV;
-
-	if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
-		*interrupt_mask |= AR5K_INT_RX;
-
-	if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
-		| AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
-		*interrupt_mask |= AR5K_INT_TX;
-
 	if (ah->ah_version != AR5K_AR5210) {
+		u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
+
 		/*HIU = Host Interface Unit (PCI etc)*/
 		if (unlikely(data & (AR5K_ISR_HIUERR)))
 			*interrupt_mask |= AR5K_INT_FATAL;
@@ -524,24 +518,93 @@
 		/*Beacon Not Ready*/
 		if (unlikely(data & (AR5K_ISR_BNR)))
 			*interrupt_mask |= AR5K_INT_BNR;
-	}
 
-	/*
-	 * XXX: BMISS interrupts may occur after association.
-	 * I found this on 5210 code but it needs testing. If this is
-	 * true we should disable them before assoc and re-enable them
-	 * after a successfull assoc + some jiffies.
-	 */
-#if 0
-	interrupt_mask &= ~AR5K_INT_BMISS;
-#endif
+		if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
+					AR5K_SISR2_DPERR |
+					AR5K_SISR2_MCABT)))
+			*interrupt_mask |= AR5K_INT_FATAL;
+
+		if (data & AR5K_ISR_TIM)
+			*interrupt_mask |= AR5K_INT_TIM;
+
+		if (data & AR5K_ISR_BCNMISC) {
+			if (sisr2 & AR5K_SISR2_TIM)
+				*interrupt_mask |= AR5K_INT_TIM;
+			if (sisr2 & AR5K_SISR2_DTIM)
+				*interrupt_mask |= AR5K_INT_DTIM;
+			if (sisr2 & AR5K_SISR2_DTIM_SYNC)
+				*interrupt_mask |= AR5K_INT_DTIM_SYNC;
+			if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
+				*interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
+			if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
+				*interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
+		}
+
+		if (data & AR5K_ISR_RXDOPPLER)
+			*interrupt_mask |= AR5K_INT_RX_DOPPLER;
+		if (data & AR5K_ISR_QCBRORN) {
+			*interrupt_mask |= AR5K_INT_QCBRORN;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+					AR5K_SISR3_QCBRORN);
+		}
+		if (data & AR5K_ISR_QCBRURN) {
+			*interrupt_mask |= AR5K_INT_QCBRURN;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+					AR5K_SISR3_QCBRURN);
+		}
+		if (data & AR5K_ISR_QTRIG) {
+			*interrupt_mask |= AR5K_INT_QTRIG;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
+					AR5K_SISR4_QTRIG);
+		}
+
+		if (data & AR5K_ISR_TXOK)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+					AR5K_SISR0_QCU_TXOK);
+
+		if (data & AR5K_ISR_TXDESC)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+					AR5K_SISR0_QCU_TXDESC);
+
+		if (data & AR5K_ISR_TXERR)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+					AR5K_SISR1_QCU_TXERR);
+
+		if (data & AR5K_ISR_TXEOL)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+					AR5K_SISR1_QCU_TXEOL);
+
+		if (data & AR5K_ISR_TXURN)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
+					AR5K_SISR2_QCU_TXURN);
+	} else {
+		if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
+				| AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
+			*interrupt_mask |= AR5K_INT_FATAL;
+
+		/*
+		 * XXX: BMISS interrupts may occur after association.
+		 * I found this on 5210 code but it needs testing. If this is
+		 * true we should disable them before assoc and re-enable them
+		 * after a successfull assoc + some jiffies.
+			interrupt_mask &= ~AR5K_INT_BMISS;
+		 */
+	}
 
 	/*
 	 * In case we didn't handle anything,
 	 * print the register value.
 	 */
 	if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
-		ATH5K_PRINTF("0x%08x\n", data);
+		ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
 
 	return 0;
 }
@@ -560,14 +623,17 @@
 {
 	enum ath5k_int old_mask, int_mask;
 
+	old_mask = ah->ah_imr;
+
 	/*
 	 * Disable card interrupts to prevent any race conditions
-	 * (they will be re-enabled afterwards).
+	 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
+	 * is set again on the new mask).
 	 */
-	ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
-	ath5k_hw_reg_read(ah, AR5K_IER);
-
-	old_mask = ah->ah_imr;
+	if (old_mask & AR5K_INT_GLOBAL) {
+		ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+		ath5k_hw_reg_read(ah, AR5K_IER);
+	}
 
 	/*
 	 * Add additional, chipset-dependent interrupt mask flags
@@ -575,30 +641,64 @@
 	 */
 	int_mask = new_mask & AR5K_INT_COMMON;
 
-	if (new_mask & AR5K_INT_RX)
-		int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
-			AR5K_IMR_RXDESC;
-
-	if (new_mask & AR5K_INT_TX)
-		int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
-			AR5K_IMR_TXURN;
-
 	if (ah->ah_version != AR5K_AR5210) {
+		/* Preserve per queue TXURN interrupt mask */
+		u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
+				& AR5K_SIMR2_QCU_TXURN;
+
 		if (new_mask & AR5K_INT_FATAL) {
 			int_mask |= AR5K_IMR_HIUERR;
-			AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
-					AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
+			simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
+				| AR5K_SIMR2_DPERR);
 		}
+
+		/*Beacon Not Ready*/
+		if (new_mask & AR5K_INT_BNR)
+			int_mask |= AR5K_INT_BNR;
+
+		if (new_mask & AR5K_INT_TIM)
+			int_mask |= AR5K_IMR_TIM;
+
+		if (new_mask & AR5K_INT_TIM)
+			simr2 |= AR5K_SISR2_TIM;
+		if (new_mask & AR5K_INT_DTIM)
+			simr2 |= AR5K_SISR2_DTIM;
+		if (new_mask & AR5K_INT_DTIM_SYNC)
+			simr2 |= AR5K_SISR2_DTIM_SYNC;
+		if (new_mask & AR5K_INT_BCN_TIMEOUT)
+			simr2 |= AR5K_SISR2_BCN_TIMEOUT;
+		if (new_mask & AR5K_INT_CAB_TIMEOUT)
+			simr2 |= AR5K_SISR2_CAB_TIMEOUT;
+
+		if (new_mask & AR5K_INT_RX_DOPPLER)
+			int_mask |= AR5K_IMR_RXDOPPLER;
+
+		/* Note: Per queue interrupt masks
+		 * are set via reset_tx_queue (qcu.c) */
+		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
+
+	} else {
+		if (new_mask & AR5K_INT_FATAL)
+			int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
+				| AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
+
+		ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
 	}
 
-	ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+	/* If RXNOFRM interrupt is masked disable it
+	 * by setting AR5K_RXNOFRM to zero */
+	if (!(new_mask & AR5K_INT_RXNOFRM))
+		ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
 
 	/* Store new interrupt mask */
 	ah->ah_imr = new_mask;
 
-	/* ..re-enable interrupts */
-	ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
-	ath5k_hw_reg_read(ah, AR5K_IER);
+	/* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
+	if (new_mask & AR5K_INT_GLOBAL) {
+		ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
+		ath5k_hw_reg_read(ah, AR5K_IER);
+	}
 
 	return old_mask;
 }
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
index ceaa6c4..450bd6e 100644
--- a/drivers/net/wireless/ath5k/initvals.c
+++ b/drivers/net/wireless/ath5k/initvals.c
@@ -1681,7 +1681,7 @@
 	 */
 
 	/* For AR5212 and combatible */
-	if (ah->ah_version == AR5K_AR5212){
+	if (ah->ah_version == AR5K_AR5212) {
 
 		/* First set of mode-specific settings */
 		ath5k_hw_ini_mode_registers(ah,
@@ -1695,7 +1695,7 @@
 					ar5212_ini, change_channel);
 
 		/* Second set of mode-specific settings */
-		if (ah->ah_radio == AR5K_RF5111){
+		if (ah->ah_radio == AR5K_RF5111) {
 
 			ath5k_hw_ini_mode_registers(ah,
 					ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
@@ -1706,7 +1706,7 @@
 					ARRAY_SIZE(rf5111_ini_bbgain),
 					rf5111_ini_bbgain, change_channel);
 
-		} else if (ah->ah_radio == AR5K_RF5112){
+		} else if (ah->ah_radio == AR5K_RF5112) {
 
 			ath5k_hw_ini_mode_registers(ah,
 					ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
@@ -1716,7 +1716,7 @@
 					ARRAY_SIZE(rf5112_ini_bbgain),
 					rf5112_ini_bbgain, change_channel);
 
-		} else if (ah->ah_radio == AR5K_RF5413){
+		} else if (ah->ah_radio == AR5K_RF5413) {
 
 			ath5k_hw_ini_mode_registers(ah,
 					ARRAY_SIZE(rf5413_ini_mode_end),
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
index a47df9a..d7f0c10 100644
--- a/drivers/net/wireless/ath5k/pcu.c
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -46,34 +46,45 @@
 {
 	u32 pcu_reg, beacon_reg, low_id, high_id;
 
-	pcu_reg = 0;
+
+	/* Preserve rest settings */
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+			| AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
 	beacon_reg = 0;
 
 	ATH5K_TRACE(ah->ah_sc);
 
 	switch (ah->ah_op_mode) {
 	case NL80211_IFTYPE_ADHOC:
-		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
-			(ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_NO_PSPOLL : 0);
+		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
 		beacon_reg |= AR5K_BCR_ADHOC;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
 		break;
 
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
-		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
-			(ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_NO_PSPOLL : 0);
+		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
 		beacon_reg |= AR5K_BCR_AP;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
 		break;
 
 	case NL80211_IFTYPE_STATION:
-		pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
-			(ah->ah_version == AR5K_AR5210 ?
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
 				AR5K_STA_ID1_PWR_SV : 0);
 	case NL80211_IFTYPE_MONITOR:
-		pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
-			(ah->ah_version == AR5K_AR5210 ?
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
 				AR5K_STA_ID1_NO_PSPOLL : 0);
 		break;
 
@@ -130,6 +141,8 @@
 		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
 		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
 	}
+
+	/* TODO: Handle ANI stats */
 }
 
 /**
@@ -254,6 +267,10 @@
  * @mac: The card's mac address
  *
  * Set station id on hw using the provided mac address
+ *
+ * NOTE: This is only called during attach, don't call it
+ * on reset because it overwrites all AR5K_STA_ID1 settings.
+ * We have set_opmode (above) for reset.
  */
 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
 {
@@ -290,8 +307,10 @@
 	 * Set simple BSSID mask on 5212
 	 */
 	if (ah->ah_version == AR5K_AR5212) {
-		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
-		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
+		ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
+							AR5K_BSS_IDM0);
+		ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
+							AR5K_BSS_IDM1);
 	}
 
 	/*
@@ -415,6 +434,9 @@
 	u32 low_id, high_id;
 	ATH5K_TRACE(ah->ah_sc);
 
+	/* Cache bssid mask so that we can restore it
+	 * on reset */
+	memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
 	if (ah->ah_version == AR5K_AR5212) {
 		low_id = AR5K_LOW_ID(mask);
 		high_id = AR5K_HIGH_ID(mask);
@@ -576,7 +598,7 @@
 		filter |= AR5K_RX_FILTER_PROM;
 	}
 
-	/*Zero length DMA*/
+	/*Zero length DMA (phy error reporting) */
 	if (data)
 		AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
 	else
@@ -661,7 +683,12 @@
 	 * Set the additional timers by mode
 	 */
 	switch (ah->ah_op_mode) {
+	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_STATION:
+		/* In STA mode timer1 is used as next wakeup
+		 * timer and timer2 as next CFP duration start
+		 * timer. Both in 1/8TUs. */
+		/* TODO: PCF handling */
 		if (ah->ah_version == AR5K_AR5210) {
 			timer1 = 0xffffffff;
 			timer2 = 0xffffffff;
@@ -669,27 +696,60 @@
 			timer1 = 0x0000ffff;
 			timer2 = 0x0007ffff;
 		}
+		/* Mark associated AP as PCF incapable for now */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
 		break;
-
+	case NL80211_IFTYPE_ADHOC:
+		AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
 	default:
+		/* On non-STA modes timer1 is used as next DMA
+		 * beacon alert (DBA) timer and timer2 as next
+		 * software beacon alert. Both in 1/8TUs. */
 		timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
 		timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
+		break;
 	}
 
+	/* Timer3 marks the end of our ATIM window
+	 * a zero length window is not allowed because
+	 * we 'll get no beacons */
 	timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
 
 	/*
 	 * Set the beacon register and enable all timers.
-	 * (next beacon, DMA beacon, software beacon, ATIM window time)
 	 */
-	ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+	/* When in AP mode zero timer0 to start TSF */
+	if (ah->ah_op_mode == NL80211_IFTYPE_AP)
+		ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+	else
+		ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
 	ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
 	ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
 	ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
 
+	/* Force a TSF reset if requested and enable beacons */
+	if (interval & AR5K_BEACON_RESET_TSF)
+		ath5k_hw_reset_tsf(ah);
+
 	ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
-			AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
-		AR5K_BEACON);
+					AR5K_BEACON_ENABLE),
+						AR5K_BEACON);
+
+	/* Flush any pending BMISS interrupts on ISR by
+	 * performing a clear-on-write operation on PISR
+	 * register for the BMISS bit (writing a bit on
+	 * ISR togles a reset for that bit and leaves
+	 * the rest bits intact) */
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
+	else
+		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
+
+	/* TODO: Set enchanced sleep registers on AR5212
+	 * based on vif->bss_conf params, until then
+	 * disable power save reporting.*/
+	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
+
 }
 
 #if 0
@@ -899,14 +959,26 @@
  */
 int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
 {
-	unsigned int i;
+	unsigned int i, type;
+	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
 
 	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
 
+	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
+
 	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
 		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
 
+	/* Reset associated MIC entry if TKIP
+	 * is enabled located at offset (entry + 64) */
+	if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+		AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
+		for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
+			ath5k_hw_reg_write(ah, 0,
+				AR5K_KEYTABLE_OFF(micentry, i));
+	}
+
 	/*
 	 * Set NULL encryption on AR5212+
 	 *
@@ -916,10 +988,16 @@
 	 * Note2: Windows driver (ndiswrapper) sets this to
 	 *        0x00000714 instead of 0x00000007
 	 */
-	if (ah->ah_version > AR5K_AR5211)
+	if (ah->ah_version > AR5K_AR5211) {
 		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
 				AR5K_KEYTABLE_TYPE(entry));
 
+		if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+			ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+				AR5K_KEYTABLE_TYPE(micentry));
+		}
+	}
+
 	return 0;
 }
 
@@ -943,17 +1021,29 @@
 		const struct ieee80211_key_conf *key, const u8 *mac)
 {
 	unsigned int i;
+	int keylen;
 	__le32 key_v[5] = {};
+	__le32 key0 = 0, key1 = 0;
+	__le32 *rxmic, *txmic;
 	u32 keytype;
+	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+	bool is_tkip;
 
 	ATH5K_TRACE(ah->ah_sc);
 
-	/* key->keylen comes in from mac80211 in bytes */
+	is_tkip = (key->alg == ALG_TKIP);
 
-	if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
+	/*
+	 * key->keylen comes in from mac80211 in bytes.
+	 * TKIP is 128 bit + 128 bit mic
+	 */
+	keylen = (is_tkip) ? (128 / 8) : key->keylen;
+
+	if (entry > AR5K_KEYTABLE_SIZE ||
+		(is_tkip && micentry > AR5K_KEYTABLE_SIZE))
 		return -EOPNOTSUPP;
 
-	switch (key->keylen) {
+	switch (keylen) {
 	/* WEP 40-bit   = 40-bit  entered key + 24 bit IV = 64-bit */
 	case 40 / 8:
 		memcpy(&key_v[0], key->key, 5);
@@ -967,24 +1057,66 @@
 		memcpy(&key_v[4], &key->key[12], 1);
 		keytype = AR5K_KEYTABLE_TYPE_104;
 		break;
-	/* WEP 128-bit  = 128-bit entered key + 24 bit IV = 152-bit */
+	/* WEP/TKIP 128-bit  = 128-bit entered key + 24 bit IV = 152-bit */
 	case 128 / 8:
 		memcpy(&key_v[0], &key->key[0], 6);
 		memcpy(&key_v[2], &key->key[6], 6);
 		memcpy(&key_v[4], &key->key[12], 4);
-		keytype = AR5K_KEYTABLE_TYPE_128;
+		keytype = is_tkip ?
+			AR5K_KEYTABLE_TYPE_TKIP :
+			AR5K_KEYTABLE_TYPE_128;
 		break;
 
 	default:
 		return -EINVAL; /* shouldn't happen */
 	}
 
+	/* intentionally corrupt key until mic is installed */
+	if (is_tkip) {
+		key0 = key_v[0] = ~key_v[0];
+		key1 = key_v[1] = ~key_v[1];
+	}
+
 	for (i = 0; i < ARRAY_SIZE(key_v); i++)
 		ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
 				AR5K_KEYTABLE_OFF(entry, i));
 
 	ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
 
+	if (is_tkip) {
+		/* Install rx/tx MIC */
+		rxmic = (__le32 *) &key->key[16];
+		txmic = (__le32 *) &key->key[24];
+#if 0
+		/* MISC_MODE register & 0x04 - for mac srev >= griffin */
+		key_v[0] = rxmic[0];
+		key_v[1] = (txmic[0] >> 16) & 0xffff;
+		key_v[2] = rxmic[1];
+		key_v[3] = txmic[0] & 0xffff;
+		key_v[4] = txmic[1];
+#else
+		key_v[0] = rxmic[0];
+		key_v[1] = 0;
+		key_v[2] = rxmic[1];
+		key_v[3] = 0;
+		key_v[4] = 0;
+#endif
+		for (i = 0; i < ARRAY_SIZE(key_v); i++)
+			ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+				AR5K_KEYTABLE_OFF(micentry, i));
+
+		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+			AR5K_KEYTABLE_TYPE(micentry));
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
+
+		/* restore first 2 words of key */
+		ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
+			AR5K_KEYTABLE_OFF(entry, 0));
+		ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
+			AR5K_KEYTABLE_OFF(entry, 1));
+	}
+
 	return ath5k_hw_set_key_lladdr(ah, entry, mac);
 }
 
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
index e43f656..69625bf 100644
--- a/drivers/net/wireless/ath5k/phy.c
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -1412,7 +1412,8 @@
 		rf_ini = rfregs_2112a;
 		rf_size = ARRAY_SIZE(rfregs_5112a);
 		if (mode < 2) {
-			ATH5K_ERR(ah->ah_sc,"invalid channel mode: %i\n",mode);
+			ATH5K_ERR(ah->ah_sc, "invalid channel mode: %i\n",
+				  mode);
 			return -EINVAL;
 		}
 		mode = mode - 2; /*no a/turboa modes for 2112*/
@@ -1708,7 +1709,7 @@
 		if (ah->ah_radio >= AR5K_RF5112) {
 			ath5k_hw_rfregs_gainf_corr(ah);
 			ah->ah_gain.g_current =
-				ah->ah_gain.g_current>=ah->ah_gain.g_f_corr ?
+				ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
 				(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
 				0;
 		}
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c
index 01bf091..1b7bc50 100644
--- a/drivers/net/wireless/ath5k/qcu.c
+++ b/drivers/net/wireless/ath5k/qcu.c
@@ -432,13 +432,30 @@
 		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
 			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
 
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
 
 		/* Update secondary interrupt mask registers */
+
+		/* Filter out inactive queues */
 		ah->ah_txq_imr_txok &= ah->ah_txq_status;
 		ah->ah_txq_imr_txerr &= ah->ah_txq_status;
 		ah->ah_txq_imr_txurn &= ah->ah_txq_status;
 		ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
 		ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+		ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+		ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+		ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+		ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
 
 		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
 			AR5K_SIMR0_QCU_TXOK) |
@@ -448,8 +465,24 @@
 			AR5K_SIMR1_QCU_TXERR) |
 			AR5K_REG_SM(ah->ah_txq_imr_txeol,
 			AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
-			AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
+		/* Update simr2 but don't overwrite rest simr2 settings */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+			AR5K_REG_SM(ah->ah_txq_imr_txurn,
+			AR5K_SIMR2_QCU_TXURN));
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+			AR5K_SIMR3_QCBRORN) |
+			AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+			AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+			AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+		/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+			AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+		/* No queue has TXNOFRM enabled, disable the interrupt
+		 * by setting AR5K_TXNOFRM to zero */
+		if (ah->ah_txq_imr_nofrm == 0)
+			ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index e557fe1..69755fc 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -234,6 +234,7 @@
 #define AR5K_TXNOFRM		0x004c
 #define	AR5K_TXNOFRM_M		0x000003ff
 #define	AR5K_TXNOFRM_QCU	0x000ffc00
+#define	AR5K_TXNOFRM_QCU_S	10
 
 /*
  * Receive frame gap timeout register
@@ -350,7 +351,7 @@
 
 #define AR5K_SISR3		0x0090			/* Register Address [5211+] */
 #define AR5K_SISR3_QCBRORN	0x000003ff	/* Mask for QCBRORN */
-#define AR5K_SISR3_QCBORN_S	0
+#define AR5K_SISR3_QCBRORN_S	0
 #define AR5K_SISR3_QCBRURN	0x03ff0000	/* Mask for QCBRURN */
 #define AR5K_SISR3_QCBRURN_S	16
 
@@ -1113,14 +1114,16 @@
 #define AR5K_PCU_MAX	0x8fff
 
 /*
- * First station id register (MAC address in lower 32 bits)
+ * First station id register (Lower 32 bits of MAC address)
  */
-#define AR5K_STA_ID0	0x8000
+#define AR5K_STA_ID0		0x8000
+#define	AR5K_STA_ID0_ARRD_L32	0xffffffff
 
 /*
- * Second station id register (MAC address in upper 16 bits)
+ * Second station id register (Upper 16 bits of MAC address + PCU settings)
  */
 #define AR5K_STA_ID1			0x8004			/* Register Address */
+#define	AR5K_STA_ID1_ADDR_U16		0x0000ffff	/* Upper 16 bits of MAC addres */
 #define AR5K_STA_ID1_AP			0x00010000	/* Set AP mode */
 #define AR5K_STA_ID1_ADHOC		0x00020000	/* Set Ad-Hoc mode */
 #define AR5K_STA_ID1_PWR_SV		0x00040000	/* Power save reporting */
@@ -1810,6 +1813,10 @@
 #define AR5K_KEYTABLE_MAC1(_n)		AR5K_KEYTABLE_OFF(_n, 7)
 #define AR5K_KEYTABLE_VALID		0x00008000
 
+/* If key type is TKIP and MIC is enabled
+ * MIC key goes in offset entry + 64 */
+#define	AR5K_KEYTABLE_MIC_OFFSET	64
+
 /* WEP 40-bit	= 40-bit  entered key + 24 bit IV = 64-bit
  * WEP 104-bit	= 104-bit entered key + 24-bit IV = 128-bit
  * WEP 128-bit	= 128-bit entered key + 24 bit IV = 152-bit
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
index 1b6d45b..b51bc03 100644
--- a/drivers/net/wireless/ath5k/reset.c
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -864,8 +864,7 @@
 
 	/* Pre-enable interrupts on 5211/5212*/
 	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_set_imr(ah, AR5K_INT_RX | AR5K_INT_TX |
-				AR5K_INT_FATAL);
+		ath5k_hw_set_imr(ah, ah->ah_imr);
 
 	/*
 	 * Set RF kill flags if supported by the device (read from the EEPROM)
diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile
index a641151..c58cfde 100644
--- a/drivers/net/wireless/ath9k/Makefile
+++ b/drivers/net/wireless/ath9k/Makefile
@@ -1,4 +1,8 @@
 ath9k-y +=	hw.o \
+		eeprom.o \
+		mac.o \
+		calib.o \
+		ani.o \
 		phy.o \
 		regd.o \
 		beacon.o \
diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c
new file mode 100644
index 0000000..ada12e9
--- /dev/null
+++ b/drivers/net/wireless/ath9k/ani.c
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
+					struct ath9k_channel *chan)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+		if (ahp->ah_ani[i].c.channel == chan->channel)
+			return i;
+		if (ahp->ah_ani[i].c.channel == 0) {
+			ahp->ah_ani[i].c.channel = chan->channel;
+			ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
+			return i;
+		}
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"No more channel states left. Using channel 0\n");
+
+	return 0;
+}
+
+static bool ath9k_hw_ani_control(struct ath_hal *ah,
+				 enum ath9k_ani_cmd cmd, int param)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState = ahp->ah_curani;
+
+	switch (cmd & ahp->ah_ani_function) {
+	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"%s: level out of range (%u > %u)\n",
+				__func__, level,
+				(unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired));
+			return false;
+		}
+
+		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+			      AR_PHY_DESIRED_SZ_TOT_DES,
+			      ahp->ah_totalSizeDesired[level]);
+		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+			      AR_PHY_AGC_CTL1_COARSE_LOW,
+			      ahp->ah_coarseLow[level]);
+		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+			      AR_PHY_AGC_CTL1_COARSE_HIGH,
+			      ahp->ah_coarseHigh[level]);
+		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+			      AR_PHY_FIND_SIG_FIRPWR,
+			      ahp->ah_firpwr[level]);
+
+		if (level > aniState->noiseImmunityLevel)
+			ahp->ah_stats.ast_ani_niup++;
+		else if (level < aniState->noiseImmunityLevel)
+			ahp->ah_stats.ast_ani_nidown++;
+		aniState->noiseImmunityLevel = level;
+		break;
+	}
+	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+		const int m1ThreshLow[] = { 127, 50 };
+		const int m2ThreshLow[] = { 127, 40 };
+		const int m1Thresh[] = { 127, 0x4d };
+		const int m2Thresh[] = { 127, 0x40 };
+		const int m2CountThr[] = { 31, 16 };
+		const int m2CountThrLow[] = { 63, 48 };
+		u32 on = param ? 1 : 0;
+
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+			      m1ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+			      m2ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M1_THRESH,
+			      m1Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M2_THRESH,
+			      m2Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M2COUNT_THR,
+			      m2CountThr[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+			      m2CountThrLow[on]);
+
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+			      m1ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+			      m2ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M1_THRESH,
+			      m1Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M2_THRESH,
+			      m2Thresh[on]);
+
+		if (on)
+			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+		else
+			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+		if (!on != aniState->ofdmWeakSigDetectOff) {
+			if (on)
+				ahp->ah_stats.ast_ani_ofdmon++;
+			else
+				ahp->ah_stats.ast_ani_ofdmoff++;
+			aniState->ofdmWeakSigDetectOff = !on;
+		}
+		break;
+	}
+	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
+		const int weakSigThrCck[] = { 8, 6 };
+		u32 high = param ? 1 : 0;
+
+		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+			      weakSigThrCck[high]);
+		if (high != aniState->cckWeakSigThreshold) {
+			if (high)
+				ahp->ah_stats.ast_ani_cckhigh++;
+			else
+				ahp->ah_stats.ast_ani_ccklow++;
+			aniState->cckWeakSigThreshold = high;
+		}
+		break;
+	}
+	case ATH9K_ANI_FIRSTEP_LEVEL:{
+		const int firstep[] = { 0, 4, 8 };
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(firstep)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"%s: level out of range (%u > %u)\n",
+				__func__, level,
+				(unsigned) ARRAY_SIZE(firstep));
+			return false;
+		}
+		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+			      AR_PHY_FIND_SIG_FIRSTEP,
+			      firstep[level]);
+		if (level > aniState->firstepLevel)
+			ahp->ah_stats.ast_ani_stepup++;
+		else if (level < aniState->firstepLevel)
+			ahp->ah_stats.ast_ani_stepdown++;
+		aniState->firstepLevel = level;
+		break;
+	}
+	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+		const int cycpwrThr1[] =
+			{ 2, 4, 6, 8, 10, 12, 14, 16 };
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(cycpwrThr1)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"%s: level out of range (%u > %u)\n",
+				__func__, level,
+				(unsigned)
+				ARRAY_SIZE(cycpwrThr1));
+			return false;
+		}
+		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+			      AR_PHY_TIMING5_CYCPWR_THR1,
+			      cycpwrThr1[level]);
+		if (level > aniState->spurImmunityLevel)
+			ahp->ah_stats.ast_ani_spurup++;
+		else if (level < aniState->spurImmunityLevel)
+			ahp->ah_stats.ast_ani_spurdown++;
+		aniState->spurImmunityLevel = level;
+		break;
+	}
+	case ATH9K_ANI_PRESENT:
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"%s: invalid cmd %u\n", __func__, cmd);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
+		"ofdmWeakSigDetectOff=%d\n",
+		aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
+		!aniState->ofdmWeakSigDetectOff);
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"cckWeakSigThreshold=%d, "
+		"firstepLevel=%d, listenTime=%d\n",
+		aniState->cckWeakSigThreshold, aniState->firstepLevel,
+		aniState->listenTime);
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+		aniState->cycleCount, aniState->ofdmPhyErrCount,
+		aniState->cckPhyErrCount);
+
+	return true;
+}
+
+static void ath9k_hw_update_mibstats(struct ath_hal *ah,
+				     struct ath9k_mib_stats *stats)
+{
+	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+	stats->rts_good += REG_READ(ah, AR_RTS_OK);
+	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void ath9k_ani_restart(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ahp->ah_curani;
+
+	aniState->listenTime = 0;
+	if (ahp->ah_hasHwPhyCounters) {
+		if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+			aniState->ofdmPhyErrBase = 0;
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"OFDM Trigger is too high for hw counters\n");
+		} else {
+			aniState->ofdmPhyErrBase =
+				AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+		}
+		if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+			aniState->cckPhyErrBase = 0;
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"CCK Trigger is too high for hw counters\n");
+		} else {
+			aniState->cckPhyErrBase =
+				AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+		}
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"%s: Writing ofdmbase=%u   cckbase=%u\n",
+			__func__, aniState->ofdmPhyErrBase,
+			aniState->cckPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+		ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+	}
+	aniState->ofdmPhyErrCount = 0;
+	aniState->cckPhyErrCount = 0;
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_channel *chan = ah->ah_curchan;
+	struct ar5416AniState *aniState;
+	enum wireless_mode mode;
+	int32_t rssi;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ahp->ah_curani;
+
+	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+					 aniState->noiseImmunityLevel + 1)) {
+			return;
+		}
+	}
+
+	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+					 aniState->spurImmunityLevel + 1)) {
+			return;
+		}
+	}
+
+	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		}
+		return;
+	}
+	rssi = BEACON_RSSI(ahp);
+	if (rssi > aniState->rssiThrHigh) {
+		if (!aniState->ofdmWeakSigDetectOff) {
+			if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+					 false)) {
+				ath9k_hw_ani_control(ah,
+					ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+				return;
+			}
+		}
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+			return;
+		}
+	} else if (rssi > aniState->rssiThrLow) {
+		if (aniState->ofdmWeakSigDetectOff)
+			ath9k_hw_ani_control(ah,
+				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     true);
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		return;
+	} else {
+		mode = ath9k_hw_chan2wmode(ah, chan);
+		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+			if (!aniState->ofdmWeakSigDetectOff)
+				ath9k_hw_ani_control(ah,
+				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     false);
+			if (aniState->firstepLevel > 0)
+				ath9k_hw_ani_control(ah,
+					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
+			return;
+		}
+	}
+}
+
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_channel *chan = ah->ah_curchan;
+	struct ar5416AniState *aniState;
+	enum wireless_mode mode;
+	int32_t rssi;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ahp->ah_curani;
+	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+					 aniState->noiseImmunityLevel + 1)) {
+			return;
+		}
+	}
+	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		}
+		return;
+	}
+	rssi = BEACON_RSSI(ahp);
+	if (rssi > aniState->rssiThrLow) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+	} else {
+		mode = ath9k_hw_chan2wmode(ah, chan);
+		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+			if (aniState->firstepLevel > 0)
+				ath9k_hw_ani_control(ah,
+					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
+		}
+	}
+}
+
+static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState;
+	int32_t rssi;
+
+	aniState = ahp->ah_curani;
+
+	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+		if (aniState->firstepLevel > 0) {
+			if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+						 aniState->firstepLevel - 1))
+				return;
+		}
+	} else {
+		rssi = BEACON_RSSI(ahp);
+		if (rssi > aniState->rssiThrHigh) {
+			/* XXX: Handle me */
+		} else if (rssi > aniState->rssiThrLow) {
+			if (aniState->ofdmWeakSigDetectOff) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+					 true) == true)
+					return;
+			}
+			if (aniState->firstepLevel > 0) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_FIRSTEP_LEVEL,
+					 aniState->firstepLevel - 1) == true)
+					return;
+			}
+		} else {
+			if (aniState->firstepLevel > 0) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_FIRSTEP_LEVEL,
+					 aniState->firstepLevel - 1) == true)
+					return;
+			}
+		}
+	}
+
+	if (aniState->spurImmunityLevel > 0) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+					 aniState->spurImmunityLevel - 1))
+			return;
+	}
+
+	if (aniState->noiseImmunityLevel > 0) {
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+				     aniState->noiseImmunityLevel - 1);
+		return;
+	}
+}
+
+static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState;
+	u32 txFrameCount, rxFrameCount, cycleCount;
+	int32_t listenTime;
+
+	txFrameCount = REG_READ(ah, AR_TFCNT);
+	rxFrameCount = REG_READ(ah, AR_RFCNT);
+	cycleCount = REG_READ(ah, AR_CCCNT);
+
+	aniState = ahp->ah_curani;
+	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+
+		listenTime = 0;
+		ahp->ah_stats.ast_ani_lzero++;
+	} else {
+		int32_t ccdelta = cycleCount - aniState->cycleCount;
+		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+		listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
+	}
+	aniState->cycleCount = cycleCount;
+	aniState->txFrameCount = txFrameCount;
+	aniState->rxFrameCount = rxFrameCount;
+
+	return listenTime;
+}
+
+void ath9k_ani_reset(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState;
+	struct ath9k_channel *chan = ah->ah_curchan;
+	int index;
+
+	if (!DO_ANI(ah))
+		return;
+
+	index = ath9k_hw_get_ani_channel_idx(ah, chan);
+	aniState = &ahp->ah_ani[index];
+	ahp->ah_curani = aniState;
+
+	if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
+	    && ah->ah_opmode != ATH9K_M_IBSS) {
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"%s: Reset ANI state opmode %u\n", __func__,
+			ah->ah_opmode);
+		ahp->ah_stats.ast_ani_reset++;
+
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+				     ATH9K_ANI_CCK_WEAK_SIG_THR);
+
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+				     ATH9K_RX_FILTER_PHYERR);
+
+		if (ah->ah_opmode == ATH9K_M_HOSTAP) {
+			ahp->ah_curani->ofdmTrigHigh =
+				ah->ah_config.ofdm_trig_high;
+			ahp->ah_curani->ofdmTrigLow =
+				ah->ah_config.ofdm_trig_low;
+			ahp->ah_curani->cckTrigHigh =
+				ah->ah_config.cck_trig_high;
+			ahp->ah_curani->cckTrigLow =
+				ah->ah_config.cck_trig_low;
+		}
+		ath9k_ani_restart(ah);
+		return;
+	}
+
+	if (aniState->noiseImmunityLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+				     aniState->noiseImmunityLevel);
+	if (aniState->spurImmunityLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+				     aniState->spurImmunityLevel);
+	if (aniState->ofdmWeakSigDetectOff)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     !aniState->ofdmWeakSigDetectOff);
+	if (aniState->cckWeakSigThreshold)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+				     aniState->cckWeakSigThreshold);
+	if (aniState->firstepLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+				     aniState->firstepLevel);
+	if (ahp->ah_hasHwPhyCounters) {
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+				     ~ATH9K_RX_FILTER_PHYERR);
+		ath9k_ani_restart(ah);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+	} else {
+		ath9k_ani_restart(ah);
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+				     ATH9K_RX_FILTER_PHYERR);
+	}
+}
+
+void ath9k_hw_ani_monitor(struct ath_hal *ah,
+			  const struct ath9k_node_stats *stats,
+			  struct ath9k_channel *chan)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416AniState *aniState;
+	int32_t listenTime;
+
+	aniState = ahp->ah_curani;
+	ahp->ah_stats.ast_nodestats = *stats;
+
+	listenTime = ath9k_hw_ani_get_listen_time(ah);
+	if (listenTime < 0) {
+		ahp->ah_stats.ast_ani_lneg++;
+		ath9k_ani_restart(ah);
+		return;
+	}
+
+	aniState->listenTime += listenTime;
+
+	if (ahp->ah_hasHwPhyCounters) {
+		u32 phyCnt1, phyCnt2;
+		u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+		ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+		phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+		phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+		if (phyCnt1 < aniState->ofdmPhyErrBase ||
+		    phyCnt2 < aniState->cckPhyErrBase) {
+			if (phyCnt1 < aniState->ofdmPhyErrBase) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+					"%s: phyCnt1 0x%x, resetting "
+					"counter value to 0x%x\n",
+					__func__, phyCnt1,
+					aniState->ofdmPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_1,
+					  aniState->ofdmPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+					  AR_PHY_ERR_OFDM_TIMING);
+			}
+			if (phyCnt2 < aniState->cckPhyErrBase) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+					"%s: phyCnt2 0x%x, resetting "
+					"counter value to 0x%x\n",
+					__func__, phyCnt2,
+					aniState->cckPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_2,
+					  aniState->cckPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+					  AR_PHY_ERR_CCK_TIMING);
+			}
+			return;
+		}
+
+		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+		ahp->ah_stats.ast_ani_ofdmerrs +=
+			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+		ahp->ah_stats.ast_ani_cckerrs +=
+			cckPhyErrCnt - aniState->cckPhyErrCount;
+		aniState->cckPhyErrCount = cckPhyErrCnt;
+	}
+
+	if (!DO_ANI(ah))
+		return;
+
+	if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
+		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+		    aniState->ofdmTrigLow / 1000 &&
+		    aniState->cckPhyErrCount <= aniState->listenTime *
+		    aniState->cckTrigLow / 1000)
+			ath9k_hw_ani_lower_immunity(ah);
+		ath9k_ani_restart(ah);
+	} else if (aniState->listenTime > ahp->ah_aniPeriod) {
+		if (aniState->ofdmPhyErrCount > aniState->listenTime *
+		    aniState->ofdmTrigHigh / 1000) {
+			ath9k_hw_ani_ofdm_err_trigger(ah);
+			ath9k_ani_restart(ah);
+		} else if (aniState->cckPhyErrCount >
+			   aniState->listenTime * aniState->cckTrigHigh /
+			   1000) {
+			ath9k_hw_ani_cck_err_trigger(ah);
+			ath9k_ani_restart(ah);
+		}
+	}
+}
+
+bool ath9k_hw_phycounters(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	return ahp->ah_hasHwPhyCounters ? true : false;
+}
+
+void ath9k_enable_mib_counters(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
+
+	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+	REG_WRITE(ah, AR_MIBC,
+		  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
+		  & 0x0f);
+	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
+
+	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
+
+	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
+				  u32 *rxc_pcnt,
+				  u32 *rxf_pcnt,
+				  u32 *txf_pcnt)
+{
+	static u32 cycles, rx_clear, rx_frame, tx_frame;
+	u32 good = 1;
+
+	u32 rc = REG_READ(ah, AR_RCCNT);
+	u32 rf = REG_READ(ah, AR_RFCNT);
+	u32 tf = REG_READ(ah, AR_TFCNT);
+	u32 cc = REG_READ(ah, AR_CCCNT);
+
+	if (cycles == 0 || cycles > cc) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			"%s: cycle counter wrap. ExtBusy = 0\n",
+			__func__);
+		good = 0;
+	} else {
+		u32 cc_d = cc - cycles;
+		u32 rc_d = rc - rx_clear;
+		u32 rf_d = rf - rx_frame;
+		u32 tf_d = tf - tx_frame;
+
+		if (cc_d != 0) {
+			*rxc_pcnt = rc_d * 100 / cc_d;
+			*rxf_pcnt = rf_d * 100 / cc_d;
+			*txf_pcnt = tf_d * 100 / cc_d;
+		} else {
+			good = 0;
+		}
+	}
+
+	cycles = cc;
+	rx_frame = rf;
+	rx_clear = rc;
+	tx_frame = tf;
+
+	return good;
+}
+
+/*
+ * Process a MIB interrupt.  We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void ath9k_hw_procmibevent(struct ath_hal *ah,
+			   const struct ath9k_node_stats *stats)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 phyCnt1, phyCnt2;
+
+	/* Reset these counters regardless */
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+	if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
+		REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+	/* Clear the mib counters and save them in the stats */
+	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+	ahp->ah_stats.ast_nodestats = *stats;
+
+	if (!DO_ANI(ah))
+		return;
+
+	/* NB: these are not reset-on-read */
+	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+		struct ar5416AniState *aniState = ahp->ah_curani;
+		u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+		ahp->ah_stats.ast_ani_ofdmerrs +=
+			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+		ahp->ah_stats.ast_ani_cckerrs +=
+			cckPhyErrCnt - aniState->cckPhyErrCount;
+		aniState->cckPhyErrCount = cckPhyErrCnt;
+
+		/*
+		 * NB: figure out which counter triggered.  If both
+		 * trigger we'll only deal with one as the processing
+		 * clobbers the error counter so the trigger threshold
+		 * check will never be true.
+		 */
+		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
+			ath9k_hw_ani_ofdm_err_trigger(ah);
+		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
+			ath9k_hw_ani_cck_err_trigger(ah);
+		/* NB: always restart to insure the h/w counters are reset */
+		ath9k_ani_restart(ah);
+	}
+}
+
+void ath9k_hw_ani_setup(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+	const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+	const int coarseLow[] = { -64, -64, -64, -64, -70 };
+	const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+	for (i = 0; i < 5; i++) {
+		ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
+		ahp->ah_coarseHigh[i] = coarseHigh[i];
+		ahp->ah_coarseLow[i] = coarseLow[i];
+		ahp->ah_firpwr[i] = firpwr[i];
+	}
+}
+
+void ath9k_hw_ani_attach(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
+
+	ahp->ah_hasHwPhyCounters = 1;
+
+	memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
+	for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+		ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
+		ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
+		ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
+		ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
+		ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+		ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+		ahp->ah_ani[i].ofdmWeakSigDetectOff =
+			!ATH9K_ANI_USE_OFDM_WEAK_SIG;
+		ahp->ah_ani[i].cckWeakSigThreshold =
+			ATH9K_ANI_CCK_WEAK_SIG_THR;
+		ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+		ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+		if (ahp->ah_hasHwPhyCounters) {
+			ahp->ah_ani[i].ofdmPhyErrBase =
+				AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+			ahp->ah_ani[i].cckPhyErrBase =
+				AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
+		}
+	}
+	if (ahp->ah_hasHwPhyCounters) {
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Setting OfdmErrBase = 0x%08x\n",
+			ahp->ah_ani[0].ofdmPhyErrBase);
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
+			ahp->ah_ani[0].cckPhyErrBase);
+
+		REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
+		ath9k_enable_mib_counters(ah);
+	}
+	ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
+	if (ah->ah_config.enable_ani)
+		ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
+}
+
+void ath9k_hw_ani_detach(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
+
+	if (ahp->ah_hasHwPhyCounters) {
+		ath9k_hw_disable_mib_counters(ah);
+		REG_WRITE(ah, AR_PHY_ERR_1, 0);
+		REG_WRITE(ah, AR_PHY_ERR_2, 0);
+	}
+}
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index accace5..3a180ce 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -138,6 +138,19 @@
 #define ATH9K_TXDESC_NOACK		0x0002
 #define ATH9K_TXDESC_RTSENA		0x0004
 #define ATH9K_TXDESC_CTSENA		0x0008
+/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on.  We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing. */
 #define ATH9K_TXDESC_INTREQ		0x0010
 #define ATH9K_TXDESC_VEOL		0x0020
 #define ATH9K_TXDESC_EXT_ONLY		0x0040
@@ -815,195 +828,251 @@
 	u16 ext_center;
 };
 
-int ath_hal_getcapability(struct ath_hal *ah,
-			  enum ath9k_capability_type type,
-			  u32 capability,
-			  u32 *result);
-const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
-						     u32 mode);
-void ath9k_hw_detach(struct ath_hal *ah);
-struct ath_hal *ath9k_hw_attach(u16 devid,
-				struct ath_softc *sc,
-				void __iomem *mem,
-				int *error);
-bool ath9k_regd_init_channels(struct ath_hal *ah,
-			      u32 maxchans, u32 *nchans,
-			      u8 *regclassids,
-			      u32 maxregids, u32 *nregids,
-			      u16 cc,
-			      bool enableOutdoor,
-			      bool enableExtendedChannels);
+/* Helpers */
+
+enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
+			       const struct ath9k_channel *chan);
+bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
+u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+bool ath9k_get_channel_edges(struct ath_hal *ah,
+			     u16 flags, u16 *low,
+			     u16 *high);
+u16 ath9k_hw_computetxtime(struct ath_hal *ah,
+			   const struct ath9k_rate_table *rates,
+			   u32 frameLen, u16 rateix,
+			   bool shortPreamble);
 u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
-				     enum ath9k_int ints);
-bool ath9k_hw_reset(struct ath_hal *ah,
-		    struct ath9k_channel *chan,
+void ath9k_hw_get_channel_centers(struct ath_hal *ah,
+				  struct ath9k_channel *chan,
+				  struct chan_centers *centers);
+
+/* Attach, Detach */
+
+const char *ath9k_hw_probe(u16 vendorid, u16 devid);
+void ath9k_hw_detach(struct ath_hal *ah);
+struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
+				void __iomem *mem, int *error);
+void ath9k_hw_rfdetach(struct ath_hal *ah);
+
+
+/* HW Reset */
+
+bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
 		    enum ath9k_ht_macmode macmode,
 		    u8 txchainmask, u8 rxchainmask,
 		    enum ath9k_ht_extprotspacing extprotspacing,
-		    bool bChannelChange,
-		    int *status);
-bool ath9k_hw_phy_disable(struct ath_hal *ah);
-void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
-			     bool *isCalDone);
-void ath9k_hw_ani_monitor(struct ath_hal *ah,
-			  const struct ath9k_node_stats *stats,
-			  struct ath9k_channel *chan);
-bool ath9k_hw_calibrate(struct ath_hal *ah,
-			struct ath9k_channel *chan,
-			u8 rxchainmask,
-			bool longcal,
-			bool *isCalDone);
-s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
-			       struct ath9k_channel *chan);
-void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
-			    u16 assocId);
-void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
-void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
-			    u16 assocId);
-bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
-void ath9k_hw_reset_tsf(struct ath_hal *ah);
-bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
-bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
-			const u8 *mac);
-bool ath9k_hw_set_keycache_entry(struct ath_hal *ah,
-				 u16 entry,
-				 const struct ath9k_keyval *k,
-				 const u8 *mac,
-				 int xorKey);
-bool ath9k_hw_set_tsfadjust(struct ath_hal *ah,
-			    u32 setting);
-void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
-bool ath9k_hw_intrpend(struct ath_hal *ah);
-bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
-bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah,
-				bool bIncTrigLevel);
-void ath9k_hw_procmibevent(struct ath_hal *ah,
-			   const struct ath9k_node_stats *stats);
-bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
-void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
-bool ath9k_hw_phycounters(struct ath_hal *ah);
+		    bool bChannelChange, int *status);
+
+/* Key Cache Management */
+
 bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry);
-bool ath9k_hw_getcapability(struct ath_hal *ah,
-			    enum ath9k_capability_type type,
-			    u32 capability,
-			    u32 *result);
-bool ath9k_hw_setcapability(struct ath_hal *ah,
-			    enum ath9k_capability_type type,
-			    u32 capability,
-			    u32 setting,
-			    int *status);
-u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
-void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
-void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
-bool ath9k_hw_setbssidmask(struct ath_hal *ah,
-			   const u8 *mask);
+bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac);
+bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
+				 const struct ath9k_keyval *k,
+				 const u8 *mac, int xorKey);
+bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
+
+/* Power Management */
+
 bool ath9k_hw_setpower(struct ath_hal *ah,
 		       enum ath9k_power_mode mode);
-enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
-u64 ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
+
+/* Beacon timers */
+
+void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period);
+void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+				    const struct ath9k_beacon_state *bs);
+
+/* Rate table */
+
+const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
+						     u32 mode);
+
+/* HW Capabilities */
+
+bool ath9k_hw_fill_cap_info(struct ath_hal *ah);
+bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 *result);
+bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 setting, int *status);
+
+/* GPIO / RFKILL / Antennae */
+
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+			 u32 ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
+#ifdef CONFIG_RFKILL
+void ath9k_enable_rfkill(struct ath_hal *ah);
+#endif
+int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
 u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
-bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
+void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
 bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
 			       enum ath9k_ant_setting settings,
 			       struct ath9k_channel *chan,
 			       u8 *tx_chainmask,
 			       u8 *rx_chainmask,
 			       u8 *antenna_cfgd);
-void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
-int ath9k_hw_select_antconfig(struct ath_hal *ah,
-			      u32 cfg);
-bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
-		       u32 txdp);
+
+/* General Operation */
+
+u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
+void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
+bool ath9k_hw_phy_disable(struct ath_hal *ah);
+bool ath9k_hw_disable(struct ath_hal *ah);
+bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
+void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
+bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
+void ath9k_hw_setopmode(struct ath_hal *ah);
+void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1);
+void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
+bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
+void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
+u64 ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_reset_tsf(struct ath_hal *ah);
+bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
+bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
+void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
+
+/* Regulatory */
+
+bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
+struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
+			 const struct ath9k_channel *c);
+u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
+u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
+				   struct ath9k_channel *chan);
+bool ath9k_regd_init_channels(struct ath_hal *ah,
+			      u32 maxchans, u32 *nchans, u8 *regclassids,
+			      u32 maxregids, u32 *nregids, u16 cc,
+			      bool enableOutdoor, bool enableExtendedChannels);
+
+/* ANI */
+
+void ath9k_ani_reset(struct ath_hal *ah);
+void ath9k_hw_ani_monitor(struct ath_hal *ah,
+			  const struct ath9k_node_stats *stats,
+			  struct ath9k_channel *chan);
+bool ath9k_hw_phycounters(struct ath_hal *ah);
+void ath9k_enable_mib_counters(struct ath_hal *ah);
+void ath9k_hw_disable_mib_counters(struct ath_hal *ah);
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
+				  u32 *rxc_pcnt,
+				  u32 *rxf_pcnt,
+				  u32 *txf_pcnt);
+void ath9k_hw_procmibevent(struct ath_hal *ah,
+			   const struct ath9k_node_stats *stats);
+void ath9k_hw_ani_setup(struct ath_hal *ah);
+void ath9k_hw_ani_attach(struct ath_hal *ah);
+void ath9k_hw_ani_detach(struct ath_hal *ah);
+
+/* Calibration */
+
+void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+			     bool *isCalDone);
+void ath9k_hw_start_nfcal(struct ath_hal *ah);
+void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
+int16_t ath9k_hw_getnf(struct ath_hal *ah,
+		       struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah);
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan);
+bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+			u8 rxchainmask, bool longcal,
+			bool *isCalDone);
+bool ath9k_hw_init_cal(struct ath_hal *ah,
+		       struct ath9k_channel *chan);
+
+
+/* EEPROM */
+
+int ath9k_hw_set_txpower(struct ath_hal *ah,
+			 struct ath9k_channel *chan,
+			 u16 cfgCtl,
+			 u8 twiceAntennaReduction,
+			 u8 twiceMaxRegulatoryPower,
+			 u8 powerLimit);
+void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan);
+bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
+				       struct ath9k_channel *chan,
+				       int16_t *ratesArray,
+				       u16 cfgCtl,
+				       u8 AntennaReduction,
+				       u8 twiceMaxRegulatoryPower,
+				       u8 powerLimit);
+bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
+				  struct ath9k_channel *chan,
+				  int16_t *pTxPowerIndexOffset);
+bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
+				      struct ath9k_channel *chan);
+int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+				    struct ath9k_channel *chan,
+				    u8 index, u16 *config);
+u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+			       enum ieee80211_band freq_band);
+u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz);
+int ath9k_hw_eeprom_attach(struct ath_hal *ah);
+
+/* Interrupt Handling */
+
+bool ath9k_hw_intrpend(struct ath_hal *ah);
+bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
+enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
+enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints);
+
+/* MAC (PCU/QCU) */
+
+void ath9k_hw_dmaRegDump(struct ath_hal *ah);
+u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
+bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp);
 bool ath9k_hw_txstart(struct ath_hal *ah, u32 q);
-u16 ath9k_hw_computetxtime(struct ath_hal *ah,
-				 const struct ath9k_rate_table *rates,
-				 u32 frameLen, u16 rateix,
-				 bool shortPreamble);
+u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
+bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel);
+bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
+bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+			 u32 segLen, bool firstSeg,
+			 bool lastSeg, const struct ath_desc *ds0);
+void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
+int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+			    u32 keyIx, enum ath9k_key_type keyType, u32 flags);
 void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
 				  struct ath_desc *lastds,
 				  u32 durUpdateEn, u32 rtsctsRate,
 				  u32 rtsctsDuration,
 				  struct ath9k_11n_rate_series series[],
 				  u32 nseries, u32 flags);
-void ath9k_hw_set11n_burstduration(struct ath_hal *ah,
-				   struct ath_desc *ds,
+void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+				u32 aggrLen);
+void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+				 u32 numDelims);
+void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
 				   u32 burstDuration);
-void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
-u32 ath9k_hw_reverse_bits(u32 val, u32 n);
-bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
-u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
-u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
-				     struct ath9k_channel *chan);
-u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
-bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
-			    struct ath9k_tx_queue_info *qinfo);
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+				     u32 vmf);
+void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
 bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
 			    const struct ath9k_tx_queue_info *qinfo);
-struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah,
-					      const struct ath9k_channel *c);
-void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
-			    u32 pktLen, enum ath9k_pkt_type type,
-			    u32 txPower, u32 keyIx,
-			    enum ath9k_key_type keyType, u32 flags);
-bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
-			 u32 segLen, bool firstSeg,
-			 bool lastSeg,
-			 const struct ath_desc *ds0);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
-					u32 *rxc_pcnt,
-					u32 *rxf_pcnt,
-					u32 *txf_pcnt);
-void ath9k_hw_dmaRegDump(struct ath_hal *ah);
-void ath9k_hw_beaconinit(struct ath_hal *ah,
-			 u32 next_beacon, u32 beacon_period);
-void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
-				    const struct ath9k_beacon_state *bs);
+bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+			    struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+			  const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
+bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
+int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+			u32 pa, struct ath_desc *nds, u64 tsf);
 bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
 			  u32 size, u32 flags);
+bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
 void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp);
 void ath9k_hw_rxena(struct ath_hal *ah);
-void ath9k_hw_setopmode(struct ath_hal *ah);
-bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
-void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
-			     u32 filter1);
-u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
 void ath9k_hw_startpcureceive(struct ath_hal *ah);
 void ath9k_hw_stoppcurecv(struct ath_hal *ah);
 bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
-int ath9k_hw_rxprocdesc(struct ath_hal *ah,
-			struct ath_desc *ds, u32 pa,
-			struct ath_desc *nds, u64 tsf);
-u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
-int ath9k_hw_txprocdesc(struct ath_hal *ah,
-			struct ath_desc *ds);
-void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
-				 u32 numDelims);
-void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
-				u32 aggrLen);
-void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
-bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
-void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
-void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
-void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah,
-				     struct ath_desc *ds, u32 vmf);
-bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
-bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
-int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
-			  const struct ath9k_tx_queue_info *qinfo);
-u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
-const char *ath9k_hw_probe(u16 vendorid, u16 devid);
-bool ath9k_hw_disable(struct ath_hal *ah);
-void ath9k_hw_rfdetach(struct ath_hal *ah);
-void ath9k_hw_get_channel_centers(struct ath_hal *ah,
-				  struct ath9k_channel *chan,
-				  struct chan_centers *centers);
-bool ath9k_get_channel_edges(struct ath_hal *ah,
-			     u16 flags, u16 *low,
-			     u16 *high);
-void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
-			u32 ah_signal_type);
-void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
-u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
-void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
+
 #endif
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 9e15c30..d186cd4 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -114,7 +114,7 @@
 	ath9k_hw_set11n_txdesc(ah, ds,
 			       skb->len + FCS_LEN,     /* frame length */
 			       ATH9K_PKT_TYPE_BEACON,  /* Atheros packet type */
-			       avp->av_btxctl.txpower, /* txpower XXX */
+			       MAX_RATE_POWER,         /* FIXME */
 			       ATH9K_TXKEYIX_INVALID,  /* no encryption */
 			       ATH9K_KEY_TYPE_CLEAR,   /* no encryption */
 			       flags                   /* no ack,
@@ -152,12 +152,14 @@
 	struct ath_vap *avp;
 	struct sk_buff *skb;
 	struct ath_txq *cabq;
+	struct ieee80211_vif *vif;
 	struct ieee80211_tx_info *info;
 	int cabq_depth;
 
-	avp = sc->sc_vaps[if_id];
-	ASSERT(avp);
+	vif = sc->sc_vaps[if_id];
+	ASSERT(vif);
 
+	avp = (void *)vif->drv_priv;
 	cabq = sc->sc_cabq;
 
 	if (avp->av_bcbuf == NULL) {
@@ -174,7 +176,7 @@
 				 PCI_DMA_TODEVICE);
 	}
 
-	skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+	skb = ieee80211_beacon_get(sc->hw, vif);
 	bf->bf_mpdu = skb;
 	if (skb == NULL)
 		return NULL;
@@ -196,7 +198,7 @@
 			       skb_end_pointer(skb) - skb->head,
 			       PCI_DMA_TODEVICE);
 
-	skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+	skb = ieee80211_get_buffered_bc(sc->hw, vif);
 
 	/*
 	 * if the CABQ traffic from previous DTIM is pending and the current
@@ -232,7 +234,7 @@
 	 */
 	while (skb) {
 		ath_tx_cabq(sc, skb);
-		skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+		skb = ieee80211_get_buffered_bc(sc->hw, vif);
 	}
 
 	return bf;
@@ -244,13 +246,16 @@
 */
 static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
 {
+	struct ieee80211_vif *vif;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_buf *bf;
 	struct ath_vap *avp;
 	struct sk_buff *skb;
 
-	avp = sc->sc_vaps[if_id];
-	ASSERT(avp);
+	vif = sc->sc_vaps[if_id];
+	ASSERT(vif);
+
+	avp = (void *)vif->drv_priv;
 
 	if (avp->av_bcbuf == NULL) {
 		DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
@@ -300,14 +305,17 @@
 */
 int ath_beacon_alloc(struct ath_softc *sc, int if_id)
 {
+	struct ieee80211_vif *vif;
 	struct ath_vap *avp;
 	struct ieee80211_hdr *hdr;
 	struct ath_buf *bf;
 	struct sk_buff *skb;
 	__le64 tstamp;
 
-	avp = sc->sc_vaps[if_id];
-	ASSERT(avp);
+	vif = sc->sc_vaps[if_id];
+	ASSERT(vif);
+
+	avp = (void *)vif->drv_priv;
 
 	/* Allocate a beacon descriptor if we haven't done so. */
 	if (!avp->av_bcbuf) {
@@ -363,7 +371,7 @@
 	 * FIXME: Fill avp->av_btxctl.txpower and
 	 * avp->av_btxctl.shortPreamble
 	 */
-	skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+	skb = ieee80211_beacon_get(sc->hw, vif);
 	if (skb == NULL) {
 		DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
 			__func__);
@@ -652,15 +660,21 @@
  */
 void ath_beacon_config(struct ath_softc *sc, int if_id)
 {
+	struct ieee80211_vif *vif;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_beacon_config conf;
+	struct ath_vap *avp;
 	enum ath9k_opmode av_opmode;
 	u32 nexttbtt, intval;
 
-	if (if_id != ATH_IF_ID_ANY)
-		av_opmode = sc->sc_vaps[if_id]->av_opmode;
-	else
+	if (if_id != ATH_IF_ID_ANY) {
+		vif = sc->sc_vaps[if_id];
+		ASSERT(vif);
+		avp = (void *)vif->drv_priv;
+		av_opmode = avp->av_opmode;
+	} else {
 		av_opmode = sc->sc_ah->ah_opmode;
+	}
 
 	memset(&conf, 0, sizeof(struct ath_beacon_config));
 
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c
new file mode 100644
index 0000000..1690759
--- /dev/null
+++ b/drivers/net/wireless/ath9k/calib.c
@@ -0,0 +1,930 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
+
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW	-60
+
+/* AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values */
+
+static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
+{
+	if (nf > ATH9K_NF_TOO_LOW) {
+		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+			"%s: noise floor value detected (%d) is "
+			"lower than what we think is a "
+			"reasonable value (%d)\n",
+			__func__, nf, ATH9K_NF_TOO_LOW);
+		return false;
+	}
+	return true;
+}
+
+static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+	int16_t nfval;
+	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+	int i, j;
+
+	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+		sort[i] = nfCalBuffer[i];
+
+	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+			if (sort[j] > sort[j - 1]) {
+				nfval = sort[j];
+				sort[j] = sort[j - 1];
+				sort[j - 1] = nfval;
+			}
+		}
+	}
+	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+	return nfval;
+}
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+					      int16_t *nfarray)
+{
+	int i;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+			h[i].currIndex = 0;
+
+		if (h[i].invalidNFcount > 0) {
+			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
+			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
+				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
+			} else {
+				h[i].invalidNFcount--;
+				h[i].privNF = nfarray[i];
+			}
+		} else {
+			h[i].privNF =
+				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+		}
+	}
+	return;
+}
+
+static void ath9k_hw_do_getnf(struct ath_hal *ah,
+			      int16_t nfarray[NUM_NF_READINGS])
+{
+	int16_t nf;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"NF calibrated [ctl] [chain 0] is %d\n", nf);
+	nfarray[0] = nf;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+			AR9280_PHY_CH1_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+			AR_PHY_CH1_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+		"NF calibrated [ctl] [chain 1] is %d\n", nf);
+	nfarray[1] = nf;
+
+	if (!AR_SREV_9280(ah)) {
+		nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
+			AR_PHY_CH2_MINCCA_PWR);
+		if (nf & 0x100)
+			nf = 0 - ((nf ^ 0x1ff) + 1);
+		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+			"NF calibrated [ctl] [chain 2] is %d\n", nf);
+		nfarray[2] = nf;
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+			AR9280_PHY_EXT_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+			AR_PHY_EXT_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+		"NF calibrated [ext] [chain 0] is %d\n", nf);
+	nfarray[3] = nf;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+			AR9280_PHY_CH1_EXT_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+			AR_PHY_CH1_EXT_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"NF calibrated [ext] [chain 1] is %d\n", nf);
+	nfarray[4] = nf;
+
+	if (!AR_SREV_9280(ah)) {
+		nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
+			AR_PHY_CH2_EXT_MINCCA_PWR);
+		if (nf & 0x100)
+			nf = 0 - ((nf ^ 0x1ff) + 1);
+		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+			"NF calibrated [ext] [chain 2] is %d\n", nf);
+		nfarray[5] = nf;
+	}
+}
+
+static bool getNoiseFloorThresh(struct ath_hal *ah,
+				const struct ath9k_channel *chan,
+				int16_t *nft)
+{
+	switch (chan->chanmode) {
+	case CHANNEL_A:
+	case CHANNEL_A_HT20:
+	case CHANNEL_A_HT40PLUS:
+	case CHANNEL_A_HT40MINUS:
+		*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
+		break;
+	case CHANNEL_B:
+	case CHANNEL_G:
+	case CHANNEL_G_HT20:
+	case CHANNEL_G_HT40PLUS:
+	case CHANNEL_G_HT40MINUS:
+		*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			"%s: invalid channel flags 0x%x\n", __func__,
+			chan->channelFlags);
+		return false;
+	}
+
+	return true;
+}
+
+static void ath9k_hw_setup_calibration(struct ath_hal *ah,
+				       struct hal_cal_list *currCal)
+{
+	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+		      currCal->calData->calCountMax);
+
+	switch (currCal->calData->calType) {
+	case IQ_MISMATCH_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: starting IQ Mismatch Calibration\n",
+			__func__);
+		break;
+	case ADC_GAIN_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: starting ADC Gain Calibration\n", __func__);
+		break;
+	case ADC_DC_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: starting ADC DC Calibration\n", __func__);
+		break;
+	case ADC_DC_INIT_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: starting Init ADC DC Calibration\n",
+			__func__);
+		break;
+	}
+
+	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+		    AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static void ath9k_hw_reset_calibration(struct ath_hal *ah,
+				       struct hal_cal_list *currCal)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	ath9k_hw_setup_calibration(ah, currCal);
+
+	currCal->calState = CAL_RUNNING;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ahp->ah_Meas0.sign[i] = 0;
+		ahp->ah_Meas1.sign[i] = 0;
+		ahp->ah_Meas2.sign[i] = 0;
+		ahp->ah_Meas3.sign[i] = 0;
+	}
+
+	ahp->ah_CalSamples = 0;
+}
+
+static void ath9k_hw_per_calibration(struct ath_hal *ah,
+				     struct ath9k_channel *ichan,
+				     u8 rxchainmask,
+				     struct hal_cal_list *currCal,
+				     bool *isCalDone)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	*isCalDone = false;
+
+	if (currCal->calState == CAL_RUNNING) {
+		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+			currCal->calData->calCollect(ah);
+			ahp->ah_CalSamples++;
+
+			if (ahp->ah_CalSamples >= currCal->calData->calNumSamples) {
+				int i, numChains = 0;
+				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+					if (rxchainmask & (1 << i))
+						numChains++;
+				}
+
+				currCal->calData->calPostProc(ah, numChains);
+				ichan->CalValid |= currCal->calData->calType;
+				currCal->calState = CAL_DONE;
+				*isCalDone = true;
+			} else {
+				ath9k_hw_setup_calibration(ah, currCal);
+			}
+		}
+	} else if (!(ichan->CalValid & currCal->calData->calType)) {
+		ath9k_hw_reset_calibration(ah, currCal);
+	}
+}
+
+static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
+				     struct ath9k_channel *chan,
+				     enum hal_cal_types calType)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	bool retval = false;
+
+	switch (calType & ahp->ah_suppCals) {
+	case IQ_MISMATCH_CAL:
+		if (!IS_CHAN_B(chan))
+			retval = true;
+		break;
+	case ADC_GAIN_CAL:
+	case ADC_DC_CAL:
+		if (!IS_CHAN_B(chan)
+		    && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+			retval = true;
+		break;
+	}
+
+	return retval;
+}
+
+static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ahp->ah_totalPowerMeasI[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ahp->ah_totalPowerMeasQ[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ahp->ah_totalIqCorrMeas[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+			ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
+			ahp->ah_totalPowerMeasQ[i],
+			ahp->ah_totalIqCorrMeas[i]);
+	}
+}
+
+static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ahp->ah_totalAdcIOddPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ahp->ah_totalAdcIEvenPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ahp->ah_totalAdcQOddPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		ahp->ah_totalAdcQEvenPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+			"oddq=0x%08x; evenq=0x%08x;\n",
+			ahp->ah_CalSamples, i,
+			ahp->ah_totalAdcIOddPhase[i],
+			ahp->ah_totalAdcIEvenPhase[i],
+			ahp->ah_totalAdcQOddPhase[i],
+			ahp->ah_totalAdcQEvenPhase[i]);
+	}
+}
+
+static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+			"oddq=0x%08x; evenq=0x%08x;\n",
+			ahp->ah_CalSamples, i,
+			ahp->ah_totalAdcDcOffsetIOddPhase[i],
+			ahp->ah_totalAdcDcOffsetIEvenPhase[i],
+			ahp->ah_totalAdcDcOffsetQOddPhase[i],
+			ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
+	}
+}
+
+static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 powerMeasQ, powerMeasI, iqCorrMeas;
+	u32 qCoffDenom, iCoffDenom;
+	int32_t qCoff, iCoff;
+	int iqCorrNeg, i;
+
+	for (i = 0; i < numChains; i++) {
+		powerMeasI = ahp->ah_totalPowerMeasI[i];
+		powerMeasQ = ahp->ah_totalPowerMeasQ[i];
+		iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting IQ Cal and Correction for Chain %d\n",
+			i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Orignal: Chn %diq_corr_meas = 0x%08x\n",
+			i, ahp->ah_totalIqCorrMeas[i]);
+
+		iqCorrNeg = 0;
+
+		if (iqCorrMeas > 0x80000000) {
+			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+			iqCorrNeg = 1;
+		}
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+			iqCorrNeg);
+
+		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+		qCoffDenom = powerMeasQ / 64;
+
+		if (powerMeasQ != 0) {
+			iCoff = iqCorrMeas / iCoffDenom;
+			qCoff = powerMeasI / qCoffDenom - 64;
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d iCoff = 0x%08x\n", i, iCoff);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d qCoff = 0x%08x\n", i, qCoff);
+
+			iCoff = iCoff & 0x3f;
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+			if (iqCorrNeg == 0x0)
+				iCoff = 0x40 - iCoff;
+
+			if (qCoff > 15)
+				qCoff = 15;
+			else if (qCoff <= -16)
+				qCoff = 16;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+				i, iCoff, qCoff);
+
+			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+				      iCoff);
+			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+				      qCoff);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"IQ Cal and Correction done for Chain %d\n",
+				i);
+		}
+	}
+
+	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
+	u32 qGainMismatch, iGainMismatch, val, i;
+
+	for (i = 0; i < numChains; i++) {
+		iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
+		iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
+		qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
+		qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting ADC Gain Cal for Chain %d\n", i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+			iOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = 0x%08x\n", i,
+			iEvenMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+			qOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = 0x%08x\n", i,
+			qEvenMeasOffset);
+
+		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+			iGainMismatch =
+				((iEvenMeasOffset * 32) /
+				 iOddMeasOffset) & 0x3f;
+			qGainMismatch =
+				((qOddMeasOffset * 32) /
+				 qEvenMeasOffset) & 0x3f;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_i = 0x%08x\n", i,
+				iGainMismatch);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_q = 0x%08x\n", i,
+				qGainMismatch);
+
+			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+			val &= 0xfffff000;
+			val |= (qGainMismatch) | (iGainMismatch << 6);
+			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"ADC Gain Cal done for Chain %d\n", i);
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
+	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+	const struct hal_percal_data *calData =
+		ahp->ah_cal_list_curr->calData;
+	u32 numSamples =
+		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+	for (i = 0; i < numChains; i++) {
+		iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
+		iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
+		qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
+		qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting ADC DC Offset Cal for Chain %d\n", i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = %d\n", i,
+			iOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = %d\n", i,
+			iEvenMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = %d\n", i,
+			qOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = %d\n", i,
+			qEvenMeasOffset);
+
+		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+			       numSamples) & 0x1ff;
+		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+			       numSamples) & 0x1ff;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+			iDcMismatch);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+			qDcMismatch);
+
+		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+		val &= 0xc0000fff;
+		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"ADC DC Offset Cal done for Chain %d\n", i);
+	}
+
+	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+			     bool *isCalDone)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_channel *ichan =
+		ath9k_regd_check_channel(ah, chan);
+	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+
+	*isCalDone = true;
+
+	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+		return;
+
+	if (currCal == NULL)
+		return;
+
+	if (ichan == NULL) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: invalid channel %u/0x%x; no mapping\n",
+			__func__, chan->channel, chan->channelFlags);
+		return;
+	}
+
+
+	if (currCal->calState != CAL_DONE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: Calibration state incorrect, %d\n",
+			__func__, currCal->calState);
+		return;
+	}
+
+
+	if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
+		return;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"%s: Resetting Cal %d state for channel %u/0x%x\n",
+		__func__, currCal->calData->calType, chan->channel,
+		chan->channelFlags);
+
+	ichan->CalValid &= ~currCal->calData->calType;
+	currCal->calState = CAL_WAITING;
+
+	*isCalDone = false;
+}
+
+void ath9k_hw_start_nfcal(struct ath_hal *ah)
+{
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_ENABLE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+	struct ath9k_nfcal_hist *h;
+	int i, j;
+	int32_t val;
+	const u32 ar5416_cca_regs[6] = {
+		AR_PHY_CCA,
+		AR_PHY_CH1_CCA,
+		AR_PHY_CH2_CCA,
+		AR_PHY_EXT_CCA,
+		AR_PHY_CH1_EXT_CCA,
+		AR_PHY_CH2_EXT_CCA
+	};
+	u8 chainmask;
+
+	if (AR_SREV_9280(ah))
+		chainmask = 0x1B;
+	else
+		chainmask = 0x3F;
+
+#ifdef ATH_NF_PER_CHAN
+	h = chan->nfCalHist;
+#else
+	h = ah->nfCalHist;
+#endif
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ar5416_cca_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
+			REG_WRITE(ah, ar5416_cca_regs[i], val);
+		}
+	}
+
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_ENABLE_NF);
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+	for (j = 0; j < 1000; j++) {
+		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+		     AR_PHY_AGC_CONTROL_NF) == 0)
+			break;
+		udelay(10);
+	}
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ar5416_cca_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (-50) << 1) & 0x1ff);
+			REG_WRITE(ah, ar5416_cca_regs[i], val);
+		}
+	}
+}
+
+int16_t ath9k_hw_getnf(struct ath_hal *ah,
+		       struct ath9k_channel *chan)
+{
+	int16_t nf, nfThresh;
+	int16_t nfarray[NUM_NF_READINGS] = { 0 };
+	struct ath9k_nfcal_hist *h;
+	u8 chainmask;
+
+	if (AR_SREV_9280(ah))
+		chainmask = 0x1B;
+	else
+		chainmask = 0x3F;
+
+	chan->channelFlags &= (~CHANNEL_CW_INT);
+	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: NF did not complete in calibration window\n",
+			__func__);
+		nf = 0;
+		chan->rawNoiseFloor = nf;
+		return chan->rawNoiseFloor;
+	} else {
+		ath9k_hw_do_getnf(ah, nfarray);
+		nf = nfarray[0];
+		if (getNoiseFloorThresh(ah, chan, &nfThresh)
+		    && nf > nfThresh) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"%s: noise floor failed detected; "
+				"detected %d, threshold %d\n", __func__,
+				nf, nfThresh);
+			chan->channelFlags |= CHANNEL_CW_INT;
+		}
+	}
+
+#ifdef ATH_NF_PER_CHAN
+	h = chan->nfCalHist;
+#else
+	h = ah->nfCalHist;
+#endif
+
+	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
+	chan->rawNoiseFloor = h[0].privNF;
+
+	return chan->rawNoiseFloor;
+}
+
+void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
+{
+	int i, j;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		ah->nfCalHist[i].currIndex = 0;
+		ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+		ah->nfCalHist[i].invalidNFcount =
+			AR_PHY_CCA_FILTERWINDOW_LENGTH;
+		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+			ah->nfCalHist[i].nfCalBuffer[j] =
+				AR_PHY_CCA_MAX_GOOD_VALUE;
+		}
+	}
+	return;
+}
+
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+	struct ath9k_channel *ichan;
+	s16 nf;
+
+	ichan = ath9k_regd_check_channel(ah, chan);
+	if (ichan == NULL) {
+		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+			"%s: invalid channel %u/0x%x; no mapping\n",
+			__func__, chan->channel, chan->channelFlags);
+		return ATH_DEFAULT_NOISE_FLOOR;
+	}
+	if (ichan->rawNoiseFloor == 0) {
+		enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
+		nf = NOISE_FLOOR[mode];
+	} else
+		nf = ichan->rawNoiseFloor;
+
+	if (!ath9k_hw_nf_in_range(ah, nf))
+		nf = ATH_DEFAULT_NOISE_FLOOR;
+
+	return nf;
+}
+
+bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+			u8 rxchainmask, bool longcal,
+			bool *isCalDone)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+	struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+	*isCalDone = true;
+
+	if (ichan == NULL) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			"%s: invalid channel %u/0x%x; no mapping\n",
+			__func__, chan->channel, chan->channelFlags);
+		return false;
+	}
+
+	if (currCal &&
+	    (currCal->calState == CAL_RUNNING ||
+	     currCal->calState == CAL_WAITING)) {
+		ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
+					 isCalDone);
+		if (*isCalDone) {
+			ahp->ah_cal_list_curr = currCal = currCal->calNext;
+
+			if (currCal->calState == CAL_WAITING) {
+				*isCalDone = false;
+				ath9k_hw_reset_calibration(ah, currCal);
+			}
+		}
+	}
+
+	if (longcal) {
+		ath9k_hw_getnf(ah, ichan);
+		ath9k_hw_loadnf(ah, ah->ah_curchan);
+		ath9k_hw_start_nfcal(ah);
+
+		if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+			chan->channelFlags |= CHANNEL_CW_INT;
+			ichan->channelFlags &= ~CHANNEL_CW_INT;
+		}
+	}
+
+	return true;
+}
+
+bool ath9k_hw_init_cal(struct ath_hal *ah,
+		       struct ath9k_channel *chan)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
+		  AR_PHY_AGC_CONTROL_CAL);
+
+	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%s: offset calibration failed to complete in 1ms; "
+			"noisy environment?\n", __func__);
+		return false;
+	}
+
+	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
+		  AR_PHY_AGC_CONTROL_NF);
+
+	ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
+
+	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+		if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
+			INIT_CAL(&ahp->ah_adcGainCalData);
+			INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"%s: enabling ADC Gain Calibration.\n",
+				__func__);
+		}
+		if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
+			INIT_CAL(&ahp->ah_adcDcCalData);
+			INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"%s: enabling ADC DC Calibration.\n",
+				__func__);
+		}
+		if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
+			INIT_CAL(&ahp->ah_iqCalData);
+			INSERT_CAL(ahp, &ahp->ah_iqCalData);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"%s: enabling IQ Calibration.\n",
+				__func__);
+		}
+
+		ahp->ah_cal_list_curr = ahp->ah_cal_list;
+
+		if (ahp->ah_cal_list_curr)
+			ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
+	}
+
+	ichan->CalValid = 0;
+
+	return true;
+}
+
+const struct hal_percal_data iq_cal_multi_sample = {
+	IQ_MISMATCH_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_iqcal_collect,
+	ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data iq_cal_single_sample = {
+	IQ_MISMATCH_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_iqcal_collect,
+	ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data adc_gain_cal_multi_sample = {
+	ADC_GAIN_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_adc_gaincal_collect,
+	ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_gain_cal_single_sample = {
+	ADC_GAIN_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_adc_gaincal_collect,
+	ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_multi_sample = {
+	ADC_DC_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_single_sample = {
+	ADC_DC_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_init_dc_cal = {
+	ADC_DC_INIT_CAL,
+	MIN_CAL_SAMPLES,
+	INIT_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index c5033f6..5f5184a 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -14,13 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
- /* Implementation of the main "ATH" layer. */
-
 #include "core.h"
 #include "regd.h"
 
-static int ath_outdoor;		/* enable outdoor use */
-
 static u32 ath_chainmask_sel_up_rssi_thres =
 	ATH_CHAINMASK_SEL_UP_RSSI_THRES;
 static u32 ath_chainmask_sel_down_rssi_thres =
@@ -47,6 +43,41 @@
 		*csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
 }
 
+static u8 parse_mpdudensity(u8 mpdudensity)
+{
+	/*
+	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
+	 *   0 for no restriction
+	 *   1 for 1/4 us
+	 *   2 for 1/2 us
+	 *   3 for 1 us
+	 *   4 for 2 us
+	 *   5 for 4 us
+	 *   6 for 8 us
+	 *   7 for 16 us
+	 */
+	switch (mpdudensity) {
+	case 0:
+		return 0;
+	case 1:
+	case 2:
+	case 3:
+		/* Our lower layer calculations limit our precision to
+		   1 microsecond */
+		return 1;
+	case 4:
+		return 2;
+	case 5:
+		return 4;
+	case 6:
+		return 8;
+	case 7:
+		return 16;
+	default:
+		return 0;
+	}
+}
+
 /*
  *  Set current operating mode
  *
@@ -155,17 +186,10 @@
 	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)) {
+	if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
+				      regclassids, ATH_REGCLASSIDS_MAX,
+				      &nregclass, CTRY_DEFAULT, false, 1)) {
 		u32 rd = ah->ah_currentRD;
-
 		DPRINTF(sc, ATH_DBG_FATAL,
 			"%s: unable to collect channel list; "
 			"regdomain likely %u country code %u\n",
@@ -186,40 +210,32 @@
 			chan_2ghz[a].max_power = c->maxTxPower;
 
 			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
-				chan_2ghz[a].flags |=
-					IEEE80211_CHAN_NO_IBSS;
+				chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
 			if (c->channelFlags & CHANNEL_PASSIVE)
-				chan_2ghz[a].flags |=
-					IEEE80211_CHAN_PASSIVE_SCAN;
+				chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
 
 			band_2ghz->n_channels = ++a;
 
 			DPRINTF(sc, ATH_DBG_CONFIG,
 				"%s: 2MHz channel: %d, "
 				"channelFlags: 0x%x\n",
-				__func__,
-				c->channel,
-				c->channelFlags);
+				__func__, c->channel, c->channelFlags);
 		} else if (IS_CHAN_5GHZ(c)) {
 			chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
 			chan_5ghz[b].center_freq = c->channel;
 			chan_5ghz[b].max_power = c->maxTxPower;
 
 			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
-				chan_5ghz[b].flags |=
-					IEEE80211_CHAN_NO_IBSS;
+				chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
 			if (c->channelFlags & CHANNEL_PASSIVE)
-				chan_5ghz[b].flags |=
-					IEEE80211_CHAN_PASSIVE_SCAN;
+				chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
 
 			band_5ghz->n_channels = ++b;
 
 			DPRINTF(sc, ATH_DBG_CONFIG,
 				"%s: 5MHz channel: %d, "
 				"channelFlags: 0x%x\n",
-				__func__,
-				c->channel,
-				c->channelFlags);
+				__func__, c->channel, c->channelFlags);
 		}
 	}
 
@@ -261,44 +277,6 @@
 }
 
 /*
- * Stop the device, grabbing the top-level lock to protect
- * against concurrent entry through ath_init (which can happen
- * if another thread does a system call and the thread doing the
- * stop is preempted).
- */
-
-static int ath_stop(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
-		__func__, sc->sc_flags & SC_OP_INVALID);
-
-	/*
-	 * Shutdown the hardware and driver:
-	 *    stop output from above
-	 *    turn off timers
-	 *    disable interrupts
-	 *    clear transmit machinery
-	 *    clear receive machinery
-	 *    turn off the radio
-	 *    reclaim beacon resources
-	 *
-	 * Note that some of this work is not possible if the
-	 * hardware is gone (invalid).
-	 */
-
-	ath_draintxq(sc, false);
-	if (!(sc->sc_flags & SC_OP_INVALID)) {
-		ath_stoprecv(sc);
-		ath9k_hw_phy_disable(ah);
-	} else
-		sc->sc_rxlink = NULL;
-
-	return 0;
-}
-
-/*
  * Set the current channel
  *
  * Set/change channels.  If the channel is really being changed, it's done
@@ -606,114 +584,6 @@
 	mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
 }
 
-/******************/
-/* VAP management */
-/******************/
-
-int ath_vap_attach(struct ath_softc *sc,
-		   int if_id,
-		   struct ieee80211_vif *if_data,
-		   enum ath9k_opmode opmode)
-{
-	struct ath_vap *avp;
-
-	if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: Invalid interface id = %u\n", __func__, if_id);
-		return -EINVAL;
-	}
-
-	switch (opmode) {
-	case ATH9K_M_STA:
-	case ATH9K_M_IBSS:
-	case ATH9K_M_MONITOR:
-		break;
-	case ATH9K_M_HOSTAP:
-		/* XXX not right, beacon buffer is allocated on RUN trans */
-		if (list_empty(&sc->sc_bbuf))
-			return -ENOMEM;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* create ath_vap */
-	avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL);
-	if (avp == NULL)
-		return -ENOMEM;
-
-	memset(avp, 0, sizeof(struct ath_vap));
-	avp->av_if_data = if_data;
-	/* Set the VAP opmode */
-	avp->av_opmode = opmode;
-	avp->av_bslot = -1;
-
-	if (opmode == ATH9K_M_HOSTAP)
-		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
-
-	sc->sc_vaps[if_id] = avp;
-	sc->sc_nvaps++;
-	/* Set the device opmode */
-	sc->sc_ah->ah_opmode = opmode;
-
-	/* default VAP configuration */
-	avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
-	avp->av_config.av_fixed_retryset = 0x03030303;
-
-	return 0;
-}
-
-int ath_vap_detach(struct ath_softc *sc, int if_id)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	struct ath_vap *avp;
-
-	avp = sc->sc_vaps[if_id];
-	if (avp == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
-			__func__, if_id);
-		return -EINVAL;
-	}
-
-	/*
-	 * Quiesce the hardware while we remove the vap.  In
-	 * particular we need to reclaim all references to the
-	 * vap state by any frames pending on the tx queues.
-	 *
-	 * XXX can we do this w/o affecting other vap's?
-	 */
-	ath9k_hw_set_interrupts(ah, 0);	/* disable interrupts */
-	ath_draintxq(sc, false);	/* stop xmit side */
-	ath_stoprecv(sc);	/* stop recv side */
-	ath_flushrecv(sc);	/* flush recv queue */
-
-	kfree(avp);
-	sc->sc_vaps[if_id] = NULL;
-	sc->sc_nvaps--;
-
-	return 0;
-}
-
-int ath_vap_config(struct ath_softc *sc,
-	int if_id, struct ath_vap_config *if_config)
-{
-	struct ath_vap *avp;
-
-	if (if_id >= ATH_BCBUF) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: Invalid interface id = %u\n", __func__, if_id);
-		return -EINVAL;
-	}
-
-	avp = sc->sc_vaps[if_id];
-	ASSERT(avp != NULL);
-
-	if (avp)
-		memcpy(&avp->av_config, if_config, sizeof(avp->av_config));
-
-	return 0;
-}
-
 /********/
 /* Core */
 /********/
@@ -727,16 +597,6 @@
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
 		__func__, sc->sc_ah->ah_opmode);
 
-	/*
-	 * Stop anything previously setup.  This is safe
-	 * whether this is the first time through or not.
-	 */
-	ath_stop(sc);
-
-	/* Initialize chanmask selection */
-	sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
-	sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
-
 	/* Reset SERDES registers */
 	ath9k_hw_configpcipowersave(ah, 0);
 
@@ -762,6 +622,7 @@
 		goto done;
 	}
 	spin_unlock_bh(&sc->sc_resetlock);
+
 	/*
 	 * This is needed only to setup initial state
 	 * but it's best done after a reset.
@@ -781,6 +642,7 @@
 		error = -EIO;
 		goto done;
 	}
+
 	/* Setup our intr mask. */
 	sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
 		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
@@ -810,30 +672,60 @@
 	    (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
 	    !sc->sc_config.swBeaconProcess)
 		sc->sc_imask |= ATH9K_INT_TIM;
-	/*
-	 *  Don't enable interrupts here as we've not yet built our
-	 *  vap and node data structures, which will be needed as soon
-	 *  as we start receiving.
-	 */
+
 	ath_setcurmode(sc, ath_chan2mode(initial_chan));
 
-	/* XXX: we must make sure h/w is ready and clear invalid flag
-	 * before turning on interrupt. */
 	sc->sc_flags &= ~SC_OP_INVALID;
+
+	/* Disable BMISS interrupt when we're not associated */
+	sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+	ath9k_hw_set_interrupts(sc->sc_ah,sc->sc_imask);
+
+	ieee80211_wake_queues(sc->hw);
 done:
 	return error;
 }
 
+void ath_stop(struct ath_softc *sc)
+{
+	struct ath_hal *ah = sc->sc_ah;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__);
+
+	ieee80211_stop_queues(sc->hw);
+
+	/* make sure h/w will not generate any interrupt
+	 * before setting the invalid flag. */
+	ath9k_hw_set_interrupts(ah, 0);
+
+	if (!(sc->sc_flags & SC_OP_INVALID)) {
+		ath_draintxq(sc, false);
+		ath_stoprecv(sc);
+		ath9k_hw_phy_disable(ah);
+	} else
+		sc->sc_rxlink = NULL;
+
+#ifdef CONFIG_RFKILL
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
+#endif
+	/* disable HAL and put h/w to sleep */
+	ath9k_hw_disable(sc->sc_ah);
+	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+
+	sc->sc_flags |= SC_OP_INVALID;
+}
+
 int ath_reset(struct ath_softc *sc, bool retry_tx)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	int status;
 	int error = 0;
 
-	ath9k_hw_set_interrupts(ah, 0);	/* disable interrupts */
-	ath_draintxq(sc, retry_tx);	/* stop xmit */
-	ath_stoprecv(sc);		/* stop recv */
-	ath_flushrecv(sc);		/* flush recv queue */
+	ath9k_hw_set_interrupts(ah, 0);
+	ath_draintxq(sc, retry_tx);
+	ath_stoprecv(sc);
+	ath_flushrecv(sc);
 
 	/* Reset chip */
 	spin_lock_bh(&sc->sc_resetlock);
@@ -848,7 +740,7 @@
 	}
 	spin_unlock_bh(&sc->sc_resetlock);
 
-	if (ath_startrecv(sc) != 0)	/* restart recv */
+	if (ath_startrecv(sc) != 0)
 		DPRINTF(sc, ATH_DBG_FATAL,
 			"%s: unable to start recv logic\n", __func__);
 
@@ -881,29 +773,6 @@
 	return error;
 }
 
-int ath_suspend(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-
-	/* No I/O if device has been surprise removed */
-	if (sc->sc_flags & SC_OP_INVALID)
-		return -EIO;
-
-	/* Shut off the interrupt before setting sc->sc_invalid to '1' */
-	ath9k_hw_set_interrupts(ah, 0);
-
-	/* XXX: we must make sure h/w will not generate any interrupt
-	 * before setting the invalid flag. */
-	sc->sc_flags |= SC_OP_INVALID;
-
-	/* disable HAL and put h/w to sleep */
-	ath9k_hw_disable(sc->sc_ah);
-
-	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
-
-	return 0;
-}
-
 /* Interrupt handler.  Most of the actual processing is deferred.
  * It's the caller's responsibility to ensure the chip is awake. */
 
@@ -1071,11 +940,9 @@
 
 	/* XXX: hardware will not be ready until ath_open() being called */
 	sc->sc_flags |= SC_OP_INVALID;
-
 	sc->sc_debug = DBG_DEFAULT;
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
 
-	/* Initialize tasklet */
+	spin_lock_init(&sc->sc_resetlock);
 	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
 	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
 		     (unsigned long)sc);
@@ -1088,8 +955,6 @@
 	/* XXX assert csz is non-zero */
 	sc->sc_cachelsz = csz << 2;	/* convert to bytes */
 
-	spin_lock_init(&sc->sc_resetlock);
-
 	ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
 	if (ah == NULL) {
 		DPRINTF(sc, ATH_DBG_FATAL,
@@ -1100,10 +965,6 @@
 	}
 	sc->sc_ah = ah;
 
-	/* Initializes the noise floor to a reasonable default value.
-	 * Later on this will be updated during ANI processing. */
-	sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
-
 	/* Get the hardware key cache size. */
 	sc->sc_keymax = ah->ah_caps.keycache_size;
 	if (sc->sc_keymax > ATH_KEYMAX) {
@@ -1131,17 +992,14 @@
 		set_bit(i + 64, sc->sc_keymap);
 		set_bit(i + 32 + 64, sc->sc_keymap);
 	}
-	/*
-	 * Collect the channel list using the default country
-	 * code and including outdoor channels.  The 802.11 layer
-	 * is resposible for filtering this list based on settings
-	 * like the phy mode.
-	 */
+
+	/* Collect the channel list using the default country code */
+
 	error = ath_setup_channels(sc);
 	if (error)
 		goto bad;
 
-	/* default to STA mode */
+	/* default to MONITOR mode */
 	sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
 
 	/* Setup rate tables */
@@ -1211,6 +1069,10 @@
 		goto bad2;
 	}
 
+	/* Initializes the noise floor to a reasonable default value.
+	 * Later on this will be updated during ANI processing. */
+
+	sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
 	setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 	sc->sc_rc = ath_rate_attach(ah);
@@ -1271,6 +1133,7 @@
 		ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
 		ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
 	}
+
 	sc->sc_slottime = ATH9K_SLOT_TIME_9;	/* default to short slot time */
 
 	/* initialize beacon slots */
@@ -1285,6 +1148,22 @@
 	ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
 #endif
 
+	/* setup channels and rates */
+
+	sc->sbands[IEEE80211_BAND_2GHZ].channels =
+		sc->channels[IEEE80211_BAND_2GHZ];
+	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
+		sc->rates[IEEE80211_BAND_2GHZ];
+	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+
+	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
+		sc->sbands[IEEE80211_BAND_5GHZ].channels =
+			sc->channels[IEEE80211_BAND_5GHZ];
+		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+			sc->rates[IEEE80211_BAND_5GHZ];
+		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+	}
+
 	return 0;
 bad2:
 	/* cleanup tx queues */
@@ -1294,128 +1173,39 @@
 bad:
 	if (ah)
 		ath9k_hw_detach(ah);
+
 	return error;
 }
 
-void ath_deinit(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	int i;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
-
-	tasklet_kill(&sc->intr_tq);
-	tasklet_kill(&sc->bcon_tasklet);
-	ath_stop(sc);
-	if (!(sc->sc_flags & SC_OP_INVALID))
-		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-	ath_rate_detach(sc->sc_rc);
-	/* cleanup tx queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
-	ath9k_hw_detach(ah);
-}
-
 /*******************/
 /* Node Management */
 /*******************/
 
-struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
+void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
-	struct ath_vap *avp;
 	struct ath_node *an;
-	DECLARE_MAC_BUF(mac);
 
-	avp = sc->sc_vaps[if_id];
-	ASSERT(avp != NULL);
+	an = (struct ath_node *)sta->drv_priv;
 
-	/* mac80211 sta_notify callback is from an IRQ context, so no sleep */
-	an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
-	if (an == NULL)
-		return NULL;
-	memset(an, 0, sizeof(*an));
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_tx_node_init(sc, an);
 
-	an->an_sc = sc;
-	memcpy(an->an_addr, addr, ETH_ALEN);
-	atomic_set(&an->an_refcnt, 1);
-
-	/* set up per-node tx/rx state */
-	ath_tx_node_init(sc, an);
-	ath_rx_node_init(sc, an);
+	an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+			     sta->ht_cap.ampdu_factor);
+	an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
 
 	ath_chainmask_sel_init(sc, an);
 	ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
-	list_add(&an->list, &sc->node_list);
-
-	return an;
 }
 
-void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
+void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
-	unsigned long flags;
-
-	DECLARE_MAC_BUF(mac);
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 
 	ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
-	an->an_flags |= ATH_NODE_CLEAN;
-	ath_tx_node_cleanup(sc, an, bh_flag);
-	ath_rx_node_cleanup(sc, an);
 
-	ath_tx_node_free(sc, an);
-	ath_rx_node_free(sc, an);
-
-	spin_lock_irqsave(&sc->node_lock, flags);
-
-	list_del(&an->list);
-
-	spin_unlock_irqrestore(&sc->node_lock, flags);
-
-	kfree(an);
-}
-
-/* Finds a node and increases the refcnt if found */
-
-struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr)
-{
-	struct ath_node *an = NULL, *an_found = NULL;
-
-	if (list_empty(&sc->node_list)) /* FIXME */
-		goto out;
-	list_for_each_entry(an, &sc->node_list, list) {
-		if (!compare_ether_addr(an->an_addr, addr)) {
-			atomic_inc(&an->an_refcnt);
-			an_found = an;
-			break;
-		}
-	}
-out:
-	return an_found;
-}
-
-/* Decrements the refcnt and if it drops to zero, detach the node */
-
-void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
-{
-	if (atomic_dec_and_test(&an->an_refcnt))
-		ath_node_detach(sc, an, bh_flag);
-}
-
-/* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */
-struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr)
-{
-	struct ath_node *an = NULL, *an_found = NULL;
-
-	if (list_empty(&sc->node_list))
-		return NULL;
-
-	list_for_each_entry(an, &sc->node_list, list)
-		if (!compare_ether_addr(an->an_addr, addr)) {
-			an_found = an;
-			break;
-		}
-
-	return an_found;
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_tx_node_cleanup(sc, an);
 }
 
 /*
@@ -1436,11 +1226,8 @@
 		for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
 			if (sc->sc_flags & SC_OP_TXAGGR)
 				ath_tx_aggr_teardown(sc, an, tidno);
-			if (sc->sc_flags & SC_OP_RXAGGR)
-				ath_rx_aggr_teardown(sc, an, tidno);
 		}
 	}
-	an->an_flags = 0;
 }
 
 /**************/
@@ -1491,27 +1278,6 @@
 	}
 }
 
-/* Return the current country and domain information */
-void ath_get_currentCountry(struct ath_softc *sc,
-	struct ath9k_country_entry *ctry)
-{
-	ath9k_regd_get_current_country(sc->sc_ah, ctry);
-
-	/* If HAL not specific yet, since it is band dependent,
-	 * use the one we passed in. */
-	if (ctry->countryCode == CTRY_DEFAULT) {
-		ctry->iso[0] = 0;
-		ctry->iso[1] = 0;
-	} else if (ctry->iso[0] && ctry->iso[1]) {
-		if (!ctry->iso[2]) {
-			if (ath_outdoor)
-				ctry->iso[2] = 'O';
-			else
-				ctry->iso[2] = 'I';
-		}
-	}
-}
-
 /**************************/
 /* Slow Antenna Diversity */
 /**************************/
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index cb3e61e..69e8d3e 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -84,9 +84,6 @@
 #define TSF_TO_TU(_h,_l) \
 	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
 
-#define ATH9K_BH_STATUS_INTACT		0
-#define ATH9K_BH_STATUS_CHANGE		1
-
 #define	ATH_TXQ_SETUP(sc, i)        ((sc)->sc_txqsetup & (1<<i))
 
 static inline unsigned long get_timestamp(void)
@@ -209,6 +206,7 @@
 	struct ath_rc_series bfs_rcs[4];	/* rate series */
 	u32 bf_type;				/* BUF_* (enum buffer_type) */
 	/* key type use to encrypt this frame */
+	u32 bfs_keyix;
 	enum ath9k_key_type bfs_keytype;
 };
 
@@ -219,6 +217,7 @@
 #define bf_seqno        	bf_state.bfs_seqno
 #define bf_tidno        	bf_state.bfs_tidno
 #define bf_rcs          	bf_state.bfs_rcs
+#define bf_keyix                bf_state.bfs_keyix
 #define bf_keytype      	bf_state.bfs_keytype
 #define bf_isdata(bf)		(bf->bf_state.bf_type & BUF_DATA)
 #define bf_isaggr(bf)		(bf->bf_state.bf_type & BUF_AGGR)
@@ -244,7 +243,6 @@
 	struct ath_buf *bf_next;	/* next subframe in the aggregate */
 	struct ath_buf *bf_rifslast;	/* last buf for RIFS burst */
 	void *bf_mpdu;			/* enclosing frame structure */
-	void *bf_node;			/* pointer to the node */
 	struct ath_desc *bf_desc;	/* virtual addr of desc */
 	dma_addr_t bf_daddr;		/* physical addr of desc */
 	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
@@ -306,15 +304,7 @@
 
 #define ATH_MAX_ANTENNA          3
 #define ATH_RXBUF                512
-#define ATH_RX_TIMEOUT           40      /* 40 milliseconds */
 #define WME_NUM_TID              16
-#define IEEE80211_BAR_CTL_TID_M  0xF000  /* tid mask */
-#define IEEE80211_BAR_CTL_TID_S  12      /* tid shift */
-
-enum ATH_RX_TYPE {
-	ATH_RX_NON_CONSUMED = 0,
-	ATH_RX_CONSUMED
-};
 
 /* per frame rx status block */
 struct ath_recv_status {
@@ -348,49 +338,18 @@
 	struct ath_recv_status rx_status;	/* cached rx status */
 };
 
-/* Per-TID aggregate receiver state for a node */
-struct ath_arx_tid {
-	struct ath_node *an;
-	struct ath_rxbuf *rxbuf;	/* re-ordering buffer */
-	struct timer_list timer;
-	spinlock_t tidlock;
-	int baw_head;			/* seq_next at head */
-	int baw_tail;			/* tail of block-ack window */
-	int seq_reset;			/* need to reset start sequence */
-	int addba_exchangecomplete;
-	u16 seq_next;			/* next expected sequence */
-	u16 baw_size;			/* block-ack window size */
-};
-
-/* Per-node receiver aggregate state */
-struct ath_arx {
-	struct ath_arx_tid tid[WME_NUM_TID];
-};
-
 int ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
 void ath_flushrecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
-void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
-void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
-void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
 void ath_handle_rx_intr(struct ath_softc *sc);
 int ath_rx_init(struct ath_softc *sc, int nbufs);
 void ath_rx_cleanup(struct ath_softc *sc);
 int ath_rx_tasklet(struct ath_softc *sc, int flush);
-int ath_rx_input(struct ath_softc *sc,
-		 struct ath_node *node,
-		 int is_ampdu,
-		 struct sk_buff *skb,
-		 struct ath_recv_status *rx_status,
-		 enum ATH_RX_TYPE *status);
 int _ath_rx_indicate(struct ath_softc *sc,
 		     struct sk_buff *skb,
 		     struct ath_recv_status *status,
 		     u16 keyix);
-int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
-		    struct ath_recv_status *status);
-
 /******/
 /* TX */
 /******/
@@ -419,12 +378,6 @@
 #define WME_AC_VO               3 /* voice */
 #define WME_NUM_AC              4
 
-enum ATH_SM_PWRSAV{
-	ATH_SM_ENABLE,
-	ATH_SM_PWRSAV_STATIC,
-	ATH_SM_PWRSAV_DYNAMIC,
-};
-
 /*
  * Data transmit queue state.  One of these exists for each
  * hardware transmit queue.  Packets sent to us from above
@@ -444,9 +397,6 @@
 	u8 axq_aggr_depth;		/* aggregates queued */
 	u32 axq_totalqueued;		/* total ever queued */
 
-	/* count to determine if descriptor should generate int on this txq. */
-	u32 axq_intrcnt;
-
 	bool stopped;			/* Is mac80211 queue stopped ? */
 	struct ath_buf *axq_linkbuf;	/* virtual addr of last buffer*/
 
@@ -460,6 +410,10 @@
 	struct list_head axq_acq;
 };
 
+#define AGGR_CLEANUP         BIT(1)
+#define AGGR_ADDBA_COMPLETE  BIT(2)
+#define AGGR_ADDBA_PROGRESS  BIT(3)
+
 /* per TID aggregate tx state for a destination */
 struct ath_atx_tid {
 	struct list_head list;		/* round-robin tid entry */
@@ -475,9 +429,7 @@
 	int baw_tail;			/* next unused tx buffer slot */
 	int sched;
 	int paused;
-	int cleanup_inprogress;
-	u32 addba_exchangecomplete:1;
-	int32_t addba_exchangeinprogress;
+	u8 state;
 	int addba_exchangeattempts;
 };
 
@@ -498,24 +450,8 @@
 
 /* per-frame tx control block */
 struct ath_tx_control {
-	struct ath_node *an;
+	struct ath_txq *txq;
 	int if_id;
-	int qnum;
-	u32 ht:1;
-	u32 ps:1;
-	u32 use_minrate:1;
-	enum ath9k_pkt_type atype;
-	enum ath9k_key_type keytype;
-	u32 flags;
-	u16 seqno;
-	u16 tidno;
-	u16 txpower;
-	u16 frmlen;
-	u32 keyix;
-	int min_rate;
-	int mcast_rate;
-	struct ath_softc *dev;
-	dma_addr_t dmacontext;
 };
 
 /* per frame tx status block */
@@ -550,33 +486,29 @@
 void ath_tx_draintxq(struct ath_softc *sc,
 		     struct ath_txq *txq, bool retry_tx);
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
-void ath_tx_node_cleanup(struct ath_softc *sc,
-			 struct ath_node *an, bool bh_flag);
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
 void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_init(struct ath_softc *sc, int nbufs);
 int ath_tx_cleanup(struct ath_softc *sc);
 int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *q);
-int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb);
+int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
+		 struct ath_tx_control *txctl);
 void ath_tx_tasklet(struct ath_softc *sc);
 u32 ath_txq_depth(struct ath_softc *sc, int qnum);
 u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
 void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
 void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-		     struct ath_xmit_status *tx_status, struct ath_node *an);
+		     struct ath_xmit_status *tx_status);
 void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
 
 /**********************/
 /* Node / Aggregation */
 /**********************/
 
-/* indicates the node is clened up */
-#define ATH_NODE_CLEAN          0x1
-/* indicates the node is 80211 power save */
-#define ATH_NODE_PWRSAVE        0x2
-
 #define ADDBA_EXCHANGE_ATTEMPTS    10
 #define ATH_AGGR_DELIM_SZ          4   /* delimiter size   */
 #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
@@ -588,6 +520,7 @@
 #define IEEE80211_SEQ_SEQ_SHIFT    4
 #define IEEE80211_SEQ_MAX          4096
 #define IEEE80211_MIN_AMPDU_BUF    0x8
+#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
 
 /* return whether a bit at index _n in bitmap _bm is set
  * _sz is the size of the bitmap  */
@@ -618,14 +551,6 @@
 	ATH_AGGR_8K_LIMITED,
 };
 
-enum ATH_AGGR_CHECK {
-	AGGR_NOT_REQUIRED,
-	AGGR_REQUIRED,
-	AGGR_CLEANUP_PROGRESS,
-	AGGR_EXCHANGE_PROGRESS,
-	AGGR_EXCHANGE_DONE
-};
-
 struct aggr_rifs_param {
 	int param_max_frames;
 	int param_max_len;
@@ -637,51 +562,30 @@
 /* Per-node aggregation state */
 struct ath_node_aggr {
 	struct ath_atx tx;	/* node transmit state */
-	struct ath_arx rx;	/* node receive state */
 };
 
 /* driver-specific node state */
 struct ath_node {
-	struct list_head list;
 	struct ath_softc *an_sc;
-	atomic_t an_refcnt;
 	struct ath_chainmask_sel an_chainmask_sel;
 	struct ath_node_aggr an_aggr;
-	u8 an_smmode; /* SM Power save mode */
-	u8 an_flags;
-	u8 an_addr[ETH_ALEN];
+	u16 maxampdu;
+	u8 mpdudensity;
 };
 
 void ath_tx_resume_tid(struct ath_softc *sc,
 	struct ath_atx_tid *tid);
-enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
-	struct ath_node *an, u8 tidno);
+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);
-void ath_rx_aggr_teardown(struct ath_softc *sc,
-	struct ath_node *an, u8 tidno);
-int ath_rx_aggr_start(struct ath_softc *sc,
-		      const u8 *addr,
-		      u16 tid,
-		      u16 *ssn);
-int ath_rx_aggr_stop(struct ath_softc *sc,
-		     const u8 *addr,
-		     u16 tid);
-int ath_tx_aggr_start(struct ath_softc *sc,
-		      const u8 *addr,
-		      u16 tid,
-		      u16 *ssn);
-int ath_tx_aggr_stop(struct ath_softc *sc,
-		     const u8 *addr,
-		     u16 tid);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn);
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 void ath_newassoc(struct ath_softc *sc,
 	struct ath_node *node, int isnew, int isuapsd);
-struct ath_node *ath_node_attach(struct ath_softc *sc,
-	u8 addr[ETH_ALEN], int if_id);
-void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
-struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]);
-void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
-struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
+void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
+void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
 
 /*******************/
 /* Beacon Handling */
@@ -745,23 +649,14 @@
 
 /* driver-specific vap state */
 struct ath_vap {
-	struct ieee80211_vif *av_if_data;
+	int av_bslot;			/* beacon slot index */
 	enum ath9k_opmode av_opmode;	/* VAP operational mode */
 	struct ath_buf *av_bcbuf;	/* beacon buffer */
 	struct ath_tx_control av_btxctl;  /* txctl information for beacon */
-	int av_bslot;			/* beacon slot index */
 	struct ath_vap_config av_config;/* vap configuration parameters*/
 	struct ath_rate_node *rc_node;
 };
 
-int ath_vap_attach(struct ath_softc *sc,
-		   int if_id,
-		   struct ieee80211_vif *if_data,
-		   enum ath9k_opmode opmode);
-int ath_vap_detach(struct ath_softc *sc, int if_id);
-int ath_vap_config(struct ath_softc *sc,
-		   int if_id, struct ath_vap_config *if_config);
-
 /*********************/
 /* Antenna diversity */
 /*********************/
@@ -919,8 +814,6 @@
 
 struct ath_ht_info {
 	enum ath9k_ht_macmode tx_chan_width;
-	u16 maxampdu;
-	u8 mpdudensity;
 	u8 ext_chan_offset;
 };
 
@@ -971,14 +864,13 @@
 
 	u8 sc_nbcnvaps;			/* # of vaps sending beacons */
 	u16 sc_nvaps;			/* # of active virtual ap's */
-	struct ath_vap *sc_vaps[ATH_BCBUF];
+	struct ieee80211_vif *sc_vaps[ATH_BCBUF];
 
 	u8 sc_mcastantenna;
 	u8 sc_defant;			/* current default antenna */
 	u8 sc_rxotherant;		/* rx's on non-default antenna */
 
 	struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
-	struct list_head node_list;
 	struct ath_ht_info sc_ht_info;
 	enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
 
@@ -1007,7 +899,6 @@
 	struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES];
 	struct ath_descdma sc_txdma;
 	u32 sc_txqsetup;
-	u32 sc_txintrperiod;	/* tx interrupt batching */
 	int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME	AC -> h/w qnum */
 	u16 seq_no; /* TX sequence number */
 
@@ -1040,7 +931,6 @@
 	spinlock_t sc_rxbuflock;
 	spinlock_t sc_txbuflock;
 	spinlock_t sc_resetlock;
-	spinlock_t node_lock;
 
 	/* LEDs */
 	struct ath_led radio_led;
@@ -1056,9 +946,8 @@
 };
 
 int ath_init(u16 devid, struct ath_softc *sc);
-void ath_deinit(struct ath_softc *sc);
 int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
-int ath_suspend(struct ath_softc *sc);
+void ath_stop(struct ath_softc *sc);
 irqreturn_t ath_isr(int irq, void *dev);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
 int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
@@ -1077,8 +966,6 @@
 void ath_setslottime(struct ath_softc *sc);
 void ath_update_txpow(struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
-void ath_get_currentCountry(struct ath_softc *sc,
-	struct ath9k_country_entry *ctry);
 u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
 
 #endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c
new file mode 100644
index 0000000..f5fd03c
--- /dev/null
+++ b/drivers/net/wireless/ath9k/eeprom.c
@@ -0,0 +1,1605 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
+				      u32 reg, u32 mask,
+				      u32 shift, u32 val)
+{
+	u32 regVal;
+
+	regVal = REG_READ(ah, reg) & ~mask;
+	regVal |= (val << shift) & mask;
+
+	REG_WRITE(ah, reg, regVal);
+
+	if (ah->ah_config.analog_shiftreg)
+		udelay(100);
+
+	return;
+}
+
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+
+	if (fbin == AR5416_BCHAN_UNUSED)
+		return fbin;
+
+	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+static inline int16_t ath9k_hw_interpolate(u16 target,
+					   u16 srcLeft, u16 srcRight,
+					   int16_t targetLeft,
+					   int16_t targetRight)
+{
+	int16_t rv;
+
+	if (srcRight == srcLeft) {
+		rv = targetLeft;
+	} else {
+		rv = (int16_t) (((target - srcLeft) * targetRight +
+				 (srcRight - target) * targetLeft) /
+				(srcRight - srcLeft));
+	}
+	return rv;
+}
+
+static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
+						  u16 listSize, u16 *indexL,
+						  u16 *indexR)
+{
+	u16 i;
+
+	if (target <= pList[0]) {
+		*indexL = *indexR = 0;
+		return true;
+	}
+	if (target >= pList[listSize - 1]) {
+		*indexL = *indexR = (u16) (listSize - 1);
+		return true;
+	}
+
+	for (i = 0; i < listSize - 1; i++) {
+		if (pList[i] == target) {
+			*indexL = *indexR = i;
+			return true;
+		}
+		if (target < pList[i + 1]) {
+			*indexL = i;
+			*indexR = (u16) (i + 1);
+			return false;
+		}
+	}
+	return false;
+}
+
+static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+
+	if (!ath9k_hw_wait(ah,
+			   AR_EEPROM_STATUS_DATA,
+			   AR_EEPROM_STATUS_DATA_BUSY |
+			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
+		return false;
+	}
+
+	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
+		   AR_EEPROM_STATUS_DATA_VAL);
+
+	return true;
+}
+
+static int ath9k_hw_flash_map(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
+
+	if (!ahp->ah_cal_mem) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"%s: cannot remap eeprom region \n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	*data = ioread16(ahp->ah_cal_mem + off);
+
+	return true;
+}
+
+static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+	if (ath9k_hw_use_flash(ah))
+		return ath9k_hw_flash_read(ah, off, data);
+	else
+		return ath9k_hw_eeprom_read(ah, off, data);
+}
+
+static bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	u16 *eep_data;
+	int addr, ar5416_eep_start_loc = 0;
+
+	if (!ath9k_hw_use_flash(ah)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"%s: Reading from EEPROM, not flash\n", __func__);
+		ar5416_eep_start_loc = 256;
+	}
+
+	if (AR_SREV_9100(ah))
+		ar5416_eep_start_loc = 256;
+
+	eep_data = (u16 *)eep;
+
+	for (addr = 0; addr < sizeof(struct ar5416_eeprom) / sizeof(u16); addr++) {
+		if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+					 eep_data)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"%s: Unable to read eeprom region \n",
+				__func__);
+			return false;
+		}
+		eep_data++;
+	}
+	return true;
+}
+
+static int ath9k_hw_check_eeprom(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep =
+		(struct ar5416_eeprom *) &ahp->ah_eeprom;
+	u16 *eepdata, temp, magic, magic2;
+	u32 sum = 0, el;
+	bool need_swap = false;
+	int i, addr, size;
+
+	if (!ath9k_hw_use_flash(ah)) {
+		if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+					 &magic)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"%s: Reading Magic # failed\n", __func__);
+			return false;
+		}
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: Read Magic = 0x%04X\n",
+			 __func__, magic);
+
+		if (magic != AR5416_EEPROM_MAGIC) {
+			magic2 = swab16(magic);
+
+			if (magic2 == AR5416_EEPROM_MAGIC) {
+				size = sizeof(struct ar5416_eeprom);
+				need_swap = true;
+				eepdata = (u16 *) (&ahp->ah_eeprom);
+
+				for (addr = 0; addr < size / sizeof(u16); addr++) {
+					temp = swab16(*eepdata);
+					*eepdata = temp;
+					eepdata++;
+
+					DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+						"0x%04X  ", *eepdata);
+
+					if (((addr + 1) % 6) == 0)
+						DPRINTF(ah->ah_sc,
+							ATH_DBG_EEPROM, "\n");
+				}
+			} else {
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"Invalid EEPROM Magic. "
+					"endianness mismatch.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
+
+	if (need_swap)
+		el = swab16(ahp->ah_eeprom.baseEepHeader.length);
+	else
+		el = ahp->ah_eeprom.baseEepHeader.length;
+
+	if (el > sizeof(struct ar5416_eeprom))
+		el = sizeof(struct ar5416_eeprom) / sizeof(u16);
+	else
+		el = el / sizeof(u16);
+
+	eepdata = (u16 *)(&ahp->ah_eeprom);
+
+	for (i = 0; i < el; i++)
+		sum ^= *eepdata++;
+
+	if (need_swap) {
+		u32 integer, j;
+		u16 word;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"EEPROM Endianness is not native.. Changing \n");
+
+		word = swab16(eep->baseEepHeader.length);
+		eep->baseEepHeader.length = word;
+
+		word = swab16(eep->baseEepHeader.checksum);
+		eep->baseEepHeader.checksum = word;
+
+		word = swab16(eep->baseEepHeader.version);
+		eep->baseEepHeader.version = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[0]);
+		eep->baseEepHeader.regDmn[0] = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[1]);
+		eep->baseEepHeader.regDmn[1] = word;
+
+		word = swab16(eep->baseEepHeader.rfSilent);
+		eep->baseEepHeader.rfSilent = word;
+
+		word = swab16(eep->baseEepHeader.blueToothOptions);
+		eep->baseEepHeader.blueToothOptions = word;
+
+		word = swab16(eep->baseEepHeader.deviceCap);
+		eep->baseEepHeader.deviceCap = word;
+
+		for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+			struct modal_eep_header *pModal =
+				&eep->modalHeader[j];
+			integer = swab32(pModal->antCtrlCommon);
+			pModal->antCtrlCommon = integer;
+
+			for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+				integer = swab32(pModal->antCtrlChain[i]);
+				pModal->antCtrlChain[i] = integer;
+			}
+
+			for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+				word = swab16(pModal->spurChans[i].spurChan);
+				pModal->spurChans[i].spurChan = word;
+			}
+		}
+	}
+
+	if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
+	    ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+			sum, ar5416_get_eep_ver(ahp));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+					   u8 *pVpdList, u16 numIntercepts,
+					   u8 *pRetVpdList)
+{
+	u16 i, k;
+	u8 currPwr = pwrMin;
+	u16 idxL = 0, idxR = 0;
+
+	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+					       numIntercepts, &(idxL),
+					       &(idxR));
+		if (idxR < 1)
+			idxR = 1;
+		if (idxL == numIntercepts - 1)
+			idxL = (u16) (numIntercepts - 2);
+		if (pPwrList[idxL] == pPwrList[idxR])
+			k = pVpdList[idxL];
+		else
+			k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
+				   (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+				  (pPwrList[idxR] - pPwrList[idxL]));
+		pRetVpdList[i] = (u8) k;
+		currPwr += 2;
+	}
+
+	return true;
+}
+
+static void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
+				struct ath9k_channel *chan,
+				struct cal_data_per_freq *pRawDataSet,
+				u8 *bChans, u16 availPiers,
+				u16 tPdGainOverlap, int16_t *pMinCalPower,
+				u16 *pPdGainBoundaries, u8 *pPDADCValues,
+				u16 numXpdGains)
+{
+	int i, j, k;
+	int16_t ss;
+	u16 idxL = 0, idxR = 0, numPiers;
+	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+	u8 minPwrT4[AR5416_NUM_PD_GAINS];
+	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+	int16_t vpdStep;
+	int16_t tmpVal;
+	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+	bool match;
+	int16_t minDelta = 0;
+	struct chan_centers centers;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	for (numPiers = 0; numPiers < availPiers; numPiers++) {
+		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+			break;
+	}
+
+	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+							     IS_CHAN_2GHZ(chan)),
+					       bChans, numPiers, &idxL, &idxR);
+
+	if (match) {
+		for (i = 0; i < numXpdGains; i++) {
+			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+					pRawDataSet[idxL].pwrPdg[i],
+					pRawDataSet[idxL].vpdPdg[i],
+					AR5416_PD_GAIN_ICEPTS,
+					vpdTableI[i]);
+		}
+	} else {
+		for (i = 0; i < numXpdGains; i++) {
+			pVpdL = pRawDataSet[idxL].vpdPdg[i];
+			pPwrL = pRawDataSet[idxL].pwrPdg[i];
+			pVpdR = pRawDataSet[idxR].vpdPdg[i];
+			pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+			maxPwrT4[i] =
+				min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
+				    pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+
+
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrL, pVpdL,
+						AR5416_PD_GAIN_ICEPTS,
+						vpdTableL[i]);
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrR, pVpdR,
+						AR5416_PD_GAIN_ICEPTS,
+						vpdTableR[i]);
+
+			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+				vpdTableI[i][j] =
+					(u8)(ath9k_hw_interpolate((u16)
+					     FREQ2FBIN(centers.
+						       synth_center,
+						       IS_CHAN_2GHZ
+						       (chan)),
+					     bChans[idxL], bChans[idxR],
+					     vpdTableL[i][j], vpdTableR[i][j]));
+			}
+		}
+	}
+
+	*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+	k = 0;
+
+	for (i = 0; i < numXpdGains; i++) {
+		if (i == (numXpdGains - 1))
+			pPdGainBoundaries[i] =
+				(u16)(maxPwrT4[i] / 2);
+		else
+			pPdGainBoundaries[i] =
+				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+		pPdGainBoundaries[i] =
+			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+		if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
+			minDelta = pPdGainBoundaries[0] - 23;
+			pPdGainBoundaries[0] = 23;
+		} else {
+			minDelta = 0;
+		}
+
+		if (i == 0) {
+			if (AR_SREV_9280_10_OR_LATER(ah))
+				ss = (int16_t)(0 - (minPwrT4[i] / 2));
+			else
+				ss = 0;
+		} else {
+			ss = (int16_t)((pPdGainBoundaries[i - 1] -
+					(minPwrT4[i] / 2)) -
+				       tPdGainOverlap + 1 + minDelta);
+		}
+		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+			ss++;
+		}
+
+		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+				(minPwrT4[i] / 2));
+		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+			tgtIndex : sizeCurrVpdTable;
+
+		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			pPDADCValues[k++] = vpdTableI[i][ss++];
+		}
+
+		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+				    vpdTableI[i][sizeCurrVpdTable - 2]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		if (tgtIndex > maxIndex) {
+			while ((ss <= tgtIndex) &&
+			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+						    (ss - maxIndex + 1) * vpdStep));
+				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+							 255 : tmpVal);
+				ss++;
+			}
+		}
+	}
+
+	while (i < AR5416_PD_GAINS_IN_MASK) {
+		pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
+		i++;
+	}
+
+	while (k < AR5416_NUM_PDADC_VALUES) {
+		pPDADCValues[k] = pPDADCValues[k - 1];
+		k++;
+	}
+
+	return;
+}
+
+static void ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
+				      struct ath9k_channel *chan,
+				      struct cal_target_power_leg *powInfo,
+				      u16 numChannels,
+				      struct cal_target_power_leg *pNewPower,
+				      u16 numRates, bool isExtTarget)
+{
+	struct chan_centers centers;
+	u16 clo, chi;
+	int i;
+	int matchIndex = -1, lowIndex = -1;
+	u16 freq;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+				       IS_CHAN_2GHZ(chan))) {
+		matchIndex = 0;
+	} else {
+		for (i = 0; (i < numChannels) &&
+			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) {
+				matchIndex = i;
+				break;
+			} else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						      IS_CHAN_2GHZ(chan))) &&
+				   (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+						      IS_CHAN_2GHZ(chan)))) {
+				lowIndex = i - 1;
+				break;
+			}
+		}
+		if ((matchIndex == -1) && (lowIndex == -1))
+			matchIndex = i - 1;
+	}
+
+	if (matchIndex != -1) {
+		*pNewPower = powInfo[matchIndex];
+	} else {
+		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+					 IS_CHAN_2GHZ(chan));
+		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+					 IS_CHAN_2GHZ(chan));
+
+		for (i = 0; i < numRates; i++) {
+			pNewPower->tPow2x[i] =
+				(u8)ath9k_hw_interpolate(freq, clo, chi,
+						powInfo[lowIndex].tPow2x[i],
+						powInfo[lowIndex + 1].tPow2x[i]);
+		}
+	}
+}
+
+static void ath9k_hw_get_target_powers(struct ath_hal *ah,
+				       struct ath9k_channel *chan,
+				       struct cal_target_power_ht *powInfo,
+				       u16 numChannels,
+				       struct cal_target_power_ht *pNewPower,
+				       u16 numRates, bool isHt40Target)
+{
+	struct chan_centers centers;
+	u16 clo, chi;
+	int i;
+	int matchIndex = -1, lowIndex = -1;
+	u16 freq;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+		matchIndex = 0;
+	} else {
+		for (i = 0; (i < numChannels) &&
+			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) {
+				matchIndex = i;
+				break;
+			} else
+				if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) &&
+				    (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+						       IS_CHAN_2GHZ(chan)))) {
+					lowIndex = i - 1;
+					break;
+				}
+		}
+		if ((matchIndex == -1) && (lowIndex == -1))
+			matchIndex = i - 1;
+	}
+
+	if (matchIndex != -1) {
+		*pNewPower = powInfo[matchIndex];
+	} else {
+		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+					 IS_CHAN_2GHZ(chan));
+		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+					 IS_CHAN_2GHZ(chan));
+
+		for (i = 0; i < numRates; i++) {
+			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
+						clo, chi,
+						powInfo[lowIndex].tPow2x[i],
+						powInfo[lowIndex + 1].tPow2x[i]);
+		}
+	}
+}
+
+static u16 ath9k_hw_get_max_edge_power(u16 freq,
+				       struct cal_ctl_edges *pRdEdgesPower,
+				       bool is2GHz)
+{
+	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	int i;
+
+	for (i = 0; (i < AR5416_NUM_BAND_EDGES) &&
+		     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+			twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+			break;
+		} else if ((i > 0) &&
+			   (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+						      is2GHz))) {
+			if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+					       is2GHz) < freq &&
+			    pRdEdgesPower[i - 1].flag) {
+				twiceMaxEdgePower =
+					pRdEdgesPower[i - 1].tPower;
+			}
+			break;
+		}
+	}
+
+	return twiceMaxEdgePower;
+}
+
+int ath9k_hw_set_txpower(struct ath_hal *ah,
+			 struct ath9k_channel *chan,
+			 u16 cfgCtl,
+			 u8 twiceAntennaReduction,
+			 u8 twiceMaxRegulatoryPower,
+			 u8 powerLimit)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *pEepData = &ahp->ah_eeprom;
+	struct modal_eep_header *pModal =
+		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+	int16_t ratesArray[Ar5416RateSize];
+	int16_t txPowerIndexOffset = 0;
+	u8 ht40PowerIncForPdadc = 2;
+	int i;
+
+	memset(ratesArray, 0, sizeof(ratesArray));
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+	}
+
+	if (!ath9k_hw_set_power_per_rate_table(ah, chan,
+					       &ratesArray[0], cfgCtl,
+					       twiceAntennaReduction,
+					       twiceMaxRegulatoryPower,
+					       powerLimit)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"ath9k_hw_set_txpower: unable to set "
+			"tx power per rate table\n");
+		return -EIO;
+	}
+
+	if (!ath9k_hw_set_power_cal_table(ah, chan, &txPowerIndexOffset)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			 "ath9k_hw_set_txpower: unable to set power table\n");
+		return -EIO;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
+		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+			ratesArray[i] = AR5416_MAX_RATE_POWER;
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		for (i = 0; i < Ar5416RateSize; i++)
+			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+	if (IS_CHAN_2GHZ(chan)) {
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+			  ATH9K_POW_SM(ratesArray[rate2s], 24)
+			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
+			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
+			  | ATH9K_POW_SM(ratesArray[rate1l], 0));
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+			  ATH9K_POW_SM(ratesArray[rate11s], 24)
+			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
+			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+	if (IS_CHAN_HT40(chan)) {
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+					 ht40PowerIncForPdadc, 0));
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+					 ht40PowerIncForPdadc, 0));
+
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+	i = rate6mb;
+
+	if (IS_CHAN_HT40(chan))
+		i = rateHt40_0;
+	else if (IS_CHAN_HT20(chan))
+		i = rateHt20_0;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ah->ah_maxPowerLevel =
+			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+	else
+		ah->ah_maxPowerLevel = ratesArray[i];
+
+	return 0;
+}
+
+void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+	struct modal_eep_header *pModal;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	u8 biaslevel;
+
+	if (ah->ah_macVersion != AR_SREV_VERSION_9160)
+		return;
+
+	if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
+		return;
+
+	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+	if (pModal->xpaBiasLvl != 0xff) {
+		biaslevel = pModal->xpaBiasLvl;
+	} else {
+		u16 resetFreqBin, freqBin, freqCount = 0;
+		struct chan_centers centers;
+
+		ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+		resetFreqBin = FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
+		freqBin = pModal->xpaBiasLvlFreq[0] & 0xff;
+		biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14);
+
+		freqCount++;
+
+		while (freqCount < 3) {
+			if (pModal->xpaBiasLvlFreq[freqCount] == 0x0)
+				break;
+
+			freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff;
+			if (resetFreqBin >= freqBin) {
+				biaslevel = (u8)(pModal->xpaBiasLvlFreq[freqCount] >> 14);
+			} else {
+				break;
+			}
+			freqCount++;
+		}
+	}
+
+	if (IS_CHAN_2GHZ(chan)) {
+		INI_RA(&ahp->ah_iniAddac, 7, 1) =
+			(INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel	<< 3;
+	} else {
+		INI_RA(&ahp->ah_iniAddac, 6, 1) =
+			(INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel	<< 6;
+	}
+}
+
+bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
+				       struct ath9k_channel *chan,
+				       int16_t *ratesArray,
+				       u16 cfgCtl,
+				       u8 AntennaReduction,
+				       u8 twiceMaxRegulatoryPower,
+				       u8 powerLimit)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *pEepData = &ahp->ah_eeprom;
+	u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	static const u16 tpScaleReductionTable[5] =
+		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+	int i;
+	int8_t twiceLargestAntenna;
+	struct cal_ctl_data *rep;
+	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+		0, { 0, 0, 0, 0}
+	};
+	struct cal_target_power_leg targetPowerOfdmExt = {
+		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+		0, { 0, 0, 0, 0 }
+	};
+	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+		0, {0, 0, 0, 0}
+	};
+	u8 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+	u16 ctlModesFor11a[] =
+		{ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
+	u16 ctlModesFor11g[] =
+		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+		  CTL_2GHT40
+		};
+	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	struct chan_centers centers;
+	int tx_chainmask;
+	u8 twiceMinEdgePower;
+
+	tx_chainmask = ahp->ah_txchainmask;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	twiceLargestAntenna = max(
+		pEepData->modalHeader
+			[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+		pEepData->modalHeader
+			[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+	twiceLargestAntenna = max((u8)twiceLargestAntenna,
+				  pEepData->modalHeader
+				  [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+	twiceLargestAntenna = (int8_t)min(AntennaReduction - twiceLargestAntenna, 0);
+
+	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+	if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
+		maxRegAllowedPower -=
+			(tpScaleReductionTable[(ah->ah_tpScale)] * 2);
+	}
+
+	scaledPower = min(powerLimit, maxRegAllowedPower);
+
+	switch (ar5416_get_ntxchains(tx_chainmask)) {
+	case 1:
+		break;
+	case 2:
+		scaledPower -=
+			pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain;
+		break;
+	case 3:
+		scaledPower -=
+			pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain;
+		break;
+	}
+
+	scaledPower = max(0, (int32_t) scaledPower);
+
+	if (IS_CHAN_2GHZ(chan)) {
+		numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+			SUB_NUM_CTL_MODES_AT_2G_40;
+		pCtlMode = ctlModesFor11g;
+
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPowerCck,
+			AR5416_NUM_2G_CCK_TARGET_POWERS,
+			&targetPowerCck, 4, false);
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPower2G,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerOfdm, 4, false);
+		ath9k_hw_get_target_powers(ah, chan,
+			pEepData->calTargetPower2GHT20,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerHt20, 8, false);
+
+		if (IS_CHAN_HT40(chan)) {
+			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+			ath9k_hw_get_target_powers(ah, chan,
+				pEepData->calTargetPower2GHT40,
+				AR5416_NUM_2G_40_TARGET_POWERS,
+				&targetPowerHt40, 8, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPowerCck,
+				AR5416_NUM_2G_CCK_TARGET_POWERS,
+				&targetPowerCckExt, 4, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPower2G,
+				AR5416_NUM_2G_20_TARGET_POWERS,
+				&targetPowerOfdmExt, 4, true);
+		}
+	} else {
+		numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+			SUB_NUM_CTL_MODES_AT_5G_40;
+		pCtlMode = ctlModesFor11a;
+
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPower5G,
+			AR5416_NUM_5G_20_TARGET_POWERS,
+			&targetPowerOfdm, 4, false);
+		ath9k_hw_get_target_powers(ah, chan,
+			pEepData->calTargetPower5GHT20,
+			AR5416_NUM_5G_20_TARGET_POWERS,
+			&targetPowerHt20, 8, false);
+
+		if (IS_CHAN_HT40(chan)) {
+			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+			ath9k_hw_get_target_powers(ah, chan,
+				pEepData->calTargetPower5GHT40,
+				AR5416_NUM_5G_40_TARGET_POWERS,
+				&targetPowerHt40, 8, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPower5G,
+				AR5416_NUM_5G_20_TARGET_POWERS,
+				&targetPowerOfdmExt, 4, true);
+		}
+	}
+
+	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+			(pCtlMode[ctlMode] == CTL_2GHT40);
+		if (isHt40CtlMode)
+			freq = centers.synth_center;
+		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+			freq = centers.ext_center;
+		else
+			freq = centers.ctl_center;
+
+		if (ar5416_get_eep_ver(ahp) == 14 && ar5416_get_eep_rev(ahp) <= 2)
+			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+			"EXT_ADDITIVE %d\n",
+			ctlMode, numCtlModes, isHt40CtlMode,
+			(pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+				"chan %d\n",
+				i, cfgCtl, pCtlMode[ctlMode],
+				pEepData->ctlIndex[i], chan->channel);
+
+			if ((((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     pEepData->ctlIndex[i]) ||
+			    (((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+				rep = &(pEepData->ctlData[i]);
+
+				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+				IS_CHAN_2GHZ(chan));
+
+				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+					"    MATCH-EE_IDX %d: ch %d is2 %d "
+					"2xMinEdge %d chainmask %d chains %d\n",
+					i, freq, IS_CHAN_2GHZ(chan),
+					twiceMinEdgePower, tx_chainmask,
+					ar5416_get_ntxchains
+					(tx_chainmask));
+				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+					twiceMaxEdgePower = min(twiceMaxEdgePower,
+								twiceMinEdgePower);
+				} else {
+					twiceMaxEdgePower = twiceMinEdgePower;
+					break;
+				}
+			}
+		}
+
+		minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			"    SEL-Min ctlMode %d pCtlMode %d "
+			"2xMaxEdge %d sP %d minCtlPwr %d\n",
+			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+			scaledPower, minCtlPower);
+
+		switch (pCtlMode[ctlMode]) {
+		case CTL_11B:
+			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+				targetPowerCck.tPow2x[i] =
+					min(targetPowerCck.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11A:
+		case CTL_11G:
+			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+				targetPowerOfdm.tPow2x[i] =
+					min(targetPowerOfdm.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_5GHT20:
+		case CTL_2GHT20:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+				targetPowerHt20.tPow2x[i] =
+					min(targetPowerHt20.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11B_EXT:
+			targetPowerCckExt.tPow2x[0] =
+				min(targetPowerCckExt.tPow2x[0], minCtlPower);
+			break;
+		case CTL_11A_EXT:
+		case CTL_11G_EXT:
+			targetPowerOfdmExt.tPow2x[0] =
+				min(targetPowerOfdmExt.tPow2x[0], minCtlPower);
+			break;
+		case CTL_5GHT40:
+		case CTL_2GHT40:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+				targetPowerHt40.tPow2x[i] =
+					min(targetPowerHt40.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+		ratesArray[rate18mb] = ratesArray[rate24mb] =
+		targetPowerOfdm.tPow2x[0];
+	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+	if (IS_CHAN_2GHZ(chan)) {
+		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+		ratesArray[rate2s] = ratesArray[rate2l] =
+			targetPowerCck.tPow2x[1];
+		ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+			targetPowerCck.tPow2x[2];
+		;
+		ratesArray[rate11s] = ratesArray[rate11l] =
+			targetPowerCck.tPow2x[3];
+		;
+	}
+	if (IS_CHAN_HT40(chan)) {
+		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+			ratesArray[rateHt40_0 + i] =
+				targetPowerHt40.tPow2x[i];
+		}
+		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+		if (IS_CHAN_2GHZ(chan)) {
+			ratesArray[rateExtCck] =
+				targetPowerCckExt.tPow2x[0];
+		}
+	}
+	return true;
+}
+
+bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
+				  struct ath9k_channel *chan,
+				  int16_t *pTxPowerIndexOffset)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *pEepData = &ahp->ah_eeprom;
+	struct cal_data_per_freq *pRawDataset;
+	u8 *pCalBChans = NULL;
+	u16 pdGainOverlap_t2;
+	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+	u16 numPiers, i, j;
+	int16_t tMinCalPower;
+	u16 numXpdGain, xpdMask;
+	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+	u32 reg32, regOffset, regChainOffset;
+	int16_t modalIdx;
+
+	modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+	xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		pdGainOverlap_t2 =
+			pEepData->modalHeader[modalIdx].pdGainOverlap;
+	} else {
+		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+	}
+
+	if (IS_CHAN_2GHZ(chan)) {
+		pCalBChans = pEepData->calFreqPier2G;
+		numPiers = AR5416_NUM_2G_CAL_PIERS;
+	} else {
+		pCalBChans = pEepData->calFreqPier5G;
+		numPiers = AR5416_NUM_5G_CAL_PIERS;
+	}
+
+	numXpdGain = 0;
+
+	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+			if (numXpdGain >= AR5416_NUM_PD_GAINS)
+				break;
+			xpdGainValues[numXpdGain] =
+				(u16)(AR5416_PD_GAINS_IN_MASK - i);
+			numXpdGain++;
+		}
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+		      (numXpdGain - 1) & 0x3);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+		      xpdGainValues[0]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+		      xpdGainValues[1]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+		      xpdGainValues[2]);
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		if (AR_SREV_5416_V20_OR_LATER(ah) &&
+		    (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+		    (i != 0)) {
+			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+		} else
+			regChainOffset = i * 0x1000;
+
+		if (pEepData->baseEepHeader.txMask & (1 << i)) {
+			if (IS_CHAN_2GHZ(chan))
+				pRawDataset = pEepData->calPierData2G[i];
+			else
+				pRawDataset = pEepData->calPierData5G[i];
+
+			ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
+					    pRawDataset, pCalBChans,
+					    numPiers, pdGainOverlap_t2,
+					    &tMinCalPower, gainBoundaries,
+					    pdadcValues, numXpdGain);
+
+			if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+				REG_WRITE(ah,
+					  AR_PHY_TPCRG5 + regChainOffset,
+					  SM(pdGainOverlap_t2,
+					     AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+					  | SM(gainBoundaries[0],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+					  | SM(gainBoundaries[1],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+					  | SM(gainBoundaries[2],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+					  | SM(gainBoundaries[3],
+				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+			}
+
+			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+			for (j = 0; j < 32; j++) {
+				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+					((pdadcValues[4 * j + 2] & 0xFF) << 16) |
+					((pdadcValues[4 * j + 3] & 0xFF) << 24);
+				REG_WRITE(ah, regOffset, reg32);
+
+				DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
+					"PDADC (%d,%4x): %4.4x %8.8x\n",
+					i, regChainOffset, regOffset,
+					reg32);
+				DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
+					"PDADC: Chain %d | PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d |\n",
+					i, 4 * j, pdadcValues[4 * j],
+					4 * j + 1, pdadcValues[4 * j + 1],
+					4 * j + 2, pdadcValues[4 * j + 2],
+					4 * j + 3,
+					pdadcValues[4 * j + 3]);
+
+				regOffset += 4;
+			}
+		}
+	}
+
+	*pTxPowerIndexOffset = 0;
+
+	return true;
+}
+
+/* XXX: Clean me up, make me more legible */
+bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
+				      struct ath9k_channel *chan)
+{
+	struct modal_eep_header *pModal;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	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, 1, &ant_config);
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		if (AR_SREV_9280(ah)) {
+			if (i >= 2)
+				break;
+		}
+
+		if (AR_SREV_5416_V20_OR_LATER(ah) &&
+		    (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
+		    && (i != 0))
+			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+		else
+			regChainOffset = i * 0x1000;
+
+		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+			  pModal->antCtrlChain[i]);
+
+		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+			  (REG_READ(ah,
+				    AR_PHY_TIMING_CTRL4(0) +
+				    regChainOffset) &
+			   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+			  SM(pModal->iqCalICh[i],
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+			  SM(pModal->iqCalQCh[i],
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+		if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+			if ((eep->baseEepHeader.version &
+			     AR5416_EEP_VER_MINOR_MASK) >=
+			    AR5416_EEP_MINOR_VER_3) {
+				txRxAttenLocal = pModal->txRxAttenCh[i];
+				if (AR_SREV_9280_10_OR_LATER(ah)) {
+					REG_RMW_FIELD(ah,
+						AR_PHY_GAIN_2GHZ +
+						regChainOffset,
+						AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+						pModal->
+						bswMargin[i]);
+					REG_RMW_FIELD(ah,
+						AR_PHY_GAIN_2GHZ +
+						regChainOffset,
+						AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+						pModal->
+						bswAtten[i]);
+					REG_RMW_FIELD(ah,
+						AR_PHY_GAIN_2GHZ +
+						regChainOffset,
+						AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+						pModal->
+						xatten2Margin[i]);
+					REG_RMW_FIELD(ah,
+						AR_PHY_GAIN_2GHZ +
+						regChainOffset,
+						AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+						pModal->
+						xatten2Db[i]);
+				} else {
+					REG_WRITE(ah,
+						  AR_PHY_GAIN_2GHZ +
+						  regChainOffset,
+						  (REG_READ(ah,
+							    AR_PHY_GAIN_2GHZ +
+							    regChainOffset) &
+						   ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+						  | SM(pModal->
+						  bswMargin[i],
+						  AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+					REG_WRITE(ah,
+						  AR_PHY_GAIN_2GHZ +
+						  regChainOffset,
+						  (REG_READ(ah,
+							    AR_PHY_GAIN_2GHZ +
+							    regChainOffset) &
+						   ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+						  | SM(pModal->bswAtten[i],
+						  AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+				}
+			}
+			if (AR_SREV_9280_10_OR_LATER(ah)) {
+				REG_RMW_FIELD(ah,
+					      AR_PHY_RXGAIN +
+					      regChainOffset,
+					      AR9280_PHY_RXGAIN_TXRX_ATTEN,
+					      txRxAttenLocal);
+				REG_RMW_FIELD(ah,
+					      AR_PHY_RXGAIN +
+					      regChainOffset,
+					      AR9280_PHY_RXGAIN_TXRX_MARGIN,
+					      pModal->rxTxMarginCh[i]);
+			} else {
+				REG_WRITE(ah,
+					  AR_PHY_RXGAIN + regChainOffset,
+					  (REG_READ(ah,
+						    AR_PHY_RXGAIN +
+						    regChainOffset) &
+					   ~AR_PHY_RXGAIN_TXRX_ATTEN) |
+					  SM(txRxAttenLocal,
+					     AR_PHY_RXGAIN_TXRX_ATTEN));
+				REG_WRITE(ah,
+					  AR_PHY_GAIN_2GHZ +
+					  regChainOffset,
+					  (REG_READ(ah,
+						    AR_PHY_GAIN_2GHZ +
+						    regChainOffset) &
+					   ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+					  SM(pModal->rxTxMarginCh[i],
+					     AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+			}
+		}
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		if (IS_CHAN_2GHZ(chan)) {
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+						  AR_AN_RF2G1_CH0_OB,
+						  AR_AN_RF2G1_CH0_OB_S,
+						  pModal->ob);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+						  AR_AN_RF2G1_CH0_DB,
+						  AR_AN_RF2G1_CH0_DB_S,
+						  pModal->db);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+						  AR_AN_RF2G1_CH1_OB,
+						  AR_AN_RF2G1_CH1_OB_S,
+						  pModal->ob_ch1);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+						  AR_AN_RF2G1_CH1_DB,
+						  AR_AN_RF2G1_CH1_DB_S,
+						  pModal->db_ch1);
+		} else {
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+						  AR_AN_RF5G1_CH0_OB5,
+						  AR_AN_RF5G1_CH0_OB5_S,
+						  pModal->ob);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+						  AR_AN_RF5G1_CH0_DB5,
+						  AR_AN_RF5G1_CH0_DB5_S,
+						  pModal->db);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+						  AR_AN_RF5G1_CH1_OB5,
+						  AR_AN_RF5G1_CH1_OB5_S,
+						  pModal->ob_ch1);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+						  AR_AN_RF5G1_CH1_DB5,
+						  AR_AN_RF5G1_CH1_DB5_S,
+						  pModal->db_ch1);
+		}
+		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+					  AR_AN_TOP2_XPABIAS_LVL,
+					  AR_AN_TOP2_XPABIAS_LVL_S,
+					  pModal->xpaBiasLvl);
+		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+					  AR_AN_TOP2_LOCALBIAS,
+					  AR_AN_TOP2_LOCALBIAS_S,
+					  pModal->local_bias);
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ForceXPAon: %d\n",
+			pModal->force_xpaon);
+		REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+			      pModal->force_xpaon);
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+		      pModal->switchSettling);
+	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+		      pModal->adcDesiredSize);
+
+	if (!AR_SREV_9280_10_OR_LATER(ah))
+		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+			      AR_PHY_DESIRED_SZ_PGA,
+			      pModal->pgaDesiredSize);
+
+	REG_WRITE(ah, AR_PHY_RF_CTL4,
+		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+		  | SM(pModal->txEndToXpaOff,
+		       AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+		  | SM(pModal->txFrameToXpaOn,
+		       AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+		  | SM(pModal->txFrameToXpaOn,
+		       AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+		      pModal->txEndToRxOn);
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+			      pModal->thresh62);
+		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+			      AR_PHY_EXT_CCA0_THRESH62,
+			      pModal->thresh62);
+	} else {
+		REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+			      pModal->thresh62);
+		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+			      AR_PHY_EXT_CCA_THRESH62,
+			      pModal->thresh62);
+	}
+
+	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+			      AR_PHY_TX_END_DATA_START,
+			      pModal->txFrameToDataStart);
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+			      pModal->txFrameToPaOn);
+	}
+
+	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_3) {
+		if (IS_CHAN_HT40(chan))
+			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+				      AR_PHY_SETTLING_SWITCH,
+				      pModal->swSettleHt40);
+	}
+
+	return true;
+}
+
+int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+				    struct ath9k_channel *chan,
+				    u8 index, u16 *config)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	struct modal_eep_header *pModal =
+		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+	struct base_eep_header *pBase = &eep->baseEepHeader;
+
+	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;
+}
+
+u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+			       enum ieee80211_band freq_band)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	struct modal_eep_header *pModal =
+		&(eep->modalHeader[IEEE80211_BAND_5GHZ == freq_band]);
+	struct base_eep_header *pBase = &eep->baseEepHeader;
+	u8 num_ant_config;
+
+	num_ant_config = 1;
+
+	if (pBase->version >= 0x0E0D)
+		if (pModal->useAnt1)
+			num_ant_config += 1;
+
+	return num_ant_config;
+}
+
+u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep =
+		(struct ar5416_eeprom *) &ahp->ah_eeprom;
+	u16 spur_val = AR_NO_SPUR;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"Getting spur idx %d is2Ghz. %d val %x\n",
+		i, is2GHz, ah->ah_config.spurchans[i][is2GHz]);
+
+	switch (ah->ah_config.spurmode) {
+	case SPUR_DISABLE:
+		break;
+	case SPUR_ENABLE_IOCTL:
+		spur_val = ah->ah_config.spurchans[i][is2GHz];
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
+		break;
+	case SPUR_ENABLE_EEPROM:
+		spur_val = eep->modalHeader[is2GHz].spurChans[i].spurChan;
+		break;
+
+	}
+
+	return spur_val;
+}
+
+u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
+			enum eeprom_param param)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
+	struct modal_eep_header *pModal = eep->modalHeader;
+	struct base_eep_header *pBase = &eep->baseEepHeader;
+
+	switch (param) {
+	case EEP_NFTHRESH_5:
+		return -pModal[0].noiseFloorThreshCh[0];
+	case EEP_NFTHRESH_2:
+		return -pModal[1].noiseFloorThreshCh[0];
+	case AR_EEPROM_MAC(0):
+		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+	case AR_EEPROM_MAC(1):
+		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+	case AR_EEPROM_MAC(2):
+		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+	case EEP_REG_0:
+		return pBase->regDmn[0];
+	case EEP_REG_1:
+		return pBase->regDmn[1];
+	case EEP_OP_CAP:
+		return pBase->deviceCap;
+	case EEP_OP_MODE:
+		return pBase->opCapFlags;
+	case EEP_RF_SILENT:
+		return pBase->rfSilent;
+	case EEP_OB_5:
+		return pModal[0].ob;
+	case EEP_DB_5:
+		return pModal[0].db;
+	case EEP_OB_2:
+		return pModal[1].ob;
+	case EEP_DB_2:
+		return pModal[1].db;
+	case EEP_MINOR_REV:
+		return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+	case EEP_TX_MASK:
+		return pBase->txMask;
+	case EEP_RX_MASK:
+		return pBase->rxMask;
+	default:
+		return 0;
+	}
+}
+
+int ath9k_hw_eeprom_attach(struct ath_hal *ah)
+{
+	int status;
+
+	if (ath9k_hw_use_flash(ah))
+		ath9k_hw_flash_map(ah);
+
+	if (!ath9k_hw_fill_eeprom(ah))
+		return -EIO;
+
+	status = ath9k_hw_check_eeprom(ah);
+
+	return status;
+}
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 98bc25c..e05c9ef 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -23,183 +23,68 @@
 #include "phy.h"
 #include "initvals.h"
 
-static void ath9k_hw_iqcal_collect(struct ath_hal *ah);
-static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains);
-static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah);
-static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah,
-					   u8 numChains);
-static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah);
-static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah,
-					 u8 numChains);
-
 static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 };
-static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
 
-static const struct hal_percal_data iq_cal_multi_sample = {
-	IQ_MISMATCH_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_iqcal_collect,
-	ath9k_hw_iqcalibrate
-};
-static const struct hal_percal_data iq_cal_single_sample = {
-	IQ_MISMATCH_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_iqcal_collect,
-	ath9k_hw_iqcalibrate
-};
-static const struct hal_percal_data adc_gain_cal_multi_sample = {
-	ADC_GAIN_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_adc_gaincal_collect,
-	ath9k_hw_adc_gaincal_calibrate
-};
-static const struct hal_percal_data adc_gain_cal_single_sample = {
-	ADC_GAIN_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_adc_gaincal_collect,
-	ath9k_hw_adc_gaincal_calibrate
-};
-static const struct hal_percal_data adc_dc_cal_multi_sample = {
-	ADC_DC_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
-static const struct hal_percal_data adc_dc_cal_single_sample = {
-	ADC_DC_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
-static const struct hal_percal_data adc_init_dc_cal = {
-	ADC_DC_INIT_CAL,
-	MIN_CAL_SAMPLES,
-	INIT_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
+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;
 
-static struct ath9k_rate_table ar5416_11a_table = {
-	8,
-	{0},
-	{
-		{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
-		{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
-		{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
-		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
-		{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
-		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
-		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
-		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}
-	},
-};
+static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type);
+static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+			      enum ath9k_ht_macmode macmode);
+static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
+			      struct ar5416_eeprom *pEepData,
+			      u32 reg, u32 value);
+static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
+static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
 
-static struct ath9k_rate_table ar5416_11b_table = {
-	4,
-	{0},
-	{
-		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
-		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
-		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1},
-		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1}
-	},
-};
+/********************/
+/* Helper Functions */
+/********************/
 
-static struct ath9k_rate_table ar5416_11g_table = {
-	12,
-	{0},
-	{
-		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
-		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
-		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
-		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
+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];
+}
 
-		{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
-		{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
-		{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
-		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
-		{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
-		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
-		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
-		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}
-	},
-};
+static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
+{
+	struct ath9k_channel *chan = ah->ah_curchan;
 
-static struct ath9k_rate_table ar5416_11ng_table = {
-	28,
-	{0},
-	{
-		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
-		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
-		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
-		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
+	if (chan && IS_CHAN_HT40(chan))
+		return ath9k_hw_mac_usec(ah, clks) / 2;
+	else
+		return ath9k_hw_mac_usec(ah, clks);
+}
 
-		{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
-		{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
-		{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
-		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
-		{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
-		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
-		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
-		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8},
-		{true, PHY_HT, 6500, 0x80, 0x00, 0, 4},
-		{true, PHY_HT, 13000, 0x81, 0x00, 1, 6},
-		{true, PHY_HT, 19500, 0x82, 0x00, 2, 6},
-		{true, PHY_HT, 26000, 0x83, 0x00, 3, 8},
-		{true, PHY_HT, 39000, 0x84, 0x00, 4, 8},
-		{true, PHY_HT, 52000, 0x85, 0x00, 5, 8},
-		{true, PHY_HT, 58500, 0x86, 0x00, 6, 8},
-		{true, PHY_HT, 65000, 0x87, 0x00, 7, 8},
-		{true, PHY_HT, 13000, 0x88, 0x00, 8, 4},
-		{true, PHY_HT, 26000, 0x89, 0x00, 9, 6},
-		{true, PHY_HT, 39000, 0x8a, 0x00, 10, 6},
-		{true, PHY_HT, 52000, 0x8b, 0x00, 11, 8},
-		{true, PHY_HT, 78000, 0x8c, 0x00, 12, 8},
-		{true, PHY_HT, 104000, 0x8d, 0x00, 13, 8},
-		{true, PHY_HT, 117000, 0x8e, 0x00, 14, 8},
-		{true, PHY_HT, 130000, 0x8f, 0x00, 15, 8},
-	},
-};
+static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
+{
+	if (ah->ah_curchan != NULL)
+		return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
+			ah->ah_curchan)];
+	else
+		return usecs * CLOCK_RATE[ATH9K_MODE_11B];
+}
 
-static struct ath9k_rate_table ar5416_11na_table = {
-	24,
-	{0},
-	{
-		{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
-		{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
-		{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
-		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
-		{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
-		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
-		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
-		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4},
-		{true, PHY_HT, 6500, 0x80, 0x00, 0, 0},
-		{true, PHY_HT, 13000, 0x81, 0x00, 1, 2},
-		{true, PHY_HT, 19500, 0x82, 0x00, 2, 2},
-		{true, PHY_HT, 26000, 0x83, 0x00, 3, 4},
-		{true, PHY_HT, 39000, 0x84, 0x00, 4, 4},
-		{true, PHY_HT, 52000, 0x85, 0x00, 5, 4},
-		{true, PHY_HT, 58500, 0x86, 0x00, 6, 4},
-		{true, PHY_HT, 65000, 0x87, 0x00, 7, 4},
-		{true, PHY_HT, 13000, 0x88, 0x00, 8, 0},
-		{true, PHY_HT, 26000, 0x89, 0x00, 9, 2},
-		{true, PHY_HT, 39000, 0x8a, 0x00, 10, 2},
-		{true, PHY_HT, 52000, 0x8b, 0x00, 11, 4},
-		{true, PHY_HT, 78000, 0x8c, 0x00, 12, 4},
-		{true, PHY_HT, 104000, 0x8d, 0x00, 13, 4},
-		{true, PHY_HT, 117000, 0x8e, 0x00, 14, 4},
-		{true, PHY_HT, 130000, 0x8f, 0x00, 15, 4},
-	},
-};
+static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
+{
+	struct ath9k_channel *chan = ah->ah_curchan;
 
-static enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
-				       const struct ath9k_channel *chan)
+	if (chan && IS_CHAN_HT40(chan))
+		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_CCK(chan))
 		return ATH9K_MODE_11A;
@@ -208,10 +93,7 @@
 	return ATH9K_MODE_11A;
 }
 
-static bool ath9k_hw_wait(struct ath_hal *ah,
-			  u32 reg,
-			  u32 mask,
-			  u32 val)
+bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val)
 {
 	int i;
 
@@ -222,80 +104,12 @@
 		udelay(AH_TIME_QUANTUM);
 	}
 	DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
-		 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
-		 __func__, reg, REG_READ(ah, reg), mask, val);
+		"%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+		__func__, reg, REG_READ(ah, reg), mask, val);
+
 	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,
-			 "%s: cannot remap eeprom region \n", __func__);
-		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 void ath9k_hw_read_revisions(struct ath_hal *ah)
-{
-	u32 val;
-
-	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
-
-	if (val == 0xFF) {
-		val = REG_READ(ah, AR_SREV);
-
-		ah->ah_macVersion =
-			(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
-
-		ah->ah_macRev = MS(val, AR_SREV_REVISION2);
-		ah->ah_isPciExpress =
-			(val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
-
-	} else {
-		if (!AR_SREV_9100(ah))
-			ah->ah_macVersion = MS(val, AR_SREV_VERSION);
-
-		ah->ah_macRev = val & AR_SREV_REVISION;
-
-		if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
-			ah->ah_isPciExpress = true;
-	}
-}
-
 u32 ath9k_hw_reverse_bits(u32 val, u32 n)
 {
 	u32 retval;
@@ -308,6 +122,278 @@
 	return retval;
 }
 
+bool ath9k_get_channel_edges(struct ath_hal *ah,
+			     u16 flags, u16 *low,
+			     u16 *high)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+	if (flags & CHANNEL_5GHZ) {
+		*low = pCap->low_5ghz_chan;
+		*high = pCap->high_5ghz_chan;
+		return true;
+	}
+	if ((flags & CHANNEL_2GHZ)) {
+		*low = pCap->low_2ghz_chan;
+		*high = pCap->high_2ghz_chan;
+		return true;
+	}
+	return false;
+}
+
+u16 ath9k_hw_computetxtime(struct ath_hal *ah,
+			   const struct ath9k_rate_table *rates,
+			   u32 frameLen, u16 rateix,
+			   bool shortPreamble)
+{
+	u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+	u32 kbps;
+
+	kbps = rates->info[rateix].rateKbps;
+
+	if (kbps == 0)
+		return 0;
+
+	switch (rates->info[rateix].phy) {
+	case PHY_CCK:
+		phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+		if (shortPreamble && rates->info[rateix].shortPreamble)
+			phyTime >>= 1;
+		numBits = frameLen << 3;
+		txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+		break;
+	case PHY_OFDM:
+		if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
+			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME_QUARTER
+				+ OFDM_PREAMBLE_TIME_QUARTER
+				+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+		} else if (ah->ah_curchan &&
+			   IS_CHAN_HALF_RATE(ah->ah_curchan)) {
+			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME_HALF +
+				OFDM_PREAMBLE_TIME_HALF
+				+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
+		} else {
+			bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+				+ (numSymbols * OFDM_SYMBOL_TIME);
+		}
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
+			"%s: unknown phy %u (rate ix %u)\n", __func__,
+			rates->info[rateix].phy, rateix);
+		txTime = 0;
+		break;
+	}
+
+	return txTime;
+}
+
+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)
+{
+	int8_t extoff;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	if (!IS_CHAN_HT40(chan)) {
+		centers->ctl_center = centers->ext_center =
+			centers->synth_center = chan->channel;
+		return;
+	}
+
+	if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+	    (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+		centers->synth_center =
+			chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+		extoff = 1;
+	} else {
+		centers->synth_center =
+			chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+		extoff = -1;
+	}
+
+	centers->ctl_center =
+		centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+	centers->ext_center =
+		centers->synth_center + (extoff *
+			 ((ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
+			  HT40_CHANNEL_CENTER_SHIFT : 15));
+
+}
+
+/******************/
+/* Chip Revisions */
+/******************/
+
+static void ath9k_hw_read_revisions(struct ath_hal *ah)
+{
+	u32 val;
+
+	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+
+	if (val == 0xFF) {
+		val = REG_READ(ah, AR_SREV);
+		ah->ah_macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+		ah->ah_macRev = MS(val, AR_SREV_REVISION2);
+		ah->ah_isPciExpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+	} else {
+		if (!AR_SREV_9100(ah))
+			ah->ah_macVersion = MS(val, AR_SREV_VERSION);
+
+		ah->ah_macRev = val & AR_SREV_REVISION;
+
+		if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
+			ah->ah_isPciExpress = true;
+	}
+}
+
+static int ath9k_hw_get_radiorev(struct ath_hal *ah)
+{
+	u32 val;
+	int i;
+
+	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
+
+	for (i = 0; i < 8; i++)
+		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+
+	return ath9k_hw_reverse_bits(val, 8);
+}
+
+/************************************/
+/* HW Attach, Detach, Init Routines */
+/************************************/
+
+static void ath9k_hw_disablepcie(struct ath_hal *ah)
+{
+	if (!AR_SREV_9100(ah))
+		return;
+
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
+
+	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+static bool ath9k_hw_chip_test(struct ath_hal *ah)
+{
+	u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
+	u32 regHold[2];
+	u32 patternData[4] = { 0x55555555,
+			       0xaaaaaaaa,
+			       0x66666666,
+			       0x99999999 };
+	int i, j;
+
+	for (i = 0; i < 2; i++) {
+		u32 addr = regAddr[i];
+		u32 wrData, rdData;
+
+		regHold[i] = REG_READ(ah, addr);
+		for (j = 0; j < 0x100; j++) {
+			wrData = (j << 16) | j;
+			REG_WRITE(ah, addr, wrData);
+			rdData = REG_READ(ah, addr);
+			if (rdData != wrData) {
+				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+					"%s: address test failed "
+					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					__func__, addr, wrData, rdData);
+				return false;
+			}
+		}
+		for (j = 0; j < 4; j++) {
+			wrData = patternData[j];
+			REG_WRITE(ah, addr, wrData);
+			rdData = REG_READ(ah, addr);
+			if (wrData != rdData) {
+				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+					"%s: address test failed "
+					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					__func__, addr, wrData, rdData);
+				return false;
+			}
+		}
+		REG_WRITE(ah, regAddr[i], regHold[i]);
+	}
+	udelay(100);
+	return true;
+}
+
+static const char *ath9k_hw_devname(u16 devid)
+{
+	switch (devid) {
+	case AR5416_DEVID_PCI:
+	case AR5416_DEVID_PCIE:
+		return "Atheros 5416";
+	case AR9160_DEVID_PCI:
+		return "Atheros 9160";
+	case AR9280_DEVID_PCI:
+	case AR9280_DEVID_PCIE:
+		return "Atheros 9280";
+	}
+
+	return NULL;
+}
+
 static void ath9k_hw_set_defaults(struct ath_hal *ah)
 {
 	int i;
@@ -345,813 +431,9 @@
 		ah->ah_config.spurchans[i][1] = AR_NO_SPUR;
 	}
 
-	ah->ah_config.intr_mitigation = 0;
+	ah->ah_config.intr_mitigation = 1;
 }
 
-static void ath9k_hw_override_ini(struct ath_hal *ah,
-					 struct ath9k_channel *chan)
-{
-	if (!AR_SREV_5416_V20_OR_LATER(ah)
-	    || AR_SREV_9280_10_OR_LATER(ah))
-		return;
-
-	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
-}
-
-static void ath9k_hw_init_bb(struct ath_hal *ah,
-			     struct ath9k_channel *chan)
-{
-	u32 synthDelay;
-
-	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-	if (IS_CHAN_CCK(chan))
-		synthDelay = (4 * synthDelay) / 22;
-	else
-		synthDelay /= 10;
-
-	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-
-	udelay(synthDelay + BASE_ACTIVATE_DELAY);
-}
-
-static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
-					  enum ath9k_opmode opmode)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	ahp->ah_maskReg = AR_IMR_TXERR |
-		AR_IMR_TXURN |
-		AR_IMR_RXERR |
-		AR_IMR_RXORN |
-		AR_IMR_BCNMISC;
-
-	if (ahp->ah_intrMitigation)
-		ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
-	else
-		ahp->ah_maskReg |= AR_IMR_RXOK;
-
-	ahp->ah_maskReg |= AR_IMR_TXOK;
-
-	if (opmode == ATH9K_M_HOSTAP)
-		ahp->ah_maskReg |= AR_IMR_MIB;
-
-	REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
-	REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
-
-	if (!AR_SREV_9100(ah)) {
-		REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
-		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
-		REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
-	}
-}
-
-static void ath9k_hw_init_qos(struct ath_hal *ah)
-{
-	REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
-	REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
-
-	REG_WRITE(ah, AR_QOS_NO_ACK,
-		  SM(2, AR_QOS_NO_ACK_TWO_BIT) |
-		  SM(5, AR_QOS_NO_ACK_BIT_OFF) |
-		  SM(0, AR_QOS_NO_ACK_BYTE_OFF));
-
-	REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
-	REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
-}
-
-static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
-				      u32 reg,
-				      u32 mask,
-				      u32 shift,
-				      u32 val)
-{
-	u32 regVal;
-
-	regVal = REG_READ(ah, reg) & ~mask;
-	regVal |= (val << shift) & mask;
-
-	REG_WRITE(ah, reg, regVal);
-
-	if (ah->ah_config.analog_shiftreg)
-		udelay(100);
-
-	return;
-}
-
-static u8 ath9k_hw_get_num_ant_config(struct ath_hal_5416 *ahp,
-				      enum ieee80211_band freq_band)
-{
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[IEEE80211_BAND_5GHZ == freq_band]);
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-	u8 num_ant_config;
-
-	num_ant_config = 1;
-
-	if (pBase->version >= 0x0E0D)
-		if (pModal->useAnt1)
-			num_ant_config += 1;
-
-	return num_ant_config;
-}
-
-static int
-ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal_5416 *ahp,
-				struct ath9k_channel *chan,
-				u8 index,
-				u16 *config)
-{
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-
-	switch (index) {
-	case 0:
-		*config = pModal->antCtrlCommon & 0xFFFF;
-		return 0;
-	case 1:
-		if (pBase->version >= 0x0E0D) {
-			if (pModal->useAnt1) {
-				*config =
-				((pModal->antCtrlCommon & 0xFFFF0000) >> 16);
-				return 0;
-			}
-		}
-		break;
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static inline bool ath9k_hw_nvram_read(struct ath_hal *ah,
-				       u32 off,
-				       u16 *data)
-{
-	if (ath9k_hw_use_flash(ah))
-		return ath9k_hw_flash_read(ah, off, data);
-	else
-		return ath9k_hw_eeprom_read(ah, off, data);
-}
-
-static bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	u16 *eep_data;
-	int addr, ar5416_eep_start_loc = 0;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "%s: Reading from EEPROM, not flash\n", __func__);
-		ar5416_eep_start_loc = 256;
-	}
-	if (AR_SREV_9100(ah))
-		ar5416_eep_start_loc = 256;
-
-	eep_data = (u16 *) eep;
-	for (addr = 0;
-	     addr < sizeof(struct ar5416_eeprom) / sizeof(u16);
-	     addr++) {
-		if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
-					 eep_data)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-				 "%s: Unable to read eeprom region \n",
-				 __func__);
-			return false;
-		}
-		eep_data++;
-	}
-	return true;
-}
-
-/* XXX: Clean me up, make me more legible */
-static bool
-ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
-				 struct ath9k_channel *chan)
-{
-	struct modal_eep_header *pModal;
-	int i, regChainOffset;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	u8 txRxAttenLocal;
-	u16 ant_config;
-
-	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
-	txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
-
-	ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, 1, &ant_config);
-	REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		if (AR_SREV_9280(ah)) {
-			if (i >= 2)
-				break;
-		}
-
-		if (AR_SREV_5416_V20_OR_LATER(ah) &&
-		    (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
-		    && (i != 0))
-			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-		else
-			regChainOffset = i * 0x1000;
-
-		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
-			  pModal->antCtrlChain[i]);
-
-		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
-			  (REG_READ(ah,
-				    AR_PHY_TIMING_CTRL4(0) +
-				    regChainOffset) &
-			   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
-			  SM(pModal->iqCalICh[i],
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
-			  SM(pModal->iqCalQCh[i],
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
-		if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
-			if ((eep->baseEepHeader.version &
-			     AR5416_EEP_VER_MINOR_MASK) >=
-			    AR5416_EEP_MINOR_VER_3) {
-				txRxAttenLocal = pModal->txRxAttenCh[i];
-				if (AR_SREV_9280_10_OR_LATER(ah)) {
-					REG_RMW_FIELD(ah,
-						AR_PHY_GAIN_2GHZ +
-						regChainOffset,
-						AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
-						pModal->
-						bswMargin[i]);
-					REG_RMW_FIELD(ah,
-						AR_PHY_GAIN_2GHZ +
-						regChainOffset,
-						AR_PHY_GAIN_2GHZ_XATTEN1_DB,
-						pModal->
-						bswAtten[i]);
-					REG_RMW_FIELD(ah,
-						AR_PHY_GAIN_2GHZ +
-						regChainOffset,
-						AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
-						pModal->
-						xatten2Margin[i]);
-					REG_RMW_FIELD(ah,
-						AR_PHY_GAIN_2GHZ +
-						regChainOffset,
-						AR_PHY_GAIN_2GHZ_XATTEN2_DB,
-						pModal->
-						xatten2Db[i]);
-				} else {
-					REG_WRITE(ah,
-						  AR_PHY_GAIN_2GHZ +
-						  regChainOffset,
-						  (REG_READ(ah,
-							    AR_PHY_GAIN_2GHZ +
-							    regChainOffset) &
-						   ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
-						  | SM(pModal->
-						  bswMargin[i],
-						  AR_PHY_GAIN_2GHZ_BSW_MARGIN));
-					REG_WRITE(ah,
-						  AR_PHY_GAIN_2GHZ +
-						  regChainOffset,
-						  (REG_READ(ah,
-							    AR_PHY_GAIN_2GHZ +
-							    regChainOffset) &
-						   ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
-						  | SM(pModal->bswAtten[i],
-						  AR_PHY_GAIN_2GHZ_BSW_ATTEN));
-				}
-			}
-			if (AR_SREV_9280_10_OR_LATER(ah)) {
-				REG_RMW_FIELD(ah,
-					      AR_PHY_RXGAIN +
-					      regChainOffset,
-					      AR9280_PHY_RXGAIN_TXRX_ATTEN,
-					      txRxAttenLocal);
-				REG_RMW_FIELD(ah,
-					      AR_PHY_RXGAIN +
-					      regChainOffset,
-					      AR9280_PHY_RXGAIN_TXRX_MARGIN,
-					      pModal->rxTxMarginCh[i]);
-			} else {
-				REG_WRITE(ah,
-					  AR_PHY_RXGAIN + regChainOffset,
-					  (REG_READ(ah,
-						    AR_PHY_RXGAIN +
-						    regChainOffset) &
-					   ~AR_PHY_RXGAIN_TXRX_ATTEN) |
-					  SM(txRxAttenLocal,
-					     AR_PHY_RXGAIN_TXRX_ATTEN));
-				REG_WRITE(ah,
-					  AR_PHY_GAIN_2GHZ +
-					  regChainOffset,
-					  (REG_READ(ah,
-						    AR_PHY_GAIN_2GHZ +
-						    regChainOffset) &
-					   ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
-					  SM(pModal->rxTxMarginCh[i],
-					     AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
-			}
-		}
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		if (IS_CHAN_2GHZ(chan)) {
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
-						  AR_AN_RF2G1_CH0_OB,
-						  AR_AN_RF2G1_CH0_OB_S,
-						  pModal->ob);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
-						  AR_AN_RF2G1_CH0_DB,
-						  AR_AN_RF2G1_CH0_DB_S,
-						  pModal->db);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
-						  AR_AN_RF2G1_CH1_OB,
-						  AR_AN_RF2G1_CH1_OB_S,
-						  pModal->ob_ch1);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
-						  AR_AN_RF2G1_CH1_DB,
-						  AR_AN_RF2G1_CH1_DB_S,
-						  pModal->db_ch1);
-		} else {
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
-						  AR_AN_RF5G1_CH0_OB5,
-						  AR_AN_RF5G1_CH0_OB5_S,
-						  pModal->ob);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
-						  AR_AN_RF5G1_CH0_DB5,
-						  AR_AN_RF5G1_CH0_DB5_S,
-						  pModal->db);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
-						  AR_AN_RF5G1_CH1_OB5,
-						  AR_AN_RF5G1_CH1_OB5_S,
-						  pModal->ob_ch1);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
-						  AR_AN_RF5G1_CH1_DB5,
-						  AR_AN_RF5G1_CH1_DB5_S,
-						  pModal->db_ch1);
-		}
-		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
-					  AR_AN_TOP2_XPABIAS_LVL,
-					  AR_AN_TOP2_XPABIAS_LVL_S,
-					  pModal->xpaBiasLvl);
-		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
-					  AR_AN_TOP2_LOCALBIAS,
-					  AR_AN_TOP2_LOCALBIAS_S,
-					  pModal->local_bias);
-		DPRINTF(ah->ah_sc, ATH_DBG_ANY, "ForceXPAon: %d\n",
-			pModal->force_xpaon);
-		REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
-			      pModal->force_xpaon);
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
-		      pModal->switchSettling);
-	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
-		      pModal->adcDesiredSize);
-
-	if (!AR_SREV_9280_10_OR_LATER(ah))
-		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
-			      AR_PHY_DESIRED_SZ_PGA,
-			      pModal->pgaDesiredSize);
-
-	REG_WRITE(ah, AR_PHY_RF_CTL4,
-		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
-		  | SM(pModal->txEndToXpaOff,
-		       AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
-		  | SM(pModal->txFrameToXpaOn,
-		       AR_PHY_RF_CTL4_FRAME_XPAA_ON)
-		  | SM(pModal->txFrameToXpaOn,
-		       AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
-	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
-		      pModal->txEndToRxOn);
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
-			      pModal->thresh62);
-		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
-			      AR_PHY_EXT_CCA0_THRESH62,
-			      pModal->thresh62);
-	} else {
-		REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
-			      pModal->thresh62);
-		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
-			      AR_PHY_EXT_CCA_THRESH62,
-			      pModal->thresh62);
-	}
-
-	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
-			      AR_PHY_TX_END_DATA_START,
-			      pModal->txFrameToDataStart);
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
-			      pModal->txFrameToPaOn);
-	}
-
-	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_3) {
-		if (IS_CHAN_HT40(chan))
-			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
-				      AR_PHY_SETTLING_SWITCH,
-				      pModal->swSettleHt40);
-	}
-
-	return true;
-}
-
-static int ath9k_hw_check_eeprom(struct ath_hal *ah)
-{
-	u32 sum = 0, el;
-	u16 *eepdata;
-	int i;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	bool need_swap = false;
-	struct ar5416_eeprom *eep =
-		(struct ar5416_eeprom *) &ahp->ah_eeprom;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		u16 magic, magic2;
-		int addr;
-
-		if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
-					&magic)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-				 "%s: Reading Magic # failed\n", __func__);
-			return false;
-		}
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: Read Magic = 0x%04X\n",
-			 __func__, magic);
-
-		if (magic != AR5416_EEPROM_MAGIC) {
-			magic2 = swab16(magic);
-
-			if (magic2 == AR5416_EEPROM_MAGIC) {
-				need_swap = true;
-				eepdata = (u16 *) (&ahp->ah_eeprom);
-
-				for (addr = 0;
-				     addr <
-					     sizeof(struct ar5416_eeprom) /
-					     sizeof(u16); addr++) {
-					u16 temp;
-
-					temp = swab16(*eepdata);
-					*eepdata = temp;
-					eepdata++;
-
-					DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-						 "0x%04X  ", *eepdata);
-					if (((addr + 1) % 6) == 0)
-						DPRINTF(ah->ah_sc,
-							 ATH_DBG_EEPROM,
-							 "\n");
-				}
-			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-					 "Invalid EEPROM Magic. "
-					"endianness missmatch.\n");
-				return -EINVAL;
-			}
-		}
-	}
-	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		 need_swap ? "True" : "False");
-
-	if (need_swap)
-		el = swab16(ahp->ah_eeprom.baseEepHeader.length);
-	else
-		el = ahp->ah_eeprom.baseEepHeader.length;
-
-	if (el > sizeof(struct ar5416_eeprom))
-		el = sizeof(struct ar5416_eeprom) / sizeof(u16);
-	else
-		el = el / sizeof(u16);
-
-	eepdata = (u16 *) (&ahp->ah_eeprom);
-
-	for (i = 0; i < el; i++)
-		sum ^= *eepdata++;
-
-	if (need_swap) {
-		u32 integer, j;
-		u16 word;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "EEPROM Endianness is not native.. Changing \n");
-
-		word = swab16(eep->baseEepHeader.length);
-		eep->baseEepHeader.length = word;
-
-		word = swab16(eep->baseEepHeader.checksum);
-		eep->baseEepHeader.checksum = word;
-
-		word = swab16(eep->baseEepHeader.version);
-		eep->baseEepHeader.version = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[0]);
-		eep->baseEepHeader.regDmn[0] = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[1]);
-		eep->baseEepHeader.regDmn[1] = word;
-
-		word = swab16(eep->baseEepHeader.rfSilent);
-		eep->baseEepHeader.rfSilent = word;
-
-		word = swab16(eep->baseEepHeader.blueToothOptions);
-		eep->baseEepHeader.blueToothOptions = word;
-
-		word = swab16(eep->baseEepHeader.deviceCap);
-		eep->baseEepHeader.deviceCap = word;
-
-		for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
-			struct modal_eep_header *pModal =
-				&eep->modalHeader[j];
-			integer = swab32(pModal->antCtrlCommon);
-			pModal->antCtrlCommon = integer;
-
-			for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-				integer = swab32(pModal->antCtrlChain[i]);
-				pModal->antCtrlChain[i] = integer;
-			}
-
-			for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
-				word = swab16(pModal->spurChans[i].spurChan);
-				pModal->spurChans[i].spurChan = word;
-			}
-		}
-	}
-
-	if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
-	    ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
-			 sum, ar5416_get_eep_ver(ahp));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static bool ath9k_hw_chip_test(struct ath_hal *ah)
-{
-	u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
-	u32 regHold[2];
-	u32 patternData[4] = { 0x55555555,
-				     0xaaaaaaaa,
-				     0x66666666,
-				     0x99999999 };
-	int i, j;
-
-	for (i = 0; i < 2; i++) {
-		u32 addr = regAddr[i];
-		u32 wrData, rdData;
-
-		regHold[i] = REG_READ(ah, addr);
-		for (j = 0; j < 0x100; j++) {
-			wrData = (j << 16) | j;
-			REG_WRITE(ah, addr, wrData);
-			rdData = REG_READ(ah, addr);
-			if (rdData != wrData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-				 "%s: address test failed "
-				"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
-				 __func__, addr, wrData, rdData);
-				return false;
-			}
-		}
-		for (j = 0; j < 4; j++) {
-			wrData = patternData[j];
-			REG_WRITE(ah, addr, wrData);
-			rdData = REG_READ(ah, addr);
-			if (wrData != rdData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-				 "%s: address test failed "
-				"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
-				 __func__, addr, wrData, rdData);
-				return false;
-			}
-		}
-		REG_WRITE(ah, regAddr[i], regHold[i]);
-	}
-	udelay(100);
-	return true;
-}
-
-u32 ath9k_hw_getrxfilter(struct ath_hal *ah)
-{
-	u32 bits = REG_READ(ah, AR_RX_FILTER);
-	u32 phybits = REG_READ(ah, AR_PHY_ERR);
-
-	if (phybits & AR_PHY_ERR_RADAR)
-		bits |= ATH9K_RX_FILTER_PHYRADAR;
-	if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
-		bits |= ATH9K_RX_FILTER_PHYERR;
-	return bits;
-}
-
-void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits)
-{
-	u32 phybits;
-
-	REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
-	phybits = 0;
-	if (bits & ATH9K_RX_FILTER_PHYRADAR)
-		phybits |= AR_PHY_ERR_RADAR;
-	if (bits & ATH9K_RX_FILTER_PHYERR)
-		phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
-	REG_WRITE(ah, AR_PHY_ERR, phybits);
-
-	if (phybits)
-		REG_WRITE(ah, AR_RXCFG,
-			  REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
-	else
-		REG_WRITE(ah, AR_RXCFG,
-			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
-}
-
-bool ath9k_hw_setcapability(struct ath_hal *ah,
-			    enum ath9k_capability_type type,
-			    u32 capability,
-			    u32 setting,
-			    int *status)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 v;
-
-	switch (type) {
-	case ATH9K_CAP_TKIP_MIC:
-		if (setting)
-			ahp->ah_staId1Defaults |=
-				AR_STA_ID1_CRPT_MIC_ENABLE;
-		else
-			ahp->ah_staId1Defaults &=
-				~AR_STA_ID1_CRPT_MIC_ENABLE;
-		return true;
-	case ATH9K_CAP_DIVERSITY:
-		v = REG_READ(ah, AR_PHY_CCK_DETECT);
-		if (setting)
-			v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-		else
-			v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-		REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-		return true;
-	case ATH9K_CAP_MCAST_KEYSRCH:
-		if (setting)
-			ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
-		else
-			ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
-		return true;
-	case ATH9K_CAP_TSF_ADJUST:
-		if (setting)
-			ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
-		else
-			ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
-		return true;
-	default:
-		return false;
-	}
-}
-
-void ath9k_hw_dmaRegDump(struct ath_hal *ah)
-{
-	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
-	int qcuOffset = 0, dcuOffset = 0;
-	u32 *qcuBase = &val[0], *dcuBase = &val[4];
-	int i;
-
-	REG_WRITE(ah, AR_MACMISC,
-		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
-		   (AR_MACMISC_MISC_OBS_BUS_1 <<
-		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "Raw DMA Debug values:\n");
-	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
-		if (i % 4 == 0)
-			DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
-
-		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "%d: %08x ", i, val[i]);
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n\n");
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
-
-	for (i = 0; i < ATH9K_NUM_QUEUES;
-	     i++, qcuOffset += 4, dcuOffset += 5) {
-		if (i == 8) {
-			qcuOffset = 0;
-			qcuBase++;
-		}
-
-		if (i == 6) {
-			dcuOffset = 0;
-			dcuBase++;
-		}
-
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			 "%2d          %2x      %1x     %2x           %2x\n",
-			 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
-			 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset +
-							     3),
-			 val[2] & (0x7 << (i * 3)) >> (i * 3),
-			 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
-		 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "qcu_complete state: %2x    dcu_complete state:     %2x\n",
-		 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "dcu_arb state:      %2x    dcu_fp state:           %2x\n",
-		 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
-		 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
-		 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		 "txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
-		 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "pcu observe 0x%x \n",
-		REG_READ(ah, AR_OBS_BUS_1));
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		"AR_CR 0x%x \n", REG_READ(ah, AR_CR));
-}
-
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
-					u32 *rxc_pcnt,
-					u32 *rxf_pcnt,
-					u32 *txf_pcnt)
-{
-	static u32 cycles, rx_clear, rx_frame, tx_frame;
-	u32 good = 1;
-
-	u32 rc = REG_READ(ah, AR_RCCNT);
-	u32 rf = REG_READ(ah, AR_RFCNT);
-	u32 tf = REG_READ(ah, AR_TFCNT);
-	u32 cc = REG_READ(ah, AR_CCCNT);
-
-	if (cycles == 0 || cycles > cc) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: cycle counter wrap. ExtBusy = 0\n",
-			 __func__);
-		good = 0;
-	} else {
-		u32 cc_d = cc - cycles;
-		u32 rc_d = rc - rx_clear;
-		u32 rf_d = rf - rx_frame;
-		u32 tf_d = tf - tx_frame;
-
-		if (cc_d != 0) {
-			*rxc_pcnt = rc_d * 100 / cc_d;
-			*rxf_pcnt = rf_d * 100 / cc_d;
-			*txf_pcnt = tf_d * 100 / cc_d;
-		} else {
-			good = 0;
-		}
-	}
-
-	cycles = cc;
-	rx_frame = rf;
-	rx_clear = rc;
-	tx_frame = tf;
-
-	return good;
-}
-
-void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
-{
-	u32 macmode;
-
-	if (mode == ATH9K_HT_MACMODE_2040 &&
-	    !ah->ah_config.cwm_ignore_extcca)
-		macmode = AR_2040_JOINED_RX_CLEAR;
-	else
-		macmode = 0;
-
-	REG_WRITE(ah, AR_2040_MODE, macmode);
-}
-
-static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
-{
-	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-}
-
-
 static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
 					      struct ath_softc *sc,
 					      void __iomem *mem,
@@ -1165,20 +447,17 @@
 	ahp = kzalloc(sizeof(struct ath_hal_5416), GFP_KERNEL);
 	if (ahp == NULL) {
 		DPRINTF(sc, ATH_DBG_FATAL,
-			 "%s: cannot allocate memory for state block\n",
-			 __func__);
+			"%s: cannot allocate memory for state block\n",
+			__func__);
 		*status = -ENOMEM;
 		return NULL;
 	}
 
 	ah = &ahp->ah;
-
 	ah->ah_sc = sc;
 	ah->ah_sh = mem;
-
 	ah->ah_magic = AR5416_MAGIC;
 	ah->ah_countryCode = CTRY_DEFAULT;
-
 	ah->ah_devid = devid;
 	ah->ah_subvendorid = 0;
 
@@ -1190,12 +469,10 @@
 
 	ah->ah_powerLimit = MAX_RATE_POWER;
 	ah->ah_tpScale = ATH9K_TP_SCALE_MAX;
-
 	ahp->ah_atimWindow = 0;
 	ahp->ah_diversityControl = ah->ah_config.diversity_control;
 	ahp->ah_antennaSwitchSwap =
 		ah->ah_config.antenna_switch_swap;
-
 	ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
 	ahp->ah_beaconInterval = 100;
 	ahp->ah_enable32kHzClock = DONT_USE_32KHZ;
@@ -1210,163 +487,6 @@
 	return ahp;
 }
 
-static int ath9k_hw_eeprom_attach(struct ath_hal *ah)
-{
-	int status;
-
-	if (ath9k_hw_use_flash(ah))
-		ath9k_hw_flash_map(ah);
-
-	if (!ath9k_hw_fill_eeprom(ah))
-		return -EIO;
-
-	status = ath9k_hw_check_eeprom(ah);
-
-	return status;
-}
-
-u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
-			      enum eeprom_param param)
-{
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	struct modal_eep_header *pModal = eep->modalHeader;
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-
-	switch (param) {
-	case EEP_NFTHRESH_5:
-		return -pModal[0].noiseFloorThreshCh[0];
-	case EEP_NFTHRESH_2:
-		return -pModal[1].noiseFloorThreshCh[0];
-	case AR_EEPROM_MAC(0):
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
-	case AR_EEPROM_MAC(1):
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
-	case AR_EEPROM_MAC(2):
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
-	case EEP_REG_0:
-		return pBase->regDmn[0];
-	case EEP_REG_1:
-		return pBase->regDmn[1];
-	case EEP_OP_CAP:
-		return pBase->deviceCap;
-	case EEP_OP_MODE:
-		return pBase->opCapFlags;
-	case EEP_RF_SILENT:
-		return pBase->rfSilent;
-	case EEP_OB_5:
-		return pModal[0].ob;
-	case EEP_DB_5:
-		return pModal[0].db;
-	case EEP_OB_2:
-		return pModal[1].ob;
-	case EEP_DB_2:
-		return pModal[1].db;
-	case EEP_MINOR_REV:
-		return pBase->version & AR5416_EEP_VER_MINOR_MASK;
-	case EEP_TX_MASK:
-		return pBase->txMask;
-	case EEP_RX_MASK:
-		return pBase->rxMask;
-	default:
-		return 0;
-	}
-}
-
-static int ath9k_hw_get_radiorev(struct ath_hal *ah)
-{
-	u32 val;
-	int i;
-
-	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
-	for (i = 0; i < 8; i++)
-		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
-	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
-	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
-	return ath9k_hw_reverse_bits(val, 8);
-}
-
-static int ath9k_hw_init_macaddr(struct ath_hal *ah)
-{
-	u32 sum;
-	int i;
-	u16 eeval;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	DECLARE_MAC_BUF(mac);
-
-	sum = 0;
-	for (i = 0; i < 3; i++) {
-		eeval = ath9k_hw_get_eeprom(ahp, AR_EEPROM_MAC(i));
-		sum += eeval;
-		ahp->ah_macaddr[2 * i] = eeval >> 8;
-		ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
-	}
-	if (sum == 0 || sum == 0xffff * 3) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "%s: mac address read failed: %s\n", __func__,
-			 print_mac(mac, ahp->ah_macaddr));
-		return -EADDRNOTAVAIL;
-	}
-
-	return 0;
-}
-
-static inline int16_t ath9k_hw_interpolate(u16 target,
-					   u16 srcLeft,
-					   u16 srcRight,
-					   int16_t targetLeft,
-					   int16_t targetRight)
-{
-	int16_t rv;
-
-	if (srcRight == srcLeft) {
-		rv = targetLeft;
-	} else {
-		rv = (int16_t) (((target - srcLeft) * targetRight +
-				 (srcRight - target) * targetLeft) /
-				(srcRight - srcLeft));
-	}
-	return rv;
-}
-
-static inline u16 ath9k_hw_fbin2freq(u8 fbin,
-					   bool is2GHz)
-{
-
-	if (fbin == AR5416_BCHAN_UNUSED)
-		return fbin;
-
-	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
-}
-
-static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah,
-					       u16 i,
-					       bool is2GHz)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416_eeprom *eep =
-		(struct ar5416_eeprom *) &ahp->ah_eeprom;
-	u16 spur_val = AR_NO_SPUR;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		 "Getting spur idx %d is2Ghz. %d val %x\n",
-		 i, is2GHz, ah->ah_config.spurchans[i][is2GHz]);
-
-	switch (ah->ah_config.spurmode) {
-	case SPUR_DISABLE:
-		break;
-	case SPUR_ENABLE_IOCTL:
-		spur_val = ah->ah_config.spurchans[i][is2GHz];
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			 "Getting spur val from new loc. %d\n", spur_val);
-		break;
-	case SPUR_ENABLE_EEPROM:
-		spur_val = eep->modalHeader[is2GHz].spurChans[i].spurChan;
-		break;
-
-	}
-	return spur_val;
-}
-
 static int ath9k_hw_rfattach(struct ath_hal *ah)
 {
 	bool rfStatus = false;
@@ -1375,8 +495,8 @@
 	rfStatus = ath9k_hw_init_rf(ah, &ecode);
 	if (!rfStatus) {
 		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			 "%s: RF setup failed, status %u\n", __func__,
-			 ecode);
+			"%s: RF setup failed, status %u\n", __func__,
+			ecode);
 		return ecode;
 	}
 
@@ -1401,9 +521,9 @@
 		break;
 	default:
 		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: 5G Radio Chip Rev 0x%02X is not "
+			"%s: 5G Radio Chip Rev 0x%02X is not "
 			"supported by this driver\n",
-			 __func__, ah->ah_analog5GhzRev);
+			__func__, ah->ah_analog5GhzRev);
 		return -EOPNOTSUPP;
 	}
 
@@ -1412,1482 +532,37 @@
 	return 0;
 }
 
-static void ath9k_hw_init_pll(struct ath_hal *ah,
-			      struct ath9k_channel *chan)
+static int ath9k_hw_init_macaddr(struct ath_hal *ah)
 {
-	u32 pll;
-
-	if (AR_SREV_9100(ah)) {
-		if (chan && IS_CHAN_5GHZ(chan))
-			pll = 0x1450;
-		else
-			pll = 0x1458;
-	} else {
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan)) {
-				pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-
-
-				if (AR_SREV_9280_20(ah)) {
-					if (((chan->channel % 20) == 0)
-					    || ((chan->channel % 10) == 0))
-						pll = 0x2850;
-					else
-						pll = 0x142c;
-				}
-			} else {
-				pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-			}
-
-		} else if (AR_SREV_9160_10_OR_LATER(ah)) {
-
-			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan))
-				pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
-			else
-				pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
-		} else {
-			pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan))
-				pll |= SM(0xa, AR_RTC_PLL_DIV);
-			else
-				pll |= SM(0xb, AR_RTC_PLL_DIV);
-		}
-	}
-	REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
-
-	udelay(RTC_PLL_SETTLE_DELAY);
-
-	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
-}
-
-static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
-			      enum ath9k_ht_macmode macmode)
-{
-	u32 phymode;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
-		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
-
-	if (IS_CHAN_HT40(chan)) {
-		phymode |= AR_PHY_FC_DYN2040_EN;
-
-		if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-		    (chan->chanmode == CHANNEL_G_HT40PLUS))
-			phymode |= AR_PHY_FC_DYN2040_PRI_CH;
-
-		if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
-			phymode |= AR_PHY_FC_DYN2040_EXT_CH;
-	}
-	REG_WRITE(ah, AR_PHY_TURBO, phymode);
-
-	ath9k_hw_set11nmac2040(ah, macmode);
-
-	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
-	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
-}
-
-static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
-{
-	u32 val;
-
-	val = REG_READ(ah, AR_STA_ID1);
-	val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
-	switch (opmode) {
-	case ATH9K_M_HOSTAP:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
-			  | AR_STA_ID1_KSRCH_MODE);
-		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
-		break;
-	case ATH9K_M_IBSS:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
-			  | AR_STA_ID1_KSRCH_MODE);
-		REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
-		break;
-	case ATH9K_M_STA:
-	case ATH9K_M_MONITOR:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
-		break;
-	}
-}
-
-static void
-ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
-{
-	u32 rfMode = 0;
-
-	if (chan == NULL)
-		return;
-
-	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
-		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
-
-	if (!AR_SREV_9280_10_OR_LATER(ah))
-		rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ :
-			AR_PHY_MODE_RF2GHZ;
-
-	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
-		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-
-	REG_WRITE(ah, AR_PHY_MODE, rfMode);
-}
-
-static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
-{
-	u32 rst_flags;
-	u32 tmpReg;
-
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
-		  AR_RTC_FORCE_WAKE_ON_INT);
-
-	if (AR_SREV_9100(ah)) {
-		rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
-			AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
-	} else {
-		tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-		if (tmpReg &
-		    (AR_INTR_SYNC_LOCAL_TIMEOUT |
-		     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-		} else {
-			REG_WRITE(ah, AR_RC, AR_RC_AHB);
-		}
-
-		rst_flags = AR_RTC_RC_MAC_WARM;
-		if (type == ATH9K_RESET_COLD)
-			rst_flags |= AR_RTC_RC_MAC_COLD;
-	}
-
-	REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
-	udelay(50);
-
-	REG_WRITE(ah, (u16) (AR_RTC_RC), 0);
-	if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			"%s: RTC stuck in MAC reset\n",
-			__func__);
-		return false;
-	}
-
-	if (!AR_SREV_9100(ah))
-		REG_WRITE(ah, AR_RC, 0);
-
-	ath9k_hw_init_pll(ah, NULL);
-
-	if (AR_SREV_9100(ah))
-		udelay(50);
-
-	return true;
-}
-
-static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
-{
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
-		  AR_RTC_FORCE_WAKE_ON_INT);
-
-	REG_WRITE(ah, (u16) (AR_RTC_RESET), 0);
-	REG_WRITE(ah, (u16) (AR_RTC_RESET), 1);
-
-	if (!ath9k_hw_wait(ah,
-			   AR_RTC_STATUS,
-			   AR_RTC_STATUS_M,
-			   AR_RTC_STATUS_ON)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: RTC not waking up\n",
-			 __func__);
-		return false;
-	}
-
-	ath9k_hw_read_revisions(ah);
-
-	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
-}
-
-static bool ath9k_hw_set_reset_reg(struct ath_hal *ah,
-				   u32 type)
-{
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE,
-		  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
-
-	switch (type) {
-	case ATH9K_RESET_POWER_ON:
-		return ath9k_hw_set_reset_power_on(ah);
-		break;
-	case ATH9K_RESET_WARM:
-	case ATH9K_RESET_COLD:
-		return ath9k_hw_set_reset(ah, type);
-		break;
-	default:
-		return false;
-	}
-}
-
-static
-struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
-					  struct ath9k_channel *chan)
-{
-	if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: invalid channel %u/0x%x; not marked as "
-			 "2GHz or 5GHz\n", __func__, chan->channel,
-			 chan->channelFlags);
-		return NULL;
-	}
-
-	if (!IS_CHAN_OFDM(chan) &&
-	      !IS_CHAN_CCK(chan) &&
-	      !IS_CHAN_HT20(chan) &&
-	      !IS_CHAN_HT40(chan)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			"%s: invalid channel %u/0x%x; not marked as "
-			"OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
-			__func__, chan->channel, chan->channelFlags);
-		return NULL;
-	}
-
-	return ath9k_regd_check_channel(ah, chan);
-}
-
-static inline bool
-ath9k_hw_get_lower_upper_index(u8 target,
-			       u8 *pList,
-			       u16 listSize,
-			       u16 *indexL,
-			       u16 *indexR)
-{
-	u16 i;
-
-	if (target <= pList[0]) {
-		*indexL = *indexR = 0;
-		return true;
-	}
-	if (target >= pList[listSize - 1]) {
-		*indexL = *indexR = (u16) (listSize - 1);
-		return true;
-	}
-
-	for (i = 0; i < listSize - 1; i++) {
-		if (pList[i] == target) {
-			*indexL = *indexR = i;
-			return true;
-		}
-		if (target < pList[i + 1]) {
-			*indexL = i;
-			*indexR = (u16) (i + 1);
-			return false;
-		}
-	}
-	return false;
-}
-
-static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
-{
-	int16_t nfval;
-	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
-	int i, j;
-
-	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
-		sort[i] = nfCalBuffer[i];
-
-	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
-		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
-			if (sort[j] > sort[j - 1]) {
-				nfval = sort[j];
-				sort[j] = sort[j - 1];
-				sort[j - 1] = nfval;
-			}
-		}
-	}
-	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
-
-	return nfval;
-}
-
-static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
-					      int16_t *nfarray)
-{
+	u32 sum;
 	int i;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
-
-		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
-			h[i].currIndex = 0;
-
-		if (h[i].invalidNFcount > 0) {
-			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE
-			    || nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
-				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
-			} else {
-				h[i].invalidNFcount--;
-				h[i].privNF = nfarray[i];
-			}
-		} else {
-			h[i].privNF =
-				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
-		}
-	}
-	return;
-}
-
-static void ar5416GetNoiseFloor(struct ath_hal *ah,
-				int16_t nfarray[NUM_NF_READINGS])
-{
-	int16_t nf;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		 "NF calibrated [ctl] [chain 0] is %d\n", nf);
-	nfarray[0] = nf;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
-			AR9280_PHY_CH1_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
-			AR_PHY_CH1_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-		 "NF calibrated [ctl] [chain 1] is %d\n", nf);
-	nfarray[1] = nf;
-
-	if (!AR_SREV_9280(ah)) {
-		nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
-			AR_PHY_CH2_MINCCA_PWR);
-		if (nf & 0x100)
-			nf = 0 - ((nf ^ 0x1ff) + 1);
-		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-			 "NF calibrated [ctl] [chain 2] is %d\n", nf);
-		nfarray[2] = nf;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
-			AR9280_PHY_EXT_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
-			AR_PHY_EXT_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-		 "NF calibrated [ext] [chain 0] is %d\n", nf);
-	nfarray[3] = nf;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
-			AR9280_PHY_CH1_EXT_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
-			AR_PHY_CH1_EXT_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		 "NF calibrated [ext] [chain 1] is %d\n", nf);
-	nfarray[4] = nf;
-
-	if (!AR_SREV_9280(ah)) {
-		nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
-			AR_PHY_CH2_EXT_MINCCA_PWR);
-		if (nf & 0x100)
-			nf = 0 - ((nf ^ 0x1ff) + 1);
-		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-			 "NF calibrated [ext] [chain 2] is %d\n", nf);
-		nfarray[5] = nf;
-	}
-}
-
-static bool
-getNoiseFloorThresh(struct ath_hal *ah,
-		    const struct ath9k_channel *chan,
-		    int16_t *nft)
-{
+	u16 eeval;
 	struct ath_hal_5416 *ahp = AH5416(ah);
 
-	switch (chan->chanmode) {
-	case CHANNEL_A:
-	case CHANNEL_A_HT20:
-	case CHANNEL_A_HT40PLUS:
-	case CHANNEL_A_HT40MINUS:
-		*nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_5);
-		break;
-	case CHANNEL_B:
-	case CHANNEL_G:
-	case CHANNEL_G_HT20:
-	case CHANNEL_G_HT40PLUS:
-	case CHANNEL_G_HT40MINUS:
-		*nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_2);
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: invalid channel flags 0x%x\n", __func__,
-			 chan->channelFlags);
-		return false;
+	sum = 0;
+	for (i = 0; i < 3; i++) {
+		eeval = ath9k_hw_get_eeprom(ah, AR_EEPROM_MAC(i));
+		sum += eeval;
+		ahp->ah_macaddr[2 * i] = eeval >> 8;
+		ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
 	}
-	return true;
-}
-
-static void ath9k_hw_start_nfcal(struct ath_hal *ah)
-{
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-}
-
-static void
-ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
-{
-	struct ath9k_nfcal_hist *h;
-	int i, j;
-	int32_t val;
-	const u32 ar5416_cca_regs[6] = {
-		AR_PHY_CCA,
-		AR_PHY_CH1_CCA,
-		AR_PHY_CH2_CCA,
-		AR_PHY_EXT_CCA,
-		AR_PHY_CH1_EXT_CCA,
-		AR_PHY_CH2_EXT_CCA
-	};
-	u8 chainmask;
-
-	if (AR_SREV_9280(ah))
-		chainmask = 0x1B;
-	else
-		chainmask = 0x3F;
-
-#ifdef ATH_NF_PER_CHAN
-	h = chan->nfCalHist;
-#else
-	h = ah->nfCalHist;
-#endif
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
+	if (sum == 0 || sum == 0xffff * 3) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"%s: mac address read failed: %pM\n", __func__,
+			ahp->ah_macaddr);
+		return -EADDRNOTAVAIL;
 	}
 
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-
-	for (j = 0; j < 1000; j++) {
-		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
-		     AR_PHY_AGC_CONTROL_NF) == 0)
-			break;
-		udelay(10);
-	}
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (-50) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
-	}
-}
-
-static int16_t ath9k_hw_getnf(struct ath_hal *ah,
-			      struct ath9k_channel *chan)
-{
-	int16_t nf, nfThresh;
-	int16_t nfarray[NUM_NF_READINGS] = { 0 };
-	struct ath9k_nfcal_hist *h;
-	u8 chainmask;
-
-	if (AR_SREV_9280(ah))
-		chainmask = 0x1B;
-	else
-		chainmask = 0x3F;
-
-	chan->channelFlags &= (~CHANNEL_CW_INT);
-	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: NF did not complete in calibration window\n",
-			 __func__);
-		nf = 0;
-		chan->rawNoiseFloor = nf;
-		return chan->rawNoiseFloor;
-	} else {
-		ar5416GetNoiseFloor(ah, nfarray);
-		nf = nfarray[0];
-		if (getNoiseFloorThresh(ah, chan, &nfThresh)
-		    && nf > nfThresh) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: noise floor failed detected; "
-				 "detected %d, threshold %d\n", __func__,
-				 nf, nfThresh);
-			chan->channelFlags |= CHANNEL_CW_INT;
-		}
-	}
-
-#ifdef ATH_NF_PER_CHAN
-	h = chan->nfCalHist;
-#else
-	h = ah->nfCalHist;
-#endif
-
-	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
-	chan->rawNoiseFloor = h[0].privNF;
-
-	return chan->rawNoiseFloor;
-}
-
-static void ath9k_hw_update_mibstats(struct ath_hal *ah,
-			      struct ath9k_mib_stats *stats)
-{
-	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
-	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
-	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
-	stats->rts_good += REG_READ(ah, AR_RTS_OK);
-	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
-}
-
-static void ath9k_enable_mib_counters(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable mib counters\n");
-
-	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-	REG_WRITE(ah, AR_MIBC,
-		  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
-		  & 0x0f);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-}
-
-static void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling MIB counters\n");
-
-	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
-
-	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-}
-
-static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
-					struct ath9k_channel *chan)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
-		if (ahp->ah_ani[i].c.channel == chan->channel)
-			return i;
-		if (ahp->ah_ani[i].c.channel == 0) {
-			ahp->ah_ani[i].c.channel = chan->channel;
-			ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
-			return i;
-		}
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		 "No more channel states left. Using channel 0\n");
 	return 0;
 }
 
-static void ath9k_hw_ani_attach(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	ahp->ah_hasHwPhyCounters = 1;
-
-	memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
-	for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
-		ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
-		ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
-		ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
-		ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
-		ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
-		ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
-		ahp->ah_ani[i].ofdmWeakSigDetectOff =
-			!ATH9K_ANI_USE_OFDM_WEAK_SIG;
-		ahp->ah_ani[i].cckWeakSigThreshold =
-			ATH9K_ANI_CCK_WEAK_SIG_THR;
-		ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
-		ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
-		if (ahp->ah_hasHwPhyCounters) {
-			ahp->ah_ani[i].ofdmPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
-			ahp->ah_ani[i].cckPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
-		}
-	}
-	if (ahp->ah_hasHwPhyCounters) {
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Setting OfdmErrBase = 0x%08x\n",
-			ahp->ah_ani[0].ofdmPhyErrBase);
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
-			ahp->ah_ani[0].cckPhyErrBase);
-
-		REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
-		ath9k_enable_mib_counters(ah);
-	}
-	ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
-	if (ah->ah_config.enable_ani)
-		ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
-}
-
-static void ath9k_hw_ani_setup(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
-	const int coarseHigh[] = { -14, -14, -14, -14, -12 };
-	const int coarseLow[] = { -64, -64, -64, -64, -70 };
-	const int firpwr[] = { -78, -78, -78, -78, -80 };
-
-	for (i = 0; i < 5; i++) {
-		ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
-		ahp->ah_coarseHigh[i] = coarseHigh[i];
-		ahp->ah_coarseLow[i] = coarseLow[i];
-		ahp->ah_firpwr[i] = firpwr[i];
-	}
-}
-
-static void ath9k_hw_ani_detach(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detaching Ani\n");
-	if (ahp->ah_hasHwPhyCounters) {
-		ath9k_hw_disable_mib_counters(ah);
-		REG_WRITE(ah, AR_PHY_ERR_1, 0);
-		REG_WRITE(ah, AR_PHY_ERR_2, 0);
-	}
-}
-
-
-static bool ath9k_hw_ani_control(struct ath_hal *ah,
-				 enum ath9k_ani_cmd cmd, int param)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState = ahp->ah_curani;
-
-	switch (cmd & ahp->ah_ani_function) {
-	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				 "%s: level out of range (%u > %u)\n",
-				 __func__, level,
-				 (unsigned) ARRAY_SIZE(ahp->
-						       ah_totalSizeDesired));
-			return false;
-		}
-
-		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
-			      AR_PHY_DESIRED_SZ_TOT_DES,
-			      ahp->ah_totalSizeDesired[level]);
-		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-			      AR_PHY_AGC_CTL1_COARSE_LOW,
-			      ahp->ah_coarseLow[level]);
-		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-			      AR_PHY_AGC_CTL1_COARSE_HIGH,
-			      ahp->ah_coarseHigh[level]);
-		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-			      AR_PHY_FIND_SIG_FIRPWR,
-			      ahp->ah_firpwr[level]);
-
-		if (level > aniState->noiseImmunityLevel)
-			ahp->ah_stats.ast_ani_niup++;
-		else if (level < aniState->noiseImmunityLevel)
-			ahp->ah_stats.ast_ani_nidown++;
-		aniState->noiseImmunityLevel = level;
-		break;
-	}
-	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
-		const int m1ThreshLow[] = { 127, 50 };
-		const int m2ThreshLow[] = { 127, 40 };
-		const int m1Thresh[] = { 127, 0x4d };
-		const int m2Thresh[] = { 127, 0x40 };
-		const int m2CountThr[] = { 31, 16 };
-		const int m2CountThrLow[] = { 63, 48 };
-		u32 on = param ? 1 : 0;
-
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
-			      m1ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
-			      m2ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M1_THRESH,
-			      m1Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M2_THRESH,
-			      m2Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M2COUNT_THR,
-			      m2CountThr[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
-			      m2CountThrLow[on]);
-
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
-			      m1ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
-			      m2ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M1_THRESH,
-			      m1Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M2_THRESH,
-			      m2Thresh[on]);
-
-		if (on)
-			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
-				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-		else
-			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
-				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-
-		if (!on != aniState->ofdmWeakSigDetectOff) {
-			if (on)
-				ahp->ah_stats.ast_ani_ofdmon++;
-			else
-				ahp->ah_stats.ast_ani_ofdmoff++;
-			aniState->ofdmWeakSigDetectOff = !on;
-		}
-		break;
-	}
-	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
-		const int weakSigThrCck[] = { 8, 6 };
-		u32 high = param ? 1 : 0;
-
-		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
-			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
-			      weakSigThrCck[high]);
-		if (high != aniState->cckWeakSigThreshold) {
-			if (high)
-				ahp->ah_stats.ast_ani_cckhigh++;
-			else
-				ahp->ah_stats.ast_ani_ccklow++;
-			aniState->cckWeakSigThreshold = high;
-		}
-		break;
-	}
-	case ATH9K_ANI_FIRSTEP_LEVEL:{
-		const int firstep[] = { 0, 4, 8 };
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(firstep)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				 "%s: level out of range (%u > %u)\n",
-				 __func__, level,
-				(unsigned) ARRAY_SIZE(firstep));
-			return false;
-		}
-		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-			      AR_PHY_FIND_SIG_FIRSTEP,
-			      firstep[level]);
-		if (level > aniState->firstepLevel)
-			ahp->ah_stats.ast_ani_stepup++;
-		else if (level < aniState->firstepLevel)
-			ahp->ah_stats.ast_ani_stepdown++;
-		aniState->firstepLevel = level;
-		break;
-	}
-	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
-		const int cycpwrThr1[] =
-			{ 2, 4, 6, 8, 10, 12, 14, 16 };
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(cycpwrThr1)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				 "%s: level out of range (%u > %u)\n",
-				 __func__, level,
-				 (unsigned)
-				ARRAY_SIZE(cycpwrThr1));
-			return false;
-		}
-		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
-			      AR_PHY_TIMING5_CYCPWR_THR1,
-			      cycpwrThr1[level]);
-		if (level > aniState->spurImmunityLevel)
-			ahp->ah_stats.ast_ani_spurup++;
-		else if (level < aniState->spurImmunityLevel)
-			ahp->ah_stats.ast_ani_spurdown++;
-		aniState->spurImmunityLevel = level;
-		break;
-	}
-	case ATH9K_ANI_PRESENT:
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"%s: invalid cmd %u\n", __func__, cmd);
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
-		"ofdmWeakSigDetectOff=%d\n",
-		 aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
-		 !aniState->ofdmWeakSigDetectOff);
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"cckWeakSigThreshold=%d, "
-		"firstepLevel=%d, listenTime=%d\n",
-		 aniState->cckWeakSigThreshold, aniState->firstepLevel,
-		 aniState->listenTime);
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
-		 aniState->cycleCount, aniState->ofdmPhyErrCount,
-		 aniState->cckPhyErrCount);
-	return true;
-}
-
-static void ath9k_ani_restart(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ahp->ah_curani;
-
-	aniState->listenTime = 0;
-	if (ahp->ah_hasHwPhyCounters) {
-		if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
-			aniState->ofdmPhyErrBase = 0;
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				 "OFDM Trigger is too high for hw counters\n");
-		} else {
-			aniState->ofdmPhyErrBase =
-				AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
-		}
-		if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
-			aniState->cckPhyErrBase = 0;
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				 "CCK Trigger is too high for hw counters\n");
-		} else {
-			aniState->cckPhyErrBase =
-				AR_PHY_COUNTMAX - aniState->cckTrigHigh;
-		}
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			 "%s: Writing ofdmbase=%u   cckbase=%u\n",
-			 __func__, aniState->ofdmPhyErrBase,
-			 aniState->cckPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
-		ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-	}
-	aniState->ofdmPhyErrCount = 0;
-	aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *chan = ah->ah_curchan;
-	struct ar5416AniState *aniState;
-	enum wireless_mode mode;
-	int32_t rssi;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ahp->ah_curani;
-
-	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-					 aniState->noiseImmunityLevel + 1)) {
-			return;
-		}
-	}
-
-	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-					 aniState->spurImmunityLevel + 1)) {
-			return;
-		}
-	}
-
-	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		}
-		return;
-	}
-	rssi = BEACON_RSSI(ahp);
-	if (rssi > aniState->rssiThrHigh) {
-		if (!aniState->ofdmWeakSigDetectOff) {
-			if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-					 false)) {
-				ath9k_hw_ani_control(ah,
-					ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-					0);
-				return;
-			}
-		}
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-			return;
-		}
-	} else if (rssi > aniState->rssiThrLow) {
-		if (aniState->ofdmWeakSigDetectOff)
-			ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     true);
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		return;
-	} else {
-		mode = ath9k_hw_chan2wmode(ah, chan);
-		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
-			if (!aniState->ofdmWeakSigDetectOff)
-				ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     false);
-			if (aniState->firstepLevel > 0)
-				ath9k_hw_ani_control(ah,
-						     ATH9K_ANI_FIRSTEP_LEVEL,
-						     0);
-			return;
-		}
-	}
-}
-
-static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *chan = ah->ah_curchan;
-	struct ar5416AniState *aniState;
-	enum wireless_mode mode;
-	int32_t rssi;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ahp->ah_curani;
-	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-					 aniState->noiseImmunityLevel + 1)) {
-			return;
-		}
-	}
-	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		}
-		return;
-	}
-	rssi = BEACON_RSSI(ahp);
-	if (rssi > aniState->rssiThrLow) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-	} else {
-		mode = ath9k_hw_chan2wmode(ah, chan);
-		if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
-			if (aniState->firstepLevel > 0)
-				ath9k_hw_ani_control(ah,
-						     ATH9K_ANI_FIRSTEP_LEVEL,
-						     0);
-		}
-	}
-}
-
-static void ath9k_ani_reset(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState;
-	struct ath9k_channel *chan = ah->ah_curchan;
-	int index;
-
-	if (!DO_ANI(ah))
-		return;
-
-	index = ath9k_hw_get_ani_channel_idx(ah, chan);
-	aniState = &ahp->ah_ani[index];
-	ahp->ah_curani = aniState;
-
-	if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
-	    && ah->ah_opmode != ATH9K_M_IBSS) {
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			 "%s: Reset ANI state opmode %u\n", __func__,
-			 ah->ah_opmode);
-		ahp->ah_stats.ast_ani_reset++;
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
-		ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
-				     ATH9K_ANI_CCK_WEAK_SIG_THR);
-		ath9k_hw_setrxfilter(ah,
-				     ath9k_hw_getrxfilter(ah) |
-				     ATH9K_RX_FILTER_PHYERR);
-		if (ah->ah_opmode == ATH9K_M_HOSTAP) {
-			ahp->ah_curani->ofdmTrigHigh =
-				ah->ah_config.ofdm_trig_high;
-			ahp->ah_curani->ofdmTrigLow =
-				ah->ah_config.ofdm_trig_low;
-			ahp->ah_curani->cckTrigHigh =
-				ah->ah_config.cck_trig_high;
-			ahp->ah_curani->cckTrigLow =
-				ah->ah_config.cck_trig_low;
-		}
-		ath9k_ani_restart(ah);
-		return;
-	}
-
-	if (aniState->noiseImmunityLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-				     aniState->noiseImmunityLevel);
-	if (aniState->spurImmunityLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-				     aniState->spurImmunityLevel);
-	if (aniState->ofdmWeakSigDetectOff)
-		ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     !aniState->ofdmWeakSigDetectOff);
-	if (aniState->cckWeakSigThreshold)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
-				     aniState->cckWeakSigThreshold);
-	if (aniState->firstepLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-				     aniState->firstepLevel);
-	if (ahp->ah_hasHwPhyCounters) {
-		ath9k_hw_setrxfilter(ah,
-				     ath9k_hw_getrxfilter(ah) &
-				     ~ATH9K_RX_FILTER_PHYERR);
-		ath9k_ani_restart(ah);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
-	} else {
-		ath9k_ani_restart(ah);
-		ath9k_hw_setrxfilter(ah,
-				     ath9k_hw_getrxfilter(ah) |
-				     ATH9K_RX_FILTER_PHYERR);
-	}
-}
-
-/*
- * Process a MIB interrupt.  We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-void ath9k_hw_procmibevent(struct ath_hal *ah,
-			   const struct ath9k_node_stats *stats)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 phyCnt1, phyCnt2;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
-	/* Reset these counters regardless */
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-	if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
-		REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
-	/* Clear the mib counters and save them in the stats */
-	ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-	ahp->ah_stats.ast_nodestats = *stats;
-
-	if (!DO_ANI(ah))
-		return;
-
-	/* NB: these are not reset-on-read */
-	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
-	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
-		struct ar5416AniState *aniState = ahp->ah_curani;
-		u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
-		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
-		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-		ahp->ah_stats.ast_ani_ofdmerrs +=
-			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
-		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-		ahp->ah_stats.ast_ani_cckerrs +=
-			cckPhyErrCnt - aniState->cckPhyErrCount;
-		aniState->cckPhyErrCount = cckPhyErrCnt;
-
-		/*
-		 * NB: figure out which counter triggered.  If both
-		 * trigger we'll only deal with one as the processing
-		 * clobbers the error counter so the trigger threshold
-		 * check will never be true.
-		 */
-		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
-			ath9k_hw_ani_ofdm_err_trigger(ah);
-		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
-			ath9k_hw_ani_cck_err_trigger(ah);
-		/* NB: always restart to insure the h/w counters are reset */
-		ath9k_ani_restart(ah);
-	}
-}
-
-static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState;
-	int32_t rssi;
-
-	aniState = ahp->ah_curani;
-
-	if (ah->ah_opmode == ATH9K_M_HOSTAP) {
-		if (aniState->firstepLevel > 0) {
-			if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-						 aniState->firstepLevel - 1)) {
-				return;
-			}
-		}
-	} else {
-		rssi = BEACON_RSSI(ahp);
-		if (rssi > aniState->rssiThrHigh) {
-			/* XXX: Handle me */
-		} else if (rssi > aniState->rssiThrLow) {
-			if (aniState->ofdmWeakSigDetectOff) {
-				if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-					 true) ==
-				    true) {
-					return;
-				}
-			}
-			if (aniState->firstepLevel > 0) {
-				if (ath9k_hw_ani_control
-				    (ah, ATH9K_ANI_FIRSTEP_LEVEL,
-				     aniState->firstepLevel - 1) ==
-				    true) {
-					return;
-				}
-			}
-		} else {
-			if (aniState->firstepLevel > 0) {
-				if (ath9k_hw_ani_control
-				    (ah, ATH9K_ANI_FIRSTEP_LEVEL,
-				     aniState->firstepLevel - 1) ==
-				    true) {
-					return;
-				}
-			}
-		}
-	}
-
-	if (aniState->spurImmunityLevel > 0) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-					 aniState->spurImmunityLevel - 1)) {
-			return;
-		}
-	}
-
-	if (aniState->noiseImmunityLevel > 0) {
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-				     aniState->noiseImmunityLevel - 1);
-		return;
-	}
-}
-
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState;
-	u32 txFrameCount, rxFrameCount, cycleCount;
-	int32_t listenTime;
-
-	txFrameCount = REG_READ(ah, AR_TFCNT);
-	rxFrameCount = REG_READ(ah, AR_RFCNT);
-	cycleCount = REG_READ(ah, AR_CCCNT);
-
-	aniState = ahp->ah_curani;
-	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
-
-		listenTime = 0;
-		ahp->ah_stats.ast_ani_lzero++;
-	} else {
-		int32_t ccdelta = cycleCount - aniState->cycleCount;
-		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
-		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
-		listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
-	}
-	aniState->cycleCount = cycleCount;
-	aniState->txFrameCount = txFrameCount;
-	aniState->rxFrameCount = rxFrameCount;
-
-	return listenTime;
-}
-
-void ath9k_hw_ani_monitor(struct ath_hal *ah,
-			  const struct ath9k_node_stats *stats,
-			  struct ath9k_channel *chan)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416AniState *aniState;
-	int32_t listenTime;
-
-	aniState = ahp->ah_curani;
-	ahp->ah_stats.ast_nodestats = *stats;
-
-	listenTime = ath9k_hw_ani_get_listen_time(ah);
-	if (listenTime < 0) {
-		ahp->ah_stats.ast_ani_lneg++;
-		ath9k_ani_restart(ah);
-		return;
-	}
-
-	aniState->listenTime += listenTime;
-
-	if (ahp->ah_hasHwPhyCounters) {
-		u32 phyCnt1, phyCnt2;
-		u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
-		ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
-		phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-		phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
-		if (phyCnt1 < aniState->ofdmPhyErrBase ||
-		    phyCnt2 < aniState->cckPhyErrBase) {
-			if (phyCnt1 < aniState->ofdmPhyErrBase) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-					 "%s: phyCnt1 0x%x, resetting "
-					 "counter value to 0x%x\n",
-					 __func__, phyCnt1,
-					 aniState->ofdmPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_1,
-					  aniState->ofdmPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_MASK_1,
-					  AR_PHY_ERR_OFDM_TIMING);
-			}
-			if (phyCnt2 < aniState->cckPhyErrBase) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-					 "%s: phyCnt2 0x%x, resetting "
-					 "counter value to 0x%x\n",
-					 __func__, phyCnt2,
-					 aniState->cckPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_2,
-					  aniState->cckPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_MASK_2,
-					  AR_PHY_ERR_CCK_TIMING);
-			}
-			return;
-		}
-
-		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-		ahp->ah_stats.ast_ani_ofdmerrs +=
-			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
-		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-		ahp->ah_stats.ast_ani_cckerrs +=
-			cckPhyErrCnt - aniState->cckPhyErrCount;
-		aniState->cckPhyErrCount = cckPhyErrCnt;
-	}
-
-	if (!DO_ANI(ah))
-		return;
-
-	if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
-		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
-		    aniState->ofdmTrigLow / 1000 &&
-		    aniState->cckPhyErrCount <= aniState->listenTime *
-		    aniState->cckTrigLow / 1000)
-			ath9k_hw_ani_lower_immunity(ah);
-		ath9k_ani_restart(ah);
-	} else if (aniState->listenTime > ahp->ah_aniPeriod) {
-		if (aniState->ofdmPhyErrCount > aniState->listenTime *
-		    aniState->ofdmTrigHigh / 1000) {
-			ath9k_hw_ani_ofdm_err_trigger(ah);
-			ath9k_ani_restart(ah);
-		} else if (aniState->cckPhyErrCount >
-			   aniState->listenTime * aniState->cckTrigHigh /
-			   1000) {
-			ath9k_hw_ani_cck_err_trigger(ah);
-			ath9k_ani_restart(ah);
-		}
-	}
-}
-
-#ifndef ATH_NF_PER_CHAN
-static void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
-{
-	int i, j;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		ah->nfCalHist[i].currIndex = 0;
-		ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
-		ah->nfCalHist[i].invalidNFcount =
-			AR_PHY_CCA_FILTERWINDOW_LENGTH;
-		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
-			ah->nfCalHist[i].nfCalBuffer[j] =
-				AR_PHY_CCA_MAX_GOOD_VALUE;
-		}
-	}
-	return;
-}
-#endif
-
-static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
-					 u32 gpio, u32 type)
-{
-	int addr;
-	u32 gpio_shift, tmp;
-
-	if (gpio > 11)
-		addr = AR_GPIO_OUTPUT_MUX3;
-	else if (gpio > 5)
-		addr = AR_GPIO_OUTPUT_MUX2;
-	else
-		addr = AR_GPIO_OUTPUT_MUX1;
-
-	gpio_shift = (gpio % 6) * 5;
-
-	if (AR_SREV_9280_20_OR_LATER(ah)
-	    || (addr != AR_GPIO_OUTPUT_MUX1)) {
-		REG_RMW(ah, addr, (type << gpio_shift),
-			(0x1f << gpio_shift));
-	} else {
-		tmp = REG_READ(ah, addr);
-		tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
-		tmp &= ~(0x1f << gpio_shift);
-		tmp |= (type << gpio_shift);
-		REG_WRITE(ah, addr, tmp);
-	}
-}
-
-void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
-			 u32 ah_signal_type)
-{
-	u32 gpio_shift;
-
-	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
-
-	gpio_shift = 2 * gpio;
-
-	REG_RMW(ah,
-		AR_GPIO_OE_OUT,
-		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
-		(AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
-{
-	REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
-		AR_GPIO_BIT(gpio));
-}
-
-/*
- * Configure GPIO Input lines
- */
-void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
-{
-	u32 gpio_shift;
-
-	ASSERT(gpio < ah->ah_caps.num_gpio_pins);
-
-	gpio_shift = gpio << 1;
-
-	REG_RMW(ah,
-		AR_GPIO_OE_OUT,
-		(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
-		(AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-#ifdef CONFIG_RFKILL
-static void ath9k_enable_rfkill(struct ath_hal *ah)
-{
-	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-
-	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-		    AR_GPIO_INPUT_MUX2_RFSILENT);
-
-	ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
-	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-}
-#endif
-
-u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
-{
-	if (gpio >= ah->ah_caps.num_gpio_pins)
-		return 0xffffffff;
-
-	if (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;
-	}
-}
-
 static int ath9k_hw_post_attach(struct ath_hal *ah)
 {
 	int ecode;
 
 	if (!ath9k_hw_chip_test(ah)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			 "%s: hardware self-test failed\n", __func__);
+			"%s: hardware self-test failed\n", __func__);
 		return -ENODEV;
 	}
 
@@ -2906,357 +581,12 @@
 		ath9k_hw_ani_setup(ah);
 		ath9k_hw_ani_attach(ah);
 	}
+
 	return 0;
 }
 
-static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
-				    struct ar5416_eeprom *pEepData,
-				    u32 reg, u32 value)
-{
-	struct base_eep_header *pBase = &(pEepData->baseEepHeader);
-
-	switch (ah->ah_devid) {
-	case AR9280_DEVID_PCI:
-		if (reg == 0x7894) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-				 "ini VAL: %x  EEPROM: %x\n", value,
-				 (pBase->version & 0xff));
-
-			if ((pBase->version & 0xff) > 0x0a) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					 "PWDCLKIND: %d\n",
-					 pBase->pwdclkind);
-				value &= ~AR_AN_TOP2_PWDCLKIND;
-				value |= AR_AN_TOP2_PWDCLKIND & (pBase->
-					 pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
-			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					 "PWDCLKIND Earlier Rev\n");
-			}
-
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-				 "final ini VAL: %x\n", value);
-		}
-		break;
-	}
-	return value;
-}
-
-static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	u16 capField = 0, eeval;
-
-	eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_0);
-
-	ah->ah_currentRD = eeval;
-
-	eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_1);
-	ah->ah_currentRDExt = eeval;
-
-	capField = ath9k_hw_get_eeprom(ahp, EEP_OP_CAP);
-
-	if (ah->ah_opmode != ATH9K_M_HOSTAP &&
-	    ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
-		if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65)
-			ah->ah_currentRD += 5;
-		else if (ah->ah_currentRD == 0x41)
-			ah->ah_currentRD = 0x43;
-		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-			 "%s: regdomain mapped to 0x%x\n", __func__,
-			 ah->ah_currentRD);
-	}
-
-	eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE);
-	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
-
-	if (eeval & AR5416_OPFLAGS_11A) {
-		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
-		if (ah->ah_config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
-				set_bit(ATH9K_MODE_11NA_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
-				set_bit(ATH9K_MODE_11NA_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NA_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
-
-	if (eeval & AR5416_OPFLAGS_11G) {
-		set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
-		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
-		if (ah->ah_config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
-				set_bit(ATH9K_MODE_11NG_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
-				set_bit(ATH9K_MODE_11NG_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NG_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
-
-	pCap->tx_chainmask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK);
-	if ((ah->ah_isPciExpress)
-	    || (eeval & AR5416_OPFLAGS_11A)) {
-		pCap->rx_chainmask =
-			ath9k_hw_get_eeprom(ahp, EEP_RX_MASK);
-	} else {
-		pCap->rx_chainmask =
-			(ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
-	}
-
-	if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
-		ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
-
-	pCap->low_2ghz_chan = 2312;
-	pCap->high_2ghz_chan = 2732;
-
-	pCap->low_5ghz_chan = 4920;
-	pCap->high_5ghz_chan = 6100;
-
-	pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
-
-	if (ah->ah_config.ht_enable)
-		pCap->hw_caps |= ATH9K_HW_CAP_HT;
-	else
-		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_GTT;
-	pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
-	pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
-
-	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
-		pCap->total_queues =
-			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
-	else
-		pCap->total_queues = ATH9K_NUM_TX_QUEUES;
-
-	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
-		pCap->keycache_size =
-			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
-	else
-		pCap->keycache_size = AR_KEYTABLE_SIZE;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-	pCap->num_mr_retries = 4;
-	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		pCap->num_gpio_pins = AR928X_NUM_GPIO;
-	else
-		pCap->num_gpio_pins = AR_NUM_GPIO;
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW;
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	} else {
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	}
-
-	if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_CST;
-		pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
-	} else {
-		pCap->rts_aggr_limit = (8 * 1024);
-	}
-
-	pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
-
-#ifdef CONFIG_RFKILL
-	ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
-	if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
-		ah->ah_rfkill_gpio =
-			MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
-		ah->ah_rfkill_polarity =
-			MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
-
-		pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
-	}
-#endif
-
-	if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
-	    (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
-	    (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
-	    (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
-	    (ah->ah_macVersion == AR_SREV_VERSION_9280))
-		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
-	else
-		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
-
-	if (AR_SREV_9280(ah))
-		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
-	else
-		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
-
-	if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
-		pCap->reg_cap =
-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
-			AR_EEPROM_EEREGCAP_EN_KK_U2 |
-			AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
-	} else {
-		pCap->reg_cap =
-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
-	}
-
-	pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
-
-	pCap->num_antcfg_5ghz =
-		ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_5GHZ);
-	pCap->num_antcfg_2ghz =
-		ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_2GHZ);
-
-	return true;
-}
-
-static void ar5416DisablePciePhy(struct ath_hal *ah)
-{
-	if (!AR_SREV_9100(ah))
-		return;
-
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
-
-	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-}
-
-static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
-{
-	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-	if (setChip) {
-		REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-			    AR_RTC_FORCE_WAKE_EN);
-		if (!AR_SREV_9100(ah))
-			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-
-		REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
-			    AR_RTC_RESET_EN);
-	}
-}
-
-static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
-{
-	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-	if (setChip) {
-		struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-			REG_WRITE(ah, AR_RTC_FORCE_WAKE,
-				  AR_RTC_FORCE_WAKE_ON_INT);
-		} else {
-			REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-				    AR_RTC_FORCE_WAKE_EN);
-		}
-	}
-}
-
-static bool ath9k_hw_set_power_awake(struct ath_hal *ah,
-				     int setChip)
-{
-	u32 val;
-	int i;
-
-	if (setChip) {
-		if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
-		    AR_RTC_STATUS_SHUTDOWN) {
-			if (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)
-			    != true) {
-				return false;
-			}
-		}
-		if (AR_SREV_9100(ah))
-			REG_SET_BIT(ah, AR_RTC_RESET,
-				       AR_RTC_RESET_EN);
-
-		REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
-			    AR_RTC_FORCE_WAKE_EN);
-		udelay(50);
-
-		for (i = POWER_UP_TIME / 50; i > 0; i--) {
-			val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
-			if (val == AR_RTC_STATUS_ON)
-				break;
-			udelay(50);
-			REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
-				       AR_RTC_FORCE_WAKE_EN);
-		}
-		if (i == 0) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				 "%s: Failed to wakeup in %uus\n",
-				 __func__, POWER_UP_TIME / 20);
-			return false;
-		}
-	}
-
-	REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-	return true;
-}
-
-bool ath9k_hw_setpower(struct ath_hal *ah,
-		       enum ath9k_power_mode mode)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	static const char *modes[] = {
-		"AWAKE",
-		"FULL-SLEEP",
-		"NETWORK SLEEP",
-		"UNDEFINED"
-	};
-	int status = true, setChip = true;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
-		 modes[ahp->ah_powerMode], modes[mode],
-		 setChip ? "set chip " : "");
-
-	switch (mode) {
-	case ATH9K_PM_AWAKE:
-		status = ath9k_hw_set_power_awake(ah, setChip);
-		break;
-	case ATH9K_PM_FULL_SLEEP:
-		ath9k_set_power_sleep(ah, setChip);
-		ahp->ah_chipFullSleep = true;
-		break;
-	case ATH9K_PM_NETWORK_SLEEP:
-		ath9k_set_power_network_sleep(ah, setChip);
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			 "%s: unknown power mode %u\n", __func__, mode);
-		return false;
-	}
-	ahp->ah_powerMode = mode;
-	return status;
-}
-
-static struct ath_hal *ath9k_hw_do_attach(u16 devid,
-					  struct ath_softc *sc,
-					  void __iomem *mem,
-					  int *status)
+static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
+					  void __iomem *mem, int *status)
 {
 	struct ath_hal_5416 *ahp;
 	struct ath_hal *ah;
@@ -3300,6 +630,7 @@
 				SER_REG_MODE_OFF;
 		}
 	}
+
 	DPRINTF(ah->ah_sc, ATH_DBG_RESET,
 		"%s: serialize_regmode is %d\n",
 		__func__, ah->ah_config.serialize_regmode);
@@ -3309,9 +640,9 @@
 	    (ah->ah_macVersion != AR_SREV_VERSION_9160) &&
 	    (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) {
 		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			 "%s: Mac Chip Rev 0x%02x.%x is not supported by "
-			 "this driver\n", __func__,
-			 ah->ah_macVersion, ah->ah_macRev);
+			"%s: Mac Chip Rev 0x%02x.%x is not supported by "
+			"this driver\n", __func__,
+			ah->ah_macVersion, ah->ah_macRev);
 		ecode = -EOPNOTSUPP;
 		goto bad;
 	}
@@ -3341,8 +672,7 @@
 			ahp->ah_adcDcCalInitData.calData =
 				&adc_init_dc_cal;
 		}
-		ahp->ah_suppCals =
-			ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+		ahp->ah_suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
 	}
 
 	if (AR_SREV_9160(ah)) {
@@ -3352,14 +682,13 @@
 	} else {
 		ahp->ah_ani_function = ATH9K_ANI_ALL;
 		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			ahp->ah_ani_function &=
-				~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+			ahp->ah_ani_function &=	~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
 		}
 	}
 
 	DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-		 "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
-		 ah->ah_macVersion, ah->ah_macRev);
+		"%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
+		ah->ah_macVersion, ah->ah_macRev);
 
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2,
@@ -3369,21 +698,16 @@
 
 		if (ah->ah_config.pcie_clock_req) {
 			INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
-				       ar9280PciePhy_clkreq_off_L1_9280,
-				       ARRAY_SIZE
-				       (ar9280PciePhy_clkreq_off_L1_9280),
-				       2);
+			       ar9280PciePhy_clkreq_off_L1_9280,
+			       ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
 		} else {
 			INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
-				       ar9280PciePhy_clkreq_always_on_L1_9280,
-				       ARRAY_SIZE
-				       (ar9280PciePhy_clkreq_always_on_L1_9280),
-				       2);
+			       ar9280PciePhy_clkreq_always_on_L1_9280,
+			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
 		}
 		INIT_INI_ARRAY(&ahp->ah_iniModesAdditional,
 			       ar9280Modes_fast_clock_9280_2,
-			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2),
-			       3);
+			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
 	} else if (AR_SREV_9280_10_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280,
 			       ARRAY_SIZE(ar9280Modes_9280), 6);
@@ -3469,7 +793,7 @@
 	if (ah->ah_isPciExpress)
 		ath9k_hw_configpcipowersave(ah, 0);
 	else
-		ar5416DisablePciePhy(ah);
+		ath9k_hw_disablepcie(ah);
 
 	ecode = ath9k_hw_post_attach(ah);
 	if (ecode != 0)
@@ -3490,10 +814,9 @@
 		}
 	}
 #endif
-
 	if (!ath9k_hw_fill_cap_info(ah)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			 "%s:failed ath9k_hw_fill_cap_info\n", __func__);
+			"%s:failed ath9k_hw_fill_cap_info\n", __func__);
 		ecode = -EINVAL;
 		goto bad;
 	}
@@ -3501,8 +824,8 @@
 	ecode = ath9k_hw_init_macaddr(ah);
 	if (ecode != 0) {
 		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			 "%s: failed initializing mac address\n",
-			 __func__);
+			"%s: failed initializing mac address\n",
+			__func__);
 		goto bad;
 	}
 
@@ -3511,1108 +834,555 @@
 	else
 		ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S);
 
-#ifndef ATH_NF_PER_CHAN
-
 	ath9k_init_nfcal_hist_buffer(ah);
-#endif
 
 	return ah;
-
 bad:
 	if (ahp)
 		ath9k_hw_detach((struct ath_hal *) ahp);
 	if (status)
 		*status = ecode;
+
 	return NULL;
 }
 
+static void ath9k_hw_init_bb(struct ath_hal *ah,
+			     struct ath9k_channel *chan)
+{
+	u32 synthDelay;
+
+	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+	if (IS_CHAN_CCK(chan))
+		synthDelay = (4 * synthDelay) / 22;
+	else
+		synthDelay /= 10;
+
+	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+	udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void ath9k_hw_init_qos(struct ath_hal *ah)
+{
+	REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
+	REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
+
+	REG_WRITE(ah, AR_QOS_NO_ACK,
+		  SM(2, AR_QOS_NO_ACK_TWO_BIT) |
+		  SM(5, AR_QOS_NO_ACK_BIT_OFF) |
+		  SM(0, AR_QOS_NO_ACK_BYTE_OFF));
+
+	REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+	REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+}
+
+static void ath9k_hw_init_pll(struct ath_hal *ah,
+			      struct ath9k_channel *chan)
+{
+	u32 pll;
+
+	if (AR_SREV_9100(ah)) {
+		if (chan && IS_CHAN_5GHZ(chan))
+			pll = 0x1450;
+		else
+			pll = 0x1458;
+	} else {
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan)) {
+				pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
+
+
+				if (AR_SREV_9280_20(ah)) {
+					if (((chan->channel % 20) == 0)
+					    || ((chan->channel % 10) == 0))
+						pll = 0x2850;
+					else
+						pll = 0x142c;
+				}
+			} else {
+				pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
+			}
+
+		} else if (AR_SREV_9160_10_OR_LATER(ah)) {
+
+			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan))
+				pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
+			else
+				pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
+		} else {
+			pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan))
+				pll |= SM(0xa, AR_RTC_PLL_DIV);
+			else
+				pll |= SM(0xb, AR_RTC_PLL_DIV);
+		}
+	}
+	REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
+
+	udelay(RTC_PLL_SETTLE_DELAY);
+
+	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+}
+
+static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	int rx_chainmask, tx_chainmask;
+
+	rx_chainmask = ahp->ah_rxchainmask;
+	tx_chainmask = ahp->ah_txchainmask;
+
+	switch (rx_chainmask) {
+	case 0x5:
+		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+			    AR_PHY_SWAP_ALT_CHAIN);
+	case 0x3:
+		if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
+			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+			break;
+		}
+	case 0x1:
+	case 0x2:
+		if (!AR_SREV_9280(ah))
+			break;
+	case 0x7:
+		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+		break;
+	default:
+		break;
+	}
+
+	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+	if (tx_chainmask == 0x5) {
+		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+			    AR_PHY_SWAP_ALT_CHAIN);
+	}
+	if (AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
+}
+
+static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, enum ath9k_opmode opmode)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	ahp->ah_maskReg = AR_IMR_TXERR |
+		AR_IMR_TXURN |
+		AR_IMR_RXERR |
+		AR_IMR_RXORN |
+		AR_IMR_BCNMISC;
+
+	if (ahp->ah_intrMitigation)
+		ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+	else
+		ahp->ah_maskReg |= AR_IMR_RXOK;
+
+	ahp->ah_maskReg |= AR_IMR_TXOK;
+
+	if (opmode == ATH9K_M_HOSTAP)
+		ahp->ah_maskReg |= AR_IMR_MIB;
+
+	REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+	REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
+
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+		REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+	}
+}
+
+static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n",
+			 __func__, us);
+		ahp->ah_acktimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_TIME_OUT,
+			      AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
+		ahp->ah_acktimeout = us;
+		return true;
+	}
+}
+
+static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n",
+			 __func__, us);
+		ahp->ah_ctstimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_TIME_OUT,
+			      AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
+		ahp->ah_ctstimeout = us;
+		return true;
+	}
+}
+
+static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah, u32 tu)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	if (tu > 0xFFFF) {
+		DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
+			"%s: bad global tx timeout %u\n", __func__, tu);
+		ahp->ah_globaltxtimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+		ahp->ah_globaltxtimeout = tu;
+		return true;
+	}
+}
+
+static void ath9k_hw_init_user_settings(struct ath_hal *ah)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n",
+		 __func__, ahp->ah_miscMode);
+
+	if (ahp->ah_miscMode != 0)
+		REG_WRITE(ah, AR_PCU_MISC,
+			  REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
+	if (ahp->ah_slottime != (u32) -1)
+		ath9k_hw_setslottime(ah, ahp->ah_slottime);
+	if (ahp->ah_acktimeout != (u32) -1)
+		ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
+	if (ahp->ah_ctstimeout != (u32) -1)
+		ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
+	if (ahp->ah_globaltxtimeout != (u32) -1)
+		ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
+}
+
+const char *ath9k_hw_probe(u16 vendorid, u16 devid)
+{
+	return vendorid == ATHEROS_VENDOR_ID ?
+		ath9k_hw_devname(devid) : NULL;
+}
+
 void ath9k_hw_detach(struct ath_hal *ah)
 {
 	if (!AR_SREV_9100(ah))
 		ath9k_hw_ani_detach(ah);
-	ath9k_hw_rfdetach(ah);
 
+	ath9k_hw_rfdetach(ah);
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 	kfree(ah);
 }
 
-bool ath9k_get_channel_edges(struct ath_hal *ah,
-			     u16 flags, u16 *low,
-			     u16 *high)
+struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
+				void __iomem *mem, int *error)
 {
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	struct ath_hal *ah = NULL;
 
-	if (flags & CHANNEL_5GHZ) {
-		*low = pCap->low_5ghz_chan;
-		*high = pCap->high_5ghz_chan;
-		return true;
-	}
-	if ((flags & CHANNEL_2GHZ)) {
-		*low = pCap->low_2ghz_chan;
-		*high = pCap->high_2ghz_chan;
-
-		return true;
-	}
-	return false;
-}
-
-static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin,
-					   u8 pwrMax,
-					   u8 *pPwrList,
-					   u8 *pVpdList,
-					   u16
-					   numIntercepts,
-					   u8 *pRetVpdList)
-{
-	u16 i, k;
-	u8 currPwr = pwrMin;
-	u16 idxL = 0, idxR = 0;
-
-	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
-		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
-					       numIntercepts, &(idxL),
-					       &(idxR));
-		if (idxR < 1)
-			idxR = 1;
-		if (idxL == numIntercepts - 1)
-			idxL = (u16) (numIntercepts - 2);
-		if (pPwrList[idxL] == pPwrList[idxR])
-			k = pVpdList[idxL];
-		else
-			k = (u16) (((currPwr -
-					   pPwrList[idxL]) *
-					  pVpdList[idxR] +
-					  (pPwrList[idxR] -
-					   currPwr) * pVpdList[idxL]) /
-					 (pPwrList[idxR] -
-					  pPwrList[idxL]));
-		pRetVpdList[i] = (u8) k;
-		currPwr += 2;
-	}
-
-	return true;
-}
-
-static void
-ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
-				    struct ath9k_channel *chan,
-				    struct cal_data_per_freq *pRawDataSet,
-				    u8 *bChans,
-				    u16 availPiers,
-				    u16 tPdGainOverlap,
-				    int16_t *pMinCalPower,
-				    u16 *pPdGainBoundaries,
-				    u8 *pPDADCValues,
-				    u16 numXpdGains)
-{
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR5416_NUM_PD_GAINS];
-	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index((u8)
-					       FREQ2FBIN(centers.
-							 synth_center,
-							 IS_CHAN_2GHZ
-							 (chan)), bChans,
-					       numPiers, &idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pRawDataSet[idxL].
-						pwrPdg[i],
-						pRawDataSet[idxL].
-						vpdPdg[i],
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] =
-				min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
-				    pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
-
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] =
-					(u8) (ath9k_hw_interpolate
-						    ((u16)
-						     FREQ2FBIN(centers.
-							       synth_center,
-							       IS_CHAN_2GHZ
-							       (chan)),
-						     bChans[idxL],
-						     bChans[idxR], vpdTableL[i]
-						     [j], vpdTableR[i]
-						     [j]));
-			}
-		}
-	}
-
-	*pMinCalPower = (int16_t) (minPwrT4[0] / 2);
-
-	k = 0;
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16) (maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16) ((maxPwrT4[i] +
-					      minPwrT4[i + 1]) / 4);
-
-		pPdGainBoundaries[i] =
-			min((u16) AR5416_MAX_RATE_POWER,
-			    pPdGainBoundaries[i]);
-
-		if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
-			minDelta = pPdGainBoundaries[0] - 23;
-			pPdGainBoundaries[0] = 23;
-		} else {
-			minDelta = 0;
-		}
-
-		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
-				ss = (int16_t) (0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t) ((pPdGainBoundaries[i - 1] -
-					 (minPwrT4[i] / 2)) -
-					tPdGainOverlap + 1 + minDelta);
-		}
-		vpdStep = (int16_t) (vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			tmpVal = (int16_t) (vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] =
-				(u8) ((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable =
-			(u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8) (pPdGainBoundaries[i] + tPdGainOverlap -
-				       (minPwrT4[i] / 2));
-		maxIndex = (tgtIndex <
-			    sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex)
-		       && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-		}
-
-		vpdStep = (int16_t) (vpdTableI[i][sizeCurrVpdTable - 1] -
-				     vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex > maxIndex) {
-			while ((ss <= tgtIndex)
-			       && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t) ((vpdTableI[i]
-						     [sizeCurrVpdTable -
-						      1] + (ss - maxIndex +
-							    1) * vpdStep));
-				pPDADCValues[k++] = (u8) ((tmpVal >
-						 255) ? 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR5416_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
-		i++;
-	}
-
-	while (k < AR5416_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k - 1];
-		k++;
-	}
-	return;
-}
-
-static bool
-ath9k_hw_set_power_cal_table(struct ath_hal *ah,
-			     struct ar5416_eeprom *pEepData,
-			     struct ath9k_channel *chan,
-			     int16_t *pTxPowerIndexOffset)
-{
-	struct cal_data_per_freq *pRawDataset;
-	u8 *pCalBChans = NULL;
-	u16 pdGainOverlap_t2;
-	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
-	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
-	u16 numPiers, i, j;
-	int16_t tMinCalPower;
-	u16 numXpdGain, xpdMask;
-	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
-	u32 reg32, regOffset, regChainOffset;
-	int16_t modalIdx;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
-	xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
-
-	if ((pEepData->baseEepHeader.
-	     version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		pdGainOverlap_t2 =
-			pEepData->modalHeader[modalIdx].pdGainOverlap;
-	} else {
-		pdGainOverlap_t2 =
-			(u16) (MS
-				     (REG_READ(ah, AR_PHY_TPCRG5),
-				      AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
-	}
-
-	if (IS_CHAN_2GHZ(chan)) {
-		pCalBChans = pEepData->calFreqPier2G;
-		numPiers = AR5416_NUM_2G_CAL_PIERS;
-	} else {
-		pCalBChans = pEepData->calFreqPier5G;
-		numPiers = AR5416_NUM_5G_CAL_PIERS;
-	}
-
-	numXpdGain = 0;
-
-	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
-		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
-			if (numXpdGain >= AR5416_NUM_PD_GAINS)
-				break;
-			xpdGainValues[numXpdGain] =
-				(u16) (AR5416_PD_GAINS_IN_MASK - i);
-			numXpdGain++;
-		}
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
-		      (numXpdGain - 1) & 0x3);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
-		      xpdGainValues[0]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
-		      xpdGainValues[1]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
-		      xpdGainValues[2]);
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		if (AR_SREV_5416_V20_OR_LATER(ah) &&
-		    (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
-		    && (i != 0)) {
-			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-		} else
-			regChainOffset = i * 0x1000;
-		if (pEepData->baseEepHeader.txMask & (1 << i)) {
-			if (IS_CHAN_2GHZ(chan))
-				pRawDataset = pEepData->calPierData2G[i];
-			else
-				pRawDataset = pEepData->calPierData5G[i];
-
-			ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
-							    pRawDataset,
-							    pCalBChans,
-							    numPiers,
-							    pdGainOverlap_t2,
-							    &tMinCalPower,
-							    gainBoundaries,
-							    pdadcValues,
-							    numXpdGain);
-
-			if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
-
-				REG_WRITE(ah,
-					  AR_PHY_TPCRG5 + regChainOffset,
-					  SM(pdGainOverlap_t2,
-					     AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
-					  | SM(gainBoundaries[0],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
-					  | SM(gainBoundaries[1],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
-					  | SM(gainBoundaries[2],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
-					  | SM(gainBoundaries[3],
-				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
-			}
-
-			regOffset =
-				AR_PHY_BASE + (672 << 2) + regChainOffset;
-			for (j = 0; j < 32; j++) {
-				reg32 =
-					((pdadcValues[4 * j + 0] & 0xFF) << 0)
-					| ((pdadcValues[4 * j + 1] & 0xFF) <<
-					   8) | ((pdadcValues[4 * j + 2] &
-						  0xFF) << 16) |
-					((pdadcValues[4 * j + 3] & 0xFF) <<
-					 24);
-				REG_WRITE(ah, regOffset, reg32);
-
-				DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
-					 "PDADC (%d,%4x): %4.4x %8.8x\n",
-					 i, regChainOffset, regOffset,
-					 reg32);
-				DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
-				"PDADC: Chain %d | PDADC %3d Value %3d | "
-				"PDADC %3d Value %3d | PDADC %3d Value %3d | "
-				"PDADC %3d Value %3d |\n",
-					 i, 4 * j, pdadcValues[4 * j],
-					 4 * j + 1, pdadcValues[4 * j + 1],
-					 4 * j + 2, pdadcValues[4 * j + 2],
-					 4 * j + 3,
-					 pdadcValues[4 * j + 3]);
-
-				regOffset += 4;
-			}
-		}
-	}
-	*pTxPowerIndexOffset = 0;
-
-	return true;
-}
-
-void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u8 i;
-
-	if (ah->ah_isPciExpress != true)
-		return;
-
-	if (ah->ah_config.pcie_powersave_enable == 2)
-		return;
-
-	if (restore)
-		return;
-
-	if (AR_SREV_9280_20_OR_LATER(ah)) {
-		for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
-			REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
-				  INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
-		}
-		udelay(1000);
-	} else if (AR_SREV_9280(ah)
-		   && (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
-
-		if (ah->ah_config.pcie_clock_req)
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
-		else
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
-
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-
-		udelay(1000);
-	} else {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-	}
-
-	REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
-
-	if (ah->ah_config.pcie_waen) {
-		REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
-	} else {
-		if (AR_SREV_9280(ah))
-			REG_WRITE(ah, AR_WA, 0x0040073f);
-		else
-			REG_WRITE(ah, AR_WA, 0x0000073f);
-	}
-}
-
-static void
-ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
-				  struct ath9k_channel *chan,
-				  struct cal_target_power_leg *powInfo,
-				  u16 numChannels,
-				  struct cal_target_power_leg *pNewPower,
-				  u16 numRates,
-				  bool isExtTarget)
-{
-	u16 clo, chi;
-	int i;
-	int matchIndex = -1, lowIndex = -1;
-	u16 freq;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
-
-	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
-		IS_CHAN_2GHZ(chan))) {
-		matchIndex = 0;
-	} else {
-		for (i = 0; (i < numChannels)
-		     && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-			if (freq ==
-			    ath9k_hw_fbin2freq(powInfo[i].bChannel,
-					       IS_CHAN_2GHZ(chan))) {
-				matchIndex = i;
-				break;
-			} else if ((freq <
-				    ath9k_hw_fbin2freq(powInfo[i].bChannel,
-						       IS_CHAN_2GHZ(chan)))
-				   && (freq >
-				       ath9k_hw_fbin2freq(powInfo[i - 1].
-							  bChannel,
-							  IS_CHAN_2GHZ
-							  (chan)))) {
-				lowIndex = i - 1;
-				break;
-			}
-		}
-		if ((matchIndex == -1) && (lowIndex == -1))
-			matchIndex = i - 1;
-	}
-
-	if (matchIndex != -1) {
-		*pNewPower = powInfo[matchIndex];
-	} else {
-		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
-					 IS_CHAN_2GHZ(chan));
-		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
-					 IS_CHAN_2GHZ(chan));
-
-		for (i = 0; i < numRates; i++) {
-			pNewPower->tPow2x[i] =
-				(u8) ath9k_hw_interpolate(freq, clo, chi,
-								powInfo
-								[lowIndex].
-								tPow2x[i],
-								powInfo
-								[lowIndex +
-								 1].tPow2x[i]);
-		}
-	}
-}
-
-static void
-ath9k_hw_get_target_powers(struct ath_hal *ah,
-			   struct ath9k_channel *chan,
-			   struct cal_target_power_ht *powInfo,
-			   u16 numChannels,
-			   struct cal_target_power_ht *pNewPower,
-			   u16 numRates,
-			   bool isHt40Target)
-{
-	u16 clo, chi;
-	int i;
-	int matchIndex = -1, lowIndex = -1;
-	u16 freq;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
-
-	if (freq <=
-		ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
-		matchIndex = 0;
-	} else {
-		for (i = 0; (i < numChannels)
-		     && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-			if (freq ==
-			    ath9k_hw_fbin2freq(powInfo[i].bChannel,
-					       IS_CHAN_2GHZ(chan))) {
-				matchIndex = i;
-				break;
-			} else
-				if ((freq <
-				     ath9k_hw_fbin2freq(powInfo[i].bChannel,
-							IS_CHAN_2GHZ(chan)))
-				    && (freq >
-					ath9k_hw_fbin2freq(powInfo[i - 1].
-							   bChannel,
-							   IS_CHAN_2GHZ
-							   (chan)))) {
-					lowIndex = i - 1;
-					break;
-				}
-		}
-		if ((matchIndex == -1) && (lowIndex == -1))
-			matchIndex = i - 1;
-	}
-
-	if (matchIndex != -1) {
-		*pNewPower = powInfo[matchIndex];
-	} else {
-		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
-					 IS_CHAN_2GHZ(chan));
-		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
-					 IS_CHAN_2GHZ(chan));
-
-		for (i = 0; i < numRates; i++) {
-			pNewPower->tPow2x[i] =
-				(u8) ath9k_hw_interpolate(freq, clo, chi,
-								powInfo
-								[lowIndex].
-								tPow2x[i],
-								powInfo
-								[lowIndex +
-								 1].tPow2x[i]);
-		}
-	}
-}
-
-static u16
-ath9k_hw_get_max_edge_power(u16 freq,
-			    struct cal_ctl_edges *pRdEdgesPower,
-			    bool is2GHz)
-{
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-	int i;
-
-	for (i = 0; (i < AR5416_NUM_BAND_EDGES)
-	     && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
-					       is2GHz)) {
-			twiceMaxEdgePower = pRdEdgesPower[i].tPower;
-			break;
-		} else if ((i > 0)
-			   && (freq <
-			       ath9k_hw_fbin2freq(pRdEdgesPower[i].
-						  bChannel, is2GHz))) {
-			if (ath9k_hw_fbin2freq
-			    (pRdEdgesPower[i - 1].bChannel, is2GHz) < freq
-			    && pRdEdgesPower[i - 1].flag) {
-				twiceMaxEdgePower =
-					pRdEdgesPower[i - 1].tPower;
-			}
-			break;
-		}
-	}
-	return twiceMaxEdgePower;
-}
-
-static bool
-ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
-				  struct ar5416_eeprom *pEepData,
-				  struct ath9k_channel *chan,
-				  int16_t *ratesArray,
-				  u16 cfgCtl,
-				  u8 AntennaReduction,
-				  u8 twiceMaxRegulatoryPower,
-				  u8 powerLimit)
-{
-	u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
-
-	int i;
-	int8_t twiceLargestAntenna;
-	struct cal_ctl_data *rep;
-	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
-		0, { 0, 0, 0, 0}
-	};
-	struct cal_target_power_leg targetPowerOfdmExt = {
-		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
-		0, { 0, 0, 0, 0 }
-	};
-	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
-		0, {0, 0, 0, 0}
-	};
-	u8 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11a[] =
-		{ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
-	u16 ctlModesFor11g[] =
-		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
-		  CTL_2GHT40
-		};
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
-	struct chan_centers centers;
-	int tx_chainmask;
-	u8 twiceMinEdgePower;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	tx_chainmask = ahp->ah_txchainmask;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	twiceLargestAntenna = max(
-		pEepData->modalHeader
-			[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
-		pEepData->modalHeader
-			[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
-	twiceLargestAntenna = max((u8) twiceLargestAntenna,
-		pEepData->modalHeader
-			[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
-	twiceLargestAntenna =
-		(int8_t) min(AntennaReduction - twiceLargestAntenna, 0);
-
-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
-	if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
-		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->ah_tpScale)] * 2);
-	}
-
-	scaledPower = min(powerLimit, maxRegAllowedPower);
-
-	switch (ar5416_get_ntxchains(tx_chainmask)) {
-	case 1:
+	switch (devid) {
+	case AR5416_DEVID_PCI:
+	case AR5416_DEVID_PCIE:
+	case AR9160_DEVID_PCI:
+	case AR9280_DEVID_PCI:
+	case AR9280_DEVID_PCIE:
+		ah = ath9k_hw_do_attach(devid, sc, mem, error);
 		break;
-	case 2:
-		scaledPower -=
-			pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
-			pwrDecreaseFor2Chain;
-		break;
-	case 3:
-		scaledPower -=
-			pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
-			pwrDecreaseFor3Chain;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+			 "devid=0x%x not supported.\n", devid);
+		ah = NULL;
+		*error = -ENXIO;
 		break;
 	}
 
-	scaledPower = max(0, (int32_t) scaledPower);
+	return ah;
+}
 
-	if (IS_CHAN_2GHZ(chan)) {
-		numCtlModes =
-			ARRAY_SIZE(ctlModesFor11g) -
-			SUB_NUM_CTL_MODES_AT_2G_40;
-		pCtlMode = ctlModesFor11g;
+/*******/
+/* INI */
+/*******/
 
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->
-			calTargetPowerCck,
-			AR5416_NUM_2G_CCK_TARGET_POWERS,
-			&targetPowerCck, 4,
-			false);
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->
-			calTargetPower2G,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerOfdm, 4,
-			false);
-		ath9k_hw_get_target_powers(ah, chan,
-			pEepData->calTargetPower2GHT20,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerHt20, 8, false);
+static void ath9k_hw_override_ini(struct ath_hal *ah,
+				  struct ath9k_channel *chan)
+{
+	if (!AR_SREV_5416_V20_OR_LATER(ah) ||
+	    AR_SREV_9280_10_OR_LATER(ah))
+		return;
 
-		if (IS_CHAN_HT40(chan)) {
-			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
-			ath9k_hw_get_target_powers(ah, chan,
-				pEepData->
-				calTargetPower2GHT40,
-				AR5416_NUM_2G_40_TARGET_POWERS,
-				&targetPowerHt40, 8,
-				true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->
-				calTargetPowerCck,
-				AR5416_NUM_2G_CCK_TARGET_POWERS,
-				&targetPowerCckExt,
-				4, true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->
-				calTargetPower2G,
-				AR5416_NUM_2G_20_TARGET_POWERS,
-				&targetPowerOfdmExt,
-				4, true);
+	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+}
+
+static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
+			      struct ar5416_eeprom *pEepData,
+			      u32 reg, u32 value)
+{
+	struct base_eep_header *pBase = &(pEepData->baseEepHeader);
+
+	switch (ah->ah_devid) {
+	case AR9280_DEVID_PCI:
+		if (reg == 0x7894) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				"ini VAL: %x  EEPROM: %x\n", value,
+				(pBase->version & 0xff));
+
+			if ((pBase->version & 0xff) > 0x0a) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+					"PWDCLKIND: %d\n",
+					pBase->pwdclkind);
+				value &= ~AR_AN_TOP2_PWDCLKIND;
+				value |= AR_AN_TOP2_PWDCLKIND &
+					(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
+			} else {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+					"PWDCLKIND Earlier Rev\n");
+			}
+
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				"final ini VAL: %x\n", value);
 		}
-	} else {
-
-		numCtlModes =
-			ARRAY_SIZE(ctlModesFor11a) -
-			SUB_NUM_CTL_MODES_AT_5G_40;
-		pCtlMode = ctlModesFor11a;
-
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->
-			calTargetPower5G,
-			AR5416_NUM_5G_20_TARGET_POWERS,
-			&targetPowerOfdm, 4,
-			false);
-		ath9k_hw_get_target_powers(ah, chan,
-			pEepData->calTargetPower5GHT20,
-			AR5416_NUM_5G_20_TARGET_POWERS,
-			&targetPowerHt20, 8, false);
-
-		if (IS_CHAN_HT40(chan)) {
-			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
-			ath9k_hw_get_target_powers(ah, chan,
-				pEepData->
-				calTargetPower5GHT40,
-				AR5416_NUM_5G_40_TARGET_POWERS,
-				&targetPowerHt40, 8,
-				true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->
-				calTargetPower5G,
-				AR5416_NUM_5G_20_TARGET_POWERS,
-				&targetPowerOfdmExt,
-				4, true);
-		}
+		break;
 	}
 
-	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
-		bool isHt40CtlMode =
-			(pCtlMode[ctlMode] == CTL_5GHT40)
-			|| (pCtlMode[ctlMode] == CTL_2GHT40);
-		if (isHt40CtlMode)
-			freq = centers.synth_center;
-		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
-			freq = centers.ext_center;
-		else
-			freq = centers.ctl_center;
+	return value;
+}
 
-		if (ar5416_get_eep_ver(ahp) == 14
-		    && ar5416_get_eep_rev(ahp) <= 2)
-			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+static int ath9k_hw_process_ini(struct ath_hal *ah,
+				struct ath9k_channel *chan,
+				enum ath9k_ht_macmode macmode)
+{
+	int i, regWrites = 0;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 modesIndex, freqIndex;
+	int status;
 
+	switch (chan->chanmode) {
+	case CHANNEL_A:
+	case CHANNEL_A_HT20:
+		modesIndex = 1;
+		freqIndex = 1;
+		break;
+	case CHANNEL_A_HT40PLUS:
+	case CHANNEL_A_HT40MINUS:
+		modesIndex = 2;
+		freqIndex = 1;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_G_HT20:
+	case CHANNEL_B:
+		modesIndex = 4;
+		freqIndex = 2;
+		break;
+	case CHANNEL_G_HT40PLUS:
+	case CHANNEL_G_HT40MINUS:
+		modesIndex = 3;
+		freqIndex = 2;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+
+	ath9k_hw_set_addac(ah, chan);
+
+	if (AR_SREV_5416_V22_OR_LATER(ah)) {
+		REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
+	} else {
+		struct ar5416IniArray temp;
+		u32 addacSize =
+			sizeof(u32) * ahp->ah_iniAddac.ia_rows *
+			ahp->ah_iniAddac.ia_columns;
+
+		memcpy(ahp->ah_addac5416_21,
+		       ahp->ah_iniAddac.ia_array, addacSize);
+
+		(ahp->ah_addac5416_21)[31 * ahp->ah_iniAddac.ia_columns + 1] = 0;
+
+		temp.ia_array = ahp->ah_addac5416_21;
+		temp.ia_columns = ahp->ah_iniAddac.ia_columns;
+		temp.ia_rows = ahp->ah_iniAddac.ia_rows;
+		REG_WRITE_ARRAY(&temp, 1, regWrites);
+	}
+
+	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+	for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
+		u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
+		u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
+
+#ifdef CONFIG_SLOW_ANT_DIV
+		if (ah->ah_devid == AR9280_DEVID_PCI)
+			val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg, val);
+#endif
+
+		REG_WRITE(ah, reg, val);
+
+		if (reg >= 0x7800 && reg < 0x78a0
+		    && ah->ah_config.analog_shiftreg) {
+			udelay(100);
+		}
+
+		DO_DELAY(regWrites);
+	}
+
+	for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
+		u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
+		u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
+
+		REG_WRITE(ah, reg, val);
+
+		if (reg >= 0x7800 && reg < 0x78a0
+		    && ah->ah_config.analog_shiftreg) {
+			udelay(100);
+		}
+
+		DO_DELAY(regWrites);
+	}
+
+	ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
+
+	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
+		REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
+				regWrites);
+	}
+
+	ath9k_hw_override_ini(ah, chan);
+	ath9k_hw_set_regs(ah, chan, macmode);
+	ath9k_hw_init_chain_masks(ah);
+
+	status = ath9k_hw_set_txpower(ah, chan,
+				      ath9k_regd_get_ctl(ah, chan),
+				      ath9k_regd_get_antenna_allowed(ah,
+								     chan),
+				      chan->maxRegTxPower * 2,
+				      min((u32) MAX_RATE_POWER,
+					  (u32) ah->ah_powerLimit));
+	if (status != 0) {
 		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
-			"EXT_ADDITIVE %d\n",
-			 ctlMode, numCtlModes, isHt40CtlMode,
-			 (pCtlMode[ctlMode] & EXT_ADDITIVE));
-
-		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
-		     i++) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
-				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
-				"chan %d\n",
-				i, cfgCtl, pCtlMode[ctlMode],
-				pEepData->ctlIndex[i], chan->channel);
-
-			if ((((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     pEepData->ctlIndex[i])
-			    ||
-			    (((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     ((pEepData->
-			       ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
-				rep = &(pEepData->ctlData[i]);
-
-				twiceMinEdgePower =
-					ath9k_hw_get_max_edge_power(freq,
-						rep->
-						ctlEdges
-						[ar5416_get_ntxchains
-						(tx_chainmask)
-						- 1],
-						IS_CHAN_2GHZ
-						(chan));
-
-				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-					"    MATCH-EE_IDX %d: ch %d is2 %d "
-					"2xMinEdge %d chainmask %d chains %d\n",
-					 i, freq, IS_CHAN_2GHZ(chan),
-					 twiceMinEdgePower, tx_chainmask,
-					 ar5416_get_ntxchains
-					 (tx_chainmask));
-				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
-					twiceMaxEdgePower =
-						min(twiceMaxEdgePower,
-						    twiceMinEdgePower);
-				} else {
-					twiceMaxEdgePower =
-						twiceMinEdgePower;
-					break;
-				}
-			}
-		}
-
-		minCtlPower = min(twiceMaxEdgePower, scaledPower);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				"    SEL-Min ctlMode %d pCtlMode %d "
-				"2xMaxEdge %d sP %d minCtlPwr %d\n",
-			 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
-			 scaledPower, minCtlPower);
-
-		switch (pCtlMode[ctlMode]) {
-		case CTL_11B:
-			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
-			     i++) {
-				targetPowerCck.tPow2x[i] =
-					min(targetPowerCck.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11A:
-		case CTL_11G:
-			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
-			     i++) {
-				targetPowerOfdm.tPow2x[i] =
-					min(targetPowerOfdm.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_5GHT20:
-		case CTL_2GHT20:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
-			     i++) {
-				targetPowerHt20.tPow2x[i] =
-					min(targetPowerHt20.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11B_EXT:
-			targetPowerCckExt.tPow2x[0] =
-				min(targetPowerCckExt.tPow2x[0], minCtlPower);
-			break;
-		case CTL_11A_EXT:
-		case CTL_11G_EXT:
-			targetPowerOfdmExt.tPow2x[0] =
-				min(targetPowerOfdmExt.tPow2x[0], minCtlPower);
-			break;
-		case CTL_5GHT40:
-		case CTL_2GHT40:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
-			     i++) {
-				targetPowerHt40.tPow2x[i] =
-					min(targetPowerHt40.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		default:
-			break;
-		}
-	}
-
-	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
-		ratesArray[rate18mb] = ratesArray[rate24mb] =
-		targetPowerOfdm.tPow2x[0];
-	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
-	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
-	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
-	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
-	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
-		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
-	if (IS_CHAN_2GHZ(chan)) {
-		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
-		ratesArray[rate2s] = ratesArray[rate2l] =
-			targetPowerCck.tPow2x[1];
-		ratesArray[rate5_5s] = ratesArray[rate5_5l] =
-			targetPowerCck.tPow2x[2];
-		;
-		ratesArray[rate11s] = ratesArray[rate11l] =
-			targetPowerCck.tPow2x[3];
-		;
-	}
-	if (IS_CHAN_HT40(chan)) {
-		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
-			ratesArray[rateHt40_0 + i] =
-				targetPowerHt40.tPow2x[i];
-		}
-		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
-		if (IS_CHAN_2GHZ(chan)) {
-			ratesArray[rateExtCck] =
-				targetPowerCckExt.tPow2x[0];
-		}
-	}
-	return true;
-}
-
-static int
-ath9k_hw_set_txpower(struct ath_hal *ah,
-		     struct ar5416_eeprom *pEepData,
-		     struct ath9k_channel *chan,
-		     u16 cfgCtl,
-		     u8 twiceAntennaReduction,
-		     u8 twiceMaxRegulatoryPower,
-		     u8 powerLimit)
-{
-	struct modal_eep_header *pModal =
-		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
-	int16_t ratesArray[Ar5416RateSize];
-	int16_t txPowerIndexOffset = 0;
-	u8 ht40PowerIncForPdadc = 2;
-	int i;
-
-	memset(ratesArray, 0, sizeof(ratesArray));
-
-	if ((pEepData->baseEepHeader.
-	     version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
-	}
-
-	if (!ath9k_hw_set_power_per_rate_table(ah, pEepData, chan,
-					       &ratesArray[0], cfgCtl,
-					       twiceAntennaReduction,
-					       twiceMaxRegulatoryPower,
-					       powerLimit)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"ath9k_hw_set_txpower: unable to set "
-			"tx power per rate table\n");
+			"%s: error init'ing transmit power\n", __func__);
 		return -EIO;
 	}
 
-	if (!ath9k_hw_set_power_cal_table
-	    (ah, pEepData, chan, &txPowerIndexOffset)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "ath9k_hw_set_txpower: unable to set power table\n");
+	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+			"%s: ar5416SetRfRegs failed\n", __func__);
 		return -EIO;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-		ratesArray[i] =
-			(int16_t) (txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		for (i = 0; i < Ar5416RateSize; i++)
-			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
-		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate6mb], 0)
-		);
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
-		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate24mb], 0)
-		);
-
-	if (IS_CHAN_2GHZ(chan)) {
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
-			  ATH9K_POW_SM(ratesArray[rate2s], 24)
-			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
-			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
-			  | ATH9K_POW_SM(ratesArray[rate1l], 0)
-			);
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
-			  ATH9K_POW_SM(ratesArray[rate11s], 24)
-			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
-			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
-			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0)
-			);
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
-		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)
-		);
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
-		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)
-		);
-
-	if (IS_CHAN_HT40(chan)) {
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
-			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
-					 ht40PowerIncForPdadc, 0)
-			);
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
-			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
-					 ht40PowerIncForPdadc, 0)
-			);
-
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
-			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
-			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
-			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
-			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0)
-			);
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
-		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
-		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)
-		);
-
-	i = rate6mb;
-	if (IS_CHAN_HT40(chan))
-		i = rateHt40_0;
-	else if (IS_CHAN_HT20(chan))
-		i = rateHt20_0;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->ah_maxPowerLevel =
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
-	else
-		ah->ah_maxPowerLevel = ratesArray[i];
-
 	return 0;
 }
 
+/****************************************/
+/* Reset and Channel Switching Routines */
+/****************************************/
+
+static void ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+	u32 rfMode = 0;
+
+	if (chan == NULL)
+		return;
+
+	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+	if (!AR_SREV_9280_10_OR_LATER(ah))
+		rfMode |= (IS_CHAN_5GHZ(chan)) ?
+			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+
+	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
+		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+	REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
+{
+	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static inline void ath9k_hw_set_dma(struct ath_hal *ah)
+{
+	u32 regval;
+
+	regval = REG_READ(ah, AR_AHB_MODE);
+	REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+
+	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
+	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
+
+	REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
+
+	regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
+	REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
+
+	REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+	if (AR_SREV_9285(ah)) {
+		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+			  AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+	} else {
+		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+			  AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+	}
+}
+
+static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
+{
+	u32 val;
+
+	val = REG_READ(ah, AR_STA_ID1);
+	val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+	switch (opmode) {
+	case ATH9K_M_HOSTAP:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
+			  | AR_STA_ID1_KSRCH_MODE);
+		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+		break;
+	case ATH9K_M_IBSS:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
+			  | AR_STA_ID1_KSRCH_MODE);
+		REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+		break;
+	case ATH9K_M_STA:
+	case ATH9K_M_MONITOR:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+		break;
+	}
+}
+
 static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah,
 						 u32 coef_scaled,
 						 u32 *coef_mantissa,
@@ -4632,9 +1402,8 @@
 	*coef_exponent = coef_exp - 16;
 }
 
-static void
-ath9k_hw_set_delta_slope(struct ath_hal *ah,
-			 struct ath9k_channel *chan)
+static void ath9k_hw_set_delta_slope(struct ath_hal *ah,
+				     struct ath9k_channel *chan)
 {
 	u32 coef_scaled, ds_coef_exp, ds_coef_man;
 	u32 clockMhzScaled = 0x64000000;
@@ -4667,8 +1436,242 @@
 		      AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
 }
 
-static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah,
-					struct ath9k_channel *chan)
+static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
+{
+	u32 rst_flags;
+	u32 tmpReg;
+
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+		  AR_RTC_FORCE_WAKE_ON_INT);
+
+	if (AR_SREV_9100(ah)) {
+		rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+			AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+	} else {
+		tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+		if (tmpReg &
+		    (AR_INTR_SYNC_LOCAL_TIMEOUT |
+		     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+		} else {
+			REG_WRITE(ah, AR_RC, AR_RC_AHB);
+		}
+
+		rst_flags = AR_RTC_RC_MAC_WARM;
+		if (type == ATH9K_RESET_COLD)
+			rst_flags |= AR_RTC_RC_MAC_COLD;
+	}
+
+	REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
+	udelay(50);
+
+	REG_WRITE(ah, (u16) (AR_RTC_RC), 0);
+	if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+			"%s: RTC stuck in MAC reset\n",
+			__func__);
+		return false;
+	}
+
+	if (!AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_RC, 0);
+
+	ath9k_hw_init_pll(ah, NULL);
+
+	if (AR_SREV_9100(ah))
+		udelay(50);
+
+	return true;
+}
+
+static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
+{
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+		  AR_RTC_FORCE_WAKE_ON_INT);
+
+	REG_WRITE(ah, (u16) (AR_RTC_RESET), 0);
+	REG_WRITE(ah, (u16) (AR_RTC_RESET), 1);
+
+	if (!ath9k_hw_wait(ah,
+			   AR_RTC_STATUS,
+			   AR_RTC_STATUS_M,
+			   AR_RTC_STATUS_ON)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: RTC not waking up\n",
+			 __func__);
+		return false;
+	}
+
+	ath9k_hw_read_revisions(ah);
+
+	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
+}
+
+static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type)
+{
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+		  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+	switch (type) {
+	case ATH9K_RESET_POWER_ON:
+		return ath9k_hw_set_reset_power_on(ah);
+		break;
+	case ATH9K_RESET_WARM:
+	case ATH9K_RESET_COLD:
+		return ath9k_hw_set_reset(ah, type);
+		break;
+	default:
+		return false;
+	}
+}
+
+static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+			      enum ath9k_ht_macmode macmode)
+{
+	u32 phymode;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
+
+	if (IS_CHAN_HT40(chan)) {
+		phymode |= AR_PHY_FC_DYN2040_EN;
+
+		if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+		    (chan->chanmode == CHANNEL_G_HT40PLUS))
+			phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+		if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
+			phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+	}
+	REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+	ath9k_hw_set11nmac2040(ah, macmode);
+
+	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static bool ath9k_hw_chip_reset(struct ath_hal *ah,
+				struct ath9k_channel *chan)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+		return false;
+
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+		return false;
+
+	ahp->ah_chipFullSleep = false;
+
+	ath9k_hw_init_pll(ah, chan);
+
+	ath9k_hw_set_rfmode(ah, chan);
+
+	return true;
+}
+
+static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
+						 struct ath9k_channel *chan)
+{
+	if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			"%s: invalid channel %u/0x%x; not marked as "
+			"2GHz or 5GHz\n", __func__, chan->channel,
+			chan->channelFlags);
+		return NULL;
+	}
+
+	if (!IS_CHAN_OFDM(chan) &&
+	    !IS_CHAN_CCK(chan) &&
+	    !IS_CHAN_HT20(chan) &&
+	    !IS_CHAN_HT40(chan)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			"%s: invalid channel %u/0x%x; not marked as "
+			"OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
+			__func__, chan->channel, chan->channelFlags);
+		return NULL;
+	}
+
+	return ath9k_regd_check_channel(ah, chan);
+}
+
+static bool ath9k_hw_channel_change(struct ath_hal *ah,
+				    struct ath9k_channel *chan,
+				    enum ath9k_ht_macmode macmode)
+{
+	u32 synthDelay, qnum;
+
+	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+		if (ath9k_hw_numtxpending(ah, qnum)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				"%s: Transmit frames pending on queue %d\n",
+				__func__, qnum);
+			return false;
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+			   AR_PHY_RFBUS_GRANT_EN)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
+			"%s: Could not kill baseband RX\n", __func__);
+		return false;
+	}
+
+	ath9k_hw_set_regs(ah, chan, macmode);
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+				"%s: failed to set channel\n", __func__);
+			return false;
+		}
+	} else {
+		if (!(ath9k_hw_set_channel(ah, chan))) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+				"%s: failed to set channel\n", __func__);
+			return false;
+		}
+	}
+
+	if (ath9k_hw_set_txpower(ah, chan,
+				 ath9k_regd_get_ctl(ah, chan),
+				 ath9k_regd_get_antenna_allowed(ah, chan),
+				 chan->maxRegTxPower * 2,
+				 min((u32) MAX_RATE_POWER,
+				     (u32) ah->ah_powerLimit)) != 0) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"%s: error init'ing transmit power\n", __func__);
+		return false;
+	}
+
+	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+	if (IS_CHAN_CCK(chan))
+		synthDelay = (4 * synthDelay) / 22;
+	else
+		synthDelay /= 10;
+
+	udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+		ath9k_hw_set_delta_slope(ah, chan);
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ath9k_hw_9280_spur_mitigate(ah, chan);
+	else
+		ath9k_hw_spur_mitigate(ah, chan);
+
+	if (!chan->oneTimeCalsDone)
+		chan->oneTimeCalsDone = true;
+
+	return true;
+}
+
+static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
 {
 	int bb_spur = AR_NO_SPUR;
 	int freq;
@@ -4918,8 +1921,7 @@
 	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
 }
 
-static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
-				   struct ath9k_channel *chan)
+static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
 {
 	int bb_spur = AR_NO_SPUR;
 	int bin, cur_bin;
@@ -5120,752 +2122,11 @@
 	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
 }
 
-static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int rx_chainmask, tx_chainmask;
-
-	rx_chainmask = ahp->ah_rxchainmask;
-	tx_chainmask = ahp->ah_txchainmask;
-
-	switch (rx_chainmask) {
-	case 0x5:
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	case 0x3:
-		if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
-			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
-			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
-			break;
-		}
-	case 0x1:
-	case 0x2:
-		if (!AR_SREV_9280(ah))
-			break;
-	case 0x7:
-		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-		break;
-	default:
-		break;
-	}
-
-	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
-	if (tx_chainmask == 0x5) {
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	}
-	if (AR_SREV_9100(ah))
-		REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
-			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
-}
-
-static void ath9k_hw_set_addac(struct ath_hal *ah,
-			       struct ath9k_channel *chan)
-{
-	struct modal_eep_header *pModal;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ar5416_eeprom *eep = &ahp->ah_eeprom;
-	u8 biaslevel;
-
-	if (ah->ah_macVersion != AR_SREV_VERSION_9160)
-		return;
-
-	if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
-		return;
-
-	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
-	if (pModal->xpaBiasLvl != 0xff) {
-		biaslevel = pModal->xpaBiasLvl;
-	} else {
-
-		u16 resetFreqBin, freqBin, freqCount = 0;
-		struct chan_centers centers;
-
-		ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-		resetFreqBin =
-			FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
-		freqBin = pModal->xpaBiasLvlFreq[0] & 0xff;
-		biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14);
-
-		freqCount++;
-
-		while (freqCount < 3) {
-			if (pModal->xpaBiasLvlFreq[freqCount] == 0x0)
-				break;
-
-			freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff;
-			if (resetFreqBin >= freqBin) {
-				biaslevel =
-					(u8) (pModal->
-						    xpaBiasLvlFreq[freqCount]
-						    >> 14);
-			} else {
-				break;
-			}
-			freqCount++;
-		}
-	}
-
-	if (IS_CHAN_2GHZ(chan)) {
-		INI_RA(&ahp->ah_iniAddac, 7, 1) =
-			(INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel
-			<< 3;
-	} else {
-		INI_RA(&ahp->ah_iniAddac, 6, 1) =
-			(INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel
-			<< 6;
-	}
-}
-
-static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks)
-{
-	if (ah->ah_curchan != NULL)
-		return clks /
-		CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)];
-	else
-		return clks / CLOCK_RATE[ATH9K_MODE_11B];
-}
-
-static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
-{
-	struct ath9k_channel *chan = ah->ah_curchan;
-
-	if (chan && IS_CHAN_HT40(chan))
-		return ath9k_hw_mac_usec(ah, clks) / 2;
-	else
-		return ath9k_hw_mac_usec(ah, clks);
-}
-
-static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
-{
-	if (ah->ah_curchan != NULL)
-		return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
-			ah->ah_curchan)];
-	else
-		return usecs * CLOCK_RATE[ATH9K_MODE_11B];
-}
-
-static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
-{
-	struct ath9k_channel *chan = ah->ah_curchan;
-
-	if (chan && IS_CHAN_HT40(chan))
-		return ath9k_hw_mac_clks(ah, usecs) * 2;
-	else
-		return ath9k_hw_mac_clks(ah, usecs);
-}
-
-static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n",
-			 __func__, us);
-		ahp->ah_acktimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_TIME_OUT,
-			      AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
-		ahp->ah_acktimeout = us;
-		return true;
-	}
-}
-
-static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n",
-			 __func__, us);
-		ahp->ah_ctstimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_TIME_OUT,
-			      AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
-		ahp->ah_ctstimeout = us;
-		return true;
-	}
-}
-static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah,
-					  u32 tu)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (tu > 0xFFFF) {
-		DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
-			"%s: bad global tx timeout %u\n", __func__, tu);
-		ahp->ah_globaltxtimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
-		ahp->ah_globaltxtimeout = tu;
-		return true;
-	}
-}
-
-bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n",
-			 __func__, us);
-		ahp->ah_slottime = (u32) -1;
-		return false;
-	} else {
-		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
-		ahp->ah_slottime = us;
-		return true;
-	}
-}
-
-static void ath9k_hw_init_user_settings(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n",
-		 __func__, ahp->ah_miscMode);
-	if (ahp->ah_miscMode != 0)
-		REG_WRITE(ah, AR_PCU_MISC,
-			  REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
-	if (ahp->ah_slottime != (u32) -1)
-		ath9k_hw_setslottime(ah, ahp->ah_slottime);
-	if (ahp->ah_acktimeout != (u32) -1)
-		ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
-	if (ahp->ah_ctstimeout != (u32) -1)
-		ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
-	if (ahp->ah_globaltxtimeout != (u32) -1)
-		ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
-}
-
-static int
-ath9k_hw_process_ini(struct ath_hal *ah,
-		     struct ath9k_channel *chan,
-		     enum ath9k_ht_macmode macmode)
-{
-	int i, regWrites = 0;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 modesIndex, freqIndex;
-	int status;
-
-	switch (chan->chanmode) {
-	case CHANNEL_A:
-	case CHANNEL_A_HT20:
-		modesIndex = 1;
-		freqIndex = 1;
-		break;
-	case CHANNEL_A_HT40PLUS:
-	case CHANNEL_A_HT40MINUS:
-		modesIndex = 2;
-		freqIndex = 1;
-		break;
-	case CHANNEL_G:
-	case CHANNEL_G_HT20:
-	case CHANNEL_B:
-		modesIndex = 4;
-		freqIndex = 2;
-		break;
-	case CHANNEL_G_HT40PLUS:
-	case CHANNEL_G_HT40MINUS:
-		modesIndex = 3;
-		freqIndex = 2;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	REG_WRITE(ah, AR_PHY(0), 0x00000007);
-
-	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-
-	ath9k_hw_set_addac(ah, chan);
-
-	if (AR_SREV_5416_V22_OR_LATER(ah)) {
-		REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
-	} else {
-		struct ar5416IniArray temp;
-		u32 addacSize =
-			sizeof(u32) * ahp->ah_iniAddac.ia_rows *
-			ahp->ah_iniAddac.ia_columns;
-
-		memcpy(ahp->ah_addac5416_21,
-		       ahp->ah_iniAddac.ia_array, addacSize);
-
-		(ahp->ah_addac5416_21)[31 *
-				       ahp->ah_iniAddac.ia_columns + 1] = 0;
-
-		temp.ia_array = ahp->ah_addac5416_21;
-		temp.ia_columns = ahp->ah_iniAddac.ia_columns;
-		temp.ia_rows = ahp->ah_iniAddac.ia_rows;
-		REG_WRITE_ARRAY(&temp, 1, regWrites);
-	}
-	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-
-	for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
-		u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
-		u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
-
-#ifdef CONFIG_SLOW_ANT_DIV
-		if (ah->ah_devid == AR9280_DEVID_PCI)
-			val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg,
-						 val);
-#endif
-
-		REG_WRITE(ah, reg, val);
-
-		if (reg >= 0x7800 && reg < 0x78a0
-		    && ah->ah_config.analog_shiftreg) {
-			udelay(100);
-		}
-
-		DO_DELAY(regWrites);
-	}
-
-	for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
-		u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
-		u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
-
-		REG_WRITE(ah, reg, val);
-
-		if (reg >= 0x7800 && reg < 0x78a0
-		    && ah->ah_config.analog_shiftreg) {
-			udelay(100);
-		}
-
-		DO_DELAY(regWrites);
-	}
-
-	ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
-
-	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
-		REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
-				regWrites);
-	}
-
-	ath9k_hw_override_ini(ah, chan);
-	ath9k_hw_set_regs(ah, chan, macmode);
-	ath9k_hw_init_chain_masks(ah);
-
-	status = ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
-				      ath9k_regd_get_ctl(ah, chan),
-				      ath9k_regd_get_antenna_allowed(ah,
-								     chan),
-				      chan->maxRegTxPower * 2,
-				      min((u32) MAX_RATE_POWER,
-					  (u32) ah->ah_powerLimit));
-	if (status != 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			 "%s: error init'ing transmit power\n", __func__);
-		return -EIO;
-	}
-
-	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			 "%s: ar5416SetRfRegs failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void ath9k_hw_setup_calibration(struct ath_hal *ah,
-					      struct hal_cal_list *currCal)
-{
-	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
-		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
-		      currCal->calData->calCountMax);
-
-	switch (currCal->calData->calType) {
-	case IQ_MISMATCH_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: starting IQ Mismatch Calibration\n",
-			 __func__);
-		break;
-	case ADC_GAIN_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: starting ADC Gain Calibration\n", __func__);
-		break;
-	case ADC_DC_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: starting ADC DC Calibration\n", __func__);
-		break;
-	case ADC_DC_INIT_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: starting Init ADC DC Calibration\n",
-			 __func__);
-		break;
-	}
-
-	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
-		    AR_PHY_TIMING_CTRL4_DO_CAL);
-}
-
-static void ath9k_hw_reset_calibration(struct ath_hal *ah,
-				       struct hal_cal_list *currCal)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	ath9k_hw_setup_calibration(ah, currCal);
-
-	currCal->calState = CAL_RUNNING;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ahp->ah_Meas0.sign[i] = 0;
-		ahp->ah_Meas1.sign[i] = 0;
-		ahp->ah_Meas2.sign[i] = 0;
-		ahp->ah_Meas3.sign[i] = 0;
-	}
-
-	ahp->ah_CalSamples = 0;
-}
-
-static void
-ath9k_hw_per_calibration(struct ath_hal *ah,
-			 struct ath9k_channel *ichan,
-			 u8 rxchainmask,
-			 struct hal_cal_list *currCal,
-			 bool *isCalDone)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	*isCalDone = false;
-
-	if (currCal->calState == CAL_RUNNING) {
-		if (!(REG_READ(ah,
-			       AR_PHY_TIMING_CTRL4(0)) &
-		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
-
-			currCal->calData->calCollect(ah);
-
-			ahp->ah_CalSamples++;
-
-			if (ahp->ah_CalSamples >=
-			    currCal->calData->calNumSamples) {
-				int i, numChains = 0;
-				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-					if (rxchainmask & (1 << i))
-						numChains++;
-				}
-
-				currCal->calData->calPostProc(ah,
-							      numChains);
-
-				ichan->CalValid |=
-					currCal->calData->calType;
-				currCal->calState = CAL_DONE;
-				*isCalDone = true;
-			} else {
-				ath9k_hw_setup_calibration(ah, currCal);
-			}
-		}
-	} else if (!(ichan->CalValid & currCal->calData->calType)) {
-		ath9k_hw_reset_calibration(ah, currCal);
-	}
-}
-
-static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah,
-					  int init_cal_count)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel ichan;
-	bool isCalDone;
-	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
-	const struct hal_percal_data *calData = currCal->calData;
-	int i;
-
-	if (currCal == NULL)
-		return false;
-
-	ichan.CalValid = 0;
-
-	for (i = 0; i < init_cal_count; i++) {
-		ath9k_hw_reset_calibration(ah, currCal);
-
-		if (!ath9k_hw_wait(ah, AR_PHY_TIMING_CTRL4(0),
-				   AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: Cal %d failed to complete in 100ms.\n",
-				 __func__, calData->calType);
-
-			ahp->ah_cal_list = ahp->ah_cal_list_last =
-				ahp->ah_cal_list_curr = NULL;
-			return false;
-		}
-
-		ath9k_hw_per_calibration(ah, &ichan, ahp->ah_rxchainmask,
-					 currCal, &isCalDone);
-		if (!isCalDone) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: Not able to run Init Cal %d.\n",
-				 __func__, calData->calType);
-		}
-		if (currCal->calNext) {
-			currCal = currCal->calNext;
-			calData = currCal->calData;
-		}
-	}
-
-	ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
-	return true;
-}
-
-static bool
-ath9k_hw_channel_change(struct ath_hal *ah,
-			struct ath9k_channel *chan,
-			enum ath9k_ht_macmode macmode)
-{
-	u32 synthDelay, qnum;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
-		if (ath9k_hw_numtxpending(ah, qnum)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				 "%s: Transmit frames pending on queue %d\n",
-				 __func__, qnum);
-			return false;
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
-	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
-			   AR_PHY_RFBUS_GRANT_EN)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
-			 "%s: Could not kill baseband RX\n", __func__);
-		return false;
-	}
-
-	ath9k_hw_set_regs(ah, chan, macmode);
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				 "%s: failed to set channel\n", __func__);
-			return false;
-		}
-	} else {
-		if (!(ath9k_hw_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				 "%s: failed to set channel\n", __func__);
-			return false;
-		}
-	}
-
-	if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
-				 ath9k_regd_get_ctl(ah, chan),
-				 ath9k_regd_get_antenna_allowed(ah, chan),
-				 chan->maxRegTxPower * 2,
-				 min((u32) MAX_RATE_POWER,
-				     (u32) ah->ah_powerLimit)) != 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "%s: error init'ing transmit power\n", __func__);
-		return false;
-	}
-
-	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-	if (IS_CHAN_CCK(chan))
-		synthDelay = (4 * synthDelay) / 22;
-	else
-		synthDelay /= 10;
-
-	udelay(synthDelay + BASE_ACTIVATE_DELAY);
-
-	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
-
-	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
-		ath9k_hw_set_delta_slope(ah, chan);
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ath9k_hw_9280_spur_mitigate(ah, chan);
-	else
-		ath9k_hw_spur_mitigate(ah, chan);
-
-	if (!chan->oneTimeCalsDone)
-		chan->oneTimeCalsDone = true;
-
-	return true;
-}
-
-static bool ath9k_hw_chip_reset(struct ath_hal *ah,
-				struct ath9k_channel *chan)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
-		return false;
-
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-		return false;
-
-	ahp->ah_chipFullSleep = false;
-
-	ath9k_hw_init_pll(ah, chan);
-
-	ath9k_hw_set_rfmode(ah, chan);
-
-	return true;
-}
-
-static inline void ath9k_hw_set_dma(struct ath_hal *ah)
-{
-	u32 regval;
-
-	regval = REG_READ(ah, AR_AHB_MODE);
-	REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
-
-	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
-	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
-
-	REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
-
-	regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
-	REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
-
-	REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
-
-	if (AR_SREV_9285(ah)) {
-		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-			  AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
-	} else {
-		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-			  AR_PCU_TXBUF_CTRL_USABLE_SIZE);
-	}
-}
-
-bool ath9k_hw_stopdmarecv(struct ath_hal *ah)
-{
-	REG_WRITE(ah, AR_CR, AR_CR_RXD);
-	if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"%s: dma failed to stop in 10ms\n"
-			"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
-			__func__,
-			REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
-		return false;
-	} else {
-		return true;
-	}
-}
-
-void ath9k_hw_startpcureceive(struct ath_hal *ah)
-{
-	REG_CLR_BIT(ah, AR_DIAG_SW,
-		    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
-	ath9k_enable_mib_counters(ah);
-
-	ath9k_ani_reset(ah);
-}
-
-void ath9k_hw_stoppcurecv(struct ath_hal *ah)
-{
-	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-
-	ath9k_hw_disable_mib_counters(ah);
-}
-
-static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
-				     struct ath9k_channel *chan,
-				     enum hal_cal_types calType)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	bool retval = false;
-
-	switch (calType & ahp->ah_suppCals) {
-	case IQ_MISMATCH_CAL:
-		if (!IS_CHAN_B(chan))
-			retval = true;
-		break;
-	case ADC_GAIN_CAL:
-	case ADC_DC_CAL:
-		if (!IS_CHAN_B(chan)
-		    && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
-			retval = true;
-		break;
-	}
-
-	return retval;
-}
-
-static bool ath9k_hw_init_cal(struct ath_hal *ah,
-			      struct ath9k_channel *chan)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *ichan =
-		ath9k_regd_check_channel(ah, chan);
-
-	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
-		  AR_PHY_AGC_CONTROL_CAL);
-
-	if (!ath9k_hw_wait
-	    (ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: offset calibration failed to complete in 1ms; "
-			 "noisy environment?\n", __func__);
-		return false;
-	}
-
-	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
-		  AR_PHY_AGC_CONTROL_NF);
-
-	ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr =
-		NULL;
-
-	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
-		if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
-			INIT_CAL(&ahp->ah_adcGainCalData);
-			INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: enabling ADC Gain Calibration.\n",
-				 __func__);
-		}
-		if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
-			INIT_CAL(&ahp->ah_adcDcCalData);
-			INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: enabling ADC DC Calibration.\n",
-				 __func__);
-		}
-		if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
-			INIT_CAL(&ahp->ah_iqCalData);
-			INSERT_CAL(ahp, &ahp->ah_iqCalData);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "%s: enabling IQ Calibration.\n",
-				 __func__);
-		}
-
-		ahp->ah_cal_list_curr = ahp->ah_cal_list;
-
-		if (ahp->ah_cal_list_curr)
-			ath9k_hw_reset_calibration(ah,
-						   ahp->ah_cal_list_curr);
-	}
-
-	ichan->CalValid = 0;
-
-	return true;
-}
-
-
-bool ath9k_hw_reset(struct ath_hal *ah,
-		    struct ath9k_channel *chan,
+bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
 		    enum ath9k_ht_macmode macmode,
 		    u8 txchainmask, u8 rxchainmask,
 		    enum ath9k_ht_extprotspacing extprotspacing,
-		    bool bChannelChange,
-		    int *status)
+		    bool bChannelChange, int *status)
 {
 	u32 saveLedState;
 	struct ath_hal_5416 *ahp = AH5416(ah);
@@ -5886,8 +2147,8 @@
 
 	if (ath9k_hw_check_chan(ah, chan) == NULL) {
 		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: invalid channel %u/0x%x; no mapping\n",
-			 __func__, chan->channel, chan->channelFlags);
+			"%s: invalid channel %u/0x%x; no mapping\n",
+			__func__, chan->channel, chan->channelFlags);
 		ecode = -EINVAL;
 		goto bad;
 	}
@@ -5965,7 +2226,7 @@
 
 	if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "%s: error setting board options\n", __func__);
+			"%s: error setting board options\n", __func__);
 		ecode = -EIO;
 		goto bad;
 	}
@@ -6055,15 +2316,15 @@
 		mask = REG_READ(ah, AR_CFG);
 		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
 			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-				 "%s CFG Byte Swap Set 0x%x\n", __func__,
-				 mask);
+				"%s CFG Byte Swap Set 0x%x\n", __func__,
+				mask);
 		} else {
 			mask =
 				INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
 			REG_WRITE(ah, AR_CFG, mask);
 			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-				 "%s Setting CFG 0x%x\n", __func__,
-				 REG_READ(ah, AR_CFG));
+				"%s Setting CFG 0x%x\n", __func__,
+				REG_READ(ah, AR_CFG));
 		}
 	} else {
 #ifdef __BIG_ENDIAN
@@ -6078,693 +2339,404 @@
 	return false;
 }
 
-bool ath9k_hw_phy_disable(struct ath_hal *ah)
+/************************/
+/* Key Cache Management */
+/************************/
+
+bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry)
 {
-	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
-}
+	u32 keyType;
 
-bool ath9k_hw_disable(struct ath_hal *ah)
-{
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-		return false;
-
-	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
-}
-
-bool
-ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
-		   u8 rxchainmask, bool longcal,
-		   bool *isCalDone)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
-	struct ath9k_channel *ichan =
-		ath9k_regd_check_channel(ah, chan);
-
-	*isCalDone = true;
-
-	if (ichan == NULL) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			 "%s: invalid channel %u/0x%x; no mapping\n",
-			 __func__, chan->channel, chan->channelFlags);
+	if (entry >= ah->ah_caps.keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			"%s: entry %u out of range\n", __func__, entry);
 		return false;
 	}
 
-	if (currCal &&
-	    (currCal->calState == CAL_RUNNING ||
-	     currCal->calState == CAL_WAITING)) {
-		ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
-					 isCalDone);
-		if (*isCalDone) {
-			ahp->ah_cal_list_curr = currCal = currCal->calNext;
+	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
 
-			if (currCal->calState == CAL_WAITING) {
-				*isCalDone = false;
-				ath9k_hw_reset_calibration(ah, currCal);
-			}
-		}
+	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+		u16 micentry = entry + 64;
+
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
 	}
 
-	if (longcal) {
-		ath9k_hw_getnf(ah, ichan);
-		ath9k_hw_loadnf(ah, ah->ah_curchan);
-		ath9k_hw_start_nfcal(ah);
-
-		if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
-
-			chan->channelFlags |= CHANNEL_CW_INT;
-			ichan->channelFlags &= ~CHANNEL_CW_INT;
-		}
-	}
+	if (ah->ah_curchan == NULL)
+		return true;
 
 	return true;
 }
 
-static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
+bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac)
 {
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
+	u32 macHi, macLo;
 
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ahp->ah_totalPowerMeasI[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ahp->ah_totalPowerMeasQ[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ahp->ah_totalIqCorrMeas[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
-			 ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
-			 ahp->ah_totalPowerMeasQ[i],
-			 ahp->ah_totalIqCorrMeas[i]);
-	}
-}
-
-static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ahp->ah_totalAdcIOddPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ahp->ah_totalAdcIEvenPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ahp->ah_totalAdcQOddPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ahp->ah_totalAdcQEvenPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			"oddq=0x%08x; evenq=0x%08x;\n",
-			 ahp->ah_CalSamples, i,
-			 ahp->ah_totalAdcIOddPhase[i],
-			 ahp->ah_totalAdcIEvenPhase[i],
-			 ahp->ah_totalAdcQOddPhase[i],
-			 ahp->ah_totalAdcQEvenPhase[i]);
-	}
-}
-
-static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	int i;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			"oddq=0x%08x; evenq=0x%08x;\n",
-			 ahp->ah_CalSamples, i,
-			 ahp->ah_totalAdcDcOffsetIOddPhase[i],
-			 ahp->ah_totalAdcDcOffsetIEvenPhase[i],
-			 ahp->ah_totalAdcDcOffsetQOddPhase[i],
-			 ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
-	}
-}
-
-static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 powerMeasQ, powerMeasI, iqCorrMeas;
-	u32 qCoffDenom, iCoffDenom;
-	int32_t qCoff, iCoff;
-	int iqCorrNeg, i;
-
-	for (i = 0; i < numChains; i++) {
-		powerMeasI = ahp->ah_totalPowerMeasI[i];
-		powerMeasQ = ahp->ah_totalPowerMeasQ[i];
-		iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Starting IQ Cal and Correction for Chain %d\n",
-			 i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
-			 i, ahp->ah_totalIqCorrMeas[i]);
-
-		iqCorrNeg = 0;
-
-
-		if (iqCorrMeas > 0x80000000) {
-			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
-			iqCorrNeg = 1;
-		}
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-			 iqCorrNeg);
-
-		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
-		qCoffDenom = powerMeasQ / 64;
-
-		if (powerMeasQ != 0) {
-
-			iCoff = iqCorrMeas / iCoffDenom;
-			qCoff = powerMeasI / qCoffDenom - 64;
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "Chn %d iCoff = 0x%08x\n", i, iCoff);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "Chn %d qCoff = 0x%08x\n", i, qCoff);
-
-
-			iCoff = iCoff & 0x3f;
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
-			if (iqCorrNeg == 0x0)
-				iCoff = 0x40 - iCoff;
-
-			if (qCoff > 15)
-				qCoff = 15;
-			else if (qCoff <= -16)
-				qCoff = 16;
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
-				i, iCoff, qCoff);
-
-			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
-				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
-				      iCoff);
-			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
-				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
-				      qCoff);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"IQ Cal and Correction done for Chain %d\n",
-				i);
-		}
-	}
-
-	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
-		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
-}
-
-static void
-ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset,
-		qEvenMeasOffset;
-	u32 qGainMismatch, iGainMismatch, val, i;
-
-	for (i = 0; i < numChains; i++) {
-		iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
-		iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
-		qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
-		qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Starting ADC Gain Cal for Chain %d\n", i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
-			 iOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
-			 iEvenMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
-			 qOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
-			 qEvenMeasOffset);
-
-		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
-			iGainMismatch =
-				((iEvenMeasOffset * 32) /
-				 iOddMeasOffset) & 0x3f;
-			qGainMismatch =
-				((qOddMeasOffset * 32) /
-				 qEvenMeasOffset) & 0x3f;
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "Chn %d gain_mismatch_i = 0x%08x\n", i,
-				 iGainMismatch);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "Chn %d gain_mismatch_q = 0x%08x\n", i,
-				 qGainMismatch);
-
-			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
-			val &= 0xfffff000;
-			val |= (qGainMismatch) | (iGainMismatch << 6);
-			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				 "ADC Gain Cal done for Chain %d\n", i);
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
-		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
-		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
-}
-
-static void
-ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
-	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
-	const struct hal_percal_data *calData =
-		ahp->ah_cal_list_curr->calData;
-	u32 numSamples =
-		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
-
-	for (i = 0; i < numChains; i++) {
-		iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
-		iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
-		qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
-		qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Starting ADC DC Offset Cal for Chain %d\n", i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_odd_i = %d\n", i,
-			 iOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_even_i = %d\n", i,
-			 iEvenMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_odd_q = %d\n", i,
-			 qOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d pwr_meas_even_q = %d\n", i,
-			 qEvenMeasOffset);
-
-		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
-			       numSamples) & 0x1ff;
-		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
-			       numSamples) & 0x1ff;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
-			 iDcMismatch);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
-			 qDcMismatch);
-
-		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
-		val &= 0xc0000fff;
-		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
-		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "ADC DC Offset Cal done for Chain %d\n", i);
-	}
-
-	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
-		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
-		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
-}
-
-bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *chan = ah->ah_curchan;
-
-	ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
-
-	if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
-				 ath9k_regd_get_ctl(ah, chan),
-				 ath9k_regd_get_antenna_allowed(ah,
-								chan),
-				 chan->maxRegTxPower * 2,
-				 min((u32) MAX_RATE_POWER,
-				     (u32) ah->ah_powerLimit)) != 0)
+	if (entry >= ah->ah_caps.keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			"%s: entry %u out of range\n", __func__, entry);
 		return false;
-
-	return true;
-}
-
-void
-ath9k_hw_get_channel_centers(struct ath_hal *ah,
-			     struct ath9k_channel *chan,
-			     struct chan_centers *centers)
-{
-	int8_t extoff;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (!IS_CHAN_HT40(chan)) {
-		centers->ctl_center = centers->ext_center =
-			centers->synth_center = chan->channel;
-		return;
 	}
 
-	if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-	    (chan->chanmode == CHANNEL_G_HT40PLUS)) {
-		centers->synth_center =
-			chan->channel + HT40_CHANNEL_CENTER_SHIFT;
-		extoff = 1;
+	if (mac != NULL) {
+		macHi = (mac[5] << 8) | mac[4];
+		macLo = (mac[3] << 24) |
+			(mac[2] << 16) |
+			(mac[1] << 8) |
+			mac[0];
+		macLo >>= 1;
+		macLo |= (macHi & 1) << 31;
+		macHi >>= 1;
 	} else {
-		centers->synth_center =
-			chan->channel - HT40_CHANNEL_CENTER_SHIFT;
-		extoff = -1;
+		macLo = macHi = 0;
 	}
-
-	centers->ctl_center = centers->synth_center - (extoff *
-		HT40_CHANNEL_CENTER_SHIFT);
-	centers->ext_center = centers->synth_center + (extoff *
-		((ahp->
-		ah_extprotspacing
-		==
-		ATH9K_HT_EXTPROTSPACING_20)
-		?
-		HT40_CHANNEL_CENTER_SHIFT
-		: 15));
-
-}
-
-void
-ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
-			bool *isCalDone)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *ichan =
-		ath9k_regd_check_channel(ah, chan);
-	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
-
-	*isCalDone = true;
-
-	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
-		return;
-
-	if (currCal == NULL)
-		return;
-
-	if (ichan == NULL) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: invalid channel %u/0x%x; no mapping\n",
-			 __func__, chan->channel, chan->channelFlags);
-		return;
-	}
-
-
-	if (currCal->calState != CAL_DONE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			 "%s: Calibration state incorrect, %d\n",
-			 __func__, currCal->calState);
-		return;
-	}
-
-
-	if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
-		return;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		 "%s: Resetting Cal %d state for channel %u/0x%x\n",
-		 __func__, currCal->calData->calType, chan->channel,
-		 chan->channelFlags);
-
-	ichan->CalValid &= ~currCal->calData->calType;
-	currCal->calState = CAL_WAITING;
-
-	*isCalDone = false;
-}
-
-void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	memcpy(mac, ahp->ah_macaddr, ETH_ALEN);
-}
-
-bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	memcpy(ahp->ah_macaddr, mac, ETH_ALEN);
-	return true;
-}
-
-void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	memcpy(mask, ahp->ah_bssidmask, ETH_ALEN);
-}
-
-bool
-ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	memcpy(ahp->ah_bssidmask, mask, ETH_ALEN);
-
-	REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
-	REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
 
 	return true;
 }
 
-void
-ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
-		       u16 assocId)
+bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
+				 const struct ath9k_keyval *k,
+				 const u8 *mac, int xorKey)
 {
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	memcpy(ahp->ah_bssid, bssid, ETH_ALEN);
-	ahp->ah_assocId = assocId;
-
-	REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
-	REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
-		  ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
-}
-
-u64 ath9k_hw_gettsf64(struct ath_hal *ah)
-{
-	u64 tsf;
-
-	tsf = REG_READ(ah, AR_TSF_U32);
-	tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
-	return tsf;
-}
-
-void ath9k_hw_reset_tsf(struct ath_hal *ah)
-{
-	int count;
-
-	count = 0;
-	while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
-		count++;
-		if (count > 10) {
-			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			 "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n",
-				 __func__);
-			break;
-		}
-		udelay(10);
-	}
-	REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
-}
-
-u32 ath9k_hw_getdefantenna(struct ath_hal *ah)
-{
-	return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
-}
-
-void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna)
-{
-	REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
-}
-
-bool
-ath9k_hw_setantennaswitch(struct ath_hal *ah,
-			  enum ath9k_ant_setting settings,
-			  struct ath9k_channel *chan,
-			  u8 *tx_chainmask,
-			  u8 *rx_chainmask,
-			  u8 *antenna_cfgd)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	static u8 tx_chainmask_cfg, rx_chainmask_cfg;
-
-	if (AR_SREV_9280(ah)) {
-		if (!tx_chainmask_cfg) {
-
-			tx_chainmask_cfg = *tx_chainmask;
-			rx_chainmask_cfg = *rx_chainmask;
-		}
-
-		switch (settings) {
-		case ATH9K_ANT_FIXED_A:
-			*tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
-			*rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
-			*antenna_cfgd = true;
-			break;
-		case ATH9K_ANT_FIXED_B:
-			if (ah->ah_caps.tx_chainmask >
-			    ATH9K_ANTENNA1_CHAINMASK) {
-				*tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
-			}
-			*rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
-			*antenna_cfgd = true;
-			break;
-		case ATH9K_ANT_VARIABLE:
-			*tx_chainmask = tx_chainmask_cfg;
-			*rx_chainmask = rx_chainmask_cfg;
-			*antenna_cfgd = true;
-			break;
-		default:
-			break;
-		}
-	} else {
-		ahp->ah_diversityControl = settings;
-	}
-
-	return true;
-}
-
-void ath9k_hw_setopmode(struct ath_hal *ah)
-{
-	ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
-}
-
-bool
-ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
-		       u32 capability, u32 *result)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
 	const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	u32 key0, key1, key2, key3, key4;
+	u32 keyType;
+	u32 xorMask = xorKey ?
+		(ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8
+		 | ATH9K_KEY_XOR) : 0;
+	struct ath_hal_5416 *ahp = AH5416(ah);
 
-	switch (type) {
-	case ATH9K_CAP_CIPHER:
-		switch (capability) {
-		case ATH9K_CIPHER_AES_CCM:
-		case ATH9K_CIPHER_AES_OCB:
-		case ATH9K_CIPHER_TKIP:
-		case ATH9K_CIPHER_WEP:
-		case ATH9K_CIPHER_MIC:
-		case ATH9K_CIPHER_CLR:
-			return true;
-		default:
+	if (entry >= pCap->keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			"%s: entry %u out of range\n", __func__, entry);
+		return false;
+	}
+
+	switch (k->kv_type) {
+	case ATH9K_CIPHER_AES_OCB:
+		keyType = AR_KEYTABLE_TYPE_AES;
+		break;
+	case ATH9K_CIPHER_AES_CCM:
+		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+				"%s: AES-CCM not supported by "
+				"mac rev 0x%x\n", __func__,
+				ah->ah_macRev);
 			return false;
 		}
-	case ATH9K_CAP_TKIP_MIC:
-		switch (capability) {
-		case 0:
-			return true;
-		case 1:
-			return (ahp->ah_staId1Defaults &
-				AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
-			false;
-		}
-	case ATH9K_CAP_TKIP_SPLIT:
-		return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
-			false : true;
-	case ATH9K_CAP_WME_TKIPMIC:
-		return 0;
-	case ATH9K_CAP_PHYCOUNTERS:
-		return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO;
-	case ATH9K_CAP_DIVERSITY:
-		return (REG_READ(ah, AR_PHY_CCK_DETECT) &
-			AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
-			true : false;
-	case ATH9K_CAP_PHYDIAG:
-		return true;
-	case ATH9K_CAP_MCAST_KEYSRCH:
-		switch (capability) {
-		case 0:
-			return true;
-		case 1:
-			if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
-				return false;
-			} else {
-				return (ahp->ah_staId1Defaults &
-					AR_STA_ID1_MCAST_KSRCH) ? true :
-					false;
-			}
-		}
-		return false;
-	case ATH9K_CAP_TSF_ADJUST:
-		return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
-			true : false;
-	case ATH9K_CAP_RFSILENT:
-		if (capability == 3)
+		keyType = AR_KEYTABLE_TYPE_CCM;
+		break;
+	case ATH9K_CIPHER_TKIP:
+		keyType = AR_KEYTABLE_TYPE_TKIP;
+		if (ATH9K_IS_MIC_ENABLED(ah)
+		    && entry + 64 >= pCap->keycache_size) {
+			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+				"%s: entry %u inappropriate for TKIP\n",
+				__func__, entry);
 			return false;
-	case ATH9K_CAP_ANT_CFG_2GHZ:
-		*result = pCap->num_antcfg_2ghz;
-		return true;
-	case ATH9K_CAP_ANT_CFG_5GHZ:
-		*result = pCap->num_antcfg_5ghz;
-		return true;
-	case ATH9K_CAP_TXPOW:
-		switch (capability) {
-		case 0:
-			return 0;
-		case 1:
-			*result = ah->ah_powerLimit;
-			return 0;
-		case 2:
-			*result = ah->ah_maxPowerLevel;
-			return 0;
-		case 3:
-			*result = ah->ah_tpScale;
-			return 0;
 		}
-		return false;
+		break;
+	case ATH9K_CIPHER_WEP:
+		if (k->kv_len < LEN_WEP40) {
+			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+				"%s: WEP key length %u too small\n",
+				__func__, k->kv_len);
+			return false;
+		}
+		if (k->kv_len <= LEN_WEP40)
+			keyType = AR_KEYTABLE_TYPE_40;
+		else if (k->kv_len <= LEN_WEP104)
+			keyType = AR_KEYTABLE_TYPE_104;
+		else
+			keyType = AR_KEYTABLE_TYPE_128;
+		break;
+	case ATH9K_CIPHER_CLR:
+		keyType = AR_KEYTABLE_TYPE_CLR;
+		break;
 	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			"%s: cipher %u not supported\n", __func__,
+			k->kv_type);
 		return false;
 	}
+
+	key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask;
+	key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff;
+	key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
+	key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
+	key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
+	if (k->kv_len <= LEN_WEP104)
+		key4 &= 0xff;
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+		u16 micentry = entry + 64;
+
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+		(void) ath9k_hw_keysetmac(ah, entry, mac);
+
+		if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
+			u32 mic0, mic1, mic2, mic3, mic4;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
+			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
+			mic4 = get_unaligned_le32(k->kv_txmic + 4);
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+
+		} else {
+			u32 mic0, mic2;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+		}
+		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+	} else {
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+		(void) ath9k_hw_keysetmac(ah, entry, mac);
+	}
+
+	if (ah->ah_curchan == NULL)
+		return true;
+
+	return true;
+}
+
+bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry)
+{
+	if (entry < ah->ah_caps.keycache_size) {
+		u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+		if (val & AR_KEYTABLE_VALID)
+			return true;
+	}
+	return false;
+}
+
+/******************************/
+/* Power Management (Chipset) */
+/******************************/
+
+static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
+{
+	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+	if (setChip) {
+		REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+			    AR_RTC_FORCE_WAKE_EN);
+		if (!AR_SREV_9100(ah))
+			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+
+		REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
+			    AR_RTC_RESET_EN);
+	}
 }
 
-int
-ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg)
+static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
 {
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_channel *chan = ah->ah_curchan;
-	const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	u16 ant_config;
-	u32 halNumAntConfig;
+	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+	if (setChip) {
+		struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
 
-	halNumAntConfig =
-		IS_CHAN_2GHZ(chan) ? pCap->num_antcfg_2ghz : pCap->
-		num_antcfg_5ghz;
+		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+			REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+				  AR_RTC_FORCE_WAKE_ON_INT);
+		} else {
+			REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+				    AR_RTC_FORCE_WAKE_EN);
+		}
+	}
+}
 
-	if (cfg < halNumAntConfig) {
-		if (!ath9k_hw_get_eeprom_antenna_cfg(ahp, chan,
-						     cfg, &ant_config)) {
-			REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
-			return 0;
+static bool ath9k_hw_set_power_awake(struct ath_hal *ah,
+				     int setChip)
+{
+	u32 val;
+	int i;
+
+	if (setChip) {
+		if ((REG_READ(ah, AR_RTC_STATUS) &
+		     AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+			if (ath9k_hw_set_reset_reg(ah,
+					   ATH9K_RESET_POWER_ON) != true) {
+				return false;
+			}
+		}
+		if (AR_SREV_9100(ah))
+			REG_SET_BIT(ah, AR_RTC_RESET,
+				    AR_RTC_RESET_EN);
+
+		REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+			    AR_RTC_FORCE_WAKE_EN);
+		udelay(50);
+
+		for (i = POWER_UP_TIME / 50; i > 0; i--) {
+			val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+			if (val == AR_RTC_STATUS_ON)
+				break;
+			udelay(50);
+			REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+				    AR_RTC_FORCE_WAKE_EN);
+		}
+		if (i == 0) {
+			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+				"%s: Failed to wakeup in %uus\n",
+				__func__, POWER_UP_TIME / 20);
+			return false;
 		}
 	}
 
-	return -EINVAL;
+	REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+	return true;
 }
 
+bool ath9k_hw_setpower(struct ath_hal *ah,
+		       enum ath9k_power_mode mode)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	static const char *modes[] = {
+		"AWAKE",
+		"FULL-SLEEP",
+		"NETWORK SLEEP",
+		"UNDEFINED"
+	};
+	int status = true, setChip = true;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
+		modes[ahp->ah_powerMode], modes[mode],
+		setChip ? "set chip " : "");
+
+	switch (mode) {
+	case ATH9K_PM_AWAKE:
+		status = ath9k_hw_set_power_awake(ah, setChip);
+		break;
+	case ATH9K_PM_FULL_SLEEP:
+		ath9k_set_power_sleep(ah, setChip);
+		ahp->ah_chipFullSleep = true;
+		break;
+	case ATH9K_PM_NETWORK_SLEEP:
+		ath9k_set_power_network_sleep(ah, setChip);
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			"%s: unknown power mode %u\n", __func__, mode);
+		return false;
+	}
+	ahp->ah_powerMode = mode;
+
+	return status;
+}
+
+void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u8 i;
+
+	if (ah->ah_isPciExpress != true)
+		return;
+
+	if (ah->ah_config.pcie_powersave_enable == 2)
+		return;
+
+	if (restore)
+		return;
+
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
+		for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
+			REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
+				  INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
+		}
+		udelay(1000);
+	} else if (AR_SREV_9280(ah) &&
+		   (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+
+		if (ah->ah_config.pcie_clock_req)
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
+		else
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
+
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
+
+		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+		udelay(1000);
+	} else {
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+	}
+
+	REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+	if (ah->ah_config.pcie_waen) {
+		REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
+	} else {
+		if (AR_SREV_9280(ah))
+			REG_WRITE(ah, AR_WA, 0x0040073f);
+		else
+			REG_WRITE(ah, AR_WA, 0x0000073f);
+	}
+}
+
+/**********************/
+/* Interrupt Handling */
+/**********************/
+
 bool ath9k_hw_intrpend(struct ath_hal *ah)
 {
 	u32 host_isr;
@@ -6791,6 +2763,7 @@
 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
 	u32 sync_cause = 0;
 	bool fatal_int = false;
+	struct ath_hal_5416 *ahp = AH5416(ah);
 
 	if (!AR_SREV_9100(ah)) {
 		if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
@@ -6800,9 +2773,8 @@
 			}
 		}
 
-		sync_cause =
-			REG_READ(ah,
-				 AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
+		sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+			AR_INTR_SYNC_DEFAULT;
 
 		*masked = 0;
 
@@ -6814,8 +2786,6 @@
 	}
 
 	if (isr) {
-		struct ath_hal_5416 *ahp = AH5416(ah);
-
 		if (isr & AR_ISR_BCNMISC) {
 			u32 isr2;
 			isr2 = REG_READ(ah, AR_ISR_S2);
@@ -6842,7 +2812,6 @@
 		*masked = isr & ATH9K_INT_COMMON;
 
 		if (ahp->ah_intrMitigation) {
-
 			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
 				*masked |= ATH9K_INT_RX;
 		}
@@ -6867,8 +2836,8 @@
 
 		if (isr & AR_ISR_RXORN) {
 			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				 "%s: receive FIFO overrun interrupt\n",
-				 __func__);
+				"%s: receive FIFO overrun interrupt\n",
+				__func__);
 		}
 
 		if (!AR_SREV_9100(ah)) {
@@ -6881,8 +2850,10 @@
 
 		*masked |= mask2;
 	}
+
 	if (AR_SREV_9100(ah))
 		return true;
+
 	if (sync_cause) {
 		fatal_int =
 			(sync_cause &
@@ -6892,32 +2863,33 @@
 		if (fatal_int) {
 			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
 				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					 "%s: received PCI FATAL interrupt\n",
-					 __func__);
+					"%s: received PCI FATAL interrupt\n",
+					__func__);
 			}
 			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
 				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					 "%s: received PCI PERR interrupt\n",
-					 __func__);
+					"%s: received PCI PERR interrupt\n",
+					__func__);
 			}
 		}
 		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
 			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				 "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
-				 __func__);
+				"%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
+				__func__);
 			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
 			REG_WRITE(ah, AR_RC, 0);
 			*masked |= ATH9K_INT_FATAL;
 		}
 		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
 			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				 "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
-				 __func__);
+				"%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
+				__func__);
 		}
 
 		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
 		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
 	}
+
 	return true;
 }
 
@@ -7035,9 +3007,11 @@
 	return omask;
 }
 
-void
-ath9k_hw_beaconinit(struct ath_hal *ah,
-		    u32 next_beacon, u32 beacon_period)
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period)
 {
 	struct ath_hal_5416 *ahp = AH5416(ah);
 	int flags = 0;
@@ -7089,9 +3063,8 @@
 	REG_SET_BIT(ah, AR_TIMER_MODE, flags);
 }
 
-void
-ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
-			       const struct ath9k_beacon_state *bs)
+void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+				    const struct ath9k_beacon_state *bs)
 {
 	u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
@@ -7154,1055 +3127,122 @@
 
 }
 
-bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry)
-{
-	if (entry < ah->ah_caps.keycache_size) {
-		u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
-		if (val & AR_KEYTABLE_VALID)
-			return true;
-	}
-	return false;
-}
+/***************/
+/* Rate tables */
+/***************/
 
-bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry)
-{
-	u32 keyType;
+static struct ath9k_rate_table ar5416_11a_table = {
+	8,
+	{0},
+	{
+		{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
+		{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
+		{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
+		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
+		{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
+		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
+		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
+		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}
+	},
+};
 
-	if (entry >= ah->ah_caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			 "%s: entry %u out of range\n", __func__, entry);
-		return false;
-	}
-	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+static struct ath9k_rate_table ar5416_11b_table = {
+	4,
+	{0},
+	{
+		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
+		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
+		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1},
+		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1}
+	},
+};
 
-	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+static struct ath9k_rate_table ar5416_11g_table = {
+	12,
+	{0},
+	{
+		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
+		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
+		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
+		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
 
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
+		{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
+		{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
+		{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
+		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
+		{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
+		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
+		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
+		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}
+	},
+};
 
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+static struct ath9k_rate_table ar5416_11ng_table = {
+	28,
+	{0},
+	{
+		{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
+		{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
+		{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
+		{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
 
-	}
+		{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
+		{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
+		{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
+		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
+		{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
+		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
+		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
+		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8},
+		{true, PHY_HT, 6500, 0x80, 0x00, 0, 4},
+		{true, PHY_HT, 13000, 0x81, 0x00, 1, 6},
+		{true, PHY_HT, 19500, 0x82, 0x00, 2, 6},
+		{true, PHY_HT, 26000, 0x83, 0x00, 3, 8},
+		{true, PHY_HT, 39000, 0x84, 0x00, 4, 8},
+		{true, PHY_HT, 52000, 0x85, 0x00, 5, 8},
+		{true, PHY_HT, 58500, 0x86, 0x00, 6, 8},
+		{true, PHY_HT, 65000, 0x87, 0x00, 7, 8},
+		{true, PHY_HT, 13000, 0x88, 0x00, 8, 4},
+		{true, PHY_HT, 26000, 0x89, 0x00, 9, 6},
+		{true, PHY_HT, 39000, 0x8a, 0x00, 10, 6},
+		{true, PHY_HT, 52000, 0x8b, 0x00, 11, 8},
+		{true, PHY_HT, 78000, 0x8c, 0x00, 12, 8},
+		{true, PHY_HT, 104000, 0x8d, 0x00, 13, 8},
+		{true, PHY_HT, 117000, 0x8e, 0x00, 14, 8},
+		{true, PHY_HT, 130000, 0x8f, 0x00, 15, 8},
+	},
+};
 
-	if (ah->ah_curchan == NULL)
-		return true;
-
-	return true;
-}
-
-bool
-ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
-		   const u8 *mac)
-{
-	u32 macHi, macLo;
-
-	if (entry >= ah->ah_caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			 "%s: entry %u out of range\n", __func__, entry);
-		return false;
-	}
-
-	if (mac != NULL) {
-		macHi = (mac[5] << 8) | mac[4];
-		macLo = (mac[3] << 24) | (mac[2] << 16)
-			| (mac[1] << 8) | mac[0];
-		macLo >>= 1;
-		macLo |= (macHi & 1) << 31;
-		macHi >>= 1;
-	} else {
-		macLo = macHi = 0;
-	}
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
-
-	return true;
-}
-
-bool
-ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
-			    const struct ath9k_keyval *k,
-			    const u8 *mac, int xorKey)
-{
-	const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	u32 key0, key1, key2, key3, key4;
-	u32 keyType;
-	u32 xorMask = xorKey ?
-		(ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8
-		 | ATH9K_KEY_XOR) : 0;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	if (entry >= pCap->keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			 "%s: entry %u out of range\n", __func__, entry);
-		return false;
-	}
-	switch (k->kv_type) {
-	case ATH9K_CIPHER_AES_OCB:
-		keyType = AR_KEYTABLE_TYPE_AES;
-		break;
-	case ATH9K_CIPHER_AES_CCM:
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				 "%s: AES-CCM not supported by "
-				 "mac rev 0x%x\n", __func__,
-				 ah->ah_macRev);
-			return false;
-		}
-		keyType = AR_KEYTABLE_TYPE_CCM;
-		break;
-	case ATH9K_CIPHER_TKIP:
-		keyType = AR_KEYTABLE_TYPE_TKIP;
-		if (ATH9K_IS_MIC_ENABLED(ah)
-		    && entry + 64 >= pCap->keycache_size) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				 "%s: entry %u inappropriate for TKIP\n",
-				 __func__, entry);
-			return false;
-		}
-		break;
-	case ATH9K_CIPHER_WEP:
-		if (k->kv_len < LEN_WEP40) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				 "%s: WEP key length %u too small\n",
-				 __func__, k->kv_len);
-			return false;
-		}
-		if (k->kv_len <= LEN_WEP40)
-			keyType = AR_KEYTABLE_TYPE_40;
-		else if (k->kv_len <= LEN_WEP104)
-			keyType = AR_KEYTABLE_TYPE_104;
-		else
-			keyType = AR_KEYTABLE_TYPE_128;
-		break;
-	case ATH9K_CIPHER_CLR:
-		keyType = AR_KEYTABLE_TYPE_CLR;
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			 "%s: cipher %u not supported\n", __func__,
-			 k->kv_type);
-		return false;
-	}
-
-	key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask;
-	key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff;
-	key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
-	key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
-	key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
-	if (k->kv_len <= LEN_WEP104)
-		key4 &= 0xff;
-
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
-
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-
-		if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
-			u32 mic0, mic1, mic2, mic3, mic4;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
-			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
-			mic4 = get_unaligned_le32(k->kv_txmic + 4);
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-
-		} else {
-			u32 mic0, mic2;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-		}
-		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-	} else {
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-	}
-
-	if (ah->ah_curchan == NULL)
-		return true;
-
-	return true;
-}
-
-bool
-ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	u32 txcfg, curLevel, newLevel;
-	enum ath9k_int omask;
-
-	if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
-		return false;
-
-	omask = ath9k_hw_set_interrupts(ah,
-					ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
-
-	txcfg = REG_READ(ah, AR_TXCFG);
-	curLevel = MS(txcfg, AR_FTRIG);
-	newLevel = curLevel;
-	if (bIncTrigLevel) {
-		if (curLevel < MAX_TX_FIFO_THRESHOLD)
-			newLevel++;
-	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
-		newLevel--;
-	if (newLevel != curLevel)
-		REG_WRITE(ah, AR_TXCFG,
-			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
-
-	ath9k_hw_set_interrupts(ah, omask);
-
-	ah->ah_txTrigLevel = newLevel;
-
-	return newLevel != curLevel;
-}
-
-bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
-			    const struct ath9k_tx_queue_info *qinfo)
-{
-	u32 cw;
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
-			 __func__, q);
-		return false;
-	}
-
-	qi = &ahp->ah_txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
-			 __func__);
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi);
-
-	qi->tqi_ver = qinfo->tqi_ver;
-	qi->tqi_subtype = qinfo->tqi_subtype;
-	qi->tqi_qflags = qinfo->tqi_qflags;
-	qi->tqi_priority = qinfo->tqi_priority;
-	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
-		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
-	else
-		qi->tqi_aifs = INIT_AIFS;
-	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
-		cw = min(qinfo->tqi_cwmin, 1024U);
-		qi->tqi_cwmin = 1;
-		while (qi->tqi_cwmin < cw)
-			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
-	} else
-		qi->tqi_cwmin = qinfo->tqi_cwmin;
-	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
-		cw = min(qinfo->tqi_cwmax, 1024U);
-		qi->tqi_cwmax = 1;
-		while (qi->tqi_cwmax < cw)
-			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
-	} else
-		qi->tqi_cwmax = INIT_CWMAX;
-
-	if (qinfo->tqi_shretry != 0)
-		qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
-	else
-		qi->tqi_shretry = INIT_SH_RETRY;
-	if (qinfo->tqi_lgretry != 0)
-		qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
-	else
-		qi->tqi_lgretry = INIT_LG_RETRY;
-	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
-	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
-	qi->tqi_burstTime = qinfo->tqi_burstTime;
-	qi->tqi_readyTime = qinfo->tqi_readyTime;
-
-	switch (qinfo->tqi_subtype) {
-	case ATH9K_WME_UPSD:
-		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
-			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
-		break;
-	default:
-		break;
-	}
-	return true;
-}
-
-bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
-			    struct ath9k_tx_queue_info *qinfo)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
-			 __func__, q);
-		return false;
-	}
-
-	qi = &ahp->ah_txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
-			 __func__);
-		return false;
-	}
-
-	qinfo->tqi_qflags = qi->tqi_qflags;
-	qinfo->tqi_ver = qi->tqi_ver;
-	qinfo->tqi_subtype = qi->tqi_subtype;
-	qinfo->tqi_qflags = qi->tqi_qflags;
-	qinfo->tqi_priority = qi->tqi_priority;
-	qinfo->tqi_aifs = qi->tqi_aifs;
-	qinfo->tqi_cwmin = qi->tqi_cwmin;
-	qinfo->tqi_cwmax = qi->tqi_cwmax;
-	qinfo->tqi_shretry = qi->tqi_shretry;
-	qinfo->tqi_lgretry = qi->tqi_lgretry;
-	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
-	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
-	qinfo->tqi_burstTime = qi->tqi_burstTime;
-	qinfo->tqi_readyTime = qi->tqi_readyTime;
-
-	return true;
-}
-
-int
-ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
-		      const struct ath9k_tx_queue_info *qinfo)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_tx_queue_info *qi;
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	int q;
-
-	switch (type) {
-	case ATH9K_TX_QUEUE_BEACON:
-		q = pCap->total_queues - 1;
-		break;
-	case ATH9K_TX_QUEUE_CAB:
-		q = pCap->total_queues - 2;
-		break;
-	case ATH9K_TX_QUEUE_PSPOLL:
-		q = 1;
-		break;
-	case ATH9K_TX_QUEUE_UAPSD:
-		q = pCap->total_queues - 3;
-		break;
-	case ATH9K_TX_QUEUE_DATA:
-		for (q = 0; q < pCap->total_queues; q++)
-			if (ahp->ah_txq[q].tqi_type ==
-			    ATH9K_TX_QUEUE_INACTIVE)
-				break;
-		if (q == pCap->total_queues) {
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				 "%s: no available tx queue\n", __func__);
-			return -1;
-		}
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n",
-			 __func__, type);
-		return -1;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
-
-	qi = &ahp->ah_txq[q];
-	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			 "%s: tx queue %u already active\n", __func__, q);
-		return -1;
-	}
-	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
-	qi->tqi_type = type;
-	if (qinfo == NULL) {
-		qi->tqi_qflags =
-			TXQ_FLAG_TXOKINT_ENABLE
-			| TXQ_FLAG_TXERRINT_ENABLE
-			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
-		qi->tqi_aifs = INIT_AIFS;
-		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
-		qi->tqi_cwmax = INIT_CWMAX;
-		qi->tqi_shretry = INIT_SH_RETRY;
-		qi->tqi_lgretry = INIT_LG_RETRY;
-		qi->tqi_physCompBuf = 0;
-	} else {
-		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
-		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
-	}
-
-	return q;
-}
-
-static void
-ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
-			    struct ath9k_tx_queue_info *qi)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-		 "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
-		 __func__, ahp->ah_txOkInterruptMask,
-		 ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
-		 ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask);
-
-	REG_WRITE(ah, AR_IMR_S0,
-		  SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
-		  | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
-	REG_WRITE(ah, AR_IMR_S1,
-		  SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
-		  | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
-	REG_RMW_FIELD(ah, AR_IMR_S2,
-		      AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
-}
-
-bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
-			 __func__, q);
-		return false;
-	}
-	qi = &ahp->ah_txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
-			 __func__, q);
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n",
-		__func__, q);
-
-	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
-	ahp->ah_txOkInterruptMask &= ~(1 << q);
-	ahp->ah_txErrInterruptMask &= ~(1 << q);
-	ahp->ah_txDescInterruptMask &= ~(1 << q);
-	ahp->ah_txEolInterruptMask &= ~(1 << q);
-	ahp->ah_txUrnInterruptMask &= ~(1 << q);
-	ath9k_hw_set_txq_interrupts(ah, qi);
-
-	return true;
-}
-
-bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-	struct ath9k_channel *chan = ah->ah_curchan;
-	struct ath9k_tx_queue_info *qi;
-	u32 cwMin, chanCwMin, value;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
-			 __func__, q);
-		return false;
-	}
-	qi = &ahp->ah_txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
-			 __func__, q);
-		return true;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q);
-
-	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
-		if (chan && IS_CHAN_B(chan))
-			chanCwMin = INIT_CWMIN_11B;
-		else
-			chanCwMin = INIT_CWMIN;
-
-		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
-	} else
-		cwMin = qi->tqi_cwmin;
-
-	REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN)
-		  | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
-		  | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
-
-	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
-		  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
-		  | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
-		  | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
-
-	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
-	REG_WRITE(ah, AR_DMISC(q),
-		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
-
-	if (qi->tqi_cbrPeriod) {
-		REG_WRITE(ah, AR_QCBRCFG(q),
-			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL)
-			  | SM(qi->tqi_cbrOverflowLimit,
-			       AR_Q_CBRCFG_OVF_THRESH));
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah,
-				   AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi->
-					tqi_cbrOverflowLimit
-					?
-					AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN
-					:
-					0));
-	}
-	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
-		REG_WRITE(ah, AR_QRDYTIMECFG(q),
-			  SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
-			  AR_Q_RDYTIMECFG_EN);
-	}
-
-	REG_WRITE(ah, AR_DCHNTIME(q),
-		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
-		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
-
-	if (qi->tqi_burstTime
-	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah,
-				   AR_QMISC(q)) |
-			  AR_Q_MISC_RDYTIME_EXP_POLICY);
-
-	}
-
-	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  AR_D_MISC_POST_FR_BKOFF_DIS);
-	}
-	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  AR_D_MISC_FRAG_BKOFF_EN);
-	}
-	switch (qi->tqi_type) {
-	case ATH9K_TX_QUEUE_BEACON:
-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
-			  | AR_Q_MISC_FSP_DBA_GATED
-			  | AR_Q_MISC_BEACON_USE
-			  | AR_Q_MISC_CBR_INCR_DIS1);
-
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
-			  | AR_D_MISC_BEACON_USE
-			  | AR_D_MISC_POST_FR_BKOFF_DIS);
-		break;
-	case ATH9K_TX_QUEUE_CAB:
-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
-			  | AR_Q_MISC_FSP_DBA_GATED
-			  | AR_Q_MISC_CBR_INCR_DIS1
-			  | AR_Q_MISC_CBR_INCR_DIS0);
-		value = (qi->tqi_readyTime
-			 - (ah->ah_config.sw_beacon_response_time -
-			    ah->ah_config.dma_beacon_response_time)
-			 -
-			 ah->ah_config.additional_swba_backoff) *
-			1024;
-		REG_WRITE(ah, AR_QRDYTIMECFG(q),
-			  value | AR_Q_RDYTIMECFG_EN);
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
-		break;
-	case ATH9K_TX_QUEUE_PSPOLL:
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah,
-				   AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
-		break;
-	case ATH9K_TX_QUEUE_UAPSD:
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
-			  | AR_D_MISC_POST_FR_BKOFF_DIS);
-		break;
-	default:
-		break;
-	}
-
-	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL) |
-			  AR_D_MISC_POST_FR_BKOFF_DIS);
-	}
-
-	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
-		ahp->ah_txOkInterruptMask |= 1 << q;
-	else
-		ahp->ah_txOkInterruptMask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
-		ahp->ah_txErrInterruptMask |= 1 << q;
-	else
-		ahp->ah_txErrInterruptMask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
-		ahp->ah_txDescInterruptMask |= 1 << q;
-	else
-		ahp->ah_txDescInterruptMask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
-		ahp->ah_txEolInterruptMask |= 1 << q;
-	else
-		ahp->ah_txEolInterruptMask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
-		ahp->ah_txUrnInterruptMask |= 1 << q;
-	else
-		ahp->ah_txUrnInterruptMask &= ~(1 << q);
-	ath9k_hw_set_txq_interrupts(ah, qi);
-
-	return true;
-}
-
-void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs)
-{
-	struct ath_hal_5416 *ahp = AH5416(ah);
-	*txqs &= ahp->ah_intrTxqs;
-	ahp->ah_intrTxqs &= ~(*txqs);
-}
-
-bool
-ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
-		    u32 segLen, bool firstSeg,
-		    bool lastSeg, const struct ath_desc *ds0)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if (firstSeg) {
-		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
-	} else if (lastSeg) {
-		ads->ds_ctl0 = 0;
-		ads->ds_ctl1 = segLen;
-		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
-		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
-	} else {
-		ads->ds_ctl0 = 0;
-		ads->ds_ctl1 = segLen | AR_TxMore;
-		ads->ds_ctl2 = 0;
-		ads->ds_ctl3 = 0;
-	}
-	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-	return true;
-}
-
-void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
-
-int
-ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
-		return -EINPROGRESS;
-
-	ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
-	ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
-	ds->ds_txstat.ts_status = 0;
-	ds->ds_txstat.ts_flags = 0;
-
-	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->ds_txstatus1 & AR_Filtered)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
-	if (ads->ds_txstatus1 & AR_FIFOUnderrun)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
-	if (ads->ds_txstatus9 & AR_TxOpExceeded)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->ds_txstatus1 & AR_TxTimerExpired)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->ds_txstatus1 & AR_DescCfgErr)
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
-		ath9k_hw_updatetxtriglevel(ah, true);
-	}
-	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
-		ath9k_hw_updatetxtriglevel(ah, true);
-	}
-	if (ads->ds_txstatus0 & AR_TxBaStatus) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
-		ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
-		ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
-	}
-
-	ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
-	switch (ds->ds_txstat.ts_rateindex) {
-	case 0:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
-		break;
-	case 1:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
-		break;
-	case 2:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
-		break;
-	case 3:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
-		break;
-	}
-
-	ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
-	ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
-	ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
-	ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
-	ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
-	ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
-	ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
-	ds->ds_txstat.evm0 = ads->AR_TxEVM0;
-	ds->ds_txstat.evm1 = ads->AR_TxEVM1;
-	ds->ds_txstat.evm2 = ads->AR_TxEVM2;
-	ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
-	ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
-	ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
-	ds->ds_txstat.ts_antenna = 1;
-
-	return 0;
-}
-
-void
-ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
-		       u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
-		       u32 keyIx, enum ath9k_key_type keyType, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ath_hal_5416 *ahp = AH5416(ah);
-
-	txPower += ahp->ah_txPowerIndexOffset;
-	if (txPower > 63)
-		txPower = 63;
-
-	ads->ds_ctl0 = (pktLen & AR_FrameLen)
-		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(txPower, AR_XmitPower)
-		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
-		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
-		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
-	ads->ds_ctl1 =
-		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-		| SM(type, AR_FrameType)
-		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
-	ads->ds_ctl6 = SM(keyType, AR_EncrType);
-
-	if (AR_SREV_9285(ah)) {
-
-		ads->ds_ctl8 = 0;
-		ads->ds_ctl9 = 0;
-		ads->ds_ctl10 = 0;
-		ads->ds_ctl11 = 0;
-	}
-}
-
-void
-ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
-			     struct ath_desc *lastds,
-			     u32 durUpdateEn, u32 rtsctsRate,
-			     u32 rtsctsDuration,
-			     struct ath9k_11n_rate_series series[],
-			     u32 nseries, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ar5416_desc *last_ads = AR5416DESC(lastds);
-	u32 ds_ctl0;
-
-	(void) nseries;
-	(void) rtsctsDuration;
-
-	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-		ds_ctl0 = ads->ds_ctl0;
-
-		if (flags & ATH9K_TXDESC_RTSENA) {
-			ds_ctl0 &= ~AR_CTSEnable;
-			ds_ctl0 |= AR_RTSEnable;
-		} else {
-			ds_ctl0 &= ~AR_RTSEnable;
-			ds_ctl0 |= AR_CTSEnable;
-		}
-
-		ads->ds_ctl0 = ds_ctl0;
-	} else {
-		ads->ds_ctl0 =
-			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
-	}
-
-	ads->ds_ctl2 = set11nTries(series, 0)
-		| set11nTries(series, 1)
-		| set11nTries(series, 2)
-		| set11nTries(series, 3)
-		| (durUpdateEn ? AR_DurUpdateEna : 0)
-		| SM(0, AR_BurstDur);
-
-	ads->ds_ctl3 = set11nRate(series, 0)
-		| set11nRate(series, 1)
-		| set11nRate(series, 2)
-		| set11nRate(series, 3);
-
-	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
-		| set11nPktDurRTSCTS(series, 1);
-
-	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
-		| set11nPktDurRTSCTS(series, 3);
-
-	ads->ds_ctl7 = set11nRateFlags(series, 0)
-		| set11nRateFlags(series, 1)
-		| set11nRateFlags(series, 2)
-		| set11nRateFlags(series, 3)
-		| SM(rtsctsRate, AR_RTSCTSRate);
-	last_ads->ds_ctl2 = ads->ds_ctl2;
-	last_ads->ds_ctl3 = ads->ds_ctl3;
-}
-
-void
-ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
-			   u32 aggrLen)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
-	ads->ds_ctl6 &= ~AR_AggrLen;
-	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
-
-void
-ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
-			    u32 numDelims)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	unsigned int ctl6;
-
-	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
-	ctl6 = ads->ds_ctl6;
-	ctl6 &= ~AR_PadDelim;
-	ctl6 |= SM(numDelims, AR_PadDelim);
-	ads->ds_ctl6 = ctl6;
-}
-
-void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 |= AR_IsAggr;
-	ads->ds_ctl1 &= ~AR_MoreAggr;
-	ads->ds_ctl6 &= ~AR_PadDelim;
-}
-
-void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
-void
-ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
-			      u32 burstDuration)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl2 &= ~AR_BurstDur;
-	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
-}
-
-void
-ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
-				u32 vmf)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if (vmf)
-		ads->ds_ctl0 |= AR_VirtMoreFrag;
-	else
-		ads->ds_ctl0 &= ~AR_VirtMoreFrag;
-}
-
-void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp)
-{
-	REG_WRITE(ah, AR_RXDP, rxdp);
-}
-
-void ath9k_hw_rxena(struct ath_hal *ah)
-{
-	REG_WRITE(ah, AR_CR, AR_CR_RXE);
-}
-
-bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set)
-{
-	if (set) {
-
-		REG_SET_BIT(ah, AR_DIAG_SW,
-			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
-		if (!ath9k_hw_wait
-		    (ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
-			u32 reg;
-
-			REG_CLR_BIT(ah, AR_DIAG_SW,
-				    (AR_DIAG_RX_DIS |
-				     AR_DIAG_RX_ABORT));
-
-			reg = REG_READ(ah, AR_OBS_BUS_1);
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
-				__func__, reg);
-
-			return false;
-		}
-	} else {
-		REG_CLR_BIT(ah, AR_DIAG_SW,
-			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-	}
-
-	return true;
-}
-
-void
-ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
-			u32 filter1)
-{
-	REG_WRITE(ah, AR_MCAST_FIL0, filter0);
-	REG_WRITE(ah, AR_MCAST_FIL1, filter1);
-}
-
-bool
-ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
-		     u32 size, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-
-	ads->ds_ctl1 = size & AR_BufLen;
-	if (flags & ATH9K_RXDESC_INTREQ)
-		ads->ds_ctl1 |= AR_RxIntrReq;
-
-	ads->ds_rxstatus8 &= ~AR_RxDone;
-	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-		memset(&(ads->u), 0, sizeof(ads->u));
-	return true;
-}
-
-int
-ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
-		    u32 pa, struct ath_desc *nds, u64 tsf)
-{
-	struct ar5416_desc ads;
-	struct ar5416_desc *adsp = AR5416DESC(ds);
-
-	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
-		return -EINPROGRESS;
-
-	ads.u.rx = adsp->u.rx;
-
-	ds->ds_rxstat.rs_status = 0;
-	ds->ds_rxstat.rs_flags = 0;
-
-	ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
-	ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
-
-	ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
-	ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
-	ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
-	ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
-	ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
-	ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
-	ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
-	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
-		ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
-	else
-		ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
-
-	ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
-	ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
-
-	ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
-	ds->ds_rxstat.rs_moreaggr =
-		(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
-	ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
-	ds->ds_rxstat.rs_flags =
-		(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
-	ds->ds_rxstat.rs_flags |=
-		(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
-
-	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
-	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
-	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
-
-	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
-
-		if (ads.ds_rxstatus8 & AR_CRCErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
-		else if (ads.ds_rxstatus8 & AR_PHYErr) {
-			u32 phyerr;
-
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
-			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
-			ds->ds_rxstat.rs_phyerr = phyerr;
-		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
-		else if (ads.ds_rxstatus8 & AR_MichaelErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
-	}
-
-	return 0;
-}
+static struct ath9k_rate_table ar5416_11na_table = {
+	24,
+	{0},
+	{
+		{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
+		{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
+		{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
+		{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
+		{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
+		{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
+		{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
+		{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4},
+		{true, PHY_HT, 6500, 0x80, 0x00, 0, 0},
+		{true, PHY_HT, 13000, 0x81, 0x00, 1, 2},
+		{true, PHY_HT, 19500, 0x82, 0x00, 2, 2},
+		{true, PHY_HT, 26000, 0x83, 0x00, 3, 4},
+		{true, PHY_HT, 39000, 0x84, 0x00, 4, 4},
+		{true, PHY_HT, 52000, 0x85, 0x00, 5, 4},
+		{true, PHY_HT, 58500, 0x86, 0x00, 6, 4},
+		{true, PHY_HT, 65000, 0x87, 0x00, 7, 4},
+		{true, PHY_HT, 13000, 0x88, 0x00, 8, 0},
+		{true, PHY_HT, 26000, 0x89, 0x00, 9, 2},
+		{true, PHY_HT, 39000, 0x8a, 0x00, 10, 2},
+		{true, PHY_HT, 52000, 0x8b, 0x00, 11, 4},
+		{true, PHY_HT, 78000, 0x8c, 0x00, 12, 4},
+		{true, PHY_HT, 104000, 0x8d, 0x00, 13, 4},
+		{true, PHY_HT, 117000, 0x8e, 0x00, 14, 4},
+		{true, PHY_HT, 130000, 0x8f, 0x00, 15, 4},
+	},
+};
 
 static void ath9k_hw_setup_rate_table(struct ath_hal *ah,
 				      struct ath9k_rate_table *rt)
@@ -8211,8 +3251,10 @@
 
 	if (rt->rateCodeToIndex[0] != 0)
 		return;
+
 	for (i = 0; i < 256; i++)
 		rt->rateCodeToIndex[i] = (u8) -1;
+
 	for (i = 0; i < rt->rateCount; i++) {
 		u8 code = rt->info[i].rateCode;
 		u8 cix = rt->info[i].controlRate;
@@ -8234,9 +3276,10 @@
 }
 
 const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
-						   u32 mode)
+						     u32 mode)
 {
 	struct ath9k_rate_table *rt;
+
 	switch (mode) {
 	case ATH9K_MODE_11A:
 		rt = &ar5416_11a_table;
@@ -8259,205 +3302,655 @@
 		break;
 	default:
 		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n",
-			 __func__, mode);
+			__func__, mode);
 		return NULL;
 	}
+
 	ath9k_hw_setup_rate_table(ah, rt);
+
 	return rt;
 }
 
-static const char *ath9k_hw_devname(u16 devid)
-{
-	switch (devid) {
-	case AR5416_DEVID_PCI:
-	case AR5416_DEVID_PCIE:
-		return "Atheros 5416";
-	case AR9160_DEVID_PCI:
-		return "Atheros 9160";
-	case AR9280_DEVID_PCI:
-	case AR9280_DEVID_PCIE:
-		return "Atheros 9280";
-	}
-	return NULL;
-}
+/*******************/
+/* HW Capabilities */
+/*******************/
 
-const char *ath9k_hw_probe(u16 vendorid, u16 devid)
+bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
 {
-	return vendorid == ATHEROS_VENDOR_ID ?
-		ath9k_hw_devname(devid) : NULL;
-}
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	u16 capField = 0, eeval;
 
-struct ath_hal *ath9k_hw_attach(u16 devid,
-				struct ath_softc *sc,
-				void __iomem *mem,
-				int *error)
-{
-	struct ath_hal *ah = NULL;
+	eeval = ath9k_hw_get_eeprom(ah, EEP_REG_0);
 
-	switch (devid) {
-	case AR5416_DEVID_PCI:
-	case AR5416_DEVID_PCIE:
-	case AR9160_DEVID_PCI:
-	case AR9280_DEVID_PCI:
-	case AR9280_DEVID_PCIE:
-		ah = ath9k_hw_do_attach(devid, sc, mem, error);
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-			 "devid=0x%x not supported.\n", devid);
-		ah = NULL;
-		*error = -ENXIO;
-		break;
+	ah->ah_currentRD = eeval;
+
+	eeval = ath9k_hw_get_eeprom(ah, EEP_REG_1);
+	ah->ah_currentRDExt = eeval;
+
+	capField = ath9k_hw_get_eeprom(ah, EEP_OP_CAP);
+
+	if (ah->ah_opmode != ATH9K_M_HOSTAP &&
+	    ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+		if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65)
+			ah->ah_currentRD += 5;
+		else if (ah->ah_currentRD == 0x41)
+			ah->ah_currentRD = 0x43;
+		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
+			"%s: regdomain mapped to 0x%x\n", __func__,
+			ah->ah_currentRD);
 	}
 
-	return ah;
-}
+	eeval = ath9k_hw_get_eeprom(ah, EEP_OP_MODE);
+	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
 
-u16
-ath9k_hw_computetxtime(struct ath_hal *ah,
-		       const struct ath9k_rate_table *rates,
-		       u32 frameLen, u16 rateix,
-		       bool shortPreamble)
-{
-	u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
-	u32 kbps;
-
-	kbps = rates->info[rateix].rateKbps;
-
-	if (kbps == 0)
-		return 0;
-	switch (rates->info[rateix].phy) {
-
-	case PHY_CCK:
-		phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
-		if (shortPreamble && rates->info[rateix].shortPreamble)
-			phyTime >>= 1;
-		numBits = frameLen << 3;
-		txTime = CCK_SIFS_TIME + phyTime
-			+ ((numBits * 1000) / kbps);
-		break;
-	case PHY_OFDM:
-		if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
-			bitsPerSymbol =
-				(kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
-
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME_QUARTER
-				+ OFDM_PREAMBLE_TIME_QUARTER
-				+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
-		} else if (ah->ah_curchan &&
-			   IS_CHAN_HALF_RATE(ah->ah_curchan)) {
-			bitsPerSymbol =
-				(kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
-
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME_HALF +
-				OFDM_PREAMBLE_TIME_HALF
-				+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
-		} else {
-			bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
-
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
-				+ (numSymbols * OFDM_SYMBOL_TIME);
-		}
-		break;
-
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
-			 "%s: unknown phy %u (rate ix %u)\n", __func__,
-			 rates->info[rateix].phy, rateix);
-		txTime = 0;
-		break;
-	}
-	return txTime;
-}
-
-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);
+	if (eeval & AR5416_OPFLAGS_11A) {
+		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
+		if (ah->ah_config.ht_enable) {
+			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
+				set_bit(ATH9K_MODE_11NA_HT20,
+					pCap->wireless_modes);
+			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
+				set_bit(ATH9K_MODE_11NA_HT40PLUS,
+					pCap->wireless_modes);
+				set_bit(ATH9K_MODE_11NA_HT40MINUS,
+					pCap->wireless_modes);
 			}
 		}
-		return (freq - 5000) / 5;
 	}
-}
 
-/* We can tune this as we go by monitoring really low values */
-#define ATH9K_NF_TOO_LOW	-60
-
-/* AR5416 may return very high value (like -31 dBm), in those cases the nf
- * is incorrect and we should use the static NF value. Later we can try to
- * find out why they are reporting these values */
-static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
-{
-	if (nf > ATH9K_NF_TOO_LOW) {
-		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-			 "%s: noise floor value detected (%d) is "
-			"lower than what we think is a "
-			"reasonable value (%d)\n",
-			 __func__, nf, ATH9K_NF_TOO_LOW);
-		return false;
+	if (eeval & AR5416_OPFLAGS_11G) {
+		set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
+		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
+		if (ah->ah_config.ht_enable) {
+			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
+				set_bit(ATH9K_MODE_11NG_HT20,
+					pCap->wireless_modes);
+			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
+				set_bit(ATH9K_MODE_11NG_HT40PLUS,
+					pCap->wireless_modes);
+				set_bit(ATH9K_MODE_11NG_HT40MINUS,
+					pCap->wireless_modes);
+			}
+		}
 	}
+
+	pCap->tx_chainmask = ath9k_hw_get_eeprom(ah, EEP_TX_MASK);
+	if ((ah->ah_isPciExpress)
+	    || (eeval & AR5416_OPFLAGS_11A)) {
+		pCap->rx_chainmask =
+			ath9k_hw_get_eeprom(ah, EEP_RX_MASK);
+	} else {
+		pCap->rx_chainmask =
+			(ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
+	}
+
+	if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
+		ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+	pCap->low_2ghz_chan = 2312;
+	pCap->high_2ghz_chan = 2732;
+
+	pCap->low_5ghz_chan = 4920;
+	pCap->high_5ghz_chan = 6100;
+
+	pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
+
+	pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
+
+	pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
+
+	if (ah->ah_config.ht_enable)
+		pCap->hw_caps |= ATH9K_HW_CAP_HT;
+	else
+		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+
+	pCap->hw_caps |= ATH9K_HW_CAP_GTT;
+	pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
+	pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
+	pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
+
+	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
+		pCap->total_queues =
+			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
+	else
+		pCap->total_queues = ATH9K_NUM_TX_QUEUES;
+
+	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+		pCap->keycache_size =
+			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
+	else
+		pCap->keycache_size = AR_KEYTABLE_SIZE;
+
+	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
+	pCap->num_mr_retries = 4;
+	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		pCap->num_gpio_pins = AR928X_NUM_GPIO;
+	else
+		pCap->num_gpio_pins = AR_NUM_GPIO;
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		pCap->hw_caps |= ATH9K_HW_CAP_WOW;
+		pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
+	} else {
+		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
+		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
+	}
+
+	if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
+		pCap->hw_caps |= ATH9K_HW_CAP_CST;
+		pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+	} else {
+		pCap->rts_aggr_limit = (8 * 1024);
+	}
+
+	pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
+
+#ifdef CONFIG_RFKILL
+	ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT);
+	if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
+		ah->ah_rfkill_gpio =
+			MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
+		ah->ah_rfkill_polarity =
+			MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
+
+		pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
+	}
+#endif
+
+	if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
+	    (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
+	    (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
+	    (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
+	    (ah->ah_macVersion == AR_SREV_VERSION_9280))
+		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+	else
+		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+
+	if (AR_SREV_9280(ah))
+		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+	else
+		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+
+	if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
+		pCap->reg_cap =
+			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+			AR_EEPROM_EEREGCAP_EN_KK_U2 |
+			AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
+	} else {
+		pCap->reg_cap =
+			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
+	}
+
+	pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
+
+	pCap->num_antcfg_5ghz =
+		ath9k_hw_get_num_ant_config(ah, IEEE80211_BAND_5GHZ);
+	pCap->num_antcfg_2ghz =
+		ath9k_hw_get_num_ant_config(ah, IEEE80211_BAND_2GHZ);
+
 	return true;
 }
 
-s16
-ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
+bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 *result)
 {
-	struct ath9k_channel *ichan;
-	s16 nf;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
 
-	ichan = ath9k_regd_check_channel(ah, chan);
-	if (ichan == NULL) {
-		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
-			 "%s: invalid channel %u/0x%x; no mapping\n",
-			 __func__, chan->channel, chan->channelFlags);
-		return ATH_DEFAULT_NOISE_FLOOR;
+	switch (type) {
+	case ATH9K_CAP_CIPHER:
+		switch (capability) {
+		case ATH9K_CIPHER_AES_CCM:
+		case ATH9K_CIPHER_AES_OCB:
+		case ATH9K_CIPHER_TKIP:
+		case ATH9K_CIPHER_WEP:
+		case ATH9K_CIPHER_MIC:
+		case ATH9K_CIPHER_CLR:
+			return true;
+		default:
+			return false;
+		}
+	case ATH9K_CAP_TKIP_MIC:
+		switch (capability) {
+		case 0:
+			return true;
+		case 1:
+			return (ahp->ah_staId1Defaults &
+				AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
+			false;
+		}
+	case ATH9K_CAP_TKIP_SPLIT:
+		return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
+			false : true;
+	case ATH9K_CAP_WME_TKIPMIC:
+		return 0;
+	case ATH9K_CAP_PHYCOUNTERS:
+		return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO;
+	case ATH9K_CAP_DIVERSITY:
+		return (REG_READ(ah, AR_PHY_CCK_DETECT) &
+			AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
+			true : false;
+	case ATH9K_CAP_PHYDIAG:
+		return true;
+	case ATH9K_CAP_MCAST_KEYSRCH:
+		switch (capability) {
+		case 0:
+			return true;
+		case 1:
+			if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
+				return false;
+			} else {
+				return (ahp->ah_staId1Defaults &
+					AR_STA_ID1_MCAST_KSRCH) ? true :
+					false;
+			}
+		}
+		return false;
+	case ATH9K_CAP_TSF_ADJUST:
+		return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
+			true : false;
+	case ATH9K_CAP_RFSILENT:
+		if (capability == 3)
+			return false;
+	case ATH9K_CAP_ANT_CFG_2GHZ:
+		*result = pCap->num_antcfg_2ghz;
+		return true;
+	case ATH9K_CAP_ANT_CFG_5GHZ:
+		*result = pCap->num_antcfg_5ghz;
+		return true;
+	case ATH9K_CAP_TXPOW:
+		switch (capability) {
+		case 0:
+			return 0;
+		case 1:
+			*result = ah->ah_powerLimit;
+			return 0;
+		case 2:
+			*result = ah->ah_maxPowerLevel;
+			return 0;
+		case 3:
+			*result = ah->ah_tpScale;
+			return 0;
+		}
+		return false;
+	default:
+		return false;
 	}
-	if (ichan->rawNoiseFloor == 0) {
-		enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
-		nf = NOISE_FLOOR[mode];
-	} else
-		nf = ichan->rawNoiseFloor;
+}
 
-	if (!ath9k_hw_nf_in_range(ah, nf))
-		nf = ATH_DEFAULT_NOISE_FLOOR;
+bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 setting, int *status)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 v;
 
-	return nf;
+	switch (type) {
+	case ATH9K_CAP_TKIP_MIC:
+		if (setting)
+			ahp->ah_staId1Defaults |=
+				AR_STA_ID1_CRPT_MIC_ENABLE;
+		else
+			ahp->ah_staId1Defaults &=
+				~AR_STA_ID1_CRPT_MIC_ENABLE;
+		return true;
+	case ATH9K_CAP_DIVERSITY:
+		v = REG_READ(ah, AR_PHY_CCK_DETECT);
+		if (setting)
+			v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+		else
+			v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+		REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+		return true;
+	case ATH9K_CAP_MCAST_KEYSRCH:
+		if (setting)
+			ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
+		else
+			ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
+		return true;
+	case ATH9K_CAP_TSF_ADJUST:
+		if (setting)
+			ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
+		else
+			ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
+		return true;
+	default:
+		return false;
+	}
+}
+
+/****************************/
+/* GPIO / RFKILL / Antennae */
+/****************************/
+
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
+					 u32 gpio, u32 type)
+{
+	int addr;
+	u32 gpio_shift, tmp;
+
+	if (gpio > 11)
+		addr = AR_GPIO_OUTPUT_MUX3;
+	else if (gpio > 5)
+		addr = AR_GPIO_OUTPUT_MUX2;
+	else
+		addr = AR_GPIO_OUTPUT_MUX1;
+
+	gpio_shift = (gpio % 6) * 5;
+
+	if (AR_SREV_9280_20_OR_LATER(ah)
+	    || (addr != AR_GPIO_OUTPUT_MUX1)) {
+		REG_RMW(ah, addr, (type << gpio_shift),
+			(0x1f << gpio_shift));
+	} else {
+		tmp = REG_READ(ah, addr);
+		tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+		tmp &= ~(0x1f << gpio_shift);
+		tmp |= (type << gpio_shift);
+		REG_WRITE(ah, addr, tmp);
+	}
+}
+
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
+{
+	u32 gpio_shift;
+
+	ASSERT(gpio < ah->ah_caps.num_gpio_pins);
+
+	gpio_shift = gpio << 1;
+
+	REG_RMW(ah,
+		AR_GPIO_OE_OUT,
+		(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+		(AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
+{
+	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;
+	}
+}
+
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+			 u32 ah_signal_type)
+{
+	u32 gpio_shift;
+
+	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+
+	gpio_shift = 2 * gpio;
+
+	REG_RMW(ah,
+		AR_GPIO_OE_OUT,
+		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+		(AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
+{
+	REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+		AR_GPIO_BIT(gpio));
+}
+
+#ifdef CONFIG_RFKILL
+void ath9k_enable_rfkill(struct ath_hal *ah)
+{
+	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+
+	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
+		    AR_GPIO_INPUT_MUX2_RFSILENT);
+
+	ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
+	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+}
+#endif
+
+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;
+}
+
+void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna)
+{
+	REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
+			       enum ath9k_ant_setting settings,
+			       struct ath9k_channel *chan,
+			       u8 *tx_chainmask,
+			       u8 *rx_chainmask,
+			       u8 *antenna_cfgd)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	static u8 tx_chainmask_cfg, rx_chainmask_cfg;
+
+	if (AR_SREV_9280(ah)) {
+		if (!tx_chainmask_cfg) {
+
+			tx_chainmask_cfg = *tx_chainmask;
+			rx_chainmask_cfg = *rx_chainmask;
+		}
+
+		switch (settings) {
+		case ATH9K_ANT_FIXED_A:
+			*tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+			*rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+			*antenna_cfgd = true;
+			break;
+		case ATH9K_ANT_FIXED_B:
+			if (ah->ah_caps.tx_chainmask >
+			    ATH9K_ANTENNA1_CHAINMASK) {
+				*tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+			}
+			*rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+			*antenna_cfgd = true;
+			break;
+		case ATH9K_ANT_VARIABLE:
+			*tx_chainmask = tx_chainmask_cfg;
+			*rx_chainmask = rx_chainmask_cfg;
+			*antenna_cfgd = true;
+			break;
+		default:
+			break;
+		}
+	} else {
+		ahp->ah_diversityControl = settings;
+	}
+
+	return true;
+}
+
+/*********************/
+/* General Operation */
+/*********************/
+
+u32 ath9k_hw_getrxfilter(struct ath_hal *ah)
+{
+	u32 bits = REG_READ(ah, AR_RX_FILTER);
+	u32 phybits = REG_READ(ah, AR_PHY_ERR);
+
+	if (phybits & AR_PHY_ERR_RADAR)
+		bits |= ATH9K_RX_FILTER_PHYRADAR;
+	if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+		bits |= ATH9K_RX_FILTER_PHYERR;
+
+	return bits;
+}
+
+void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits)
+{
+	u32 phybits;
+
+	REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
+	phybits = 0;
+	if (bits & ATH9K_RX_FILTER_PHYRADAR)
+		phybits |= AR_PHY_ERR_RADAR;
+	if (bits & ATH9K_RX_FILTER_PHYERR)
+		phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+	REG_WRITE(ah, AR_PHY_ERR, phybits);
+
+	if (phybits)
+		REG_WRITE(ah, AR_RXCFG,
+			  REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
+	else
+		REG_WRITE(ah, AR_RXCFG,
+			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
+}
+
+bool ath9k_hw_phy_disable(struct ath_hal *ah)
+{
+	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
+}
+
+bool ath9k_hw_disable(struct ath_hal *ah)
+{
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+		return false;
+
+	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
+}
+
+bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
+{
+	struct ath9k_channel *chan = ah->ah_curchan;
+
+	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,
+				 min((u32) MAX_RATE_POWER,
+				     (u32) ah->ah_powerLimit)) != 0)
+		return false;
+
+	return true;
+}
+
+void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	memcpy(mac, ahp->ah_macaddr, ETH_ALEN);
+}
+
+bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	memcpy(ahp->ah_macaddr, mac, ETH_ALEN);
+
+	return true;
+}
+
+void ath9k_hw_setopmode(struct ath_hal *ah)
+{
+	ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
+}
+
+void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1)
+{
+	REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+	REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	memcpy(mask, ahp->ah_bssidmask, ETH_ALEN);
+}
+
+bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	memcpy(ahp->ah_bssidmask, mask, ETH_ALEN);
+
+	REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
+	REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
+
+	return true;
+}
+
+void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	memcpy(ahp->ah_bssid, bssid, ETH_ALEN);
+	ahp->ah_assocId = assocId;
+
+	REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
+	REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
+		  ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
+}
+
+u64 ath9k_hw_gettsf64(struct ath_hal *ah)
+{
+	u64 tsf;
+
+	tsf = REG_READ(ah, AR_TSF_U32);
+	tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
+
+	return tsf;
+}
+
+void ath9k_hw_reset_tsf(struct ath_hal *ah)
+{
+	int count;
+
+	count = 0;
+	while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
+		count++;
+		if (count > 10) {
+			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+				"%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n",
+				__func__);
+			break;
+		}
+		udelay(10);
+	}
+	REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
 }
 
 bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
@@ -8468,110 +3961,35 @@
 		ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
 	else
 		ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
+
 	return true;
 }
 
-bool ath9k_hw_phycounters(struct ath_hal *ah)
+bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
 {
 	struct ath_hal_5416 *ahp = AH5416(ah);
 
-	return ahp->ah_hasHwPhyCounters ? true : false;
-}
-
-u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q)
-{
-	return REG_READ(ah, AR_QTXDP(q));
-}
-
-bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
-		       u32 txdp)
-{
-	REG_WRITE(ah, AR_QTXDP(q), txdp);
-
-	return true;
-}
-
-bool ath9k_hw_txstart(struct ath_hal *ah, u32 q)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
-
-	REG_WRITE(ah, AR_Q_TXE, 1 << q);
-
-	return true;
-}
-
-u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q)
-{
-	u32 npend;
-
-	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
-	if (npend == 0) {
-
-		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
-			npend = 1;
+	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n",
+			 __func__, us);
+		ahp->ah_slottime = (u32) -1;
+		return false;
+	} else {
+		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
+		ahp->ah_slottime = us;
+		return true;
 	}
-	return npend;
 }
 
-bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
+void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
 {
-	u32 wait;
+	u32 macmode;
 
-	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+	if (mode == ATH9K_HT_MACMODE_2040 &&
+	    !ah->ah_config.cwm_ignore_extcca)
+		macmode = AR_2040_JOINED_RX_CLEAR;
+	else
+		macmode = 0;
 
-	for (wait = 1000; wait != 0; wait--) {
-		if (ath9k_hw_numtxpending(ah, q) == 0)
-			break;
-		udelay(100);
-	}
-
-	if (ath9k_hw_numtxpending(ah, q)) {
-		u32 tsfLow, j;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			 "%s: Num of pending TX Frames %d on Q %d\n",
-			 __func__, ath9k_hw_numtxpending(ah, q), q);
-
-		for (j = 0; j < 2; j++) {
-			tsfLow = REG_READ(ah, AR_TSF_L32);
-			REG_WRITE(ah, AR_QUIET2,
-				  SM(10, AR_QUIET2_QUIET_DUR));
-			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
-			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
-			REG_SET_BIT(ah, AR_TIMER_MODE,
-				       AR_QUIET_TIMER_EN);
-
-			if ((REG_READ(ah, AR_TSF_L32) >> 10) ==
-			    (tsfLow >> 10)) {
-				break;
-			}
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"%s: TSF have moved while trying to set "
-				"quiet time TSF: 0x%08x\n",
-				__func__, tsfLow);
-		}
-
-		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-
-		udelay(200);
-		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
-
-		wait = 1000;
-
-		while (ath9k_hw_numtxpending(ah, q)) {
-			if ((--wait) == 0) {
-				DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
-					"%s: Failed to stop Tx DMA in 100 "
-					"msec after killing last frame\n",
-					__func__);
-				break;
-			}
-			udelay(100);
-		}
-
-		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-	}
-
-	REG_WRITE(ah, AR_Q_TXD, 0);
-	return wait != 0;
+	REG_WRITE(ah, AR_2040_MODE, macmode);
 }
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h
index 2113818..6a29f2d 100644
--- a/drivers/net/wireless/ath9k/hw.h
+++ b/drivers/net/wireless/ath9k/hw.h
@@ -923,7 +923,7 @@
 #define OFDM_PLCP_BITS_QUARTER      22
 #define OFDM_SYMBOL_TIME_QUARTER    16
 
-u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
+u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
 			enum eeprom_param param);
 
 #endif
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c
new file mode 100644
index 0000000..c344a81
--- /dev/null
+++ b/drivers/net/wireless/ath9k/mac.c
@@ -0,0 +1,1031 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static void ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
+					struct ath9k_tx_queue_info *qi)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+		"%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+		__func__, ahp->ah_txOkInterruptMask,
+		ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
+		ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask);
+
+	REG_WRITE(ah, AR_IMR_S0,
+		  SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
+		  | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
+	REG_WRITE(ah, AR_IMR_S1,
+		  SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
+		  | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
+	REG_RMW_FIELD(ah, AR_IMR_S2,
+		      AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+}
+
+void ath9k_hw_dmaRegDump(struct ath_hal *ah)
+{
+	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
+	int qcuOffset = 0, dcuOffset = 0;
+	u32 *qcuBase = &val[0], *dcuBase = &val[4];
+	int i;
+
+	REG_WRITE(ah, AR_MACMISC,
+		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+		   (AR_MACMISC_MISC_OBS_BUS_1 <<
+		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "Raw DMA Debug values:\n");
+
+	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
+		if (i % 4 == 0)
+			DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
+
+		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
+		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "%d: %08x ", i, val[i]);
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n\n");
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+
+	for (i = 0; i < ATH9K_NUM_QUEUES;
+	     i++, qcuOffset += 4, dcuOffset += 5) {
+		if (i == 8) {
+			qcuOffset = 0;
+			qcuBase++;
+		}
+
+		if (i == 6) {
+			dcuOffset = 0;
+			dcuBase++;
+		}
+
+		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+			"%2d          %2x      %1x     %2x           %2x\n",
+			i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+			(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+			val[2] & (0x7 << (i * 3)) >> (i * 3),
+			(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
+		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
+		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
+		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
+		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
+		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
+		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "pcu observe 0x%x \n",
+		REG_READ(ah, AR_OBS_BUS_1));
+	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		"AR_CR 0x%x \n", REG_READ(ah, AR_CR));
+}
+
+u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q)
+{
+	return REG_READ(ah, AR_QTXDP(q));
+}
+
+bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp)
+{
+	REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+	return true;
+}
+
+bool ath9k_hw_txstart(struct ath_hal *ah, u32 q)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
+
+	REG_WRITE(ah, AR_Q_TXE, 1 << q);
+
+	return true;
+}
+
+u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q)
+{
+	u32 npend;
+
+	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+	if (npend == 0) {
+
+		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+			npend = 1;
+	}
+
+	return npend;
+}
+
+bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	u32 txcfg, curLevel, newLevel;
+	enum ath9k_int omask;
+
+	if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
+		return false;
+
+	omask = ath9k_hw_set_interrupts(ah, ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
+
+	txcfg = REG_READ(ah, AR_TXCFG);
+	curLevel = MS(txcfg, AR_FTRIG);
+	newLevel = curLevel;
+	if (bIncTrigLevel) {
+		if (curLevel < MAX_TX_FIFO_THRESHOLD)
+			newLevel++;
+	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+		newLevel--;
+	if (newLevel != curLevel)
+		REG_WRITE(ah, AR_TXCFG,
+			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+	ath9k_hw_set_interrupts(ah, omask);
+
+	ah->ah_txTrigLevel = newLevel;
+
+	return newLevel != curLevel;
+}
+
+bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
+{
+	u32 tsfLow, j, wait;
+
+	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+
+	for (wait = 1000; wait != 0; wait--) {
+		if (ath9k_hw_numtxpending(ah, q) == 0)
+			break;
+		udelay(100);
+	}
+
+	if (ath9k_hw_numtxpending(ah, q)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+			"%s: Num of pending TX Frames %d on Q %d\n",
+			__func__, ath9k_hw_numtxpending(ah, q), q);
+
+		for (j = 0; j < 2; j++) {
+			tsfLow = REG_READ(ah, AR_TSF_L32);
+			REG_WRITE(ah, AR_QUIET2,
+				  SM(10, AR_QUIET2_QUIET_DUR));
+			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
+			REG_SET_BIT(ah, AR_TIMER_MODE,
+				       AR_QUIET_TIMER_EN);
+
+			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
+				break;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				"%s: TSF have moved while trying to set "
+				"quiet time TSF: 0x%08x\n",
+				__func__, tsfLow);
+		}
+
+		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+
+		udelay(200);
+		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+		wait = 1000;
+
+		while (ath9k_hw_numtxpending(ah, q)) {
+			if ((--wait) == 0) {
+				DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
+					"%s: Failed to stop Tx DMA in 100 "
+					"msec after killing last frame\n",
+					__func__);
+				break;
+			}
+			udelay(100);
+		}
+
+		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	}
+
+	REG_WRITE(ah, AR_Q_TXD, 0);
+
+	return wait != 0;
+}
+
+bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+			 u32 segLen, bool firstSeg,
+			 bool lastSeg, const struct ath_desc *ds0)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if (firstSeg) {
+		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+	} else if (lastSeg) {
+		ads->ds_ctl0 = 0;
+		ads->ds_ctl1 = segLen;
+		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+	} else {
+		ads->ds_ctl0 = 0;
+		ads->ds_ctl1 = segLen | AR_TxMore;
+		ads->ds_ctl2 = 0;
+		ads->ds_ctl3 = 0;
+	}
+	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+	return true;
+}
+
+void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+}
+
+int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+		return -EINPROGRESS;
+
+	ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+	ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
+	ds->ds_txstat.ts_status = 0;
+	ds->ds_txstat.ts_flags = 0;
+
+	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
+	if (ads->ds_txstatus1 & AR_Filtered)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
+	if (ads->ds_txstatus1 & AR_FIFOUnderrun)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
+	if (ads->ds_txstatus9 & AR_TxOpExceeded)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
+	if (ads->ds_txstatus1 & AR_TxTimerExpired)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+
+	if (ads->ds_txstatus1 & AR_DescCfgErr)
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+		ath9k_hw_updatetxtriglevel(ah, true);
+	}
+	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+		ath9k_hw_updatetxtriglevel(ah, true);
+	}
+	if (ads->ds_txstatus0 & AR_TxBaStatus) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
+		ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
+		ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
+	}
+
+	ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+	switch (ds->ds_txstat.ts_rateindex) {
+	case 0:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+		break;
+	case 1:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+		break;
+	case 2:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+		break;
+	case 3:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+		break;
+	}
+
+	ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+	ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+	ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+	ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+	ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+	ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+	ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+	ds->ds_txstat.evm0 = ads->AR_TxEVM0;
+	ds->ds_txstat.evm1 = ads->AR_TxEVM1;
+	ds->ds_txstat.evm2 = ads->AR_TxEVM2;
+	ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+	ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+	ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+	ds->ds_txstat.ts_antenna = 1;
+
+	return 0;
+}
+
+void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+			    u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	txPower += ahp->ah_txPowerIndexOffset;
+	if (txPower > 63)
+		txPower = 63;
+
+	ads->ds_ctl0 = (pktLen & AR_FrameLen)
+		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+		| SM(txPower, AR_XmitPower)
+		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+
+	ads->ds_ctl1 =
+		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+		| SM(type, AR_FrameType)
+		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+	ads->ds_ctl6 = SM(keyType, AR_EncrType);
+
+	if (AR_SREV_9285(ah)) {
+		ads->ds_ctl8 = 0;
+		ads->ds_ctl9 = 0;
+		ads->ds_ctl10 = 0;
+		ads->ds_ctl11 = 0;
+	}
+}
+
+void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
+				  struct ath_desc *lastds,
+				  u32 durUpdateEn, u32 rtsctsRate,
+				  u32 rtsctsDuration,
+				  struct ath9k_11n_rate_series series[],
+				  u32 nseries, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	struct ar5416_desc *last_ads = AR5416DESC(lastds);
+	u32 ds_ctl0;
+
+	(void) nseries;
+	(void) rtsctsDuration;
+
+	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+		ds_ctl0 = ads->ds_ctl0;
+
+		if (flags & ATH9K_TXDESC_RTSENA) {
+			ds_ctl0 &= ~AR_CTSEnable;
+			ds_ctl0 |= AR_RTSEnable;
+		} else {
+			ds_ctl0 &= ~AR_RTSEnable;
+			ds_ctl0 |= AR_CTSEnable;
+		}
+
+		ads->ds_ctl0 = ds_ctl0;
+	} else {
+		ads->ds_ctl0 =
+			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+	}
+
+	ads->ds_ctl2 = set11nTries(series, 0)
+		| set11nTries(series, 1)
+		| set11nTries(series, 2)
+		| set11nTries(series, 3)
+		| (durUpdateEn ? AR_DurUpdateEna : 0)
+		| SM(0, AR_BurstDur);
+
+	ads->ds_ctl3 = set11nRate(series, 0)
+		| set11nRate(series, 1)
+		| set11nRate(series, 2)
+		| set11nRate(series, 3);
+
+	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+		| set11nPktDurRTSCTS(series, 1);
+
+	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+		| set11nPktDurRTSCTS(series, 3);
+
+	ads->ds_ctl7 = set11nRateFlags(series, 0)
+		| set11nRateFlags(series, 1)
+		| set11nRateFlags(series, 2)
+		| set11nRateFlags(series, 3)
+		| SM(rtsctsRate, AR_RTSCTSRate);
+	last_ads->ds_ctl2 = ads->ds_ctl2;
+	last_ads->ds_ctl3 = ads->ds_ctl3;
+}
+
+void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+				u32 aggrLen)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+	ads->ds_ctl6 &= ~AR_AggrLen;
+	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+}
+
+void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+				 u32 numDelims)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	unsigned int ctl6;
+
+	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+	ctl6 = ads->ds_ctl6;
+	ctl6 &= ~AR_PadDelim;
+	ctl6 |= SM(numDelims, AR_PadDelim);
+	ads->ds_ctl6 = ctl6;
+}
+
+void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 |= AR_IsAggr;
+	ads->ds_ctl1 &= ~AR_MoreAggr;
+	ads->ds_ctl6 &= ~AR_PadDelim;
+}
+
+void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
+				   u32 burstDuration)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl2 &= ~AR_BurstDur;
+	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+				     u32 vmf)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if (vmf)
+		ads->ds_ctl0 |= AR_VirtMoreFrag;
+	else
+		ads->ds_ctl0 &= ~AR_VirtMoreFrag;
+}
+
+void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+
+	*txqs &= ahp->ah_intrTxqs;
+	ahp->ah_intrTxqs &= ~(*txqs);
+}
+
+bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
+			    const struct ath9k_tx_queue_info *qinfo)
+{
+	u32 cw;
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
+			 __func__, q);
+		return false;
+	}
+
+	qi = &ahp->ah_txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
+			 __func__);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi);
+
+	qi->tqi_ver = qinfo->tqi_ver;
+	qi->tqi_subtype = qinfo->tqi_subtype;
+	qi->tqi_qflags = qinfo->tqi_qflags;
+	qi->tqi_priority = qinfo->tqi_priority;
+	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+	else
+		qi->tqi_aifs = INIT_AIFS;
+	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+		cw = min(qinfo->tqi_cwmin, 1024U);
+		qi->tqi_cwmin = 1;
+		while (qi->tqi_cwmin < cw)
+			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+	} else
+		qi->tqi_cwmin = qinfo->tqi_cwmin;
+	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+		cw = min(qinfo->tqi_cwmax, 1024U);
+		qi->tqi_cwmax = 1;
+		while (qi->tqi_cwmax < cw)
+			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+	} else
+		qi->tqi_cwmax = INIT_CWMAX;
+
+	if (qinfo->tqi_shretry != 0)
+		qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
+	else
+		qi->tqi_shretry = INIT_SH_RETRY;
+	if (qinfo->tqi_lgretry != 0)
+		qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+	else
+		qi->tqi_lgretry = INIT_LG_RETRY;
+	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+	qi->tqi_burstTime = qinfo->tqi_burstTime;
+	qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+	switch (qinfo->tqi_subtype) {
+	case ATH9K_WME_UPSD:
+		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
+			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+			    struct ath9k_tx_queue_info *qinfo)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
+			 __func__, q);
+		return false;
+	}
+
+	qi = &ahp->ah_txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
+			 __func__);
+		return false;
+	}
+
+	qinfo->tqi_qflags = qi->tqi_qflags;
+	qinfo->tqi_ver = qi->tqi_ver;
+	qinfo->tqi_subtype = qi->tqi_subtype;
+	qinfo->tqi_qflags = qi->tqi_qflags;
+	qinfo->tqi_priority = qi->tqi_priority;
+	qinfo->tqi_aifs = qi->tqi_aifs;
+	qinfo->tqi_cwmin = qi->tqi_cwmin;
+	qinfo->tqi_cwmax = qi->tqi_cwmax;
+	qinfo->tqi_shretry = qi->tqi_shretry;
+	qinfo->tqi_lgretry = qi->tqi_lgretry;
+	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
+	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
+	qinfo->tqi_burstTime = qi->tqi_burstTime;
+	qinfo->tqi_readyTime = qi->tqi_readyTime;
+
+	return true;
+}
+
+int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+			  const struct ath9k_tx_queue_info *qinfo)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_tx_queue_info *qi;
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	int q;
+
+	switch (type) {
+	case ATH9K_TX_QUEUE_BEACON:
+		q = pCap->total_queues - 1;
+		break;
+	case ATH9K_TX_QUEUE_CAB:
+		q = pCap->total_queues - 2;
+		break;
+	case ATH9K_TX_QUEUE_PSPOLL:
+		q = 1;
+		break;
+	case ATH9K_TX_QUEUE_UAPSD:
+		q = pCap->total_queues - 3;
+		break;
+	case ATH9K_TX_QUEUE_DATA:
+		for (q = 0; q < pCap->total_queues; q++)
+			if (ahp->ah_txq[q].tqi_type ==
+			    ATH9K_TX_QUEUE_INACTIVE)
+				break;
+		if (q == pCap->total_queues) {
+			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				"%s: no available tx queue\n", __func__);
+			return -1;
+		}
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n",
+			__func__, type);
+		return -1;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
+
+	qi = &ahp->ah_txq[q];
+	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+			"%s: tx queue %u already active\n", __func__, q);
+		return -1;
+	}
+	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
+	qi->tqi_type = type;
+	if (qinfo == NULL) {
+		qi->tqi_qflags =
+			TXQ_FLAG_TXOKINT_ENABLE
+			| TXQ_FLAG_TXERRINT_ENABLE
+			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
+		qi->tqi_aifs = INIT_AIFS;
+		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+		qi->tqi_cwmax = INIT_CWMAX;
+		qi->tqi_shretry = INIT_SH_RETRY;
+		qi->tqi_lgretry = INIT_LG_RETRY;
+		qi->tqi_physCompBuf = 0;
+	} else {
+		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
+	}
+
+	return q;
+}
+
+bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
+			 __func__, q);
+		return false;
+	}
+	qi = &ahp->ah_txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
+			 __func__, q);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n",
+		__func__, q);
+
+	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
+	ahp->ah_txOkInterruptMask &= ~(1 << q);
+	ahp->ah_txErrInterruptMask &= ~(1 << q);
+	ahp->ah_txDescInterruptMask &= ~(1 << q);
+	ahp->ah_txEolInterruptMask &= ~(1 << q);
+	ahp->ah_txUrnInterruptMask &= ~(1 << q);
+	ath9k_hw_set_txq_interrupts(ah, qi);
+
+	return true;
+}
+
+bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
+{
+	struct ath_hal_5416 *ahp = AH5416(ah);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+	struct ath9k_channel *chan = ah->ah_curchan;
+	struct ath9k_tx_queue_info *qi;
+	u32 cwMin, chanCwMin, value;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
+			 __func__, q);
+		return false;
+	}
+
+	qi = &ahp->ah_txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
+			 __func__, q);
+		return true;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q);
+
+	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+		if (chan && IS_CHAN_B(chan))
+			chanCwMin = INIT_CWMIN_11B;
+		else
+			chanCwMin = INIT_CWMIN;
+
+		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
+	} else
+		cwMin = qi->tqi_cwmin;
+
+	REG_WRITE(ah, AR_DLCL_IFS(q),
+		  SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+		  SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+		  SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+		  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+		  SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+		  SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+	REG_WRITE(ah, AR_DMISC(q),
+		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+	if (qi->tqi_cbrPeriod) {
+		REG_WRITE(ah, AR_QCBRCFG(q),
+			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+			  SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
+			  (qi->tqi_cbrOverflowLimit ?
+			   AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+	}
+	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+			  SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+			  AR_Q_RDYTIMECFG_EN);
+	}
+
+	REG_WRITE(ah, AR_DCHNTIME(q),
+		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+	if (qi->tqi_burstTime
+	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) |
+			  AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+	}
+
+	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+	}
+	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_FRAG_BKOFF_EN);
+	}
+	switch (qi->tqi_type) {
+	case ATH9K_TX_QUEUE_BEACON:
+		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+			  | AR_Q_MISC_FSP_DBA_GATED
+			  | AR_Q_MISC_BEACON_USE
+			  | AR_Q_MISC_CBR_INCR_DIS1);
+
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+			  | AR_D_MISC_BEACON_USE
+			  | AR_D_MISC_POST_FR_BKOFF_DIS);
+		break;
+	case ATH9K_TX_QUEUE_CAB:
+		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+			  | AR_Q_MISC_FSP_DBA_GATED
+			  | AR_Q_MISC_CBR_INCR_DIS1
+			  | AR_Q_MISC_CBR_INCR_DIS0);
+		value = (qi->tqi_readyTime -
+			 (ah->ah_config.sw_beacon_response_time -
+			  ah->ah_config.dma_beacon_response_time) -
+			 ah->ah_config.additional_swba_backoff) * 1024;
+		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+			  value | AR_Q_RDYTIMECFG_EN);
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+		break;
+	case ATH9K_TX_QUEUE_PSPOLL:
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
+		break;
+	case ATH9K_TX_QUEUE_UAPSD:
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+		break;
+	default:
+		break;
+	}
+
+	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+	}
+
+	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+		ahp->ah_txOkInterruptMask |= 1 << q;
+	else
+		ahp->ah_txOkInterruptMask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
+		ahp->ah_txErrInterruptMask |= 1 << q;
+	else
+		ahp->ah_txErrInterruptMask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+		ahp->ah_txDescInterruptMask |= 1 << q;
+	else
+		ahp->ah_txDescInterruptMask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+		ahp->ah_txEolInterruptMask |= 1 << q;
+	else
+		ahp->ah_txEolInterruptMask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+		ahp->ah_txUrnInterruptMask |= 1 << q;
+	else
+		ahp->ah_txUrnInterruptMask &= ~(1 << q);
+	ath9k_hw_set_txq_interrupts(ah, qi);
+
+	return true;
+}
+
+int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+			u32 pa, struct ath_desc *nds, u64 tsf)
+{
+	struct ar5416_desc ads;
+	struct ar5416_desc *adsp = AR5416DESC(ds);
+	u32 phyerr;
+
+	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+		return -EINPROGRESS;
+
+	ads.u.rx = adsp->u.rx;
+
+	ds->ds_rxstat.rs_status = 0;
+	ds->ds_rxstat.rs_flags = 0;
+
+	ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+	ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
+
+	ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+	ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
+	ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
+	ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
+	ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
+	ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
+	ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
+	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+		ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+	else
+		ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+	ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
+	ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+	ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+	ds->ds_rxstat.rs_moreaggr =
+		(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+	ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+	ds->ds_rxstat.rs_flags =
+		(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+	ds->ds_rxstat.rs_flags |=
+		(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+		if (ads.ds_rxstatus8 & AR_CRCErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
+		else if (ads.ds_rxstatus8 & AR_PHYErr) {
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
+			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+			ds->ds_rxstat.rs_phyerr = phyerr;
+		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
+		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
+	}
+
+	return 0;
+}
+
+bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
+			  u32 size, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+	ads->ds_ctl1 = size & AR_BufLen;
+	if (flags & ATH9K_RXDESC_INTREQ)
+		ads->ds_ctl1 |= AR_RxIntrReq;
+
+	ads->ds_rxstatus8 &= ~AR_RxDone;
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+		memset(&(ads->u), 0, sizeof(ads->u));
+
+	return true;
+}
+
+bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set)
+{
+	u32 reg;
+
+	if (set) {
+		REG_SET_BIT(ah, AR_DIAG_SW,
+			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+		if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
+			REG_CLR_BIT(ah, AR_DIAG_SW,
+				    (AR_DIAG_RX_DIS |
+				     AR_DIAG_RX_ABORT));
+
+			reg = REG_READ(ah, AR_OBS_BUS_1);
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
+				__func__, reg);
+
+			return false;
+		}
+	} else {
+		REG_CLR_BIT(ah, AR_DIAG_SW,
+			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+	}
+
+	return true;
+}
+
+void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp)
+{
+	REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+void ath9k_hw_rxena(struct ath_hal *ah)
+{
+	REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+void ath9k_hw_startpcureceive(struct ath_hal *ah)
+{
+	REG_CLR_BIT(ah, AR_DIAG_SW,
+		    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+	ath9k_enable_mib_counters(ah);
+
+	ath9k_ani_reset(ah);
+}
+
+void ath9k_hw_stoppcurecv(struct ath_hal *ah)
+{
+	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
+
+	ath9k_hw_disable_mib_counters(ah);
+}
+
+bool ath9k_hw_stopdmarecv(struct ath_hal *ah)
+{
+	REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+	if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+			"%s: dma failed to stop in 10ms\n"
+			"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
+			__func__,
+			REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
+		return false;
+	} else {
+		return true;
+	}
+}
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index f05f584..f830fe1 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -21,8 +21,6 @@
 
 #define ATH_PCI_VERSION "0.1"
 
-#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR	13
-
 static char *dev_info = "ath9k";
 
 MODULE_AUTHOR("Atheros Communications");
@@ -39,6 +37,8 @@
 	{ 0 }
 };
 
+static void ath_detach(struct ath_softc *sc);
+
 static int ath_get_channel(struct ath_softc *sc,
 			   struct ieee80211_channel *chan)
 {
@@ -61,24 +61,24 @@
 
 	switch (chan->band) {
 	case IEEE80211_BAND_2GHZ:
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_20))
 			chanmode = CHANNEL_G_HT20;
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_G_HT40PLUS;
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_G_HT40MINUS;
 		break;
 	case IEEE80211_BAND_5GHZ:
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_20))
 			chanmode = CHANNEL_A_HT20;
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_A_HT40PLUS;
-		if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
+		if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
 		    (tx_chan_width == ATH9K_HT_MACMODE_2040))
 			chanmode = CHANNEL_A_HT40MINUS;
 		break;
@@ -164,7 +164,7 @@
 	if (!sc->sc_vaps[0])
 		return -EIO;
 
-	vif = sc->sc_vaps[0]->av_if_data;
+	vif = sc->sc_vaps[0];
 	opmode = vif->type;
 
 	/*
@@ -215,24 +215,24 @@
 	ath_key_reset(sc, key->keyidx, freeslot);
 }
 
-static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
+static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
 {
 #define	ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3	/* 2 ^ 16 */
 #define	ATH9K_HT_CAP_MPDUDENSITY_8 0x6		/* 8 usec */
 
-	ht_info->ht_supported = 1;
-	ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
-			|(u16)IEEE80211_HT_CAP_SM_PS
-			|(u16)IEEE80211_HT_CAP_SGI_40
-			|(u16)IEEE80211_HT_CAP_DSSSCCK40;
+	ht_info->ht_supported = true;
+	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+		       IEEE80211_HT_CAP_SM_PS |
+		       IEEE80211_HT_CAP_SGI_40 |
+		       IEEE80211_HT_CAP_DSSSCCK40;
 
 	ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
 	ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
-	/* setup supported mcs set */
-	memset(ht_info->supp_mcs_set, 0, 16);
-	ht_info->supp_mcs_set[0] = 0xff;
-	ht_info->supp_mcs_set[1] = 0xff;
-	ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
+	/* set up supported mcs set */
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+	ht_info->mcs.rx_mask[0] = 0xff;
+	ht_info->mcs.rx_mask[1] = 0xff;
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 }
 
 static int ath_rate2idx(struct ath_softc *sc, int rate)
@@ -279,8 +279,15 @@
 	rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
 	rx_status->antenna = status->antenna;
 
-	/* XXX Fix me, 64 cannot be the max rssi value, rigure it out */
-	rx_status->qual = status->rssi * 100 / 64;
+	/* at 45 you will be able to use MCS 15 reliably. A more elaborate
+	 * scheme can be used here but it requires tables of SNR/throughput for
+	 * each possible mode used. */
+	rx_status->qual = status->rssi * 100 / 45;
+
+	/* rssi can be more than 45 though, anything above that
+	 * should be considered at 100% */
+	if (rx_status->qual > 100)
+		rx_status->qual = 100;
 
 	if (status->flags & ATH_RX_MIC_ERROR)
 		rx_status->flag |= RX_FLAG_MMIC_ERROR;
@@ -290,92 +297,37 @@
 	rx_status->flag |= RX_FLAG_TSFT;
 }
 
-static u8 parse_mpdudensity(u8 mpdudensity)
-{
-	/*
-	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
-	 *   0 for no restriction
-	 *   1 for 1/4 us
-	 *   2 for 1/2 us
-	 *   3 for 1 us
-	 *   4 for 2 us
-	 *   5 for 4 us
-	 *   6 for 8 us
-	 *   7 for 16 us
-	 */
-	switch (mpdudensity) {
-	case 0:
-		return 0;
-	case 1:
-	case 2:
-	case 3:
-		/* Our lower layer calculations limit our precision to
-		   1 microsecond */
-		return 1;
-	case 4:
-		return 2;
-	case 5:
-		return 4;
-	case 6:
-		return 8;
-	case 7:
-		return 16;
-	default:
-		return 0;
-	}
-}
-
 static void ath9k_ht_conf(struct ath_softc *sc,
 			  struct ieee80211_bss_conf *bss_conf)
 {
-#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
 	struct ath_ht_info *ht_info = &sc->sc_ht_info;
 
-	if (bss_conf->assoc_ht) {
-		ht_info->ext_chan_offset =
-			bss_conf->ht_bss_conf->bss_cap &
-				IEEE80211_HT_IE_CHA_SEC_OFFSET;
+	if (sc->hw->conf.ht.enabled) {
+		ht_info->ext_chan_offset = bss_conf->ht.secondary_channel_offset;
 
-		if (!(bss_conf->ht_conf->cap &
-			IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
-			    (bss_conf->ht_bss_conf->bss_cap &
-				IEEE80211_HT_IE_CHA_WIDTH))
+		if (bss_conf->ht.width_40_ok)
 			ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
 		else
 			ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
 
 		ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
-		ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
-					bss_conf->ht_conf->ampdu_factor);
-		ht_info->mpdudensity =
-			parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
-
 	}
-
-#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
 }
 
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
+				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_channel *curchan = hw->conf.channel;
-	struct ath_vap *avp;
+	struct ath_vap *avp = (void *)vif->drv_priv;
 	int pos;
-	DECLARE_MAC_BUF(mac);
 
 	if (bss_conf->assoc) {
 		DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
 			__func__,
 			bss_conf->aid);
 
-		avp = sc->sc_vaps[0];
-		if (avp == NULL) {
-			DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
-				__func__);
-			return;
-		}
-
 		/* New association, store aid */
 		if (avp->av_opmode == ATH9K_M_STA) {
 			sc->sc_curaid = bss_conf->aid;
@@ -394,12 +346,12 @@
 		sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
 
 		/* Update chainmask */
-		ath_update_chainmask(sc, bss_conf->assoc_ht);
+		ath_update_chainmask(sc, hw->conf.ht.enabled);
 
 		DPRINTF(sc, ATH_DBG_CONFIG,
-			"%s: bssid %s aid 0x%x\n",
+			"%s: bssid %pM aid 0x%x\n",
 			__func__,
-			print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+			sc->sc_curbssid, sc->sc_curaid);
 
 		DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 			__func__,
@@ -412,7 +364,7 @@
 			return;
 		}
 
-		if (hw->conf.ht_conf.ht_supported)
+		if (hw->conf.ht.enabled)
 			sc->sc_ah->ah_channels[pos].chanmode =
 				ath_get_extchanmode(sc, curchan);
 		else
@@ -456,7 +408,7 @@
 }
 
 void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-		     struct ath_xmit_status *tx_status, struct ath_node *an)
+		     struct ath_xmit_status *tx_status)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -464,12 +416,13 @@
 	DPRINTF(sc, ATH_DBG_XMIT,
 		"%s: TX complete: skb: %p\n", __func__, skb);
 
+	ieee80211_tx_info_clear_status(tx_info);
 	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
 		tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
-		/* free driver's private data area of tx_info */
-		if (tx_info->driver_data[0] != NULL)
-			kfree(tx_info->driver_data[0]);
-			tx_info->driver_data[0] = NULL;
+		/* free driver's private data area of tx_info, XXX: HACK! */
+		if (tx_info->control.vif != NULL)
+			kfree(tx_info->control.vif);
+			tx_info->control.vif = NULL;
 	}
 
 	if (tx_status->flags & ATH_TX_BAR) {
@@ -477,21 +430,14 @@
 		tx_status->flags &= ~ATH_TX_BAR;
 	}
 
-	if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
-		if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-			/* Frame was not ACKed, but an ACK was expected */
-			tx_info->status.excessive_retries = 1;
-		}
-	} else {
+	if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
 		/* Frame was ACKed */
 		tx_info->flags |= IEEE80211_TX_STAT_ACK;
 	}
 
-	tx_info->status.retry_count = tx_status->retries;
+	tx_info->status.rates[0].count = tx_status->retries + 1;
 
 	ieee80211_tx_status(hw, skb);
-	if (an)
-		ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
 }
 
 int _ath_rx_indicate(struct ath_softc *sc,
@@ -500,12 +446,10 @@
 		     u16 keyix)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	struct ath_node *an = NULL;
 	struct ieee80211_rx_status rx_status;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 	int padsize;
-	enum ATH_RX_TYPE st;
 
 	/* see if any padding is done by the hw and remove it */
 	if (hdrlen & 3) {
@@ -529,34 +473,6 @@
 			rx_status.flag |= RX_FLAG_DECRYPTED;
 	}
 
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, hdr->addr2);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (an) {
-		ath_rx_input(sc, an,
-			     hw->conf.ht_conf.ht_supported,
-			     skb, status, &st);
-	}
-	if (!an || (st != ATH_RX_CONSUMED))
-		__ieee80211_rx(hw, skb, &rx_status);
-
-	return 0;
-}
-
-int ath_rx_subframe(struct ath_node *an,
-		    struct sk_buff *skb,
-		    struct ath_recv_status *status)
-{
-	struct ath_softc *sc = an->an_sc;
-	struct ieee80211_hw *hw = sc->hw;
-	struct ieee80211_rx_status rx_status;
-
-	/* Prepare rx status */
-	ath9k_rx_prepare(sc, skb, status, &rx_status);
-	if (!(status->flags & ATH_RX_DECRYPT_ERROR))
-		rx_status.flag |= RX_FLAG_DECRYPTED;
-
 	__ieee80211_rx(hw, skb, &rx_status);
 
 	return 0;
@@ -678,6 +594,7 @@
 }
 
 #ifdef CONFIG_RFKILL
+
 /*******************/
 /*	Rfkill	   */
 /*******************/
@@ -878,43 +795,72 @@
 		sc->rf_kill.rfkill = NULL;
 	}
 }
+
+static int ath_start_rfkill_poll(struct ath_softc *sc)
+{
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		queue_delayed_work(sc->hw->workqueue,
+				   &sc->rf_kill.rfkill_poll, 0);
+
+	if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
+		if (rfkill_register(sc->rf_kill.rfkill)) {
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"Unable to register rfkill\n");
+			rfkill_free(sc->rf_kill.rfkill);
+
+			/* Deinitialize the device */
+			if (sc->pdev->irq)
+				free_irq(sc->pdev->irq, sc);
+			ath_detach(sc);
+			pci_iounmap(sc->pdev, sc->mem);
+			pci_release_region(sc->pdev, 0);
+			pci_disable_device(sc->pdev);
+			ieee80211_free_hw(sc->hw);
+			return -EIO;
+		} else {
+			sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
+		}
+	}
+
+	return 0;
+}
 #endif /* CONFIG_RFKILL */
 
-static int ath_detach(struct ath_softc *sc)
+static void ath_detach(struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
+	int i = 0;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
 
-	/* Deinit LED control */
+	ieee80211_unregister_hw(hw);
+
 	ath_deinit_leds(sc);
 
 #ifdef CONFIG_RFKILL
-	/* deinit rfkill */
 	ath_deinit_rfkill(sc);
 #endif
-
-	/* Unregister hw */
-
-	ieee80211_unregister_hw(hw);
-
-	/* unregister Rate control */
 	ath_rate_control_unregister();
-
-	/* tx/rx cleanup */
+	ath_rate_detach(sc->sc_rc);
 
 	ath_rx_cleanup(sc);
 	ath_tx_cleanup(sc);
 
-	/* Deinit */
+	tasklet_kill(&sc->intr_tq);
+	tasklet_kill(&sc->bcon_tasklet);
 
-	ath_deinit(sc);
+	if (!(sc->sc_flags & SC_OP_INVALID))
+		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
 
-	return 0;
+	/* cleanup tx queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
+
+	ath9k_hw_detach(sc->sc_ah);
 }
 
-static int ath_attach(u16 devid,
-		      struct ath_softc *sc)
+static int ath_attach(u16 devid, struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	int error = 0;
@@ -925,50 +871,23 @@
 	if (error != 0)
 		return error;
 
-	/* Init nodes */
-
-	INIT_LIST_HEAD(&sc->node_list);
-	spin_lock_init(&sc->node_lock);
-
 	/* get mac address from hardware and set in mac80211 */
 
 	SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
 
-	/* setup channels and rates */
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		IEEE80211_HW_SIGNAL_DBM |
+		IEEE80211_HW_AMPDU_AGGREGATION;
 
-	sc->sbands[IEEE80211_BAND_2GHZ].channels =
-		sc->channels[IEEE80211_BAND_2GHZ];
-	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
-		sc->rates[IEEE80211_BAND_2GHZ];
-	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
-
-	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
-		/* Setup HT capabilities for 2.4Ghz*/
-		setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
-
-	hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-		&sc->sbands[IEEE80211_BAND_2GHZ];
-
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
-		sc->sbands[IEEE80211_BAND_5GHZ].channels =
-			sc->channels[IEEE80211_BAND_5GHZ];
-		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
-			sc->rates[IEEE80211_BAND_5GHZ];
-		sc->sbands[IEEE80211_BAND_5GHZ].band =
-			IEEE80211_BAND_5GHZ;
-
-		if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
-			/* Setup HT capabilities for 5Ghz*/
-			setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
-
-		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			&sc->sbands[IEEE80211_BAND_5GHZ];
-	}
-
-	/* FIXME: Have to figure out proper hw init values later */
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC);
 
 	hw->queues = 4;
-	hw->ampdu_queues = 1;
+	hw->sta_data_size = sizeof(struct ath_node);
+	hw->vif_data_size = sizeof(struct ath_vap);
 
 	/* Register rate control */
 	hw->rate_control_algorithm = "ath9k_rate_control";
@@ -981,6 +900,17 @@
 		goto bad;
 	}
 
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
+		setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+		if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes))
+			setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+	}
+
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] =	&sc->sbands[IEEE80211_BAND_2GHZ];
+	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes))
+		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&sc->sbands[IEEE80211_BAND_5GHZ];
+
 	error = ieee80211_register_hw(hw);
 	if (error != 0) {
 		ath_rate_control_unregister();
@@ -1026,62 +956,44 @@
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
 		"initial channel: %d MHz\n", __func__, curchan->center_freq);
 
+	memset(&sc->sc_ht_info, 0, sizeof(struct ath_ht_info));
+
 	/* setup initial channel */
 
 	pos = ath_get_channel(sc, curchan);
 	if (pos == -1) {
 		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
-		return -EINVAL;
+		error = -EINVAL;
+		goto exit;
 	}
 
 	sc->sc_ah->ah_channels[pos].chanmode =
 		(curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
 
-	/* open ath_dev */
 	error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
 	if (error) {
 		DPRINTF(sc, ATH_DBG_FATAL,
 			"%s: Unable to complete ath_open\n", __func__);
-		return error;
+		goto exit;
 	}
 
 #ifdef CONFIG_RFKILL
-	/* Start rfkill polling */
-	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		queue_delayed_work(sc->hw->workqueue,
-				   &sc->rf_kill.rfkill_poll, 0);
-
-	if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
-		if (rfkill_register(sc->rf_kill.rfkill)) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-					"Unable to register rfkill\n");
-			rfkill_free(sc->rf_kill.rfkill);
-
-			/* Deinitialize the device */
-			if (sc->pdev->irq)
-				free_irq(sc->pdev->irq, sc);
-			ath_detach(sc);
-			pci_iounmap(sc->pdev, sc->mem);
-			pci_release_region(sc->pdev, 0);
-			pci_disable_device(sc->pdev);
-			ieee80211_free_hw(hw);
-			return -EIO;
-		} else {
-			sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
-		}
-	}
+	error = ath_start_rfkill_poll(sc);
 #endif
 
-	ieee80211_wake_queues(hw);
-	return 0;
+exit:
+	return error;
 }
 
 static int ath9k_tx(struct ieee80211_hw *hw,
 		    struct sk_buff *skb)
 {
-	struct ath_softc *sc = hw->priv;
-	int hdrlen, padsize;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ath_softc *sc = hw->priv;
+	struct ath_tx_control txctl;
+	int hdrlen, padsize;
+
+	memset(&txctl, 0, sizeof(struct ath_tx_control));
 
 	/*
 	 * As a temporary workaround, assign seq# here; this will likely need
@@ -1106,45 +1018,47 @@
 		memmove(skb->data, skb->data + padsize, hdrlen);
 	}
 
+	/* Check if a tx queue is available */
+
+	txctl.txq = ath_test_get_txq(sc, skb);
+	if (!txctl.txq)
+		goto exit;
+
 	DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n",
 		__func__,
 		skb);
 
-	if (ath_tx_start(sc, skb) != 0) {
+	if (ath_tx_start(sc, skb, &txctl) != 0) {
 		DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
-		dev_kfree_skb_any(skb);
-		/* FIXME: Check for proper return value from ATH_DEV */
-		return 0;
+		goto exit;
 	}
 
 	return 0;
+exit:
+	dev_kfree_skb_any(skb);
+	return 0;
 }
 
 static void ath9k_stop(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
-	int error;
+
+	if (sc->sc_flags & SC_OP_INVALID) {
+		DPRINTF(sc, ATH_DBG_ANY, "%s: Device not present\n", __func__);
+		return;
+	}
+
+	ath_stop(sc);
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
-
-	error = ath_suspend(sc);
-	if (error)
-		DPRINTF(sc, ATH_DBG_CONFIG,
-			"%s: Device is no longer present\n", __func__);
-
-	ieee80211_stop_queues(hw);
-
-#ifdef CONFIG_RFKILL
-	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
-#endif
 }
 
 static int ath9k_add_interface(struct ieee80211_hw *hw,
 			       struct ieee80211_if_init_conf *conf)
 {
 	struct ath_softc *sc = hw->priv;
-	int error, ic_opmode = 0;
+	struct ath_vap *avp = (void *)conf->vif->drv_priv;
+	int ic_opmode = 0;
 
 	/* Support only vap for now */
 
@@ -1172,13 +1086,22 @@
 		__func__,
 		ic_opmode);
 
-	error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
-	if (error) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: Unable to attach vap, error: %d\n",
-			__func__, error);
-		return error;
-	}
+	/* Set the VAP opmode */
+	avp->av_opmode = ic_opmode;
+	avp->av_bslot = -1;
+
+	if (ic_opmode == ATH9K_M_HOSTAP)
+		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
+
+	sc->sc_vaps[0] = conf->vif;
+	sc->sc_nvaps++;
+
+	/* Set the device opmode */
+	sc->sc_ah->ah_opmode = ic_opmode;
+
+	/* default VAP configuration */
+	avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
+	avp->av_config.av_fixed_retryset = 0x03030303;
 
 	if (conf->type == NL80211_IFTYPE_AP) {
 		/* TODO: is this a suitable place to start ANI for AP mode? */
@@ -1194,27 +1117,16 @@
 				   struct ieee80211_if_init_conf *conf)
 {
 	struct ath_softc *sc = hw->priv;
-	struct ath_vap *avp;
-	int error;
+	struct ath_vap *avp = (void *)conf->vif->drv_priv;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
 
-	avp = sc->sc_vaps[0];
-	if (avp == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
-			__func__);
-		return;
-	}
-
 #ifdef CONFIG_SLOW_ANT_DIV
 	ath_slow_ant_div_stop(&sc->sc_antdiv);
 #endif
 	/* Stop ANI */
 	del_timer_sync(&sc->sc_ani.timer);
 
-	/* Update ratectrl */
-	ath_rate_newstate(sc, avp);
-
 	/* Reclaim beacon resources */
 	if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
 	    sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
@@ -1222,29 +1134,26 @@
 		ath_beacon_return(sc, avp);
 	}
 
-	/* Set interrupt mask */
-	sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
 	sc->sc_flags &= ~SC_OP_BEACONS;
 
-	error = ath_vap_detach(sc, 0);
-	if (error)
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: Unable to detach vap, error: %d\n",
-			__func__, error);
+	sc->sc_vaps[0] = NULL;
+	sc->sc_nvaps--;
 }
 
-static int ath9k_config(struct ieee80211_hw *hw,
-			struct ieee80211_conf *conf)
+static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ieee80211_channel *curchan = hw->conf.channel;
+	struct ieee80211_conf *conf = &hw->conf;
 	int pos;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 		__func__,
 		curchan->center_freq);
 
+	/* Update chainmask */
+	ath_update_chainmask(sc, conf->ht.enabled);
+
 	pos = ath_get_channel(sc, curchan);
 	if (pos == -1) {
 		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
@@ -1255,11 +1164,12 @@
 		(curchan->band == IEEE80211_BAND_2GHZ) ?
 		CHANNEL_G : CHANNEL_A;
 
-	if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
+	if (sc->sc_curaid && hw->conf.ht.enabled)
 		sc->sc_ah->ah_channels[pos].chanmode =
 			ath_get_extchanmode(sc, curchan);
 
-	sc->sc_config.txpowlimit = 2 * conf->power_level;
+	if (changed & IEEE80211_CONF_CHANGE_POWER)
+		sc->sc_config.txpowlimit = 2 * conf->power_level;
 
 	/* set h/w channel */
 	if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
@@ -1275,17 +1185,9 @@
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hal *ah = sc->sc_ah;
-	struct ath_vap *avp;
+	struct ath_vap *avp = (void *)vif->drv_priv;
 	u32 rfilt = 0;
 	int error, i;
-	DECLARE_MAC_BUF(mac);
-
-	avp = sc->sc_vaps[0];
-	if (avp == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
-			__func__);
-		return -EINVAL;
-	}
 
 	/* TODO: Need to decide which hw opmode to use for multi-interface
 	 * cases */
@@ -1315,27 +1217,10 @@
 			/* Set aggregation protection mode parameters */
 			sc->sc_config.ath_aggr_prot = 0;
 
-			/*
-			 * Reset our TSF so that its value is lower than the
-			 * beacon that we are trying to catch.
-			 * Only then hw will update its TSF register with the
-			 * new beacon. Reset the TSF before setting the BSSID
-			 * to avoid allowing in any frames that would update
-			 * our TSF only to have us clear it
-			 * immediately thereafter.
-			 */
-			ath9k_hw_reset_tsf(sc->sc_ah);
-
-			/* Disable BMISS interrupt when we're not associated */
-			ath9k_hw_set_interrupts(sc->sc_ah,
-					sc->sc_imask &
-					~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
-			sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-
 			DPRINTF(sc, ATH_DBG_CONFIG,
-				"%s: RX filter 0x%x bssid %s aid 0x%x\n",
+				"%s: RX filter 0x%x bssid %pM aid 0x%x\n",
 				__func__, rfilt,
-				print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+				sc->sc_curbssid, sc->sc_curaid);
 
 			/* need to reconfigure the beacon */
 			sc->sc_flags &= ~SC_OP_BEACONS ;
@@ -1367,7 +1252,7 @@
 	}
 
 	/* Check for WLAN_CAPABILITY_PRIVACY ? */
-	if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
+	if ((avp->av_opmode != ATH9K_M_STA)) {
 		for (i = 0; i < IEEE80211_WEP_NKID; i++)
 			if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
 				ath9k_hw_keysetmac(sc->sc_ah,
@@ -1422,37 +1307,13 @@
 			     struct ieee80211_sta *sta)
 {
 	struct ath_softc *sc = hw->priv;
-	struct ath_node *an;
-	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
-
-	spin_lock_irqsave(&sc->node_lock, flags);
-	an = ath_node_find(sc, sta->addr);
-	spin_unlock_irqrestore(&sc->node_lock, flags);
 
 	switch (cmd) {
 	case STA_NOTIFY_ADD:
-		spin_lock_irqsave(&sc->node_lock, flags);
-		if (!an) {
-			ath_node_attach(sc, sta->addr, 0);
-			DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
-				__func__, print_mac(mac, sta->addr));
-		} else {
-			ath_node_get(sc, sta->addr);
-		}
-		spin_unlock_irqrestore(&sc->node_lock, flags);
+		ath_node_attach(sc, sta);
 		break;
 	case STA_NOTIFY_REMOVE:
-		if (!an)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"%s: Removal of a non-existent node\n",
-				__func__);
-		else {
-			ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
-			DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
-				__func__,
-				print_mac(mac, sta->addr));
-		}
+		ath_node_detach(sc, sta);
 		break;
 	default:
 		break;
@@ -1558,9 +1419,8 @@
 	}
 
 	if (changed & BSS_CHANGED_HT) {
-		DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
-			__func__,
-			bss_conf->assoc_ht);
+		DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT\n",
+			__func__);
 		ath9k_ht_conf(sc, bss_conf);
 	}
 
@@ -1568,7 +1428,7 @@
 		DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
 			__func__,
 			bss_conf->assoc);
-		ath9k_bss_assoc_info(sc, bss_conf);
+		ath9k_bss_assoc_info(sc, vif, bss_conf);
 	}
 }
 
@@ -1601,21 +1461,13 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
-		if (ret < 0)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"%s: Unable to start RX aggregation\n",
-				__func__);
+		if (!(sc->sc_flags & SC_OP_RXAGGR))
+			ret = -ENOTSUPP;
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
-		ret = ath_rx_aggr_stop(sc, sta->addr, tid);
-		if (ret < 0)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"%s: Unable to stop RX aggregation\n",
-				__func__);
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
+		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
 		if (ret < 0)
 			DPRINTF(sc, ATH_DBG_FATAL,
 				"%s: Unable to start TX aggregation\n",
@@ -1624,7 +1476,7 @@
 			ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
 		break;
 	case IEEE80211_AMPDU_TX_STOP:
-		ret = ath_tx_aggr_stop(sc, sta->addr, tid);
+		ret = ath_tx_aggr_stop(sc, sta, tid);
 		if (ret < 0)
 			DPRINTF(sc, ATH_DBG_FATAL,
 				"%s: Unable to stop TX aggregation\n",
@@ -1632,6 +1484,9 @@
 
 		ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
 		break;
+	case IEEE80211_AMPDU_TX_RESUME:
+		ath_tx_aggr_resume(sc, sta, tid);
+		break;
 	default:
 		DPRINTF(sc, ATH_DBG_FATAL,
 			"%s: Unknown AMPDU action\n", __func__);
@@ -1654,21 +1509,12 @@
 	.config 	    = ath9k_config,
 	.config_interface   = ath9k_config_interface,
 	.configure_filter   = ath9k_configure_filter,
-	.get_stats          = NULL,
 	.sta_notify         = ath9k_sta_notify,
 	.conf_tx 	    = ath9k_conf_tx,
-	.get_tx_stats 	    = NULL,
 	.bss_info_changed   = ath9k_bss_info_changed,
-	.set_tim            = NULL,
 	.set_key            = ath9k_set_key,
-	.hw_scan            = NULL,
-	.get_tkip_seq       = NULL,
-	.set_rts_threshold  = NULL,
-	.set_frag_threshold = NULL,
-	.set_retry_limit    = NULL,
 	.get_tsf 	    = ath9k_get_tsf,
 	.reset_tsf 	    = ath9k_reset_tsf,
-	.tx_last_beacon     = NULL,
 	.ampdu_action       = ath9k_ampdu_action,
 	.set_frag_threshold = ath9k_no_fragmentation,
 };
@@ -1746,16 +1592,6 @@
 		goto bad2;
 	}
 
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_NOISE_DBM;
-
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_AP) |
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
-
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	pci_set_drvdata(pdev, hw);
 
@@ -1803,17 +1639,10 @@
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_softc *sc = hw->priv;
-	enum ath9k_int status;
 
-	if (pdev->irq) {
-		ath9k_hw_set_interrupts(sc->sc_ah, 0);
-		/* clear the ISR */
-		ath9k_hw_getisr(sc->sc_ah, &status);
-		sc->sc_flags |= SC_OP_INVALID;
-		free_irq(pdev->irq, sc);
-	}
 	ath_detach(sc);
-
+	if (pdev->irq)
+		free_irq(pdev->irq, sc);
 	pci_iounmap(pdev, sc->mem);
 	pci_release_region(pdev, 0);
 	pci_disable_device(pdev);
diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c
index eb9121f..4f1c8bf 100644
--- a/drivers/net/wireless/ath9k/phy.c
+++ b/drivers/net/wireless/ath9k/phy.c
@@ -215,7 +215,7 @@
 	if (AR_SREV_9280_10_OR_LATER(ah))
 		return true;
 
-	eepMinorRev = ath9k_hw_get_eeprom(ahp, EEP_MINOR_REV);
+	eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV);
 
 	RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1);
 
@@ -235,15 +235,15 @@
 
 	if (eepMinorRev >= 2) {
 		if (IS_CHAN_2GHZ(chan)) {
-			ob2GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_2);
-			db2GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_2);
+			ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2);
+			db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2);
 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
 						   ob2GHz, 3, 197, 0);
 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
 						   db2GHz, 3, 194, 0);
 		} else {
-			ob5GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_5);
-			db5GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_5);
+			ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5);
+			db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5);
 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
 						   ob5GHz, 3, 203, 0);
 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index cca2fc5..aa6bfd7 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -816,7 +816,7 @@
 }
 
 u8 ath_rate_findrateix(struct ath_softc *sc,
-			     u8 dot11rate)
+		       u8 dot11rate)
 {
 	const struct ath_rate_table *ratetable;
 	struct ath_rate_softc *rsc = sc->sc_rc;
@@ -1838,7 +1838,7 @@
 	struct ath_softc *sc = hw->priv;
 	u32 capflag = 0;
 
-	if (hw->conf.ht_conf.ht_supported) {
+	if (hw->conf.ht.enabled) {
 		capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG;
 		if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040)
 			capflag |= ATH_RC_CW40_FLAG;
@@ -1864,73 +1864,26 @@
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+	/* XXX: UGLY HACK!! */
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
 
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, hdr->addr1);
-	spin_unlock_bh(&sc->node_lock);
+	an = (struct ath_node *)sta->drv_priv;
 
-	if (!an || !priv_sta || !ieee80211_is_data(fc)) {
-		if (tx_info->driver_data[0] != NULL) {
-			kfree(tx_info->driver_data[0]);
-			tx_info->driver_data[0] = NULL;
-		}
+	if (tx_info_priv == NULL)
 		return;
-	}
-	if (tx_info->driver_data[0] != NULL) {
+
+	if (an && priv_sta && ieee80211_is_data(fc))
 		ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
-		kfree(tx_info->driver_data[0]);
-		tx_info->driver_data[0] = NULL;
-	}
+
+	kfree(tx_info_priv);
+	tx_info->control.vif = NULL;
 }
 
-static void ath_tx_aggr_resp(struct ath_softc *sc,
-			     struct ieee80211_supported_band *sband,
-			     struct ieee80211_sta *sta,
-			     struct ath_node *an,
-			     u8 tidno)
+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+			 struct ieee80211_tx_rate_control *txrc)
 {
-	struct ath_atx_tid *txtid;
-	u16 buffersize = 0;
-	int state;
-	struct sta_info *si;
-
-	if (!(sc->sc_flags & SC_OP_TXAGGR))
-		return;
-
-	txtid = ATH_AN_2_TID(an, tidno);
-	if (!txtid->paused)
-		return;
-
-	/*
-	 * XXX: This is entirely busted, we aren't supposed to
-	 *	access the sta from here because it's internal
-	 *	to mac80211, and looking at the state without
-	 *	locking is wrong too.
-	 */
-	si = container_of(sta, struct sta_info, sta);
-	buffersize = IEEE80211_MIN_AMPDU_BUF <<
-		sband->ht_info.ampdu_factor; /* FIXME */
-	state = si->ampdu_mlme.tid_state_tx[tidno];
-
-	if (state & HT_ADDBA_RECEIVED_MSK) {
-		txtid->addba_exchangecomplete = 1;
-		txtid->addba_exchangeinprogress = 0;
-		txtid->baw_size = buffersize;
-
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: Resuming tid, buffersize: %d\n",
-			__func__,
-			buffersize);
-
-		ath_tx_resume_tid(sc, txtid);
-	}
-}
-
-static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
-			 struct ieee80211_sta *sta, void *priv_sta,
-			 struct sk_buff *skb, struct rate_selection *sel)
-{
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct sk_buff *skb = txrc->skb;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ath_softc *sc = priv;
 	struct ieee80211_hw *hw = sc->hw;
@@ -1938,25 +1891,24 @@
 	struct ath_rate_node *ath_rc_priv = priv_sta;
 	struct ath_node *an;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	int is_probe = FALSE, chk, ret;
+	int is_probe = FALSE;
 	s8 lowest_idx;
 	__le16 fc = hdr->frame_control;
 	u8 *qc, tid;
-	DECLARE_MAC_BUF(mac);
 
 	DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
 
-	/* allocate driver private area of tx_info */
-	tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
-	ASSERT(tx_info->driver_data[0] != NULL);
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+	/* allocate driver private area of tx_info, XXX: UGLY HACK! */
+	tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
+	ASSERT(tx_info_priv != NULL);
 
 	lowest_idx = rate_lowest_index(sband, sta);
 	tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
 	/* lowest rate for management and multicast/broadcast frames */
 	if (!ieee80211_is_data(fc) ||
 	    is_multicast_ether_addr(hdr->addr1) || !sta) {
-		sel->rate_idx = lowest_idx;
+		tx_info->control.rates[0].idx = lowest_idx;
 		return;
 	}
 
@@ -1967,8 +1919,10 @@
 			  tx_info_priv->rcs,
 			  &is_probe,
 			  false);
+#if 0
 	if (is_probe)
 		sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
+#endif
 
 	/* Ratecontrol sometimes returns invalid rate index */
 	if (tx_info_priv->rcs[0].rix != 0xff)
@@ -1976,43 +1930,18 @@
 	else
 		tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix;
 
-	sel->rate_idx = tx_info_priv->rcs[0].rix;
+	tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix;
 
 	/* Check if aggregation has to be enabled for this tid */
 
-	if (hw->conf.ht_conf.ht_supported) {
+	if (hw->conf.ht.enabled) {
 		if (ieee80211_is_data_qos(fc)) {
 			qc = ieee80211_get_qos_ctl(hdr);
 			tid = qc[0] & 0xf;
+			an = (struct ath_node *)sta->drv_priv;
 
-			spin_lock_bh(&sc->node_lock);
-			an = ath_node_find(sc, hdr->addr1);
-			spin_unlock_bh(&sc->node_lock);
-
-			if (!an) {
-				DPRINTF(sc, ATH_DBG_AGGR,
-					"%s: Node not found to "
-					"init/chk TX aggr\n", __func__);
-				return;
-			}
-
-			chk = ath_tx_aggr_check(sc, an, tid);
-			if (chk == AGGR_REQUIRED) {
-				ret = ieee80211_start_tx_ba_session(hw,
-					hdr->addr1, tid);
-				if (ret)
-					DPRINTF(sc, ATH_DBG_AGGR,
-						"%s: Unable to start tx "
-						"aggr for: %s\n",
-						__func__,
-						print_mac(mac, hdr->addr1));
-				else
-					DPRINTF(sc, ATH_DBG_AGGR,
-						"%s: Started tx aggr for: %s\n",
-						__func__,
-						print_mac(mac, hdr->addr1));
-			} else if (chk == AGGR_EXCHANGE_PROGRESS)
-				ath_tx_aggr_resp(sc, sband, sta, an, tid);
+			if(ath_tx_aggr_check(sc, an, tid))
+				ieee80211_start_tx_ba_session(hw, hdr->addr1, tid);
 		}
 	}
 }
@@ -2027,9 +1956,9 @@
 	DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
 
 	ath_setup_rates(sc, sband, sta, ath_rc_priv);
-	if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-		for (i = 0; i < MCS_SET_SIZE; i++) {
-			if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
+	if (sta->ht_cap.ht_supported) {
+		for (i = 0; i < 77; i++) {
+			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
 				ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
 			if (j == ATH_RATE_MAX)
 				break;
@@ -2039,11 +1968,6 @@
 	ath_rc_node_update(sc->hw, priv_sta);
 }
 
-static void ath_rate_clear(void *priv)
-{
-	return;
-}
-
 static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
 	struct ath_softc *sc = hw->priv;
@@ -2059,12 +1983,18 @@
 
 static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 {
+	struct ieee80211_vif *vif;
 	struct ath_softc *sc = priv;
-	struct ath_vap *avp = sc->sc_vaps[0];
+	struct ath_vap *avp;
 	struct ath_rate_node *rate_priv;
 
 	DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
 
+	vif = sc->sc_vaps[0];
+	ASSERT(vif);
+
+	avp = (void *)vif->drv_priv;
+
 	rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
 	if (!rate_priv) {
 		DPRINTF(sc, ATH_DBG_FATAL,
@@ -2093,7 +2023,6 @@
 	.tx_status = ath_tx_status,
 	.get_rate = ath_get_rate,
 	.rate_init = ath_rate_init,
-	.clear = ath_rate_clear,
 	.alloc = ath_rate_alloc,
 	.free = ath_rate_free,
 	.alloc_sta = ath_rate_alloc_sta,
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h
index b95b415..6671097 100644
--- a/drivers/net/wireless/ath9k/rc.h
+++ b/drivers/net/wireless/ath9k/rc.h
@@ -59,7 +59,6 @@
 #define FALSE 0
 
 #define ATH_RATE_MAX	30
-#define MCS_SET_SIZE	128
 
 enum ieee80211_fixed_rate_mode {
 	IEEE80211_FIXED_RATE_NONE  = 0,
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 4983402..2ecb0a0 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -64,328 +64,6 @@
 	ath9k_hw_rxena(ah);
 }
 
-/* Process received BAR frame */
-
-static int ath_bar_rx(struct ath_softc *sc,
-		      struct ath_node *an,
-		      struct sk_buff *skb)
-{
-	struct ieee80211_bar *bar;
-	struct ath_arx_tid *rxtid;
-	struct sk_buff *tskb;
-	struct ath_recv_status *rx_status;
-	int tidno, index, cindex;
-	u16 seqno;
-
-	/* look at BAR contents	 */
-
-	bar = (struct ieee80211_bar *)skb->data;
-	tidno = (le16_to_cpu(bar->control) & IEEE80211_BAR_CTL_TID_M)
-		>> IEEE80211_BAR_CTL_TID_S;
-	seqno = le16_to_cpu(bar->start_seq_num) >> IEEE80211_SEQ_SEQ_SHIFT;
-
-	/* process BAR - indicate all pending RX frames till the BAR seqno */
-
-	rxtid = &an->an_aggr.rx.tid[tidno];
-
-	spin_lock_bh(&rxtid->tidlock);
-
-	/* get relative index */
-
-	index = ATH_BA_INDEX(rxtid->seq_next, seqno);
-
-	/* drop BAR if old sequence (index is too large) */
-
-	if ((index > rxtid->baw_size) &&
-	    (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2))))
-		/* discard frame, ieee layer may not treat frame as a dup */
-		goto unlock_and_free;
-
-	/* complete receive processing for all pending frames upto BAR seqno */
-
-	cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-	while ((rxtid->baw_head != rxtid->baw_tail) &&
-	       (rxtid->baw_head != cindex)) {
-		tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf;
-		rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status;
-		rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL;
-
-		if (tskb != NULL)
-			ath_rx_subframe(an, tskb, rx_status);
-
-		INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-		INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-	}
-
-	/* ... and indicate rest of the frames in-order */
-
-	while (rxtid->baw_head != rxtid->baw_tail &&
-	       rxtid->rxbuf[rxtid->baw_head].rx_wbuf != NULL) {
-		tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf;
-		rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status;
-		rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL;
-
-		ath_rx_subframe(an, tskb, rx_status);
-
-		INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-		INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-	}
-
-unlock_and_free:
-	spin_unlock_bh(&rxtid->tidlock);
-	/* free bar itself */
-	dev_kfree_skb(skb);
-	return IEEE80211_FTYPE_CTL;
-}
-
-/* Function to handle a subframe of aggregation when HT is enabled */
-
-static int ath_ampdu_input(struct ath_softc *sc,
-			   struct ath_node *an,
-			   struct sk_buff *skb,
-			   struct ath_recv_status *rx_status)
-{
-	struct ieee80211_hdr *hdr;
-	struct ath_arx_tid *rxtid;
-	struct ath_rxbuf *rxbuf;
-	u8 type, subtype;
-	u16 rxseq;
-	int tid = 0, index, cindex, rxdiff;
-	__le16 fc;
-	u8 *qc;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-
-	/* collect stats of frames with non-zero version */
-
-	if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_VERS) != 0) {
-		dev_kfree_skb(skb);
-		return -1;
-	}
-
-	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
-	subtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
-
-	if (ieee80211_is_back_req(fc))
-		return ath_bar_rx(sc, an, skb);
-
-	/* special aggregate processing only for qos unicast data frames */
-
-	if (!ieee80211_is_data(fc) ||
-	    !ieee80211_is_data_qos(fc) ||
-	    is_multicast_ether_addr(hdr->addr1))
-		return ath_rx_subframe(an, skb, rx_status);
-
-	/* lookup rx tid state */
-
-	if (ieee80211_is_data_qos(fc)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & 0xf;
-	}
-
-	if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
-		/* Drop the frame not belonging to me. */
-		if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) {
-			dev_kfree_skb(skb);
-			return -1;
-		}
-	}
-
-	rxtid = &an->an_aggr.rx.tid[tid];
-
-	spin_lock(&rxtid->tidlock);
-
-	rxdiff = (rxtid->baw_tail - rxtid->baw_head) &
-		(ATH_TID_MAX_BUFS - 1);
-
-	/*
-	 * If the ADDBA exchange has not been completed by the source,
-	 * process via legacy path (i.e. no reordering buffer is needed)
-	 */
-	if (!rxtid->addba_exchangecomplete) {
-		spin_unlock(&rxtid->tidlock);
-		return ath_rx_subframe(an, skb, rx_status);
-	}
-
-	/* extract sequence number from recvd frame */
-
-	rxseq = le16_to_cpu(hdr->seq_ctrl) >> IEEE80211_SEQ_SEQ_SHIFT;
-
-	if (rxtid->seq_reset) {
-		rxtid->seq_reset = 0;
-		rxtid->seq_next = rxseq;
-	}
-
-	index = ATH_BA_INDEX(rxtid->seq_next, rxseq);
-
-	/* drop frame if old sequence (index is too large) */
-
-	if (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2))) {
-		/* discard frame, ieee layer may not treat frame as a dup */
-		spin_unlock(&rxtid->tidlock);
-		dev_kfree_skb(skb);
-		return IEEE80211_FTYPE_DATA;
-	}
-
-	/* sequence number is beyond block-ack window */
-
-	if (index >= rxtid->baw_size) {
-
-		/* complete receive processing for all pending frames */
-
-		while (index >= rxtid->baw_size) {
-
-			rxbuf = rxtid->rxbuf + rxtid->baw_head;
-
-			if (rxbuf->rx_wbuf != NULL) {
-				ath_rx_subframe(an, rxbuf->rx_wbuf,
-						&rxbuf->rx_status);
-				rxbuf->rx_wbuf = NULL;
-			}
-
-			INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-			INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-
-			index--;
-		}
-	}
-
-	/* add buffer to the recv ba window */
-
-	cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-	rxbuf = rxtid->rxbuf + cindex;
-
-	if (rxbuf->rx_wbuf != NULL) {
-		spin_unlock(&rxtid->tidlock);
-		/* duplicate frame */
-		dev_kfree_skb(skb);
-		return IEEE80211_FTYPE_DATA;
-	}
-
-	rxbuf->rx_wbuf = skb;
-	rxbuf->rx_time = get_timestamp();
-	rxbuf->rx_status = *rx_status;
-
-	/* advance tail if sequence received is newer
-	 * than any received so far */
-
-	if (index >= rxdiff) {
-		rxtid->baw_tail = cindex;
-		INCR(rxtid->baw_tail, ATH_TID_MAX_BUFS);
-	}
-
-	/* indicate all in-order received frames */
-
-	while (rxtid->baw_head != rxtid->baw_tail) {
-		rxbuf = rxtid->rxbuf + rxtid->baw_head;
-		if (!rxbuf->rx_wbuf)
-			break;
-
-		ath_rx_subframe(an, rxbuf->rx_wbuf, &rxbuf->rx_status);
-		rxbuf->rx_wbuf = NULL;
-
-		INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-		INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-	}
-
-	/*
-	 * start a timer to flush all received frames if there are pending
-	 * receive frames
-	 */
-	if (rxtid->baw_head != rxtid->baw_tail)
-		mod_timer(&rxtid->timer, ATH_RX_TIMEOUT);
-	else
-		del_timer_sync(&rxtid->timer);
-
-	spin_unlock(&rxtid->tidlock);
-	return IEEE80211_FTYPE_DATA;
-}
-
-/* Timer to flush all received sub-frames */
-
-static void ath_rx_timer(unsigned long data)
-{
-	struct ath_arx_tid *rxtid = (struct ath_arx_tid *)data;
-	struct ath_node *an = rxtid->an;
-	struct ath_rxbuf *rxbuf;
-	int nosched;
-
-	spin_lock_bh(&rxtid->tidlock);
-	while (rxtid->baw_head != rxtid->baw_tail) {
-		rxbuf = rxtid->rxbuf + rxtid->baw_head;
-		if (!rxbuf->rx_wbuf) {
-			INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-			INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-			continue;
-		}
-
-		/*
-		 * Stop if the next one is a very recent frame.
-		 *
-		 * Call get_timestamp in every iteration to protect against the
-		 * case in which a new frame is received while we are executing
-		 * this function. Using a timestamp obtained before entering
-		 * the loop could lead to a very large time interval
-		 * (a negative value typecast to unsigned), breaking the
-		 * function's logic.
-		 */
-		if ((get_timestamp() - rxbuf->rx_time) <
-			(ATH_RX_TIMEOUT * HZ / 1000))
-			break;
-
-		ath_rx_subframe(an, rxbuf->rx_wbuf,
-				&rxbuf->rx_status);
-		rxbuf->rx_wbuf = NULL;
-
-		INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-		INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-	}
-
-	/*
-	 * start a timer to flush all received frames if there are pending
-	 * receive frames
-	 */
-	if (rxtid->baw_head != rxtid->baw_tail)
-		nosched = 0;
-	else
-		nosched = 1; /* no need to re-arm the timer again */
-
-	spin_unlock_bh(&rxtid->tidlock);
-}
-
-/* Free all pending sub-frames in the re-ordering buffer */
-
-static void ath_rx_flush_tid(struct ath_softc *sc,
-	struct ath_arx_tid *rxtid, int drop)
-{
-	struct ath_rxbuf *rxbuf;
-	unsigned long flag;
-
-	spin_lock_irqsave(&rxtid->tidlock, flag);
-	while (rxtid->baw_head != rxtid->baw_tail) {
-		rxbuf = rxtid->rxbuf + rxtid->baw_head;
-		if (!rxbuf->rx_wbuf) {
-			INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-			INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-			continue;
-		}
-
-		if (drop)
-			dev_kfree_skb(rxbuf->rx_wbuf);
-		else
-			ath_rx_subframe(rxtid->an,
-					rxbuf->rx_wbuf,
-					&rxbuf->rx_status);
-
-		rxbuf->rx_wbuf = NULL;
-
-		INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
-		INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-	}
-	spin_unlock_irqrestore(&rxtid->tidlock, flag);
-}
-
 static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
 	u32 len)
 {
@@ -716,24 +394,6 @@
 	spin_unlock_bh(&sc->sc_rxflushlock);
 }
 
-/* Process an individual frame */
-
-int ath_rx_input(struct ath_softc *sc,
-		 struct ath_node *an,
-		 int is_ampdu,
-		 struct sk_buff *skb,
-		 struct ath_recv_status *rx_status,
-		 enum ATH_RX_TYPE *status)
-{
-	if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) {
-		*status = ATH_RX_CONSUMED;
-		return ath_ampdu_input(sc, an, skb, rx_status);
-	} else {
-		*status = ATH_RX_NON_CONSUMED;
-		return -1;
-	}
-}
-
 /* Process receive queue, as well as LED, etc. */
 
 int ath_rx_tasklet(struct ath_softc *sc, int flush)
@@ -1092,200 +752,3 @@
 	return 0;
 #undef PA2DESC
 }
-
-/* Process ADDBA request in per-TID data structure */
-
-int ath_rx_aggr_start(struct ath_softc *sc,
-		      const u8 *addr,
-		      u16 tid,
-		      u16 *ssn)
-{
-	struct ath_arx_tid *rxtid;
-	struct ath_node *an;
-	struct ieee80211_hw *hw = sc->hw;
-	struct ieee80211_supported_band *sband;
-	u16 buffersize = 0;
-
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, (u8 *) addr);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (!an) {
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: Node not found to initialize RX aggregation\n",
-			__func__);
-		return -1;
-	}
-
-	sband = hw->wiphy->bands[hw->conf.channel->band];
-	buffersize = IEEE80211_MIN_AMPDU_BUF <<
-		sband->ht_info.ampdu_factor; /* FIXME */
-
-	rxtid = &an->an_aggr.rx.tid[tid];
-
-	spin_lock_bh(&rxtid->tidlock);
-	if (sc->sc_flags & SC_OP_RXAGGR) {
-		/* Allow aggregation reception
-		 * Adjust rx BA window size. Peer might indicate a
-		 * zero buffer size for a _dont_care_ condition.
-		 */
-		if (buffersize)
-			rxtid->baw_size = min(buffersize, rxtid->baw_size);
-
-		/* set rx sequence number */
-		rxtid->seq_next = *ssn;
-
-		/* Allocate the receive buffers for this TID */
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: Allcating rxbuffer for TID %d\n", __func__, tid);
-
-		if (rxtid->rxbuf == NULL) {
-			/*
-			* If the rxbuff is not NULL at this point, we *probably*
-			* already allocated the buffer on a previous ADDBA,
-			* and this is a subsequent ADDBA that got through.
-			* Don't allocate, but use the value in the pointer,
-			* we zero it out when we de-allocate.
-			*/
-			rxtid->rxbuf = kmalloc(ATH_TID_MAX_BUFS *
-				sizeof(struct ath_rxbuf), GFP_ATOMIC);
-		}
-		if (rxtid->rxbuf == NULL) {
-			DPRINTF(sc, ATH_DBG_AGGR,
-				"%s: Unable to allocate RX buffer, "
-				"refusing ADDBA\n", __func__);
-		} else {
-			/* Ensure the memory is zeroed out (all internal
-			 * pointers are null) */
-			memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS *
-				sizeof(struct ath_rxbuf));
-			DPRINTF(sc, ATH_DBG_AGGR,
-				"%s: Allocated @%p\n", __func__, rxtid->rxbuf);
-
-			/* Allow aggregation reception */
-			rxtid->addba_exchangecomplete = 1;
-		}
-	}
-	spin_unlock_bh(&rxtid->tidlock);
-
-	return 0;
-}
-
-/* Process DELBA */
-
-int ath_rx_aggr_stop(struct ath_softc *sc,
-		     const u8 *addr,
-		     u16 tid)
-{
-	struct ath_node *an;
-
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, (u8 *) addr);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (!an) {
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: RX aggr stop for non-existent node\n", __func__);
-		return -1;
-	}
-
-	ath_rx_aggr_teardown(sc, an, tid);
-	return 0;
-}
-
-/* Rx aggregation tear down */
-
-void ath_rx_aggr_teardown(struct ath_softc *sc,
-	struct ath_node *an, u8 tid)
-{
-	struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid];
-
-	if (!rxtid->addba_exchangecomplete)
-		return;
-
-	del_timer_sync(&rxtid->timer);
-	ath_rx_flush_tid(sc, rxtid, 0);
-	rxtid->addba_exchangecomplete = 0;
-
-	/* De-allocate the receive buffer array allocated when addba started */
-
-	if (rxtid->rxbuf) {
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: Deallocating TID %d rxbuff @%p\n",
-			__func__, tid, rxtid->rxbuf);
-		kfree(rxtid->rxbuf);
-
-		/* Set pointer to null to avoid reuse*/
-		rxtid->rxbuf = NULL;
-	}
-}
-
-/* Initialize per-node receive state */
-
-void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
-{
-	if (sc->sc_flags & SC_OP_RXAGGR) {
-		struct ath_arx_tid *rxtid;
-		int tidno;
-
-		/* Init per tid rx state */
-		for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno];
-				tidno < WME_NUM_TID;
-				tidno++, rxtid++) {
-			rxtid->an        = an;
-			rxtid->seq_reset = 1;
-			rxtid->seq_next  = 0;
-			rxtid->baw_size  = WME_MAX_BA;
-			rxtid->baw_head  = rxtid->baw_tail = 0;
-
-			/*
-			 * Ensure the buffer pointer is null at this point
-			 * (needs to be allocated when addba is received)
-			*/
-
-			rxtid->rxbuf     = NULL;
-			setup_timer(&rxtid->timer, ath_rx_timer,
-				(unsigned long)rxtid);
-			spin_lock_init(&rxtid->tidlock);
-
-			/* ADDBA state */
-			rxtid->addba_exchangecomplete = 0;
-		}
-	}
-}
-
-void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
-{
-	if (sc->sc_flags & SC_OP_RXAGGR) {
-		struct ath_arx_tid *rxtid;
-		int tidno, i;
-
-		/* Init per tid rx state */
-		for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno];
-				tidno < WME_NUM_TID;
-				tidno++, rxtid++) {
-
-			if (!rxtid->addba_exchangecomplete)
-				continue;
-
-			/* must cancel timer first */
-			del_timer_sync(&rxtid->timer);
-
-			/* drop any pending sub-frames */
-			ath_rx_flush_tid(sc, rxtid, 1);
-
-			for (i = 0; i < ATH_TID_MAX_BUFS; i++)
-				ASSERT(rxtid->rxbuf[i].rx_wbuf == NULL);
-
-			rxtid->addba_exchangecomplete = 0;
-		}
-	}
-
-}
-
-/* Cleanup per-node receive state */
-
-void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
-{
-	ath_rx_node_cleanup(sc, an);
-}
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3a47579..8937728 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -65,11 +65,12 @@
  * NB: must be called with txq lock held
  */
 
-static void ath_tx_txqaddbuf(struct ath_softc *sc,
-		struct ath_txq *txq, struct list_head *head)
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+			     struct list_head *head)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_buf *bf;
+
 	/*
 	 * Insert the frame on the outbound list and
 	 * pass it on to the hardware.
@@ -124,27 +125,29 @@
 
 /* Check if it's okay to send out aggregates */
 
-static int ath_aggr_query(struct ath_softc *sc,
-	struct ath_node *an, u8 tidno)
+static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
 {
 	struct ath_atx_tid *tid;
 	tid = ATH_AN_2_TID(an, tidno);
 
-	if (tid->addba_exchangecomplete || tid->addba_exchangeinprogress)
+	if (tid->state & AGGR_ADDBA_COMPLETE ||
+	    tid->state & AGGR_ADDBA_PROGRESS)
 		return 1;
 	else
 		return 0;
 }
 
-static enum ath9k_pkt_type get_hal_packet_type(struct ieee80211_hdr *hdr)
+/* Calculate Atheros packet type from IEEE80211 packet header */
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
 {
+	struct ieee80211_hdr *hdr;
 	enum ath9k_pkt_type htype;
 	__le16 fc;
 
+	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
 
-	/* Calculate Atheros packet type from IEEE80211 packet header */
-
 	if (ieee80211_is_beacon(fc))
 		htype = ATH9K_PKT_TYPE_BEACON;
 	else if (ieee80211_is_probe_resp(fc))
@@ -159,232 +162,176 @@
 	return htype;
 }
 
-static void fill_min_rates(struct sk_buff *skb, struct ath_tx_control *txctl)
+static bool check_min_rate(struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_info_priv *tx_info_priv;
+	bool use_minrate = false;
 	__le16 fc;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
 
 	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
-		txctl->use_minrate = 1;
-		txctl->min_rate = tx_info_priv->min_rate;
+		use_minrate = true;
 	} else if (ieee80211_is_data(fc)) {
 		if (ieee80211_is_nullfunc(fc) ||
-			/* Port Access Entity (IEEE 802.1X) */
-			(skb->protocol == cpu_to_be16(0x888E))) {
-			txctl->use_minrate = 1;
-			txctl->min_rate = tx_info_priv->min_rate;
+		    /* Port Access Entity (IEEE 802.1X) */
+		    (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+			use_minrate = true;
 		}
-		if (is_multicast_ether_addr(hdr->addr1))
-			txctl->mcast_rate = tx_info_priv->min_rate;
 	}
 
+	return use_minrate;
 }
 
-/* This function will setup additional txctl information, mostly rate stuff */
-/* FIXME: seqno, ps */
-static int ath_tx_prepare(struct ath_softc *sc,
-			  struct sk_buff *skb,
-			  struct ath_tx_control *txctl)
+static int get_hw_crypto_keytype(struct sk_buff *skb)
 {
-	struct ieee80211_hw *hw = sc->hw;
-	struct ieee80211_hdr *hdr;
-	struct ath_rc_series *rcs;
-	struct ath_txq *txq = NULL;
-	const struct ath9k_rate_table *rt;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+	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;
+	}
+
+	return ATH9K_KEY_TYPE_CLEAR;
+}
+
+static void setup_rate_retries(struct ath_softc *sc, struct sk_buff *skb)
+{
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ath_tx_info_priv *tx_info_priv;
-	int hdrlen;
-	u8 rix, antenna;
+	struct ath_rc_series *rcs;
+	struct ieee80211_hdr *hdr;
+	const struct ath9k_rate_table *rt;
+	bool use_minrate;
 	__le16 fc;
-	u8 *qc;
-
-	txctl->dev = sc;
-	hdr = (struct ieee80211_hdr *)skb->data;
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	fc = hdr->frame_control;
+	u8 rix;
 
 	rt = sc->sc_currates;
 	BUG_ON(!rt);
 
-	/* Fill misc fields */
-
-	spin_lock_bh(&sc->node_lock);
-	txctl->an = ath_node_get(sc, hdr->addr1);
-	/* create a temp node, if the node is not there already */
-	if (!txctl->an)
-		txctl->an = ath_node_attach(sc, hdr->addr1, 0);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (ieee80211_is_data_qos(fc)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		txctl->tidno = qc[0] & 0xf;
-	}
-
-	txctl->if_id = 0;
-	txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3);
-	txctl->txpower = MAX_RATE_POWER; /* FIXME */
-
-	/* Fill Key related fields */
-
-	txctl->keytype = ATH9K_KEY_TYPE_CLEAR;
-	txctl->keyix = ATH9K_TXKEYIX_INVALID;
-
-	if (tx_info->control.hw_key) {
-		txctl->keyix = tx_info->control.hw_key->hw_key_idx;
-		txctl->frmlen += tx_info->control.hw_key->icv_len;
-
-		if (tx_info->control.hw_key->alg == ALG_WEP)
-			txctl->keytype = ATH9K_KEY_TYPE_WEP;
-		else if (tx_info->control.hw_key->alg == ALG_TKIP)
-			txctl->keytype = ATH9K_KEY_TYPE_TKIP;
-		else if (tx_info->control.hw_key->alg == ALG_CCMP)
-			txctl->keytype = ATH9K_KEY_TYPE_AES;
-	}
-
-	/* Fill packet type */
-
-	txctl->atype = get_hal_packet_type(hdr);
-
-	/* Fill qnum */
-
-	if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) {
-		txctl->qnum = 0;
-		txq = sc->sc_cabq;
-	} else {
-		txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
-		txq = &sc->sc_txq[txctl->qnum];
-	}
-	spin_lock_bh(&txq->axq_lock);
-
-	/* Try to avoid running out of descriptors */
-	if (txq->axq_depth >= (ATH_TXBUF - 20) &&
-	    !(txctl->flags & ATH9K_TXDESC_CAB)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: TX queue: %d is full, depth: %d\n",
-			__func__,
-			txctl->qnum,
-			txq->axq_depth);
-		ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
-		txq->stopped = 1;
-		spin_unlock_bh(&txq->axq_lock);
-		return -1;
-	}
-
-	spin_unlock_bh(&txq->axq_lock);
-
-	/* Fill rate */
-
-	fill_min_rates(skb, txctl);
-
-	/* Fill flags */
-
-	txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
-
-	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-		txctl->flags |= ATH9K_TXDESC_NOACK;
-	if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
-		txctl->flags |= ATH9K_TXDESC_RTSENA;
-
-	/*
-	 * Setup for rate calculations.
-	 */
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; /* HACK */
 	rcs = tx_info_priv->rcs;
 
-	if (ieee80211_is_data(fc) && !txctl->use_minrate) {
+	/* Check if min rates have to be used */
+	use_minrate = check_min_rate(skb);
 
-		/* Enable HT only for DATA frames and not for EAPOL */
-		txctl->ht = (hw->conf.ht_conf.ht_supported &&
-			    (tx_info->flags & IEEE80211_TX_CTL_AMPDU));
-
+	if (ieee80211_is_data(fc) && !use_minrate) {
 		if (is_multicast_ether_addr(hdr->addr1)) {
-			rcs[0].rix = (u8)
-				ath_tx_findindex(rt, txctl->mcast_rate);
-
-			/*
-			 * mcast packets are not re-tried.
-			 */
+			rcs[0].rix =
+				ath_tx_findindex(rt, tx_info_priv->min_rate);
+			/* mcast packets are not re-tried */
 			rcs[0].tries = 1;
 		}
-		/* For HT capable stations, we save tidno for later use.
-		 * We also override seqno set by upper layer with the one
-		 * in tx aggregation state.
-		 *
-		 * First, the fragmentation stat is determined.
-		 * If fragmentation is on, the sequence number is
-		 * not overridden, since it has been
-		 * incremented by the fragmentation routine.
-		 */
-		if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) &&
-		    txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
-			struct ath_atx_tid *tid;
-
-			tid = ATH_AN_2_TID(txctl->an, txctl->tidno);
-
-			hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
-				IEEE80211_SEQ_SEQ_SHIFT);
-			txctl->seqno = tid->seq_next;
-			INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-		}
 	} else {
 		/* for management and control frames,
-		 * or for NULL and EAPOL frames */
-		if (txctl->min_rate)
-			rcs[0].rix = ath_rate_findrateix(sc, txctl->min_rate);
+		   or for NULL and EAPOL frames */
+		if (use_minrate)
+			rcs[0].rix = ath_rate_findrateix(sc, tx_info_priv->min_rate);
 		else
 			rcs[0].rix = 0;
 		rcs[0].tries = ATH_MGT_TXMAXTRY;
 	}
+
 	rix = rcs[0].rix;
 
 	if (ieee80211_has_morefrags(fc) ||
 	    (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
-		/*
-		**  Force hardware to use computed duration for next
-		**  fragment by disabling multi-rate retry, which
-		**  updates duration based on the multi-rate
-		**  duration table.
-		*/
 		rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
 		rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
 		/* reset tries but keep rate index */
 		rcs[0].tries = ATH_TXMAXTRY;
 	}
+}
 
-	/*
-	 * Determine if a tx interrupt should be generated for
-	 * this descriptor.  We take a tx interrupt to reap
-	 * descriptors when the h/w hits an EOL condition or
-	 * when the descriptor is specifically marked to generate
-	 * an interrupt.  We periodically mark descriptors in this
-	 * way to insure timely replenishing of the supply needed
-	 * for sending frames.  Defering interrupts reduces system
-	 * load and potentially allows more concurrent work to be
-	 * done but if done to aggressively can cause senders to
-	 * backup.
-	 *
-	 * NB: use >= to deal with sc_txintrperiod changing
-	 *     dynamically through sysctl.
-	 */
-	spin_lock_bh(&txq->axq_lock);
-	if ((++txq->axq_intrcnt >= sc->sc_txintrperiod)) {
-		txctl->flags |= ATH9K_TXDESC_INTREQ;
-		txq->axq_intrcnt = 0;
-	}
-	spin_unlock_bh(&txq->axq_lock);
+/* Called only when tx aggregation is enabled and HT is supported */
 
-	if (is_multicast_ether_addr(hdr->addr1)) {
-		antenna = sc->sc_mcastantenna + 1;
-		sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1;
+static void assign_aggr_tid_seqno(struct sk_buff *skb,
+				  struct ath_buf *bf)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr;
+	struct ath_node *an;
+	struct ath_atx_tid *tid;
+	__le16 fc;
+	u8 *qc;
+
+	if (!tx_info->control.sta)
+		return;
+
+	an = (struct ath_node *)tx_info->control.sta->drv_priv;
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	/* Get tidno */
+
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		bf->bf_tidno = qc[0] & 0xf;
 	}
 
-	return 0;
+	/* Get seqno */
+
+	if (ieee80211_is_data(fc) && !check_min_rate(skb)) {
+		/* For HT capable stations, we save tidno for later use.
+		 * We also override seqno set by upper layer with the one
+		 * in tx aggregation state.
+		 *
+		 * 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);
+	}
+}
+
+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;
+
+	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+	flags |= ATH9K_TXDESC_INTREQ;
+
+	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;
+
+	return flags;
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+	struct ath_buf *bf = NULL;
+
+	spin_lock_bh(&sc->sc_txbuflock);
+
+	if (unlikely(list_empty(&sc->sc_txbuf))) {
+		spin_unlock_bh(&sc->sc_txbuflock);
+		return NULL;
+	}
+
+	bf = list_first_entry(&sc->sc_txbuf, struct ath_buf, list);
+	list_del(&bf->list);
+
+	spin_unlock_bh(&sc->sc_txbuflock);
+
+	return bf;
 }
 
 /* To complete a chain of buffers associated a frame */
@@ -414,13 +361,14 @@
 		if (bf_isxretried(bf))
 			tx_status.flags |= ATH_TX_XRETRY;
 	}
+
 	/* Unmap this frame */
 	pci_unmap_single(sc->pdev,
 			 bf->bf_dmacontext,
 			 skb->len,
 			 PCI_DMA_TODEVICE);
 	/* complete this frame */
-	ath_tx_complete(sc, skb, &tx_status, bf->bf_node);
+	ath_tx_complete(sc, skb, &tx_status);
 
 	/*
 	 * Return the list of ath_buf of this mpdu to free queue
@@ -505,11 +453,9 @@
 
 /* Compute the number of bad frames */
 
-static int ath_tx_num_badfrms(struct ath_softc *sc,
-	struct ath_buf *bf, int txok)
+static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
+			      int txok)
 {
-	struct ath_node *an = bf->bf_node;
-	int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
 	struct ath_buf *bf_last = bf->bf_lastbf;
 	struct ath_desc *ds = bf_last->bf_desc;
 	u16 seq_st = 0;
@@ -518,7 +464,7 @@
 	int nbad = 0;
 	int isaggr = 0;
 
-	if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
+	if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
 		return 0;
 
 	isaggr = bf_isaggr(bf);
@@ -553,8 +499,8 @@
 
 /* Update block ack window */
 
-static void ath_tx_update_baw(struct ath_softc *sc,
-	struct ath_atx_tid *tid, int seqno)
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+			      int seqno)
 {
 	int index, cindex;
 
@@ -578,12 +524,8 @@
  * half_gi - to use 4us v/s 3.6 us for symbol time
  */
 
-static u32 ath_pkt_duration(struct ath_softc *sc,
-				  u8 rix,
-				  struct ath_buf *bf,
-				  int width,
-				  int half_gi,
-				  bool shortPreamble)
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
+			    int width, int half_gi, bool shortPreamble)
 {
 	const struct ath9k_rate_table *rt = sc->sc_currates;
 	u32 nbits, nsymbits, duration, nsymbols;
@@ -597,11 +539,8 @@
 	 * for legacy rates, use old function to compute packet duration
 	 */
 	if (!IS_HT_RATE(rc))
-		return ath9k_hw_computetxtime(sc->sc_ah,
-					     rt,
-					     pktlen,
-					     rix,
-					     shortPreamble);
+		return ath9k_hw_computetxtime(sc->sc_ah, rt, pktlen, rix,
+					      shortPreamble);
 	/*
 	 * find number of symbols: PLCP + data
 	 */
@@ -619,6 +558,7 @@
 	 */
 	streams = HT_RC_2_STREAMS(rc);
 	duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
 	return duration;
 }
 
@@ -631,11 +571,18 @@
 	struct ath_desc *ds = bf->bf_desc;
 	struct ath_desc *lastds = bf->bf_lastbf->bf_desc;
 	struct ath9k_11n_rate_series series[4];
-	int i, flags, rtsctsena = 0, dynamic_mimops = 0;
+	int i, flags, rtsctsena = 0;
 	u32 ctsduration = 0;
 	u8 rix = 0, cix, ctsrate = 0;
-	u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit;
-	struct ath_node *an = (struct ath_node *) bf->bf_node;
+	struct ath_node *an = NULL;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+
+	skb = (struct sk_buff *)bf->bf_mpdu;
+	tx_info = IEEE80211_SKB_CB(skb);
+
+	if (tx_info->control.sta)
+		an = (struct ath_node *)tx_info->control.sta->drv_priv;
 
 	/*
 	 * get the cix for the lowest valid rix.
@@ -674,24 +621,11 @@
 	 * use RTS.
 	 */
 	if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
-		BUG_ON(!an);
 		/*
 		 * 802.11g protection not needed, use our default behavior
 		 */
 		if (!rtsctsena)
 			flags = ATH9K_TXDESC_RTSENA;
-		/*
-		 * For dynamic MIMO PS, RTS needs to precede the first aggregate
-		 * and the second aggregate should have any protection at all.
-		 */
-		if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) {
-			if (!bf_isaggrburst(bf)) {
-				flags = ATH9K_TXDESC_RTSENA;
-				dynamic_mimops = 1;
-			} else {
-				flags = 0;
-			}
-		}
 	}
 
 	/*
@@ -707,7 +641,7 @@
 	/*
 	 *  For AR5416 - RTS cannot be followed by a frame larger than 8K.
 	 */
-	if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) {
+	if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) {
 		/*
 		 * Ensure that in the case of SM Dynamic power save
 		 * while we are bursting the second aggregate the
@@ -720,8 +654,8 @@
 	 * CTS transmit rate is derived from the transmit rate
 	 * by looking in the h/w rate table.  We must also factor
 	 * in whether or not a short preamble is to be used.
+	 * NB: cix is set above where RTS/CTS is enabled
 	 */
-	/* NB: cix is set above where RTS/CTS is enabled */
 	BUG_ON(cix == 0xff);
 	ctsrate = rt->info[cix].rateCode |
 		(bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
@@ -750,39 +684,18 @@
 			((bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG) ?
 				ATH9K_RATESERIES_HALFGI : 0);
 
-		series[i].PktDuration = ath_pkt_duration(
-			sc, rix, bf,
-			(bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
-			(bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
-			bf_isshpreamble(bf));
+		series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
+			 (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
+			 (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
+			 bf_isshpreamble(bf));
 
-		if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) &&
-		    (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) {
-			/*
-			 * When sending to an HT node that has enabled static
-			 * SM/MIMO power save, send at single stream rates but
-			 * use maximum allowed transmit chains per user,
-			 * hardware, regulatory, or country limits for
-			 * better range.
-			 */
+		if (bf_isht(bf) && an)
+			series[i].ChSel = ath_chainmask_sel_logic(sc, an);
+		else
 			series[i].ChSel = sc->sc_tx_chainmask;
-		} else {
-			if (bf_isht(bf))
-				series[i].ChSel =
-					ath_chainmask_sel_logic(sc, an);
-			else
-				series[i].ChSel = sc->sc_tx_chainmask;
-		}
 
 		if (rtsctsena)
 			series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-
-		/*
-		 * Set RTS for all rates if node is in dynamic powersave
-		 * mode and we are using dual stream rates.
-		 */
-		if (dynamic_mimops && (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG))
-			series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
 	}
 
 	/*
@@ -828,6 +741,7 @@
 				     ctsrate,
 				     ctsduration,
 				     series, 4, flags);
+
 	if (sc->sc_config.ath_aggr_prot && flags)
 		ath9k_hw_set11n_burstduration(ah, ds, 8192);
 }
@@ -854,7 +768,9 @@
 
 	skb = (struct sk_buff *)bf->bf_mpdu;
 	tx_info = IEEE80211_SKB_CB(skb);
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+
+	/* XXX: HACK! */
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
 	memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
 
 	/* update starting sequence number for subsequent ADDBA request */
@@ -906,8 +822,10 @@
 				      struct list_head *bf_q,
 				      int txok)
 {
-	struct ath_node *an = bf->bf_node;
-	struct ath_atx_tid *tid = ATH_AN_2_TID(an, bf->bf_tidno);
+	struct ath_node *an = NULL;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+	struct ath_atx_tid *tid = NULL;
 	struct ath_buf *bf_last = bf->bf_lastbf;
 	struct ath_desc *ds = bf_last->bf_desc;
 	struct ath_buf *bf_next, *bf_lastq = NULL;
@@ -915,7 +833,14 @@
 	u16 seq_st = 0;
 	u32 ba[WME_BA_BMP_SIZE >> 5];
 	int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
-	int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
+
+	skb = (struct sk_buff *)bf->bf_mpdu;
+	tx_info = IEEE80211_SKB_CB(skb);
+
+	if (tx_info->control.sta) {
+		an = (struct ath_node *)tx_info->control.sta->drv_priv;
+		tid = ATH_AN_2_TID(an, bf->bf_tidno);
+	}
 
 	isaggr = bf_isaggr(bf);
 	if (isaggr) {
@@ -961,7 +886,7 @@
 			/* transmit completion */
 		} else {
 
-			if (!tid->cleanup_inprogress && !isnodegone &&
+			if (!(tid->state & AGGR_CLEANUP) &&
 			    ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
 				if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
 					ath_tx_set_retry(sc, bf);
@@ -1049,7 +974,6 @@
 
 				/* copy descriptor content */
 				tbf->bf_mpdu = bf_last->bf_mpdu;
-				tbf->bf_node = bf_last->bf_node;
 				tbf->bf_buf_addr = bf_last->bf_buf_addr;
 				*(tbf->bf_desc) = *(bf_last->bf_desc);
 
@@ -1090,25 +1014,16 @@
 		bf = bf_next;
 	}
 
-	/*
-	 * node is already gone. no more assocication
-	 * with the node. the node might have been freed
-	 * any  node acces can result in panic.note tid
-	 * is part of the node.
-	 */
-	if (isnodegone)
-		return;
-
-	if (tid->cleanup_inprogress) {
+	if (tid->state & AGGR_CLEANUP) {
 		/* check to see if we're done with cleaning the h/w queue */
 		spin_lock_bh(&txq->axq_lock);
 
 		if (tid->baw_head == tid->baw_tail) {
-			tid->addba_exchangecomplete = 0;
+			tid->state &= ~AGGR_ADDBA_COMPLETE;
 			tid->addba_exchangeattempts = 0;
 			spin_unlock_bh(&txq->axq_lock);
 
-			tid->cleanup_inprogress = false;
+			tid->state &= ~AGGR_CLEANUP;
 
 			/* send buffered frames as singles */
 			ath_tx_flush_tid(sc, tid);
@@ -1158,7 +1073,6 @@
 	nacked = 0;
 	for (;;) {
 		spin_lock_bh(&txq->axq_lock);
-		txq->axq_intrcnt = 0; /* reset periodic desc intr count */
 		if (list_empty(&txq->axq_q)) {
 			txq->axq_link = NULL;
 			txq->axq_linkbuf = NULL;
@@ -1248,8 +1162,9 @@
 		}
 		skb = bf->bf_mpdu;
 		tx_info = IEEE80211_SKB_CB(skb);
-		tx_info_priv = (struct ath_tx_info_priv *)
-			tx_info->driver_data[0];
+
+		/* XXX: HACK! */
+		tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif;
 		if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
 			tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 		if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
@@ -1317,26 +1232,21 @@
 static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
 {
 	struct ath_hal *ah = sc->sc_ah;
-	int i;
-	int npend = 0;
+	int i, status, npend = 0;
 
-	/* XXX return value */
 	if (!(sc->sc_flags & SC_OP_INVALID)) {
 		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 			if (ATH_TXQ_SETUP(sc, i)) {
 				ath_tx_stopdma(sc, &sc->sc_txq[i]);
-
 				/* The TxDMA may not really be stopped.
 				 * Double check the hal tx pending count */
 				npend += ath9k_hw_numtxpending(ah,
-					sc->sc_txq[i].axq_qnum);
+						       sc->sc_txq[i].axq_qnum);
 			}
 		}
 	}
 
 	if (npend) {
-		int status;
-
 		/* TxDMA not stopped, reset the hal */
 		DPRINTF(sc, ATH_DBG_XMIT,
 			"%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
@@ -1392,7 +1302,6 @@
  */
 
 static int ath_tx_send_ampdu(struct ath_softc *sc,
-			     struct ath_txq *txq,
 			     struct ath_atx_tid *tid,
 			     struct list_head *bf_head,
 			     struct ath_tx_control *txctl)
@@ -1406,8 +1315,6 @@
 
 	bf = list_first_entry(bf_head, struct ath_buf, list);
 	bf->bf_state.bf_type |= BUF_AMPDU;
-	bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */
-	bf->bf_tidno = txctl->tidno;
 
 	/*
 	 * Do not queue to h/w when any of the following conditions is true:
@@ -1418,19 +1325,20 @@
 	 */
 	if (!list_empty(&tid->buf_q) || tid->paused ||
 	    !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
-	    txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
+	    txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
 		/*
 		 * Add this frame to software queue for scheduling later
 		 * for aggregation.
 		 */
 		list_splice_tail_init(bf_head, &tid->buf_q);
-		ath_tx_queue_tid(txq, tid);
+		ath_tx_queue_tid(txctl->txq, tid);
 		return 0;
 	}
 
 	skb = (struct sk_buff *)bf->bf_mpdu;
 	tx_info = IEEE80211_SKB_CB(skb);
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+	/* XXX: HACK! */
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
 	memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
 
 	/* Add sub-frame to BAW */
@@ -1440,7 +1348,8 @@
 	bf->bf_nframes = 1;
 	bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */
 	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txq, bf_head);
+	ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
+
 	return 0;
 }
 
@@ -1450,7 +1359,8 @@
  */
 
 static u32 ath_lookup_rate(struct ath_softc *sc,
-				 struct ath_buf *bf)
+			   struct ath_buf *bf,
+			   struct ath_atx_tid *tid)
 {
 	const struct ath9k_rate_table *rt = sc->sc_currates;
 	struct sk_buff *skb;
@@ -1460,11 +1370,10 @@
 	u16 aggr_limit, legacy = 0, maxampdu;
 	int i;
 
-
 	skb = (struct sk_buff *)bf->bf_mpdu;
 	tx_info = IEEE80211_SKB_CB(skb);
 	tx_info_priv = (struct ath_tx_info_priv *)
-		tx_info->driver_data[0];
+		tx_info->control.vif; /* XXX: HACK! */
 	memcpy(bf->bf_rcs,
 		tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
 
@@ -1504,7 +1413,7 @@
 	 * The IE, however can hold upto 65536, which shows up here
 	 * as zero. Ignore 65536 since we  are constrained by hw.
 	 */
-	maxampdu = sc->sc_ht_info.maxampdu;
+	maxampdu = tid->an->maxampdu;
 	if (maxampdu)
 		aggr_limit = min(aggr_limit, maxampdu);
 
@@ -1518,6 +1427,7 @@
  */
 
 static int ath_compute_num_delims(struct ath_softc *sc,
+				  struct ath_atx_tid *tid,
 				  struct ath_buf *bf,
 				  u16 frmlen)
 {
@@ -1545,7 +1455,7 @@
 	 * required minimum length for subframe. Take into account
 	 * whether high rate is 20 or 40Mhz and half or full GI.
 	 */
-	mpdudensity = sc->sc_ht_info.mpdudensity;
+	mpdudensity = tid->an->mpdudensity;
 
 	/*
 	 * If there is no mpdu density restriction, no further calculation
@@ -1619,7 +1529,7 @@
 		}
 
 		if (!rl) {
-			aggr_limit = ath_lookup_rate(sc, bf);
+			aggr_limit = ath_lookup_rate(sc, bf, tid);
 			rl = 1;
 			/*
 			 * Is rate dual stream
@@ -1657,7 +1567,7 @@
 		 * Get the delimiters needed to meet the MPDU
 		 * density for this node.
 		 */
-		ndelim = ath_compute_num_delims(sc, bf_first, bf->bf_frmlen);
+		ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
 
 		bpad = PADBYTES(al_delta) + (ndelim << 2);
 
@@ -1799,8 +1709,8 @@
 
 static void ath_tid_drain(struct ath_softc *sc,
 			  struct ath_txq *txq,
-			  struct ath_atx_tid *tid,
-			  bool bh_flag)
+			  struct ath_atx_tid *tid)
+
 {
 	struct ath_buf *bf;
 	struct list_head bf_head;
@@ -1821,18 +1731,12 @@
 		 * do not indicate packets while holding txq spinlock.
 		 * unlock is intentional here
 		 */
-		if (likely(bh_flag))
-			spin_unlock_bh(&txq->axq_lock);
-		else
-			spin_unlock(&txq->axq_lock);
+		spin_unlock(&txq->axq_lock);
 
 		/* complete this sub-frame */
 		ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
 
-		if (likely(bh_flag))
-			spin_lock_bh(&txq->axq_lock);
-		else
-			spin_lock(&txq->axq_lock);
+		spin_lock(&txq->axq_lock);
 	}
 
 	/*
@@ -1851,8 +1755,7 @@
  */
 
 static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
-					  struct ath_txq *txq,
-					  bool bh_flag)
+					  struct ath_txq *txq)
 {
 	struct ath_atx_ac *ac, *ac_tmp;
 	struct ath_atx_tid *tid, *tid_tmp;
@@ -1863,51 +1766,32 @@
 		list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
 			list_del(&tid->list);
 			tid->sched = false;
-			ath_tid_drain(sc, txq, tid, bh_flag);
+			ath_tid_drain(sc, txq, tid);
 		}
 	}
 }
 
-static int ath_tx_start_dma(struct ath_softc *sc,
-			    struct sk_buff *skb,
-			    struct scatterlist *sg,
-			    u32 n_sg,
-			    struct ath_tx_control *txctl)
+static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
+				struct sk_buff *skb, struct scatterlist *sg,
+				struct ath_tx_control *txctl)
 {
-	struct ath_node *an = txctl->an;
-	struct ath_buf *bf = NULL;
-	struct list_head bf_head;
-	struct ath_desc *ds;
-	struct ath_hal *ah = sc->sc_ah;
-	struct ath_txq *txq;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ath_tx_info_priv *tx_info_priv;
 	struct ath_rc_series *rcs;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
-	__le16 fc = hdr->frame_control;
+	int hdrlen;
+	__le16 fc;
 
-	if (unlikely(txctl->flags & ATH9K_TXDESC_CAB))
-		txq = sc->sc_cabq;
-	else
-		txq = &sc->sc_txq[txctl->qnum];
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	fc = hdr->frame_control;
+	rcs = tx_info_priv->rcs;
 
-	/* For each sglist entry, allocate an ath_buf for DMA */
-	INIT_LIST_HEAD(&bf_head);
-	spin_lock_bh(&sc->sc_txbuflock);
-	if (unlikely(list_empty(&sc->sc_txbuf))) {
-		spin_unlock_bh(&sc->sc_txbuflock);
-		return -ENOMEM;
-	}
-
-	bf = list_first_entry(&sc->sc_txbuf, struct ath_buf, list);
-	list_del(&bf->list);
-	spin_unlock_bh(&sc->sc_txbuflock);
-
-	list_add_tail(&bf->list, &bf_head);
-
-	/* set up this buffer */
 	ATH_TXBUF_RESET(bf);
-	bf->bf_frmlen = txctl->frmlen;
+
+	/* Frame type */
+
+	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
 
 	ieee80211_is_data(fc) ?
 		(bf->bf_state.bf_type |= BUF_DATA) :
@@ -1921,120 +1805,142 @@
 	(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 &&
+	 (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ?
+		(bf->bf_state.bf_type |= BUF_HT) :
+		(bf->bf_state.bf_type &= ~BUF_HT);
 
-	bf->bf_flags = txctl->flags;
-	bf->bf_keytype = txctl->keytype;
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
-	rcs = tx_info_priv->rcs;
+	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
+
+	/* Crypto */
+
+	bf->bf_keytype = get_hw_crypto_keytype(skb);
+
+	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
+		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
+		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
+	} else {
+		bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
+	}
+
+	/* Rate series */
+
+	setup_rate_retries(sc, skb);
+
 	bf->bf_rcs[0] = rcs[0];
 	bf->bf_rcs[1] = rcs[1];
 	bf->bf_rcs[2] = rcs[2];
 	bf->bf_rcs[3] = rcs[3];
-	bf->bf_node = an;
+
+	/* Assign seqno, tidno */
+
+	if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR))
+		assign_aggr_tid_seqno(skb, bf);
+
+	/* DMA setup */
+
 	bf->bf_mpdu = skb;
-	bf->bf_buf_addr = sg_dma_address(sg);
+	bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
+					   skb->len, PCI_DMA_TODEVICE);
+	bf->bf_buf_addr = bf->bf_dmacontext;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+			     struct scatterlist *sg, u32 n_sg,
+			     struct ath_tx_control *txctl)
+{
+	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
+	struct ath_node *an = NULL;
+	struct list_head bf_head;
+	struct ath_desc *ds;
+	struct ath_atx_tid *tid;
+	struct ath_hal *ah = sc->sc_ah;
+	int frm_type;
+
+	frm_type = get_hw_packet_type(skb);
+
+	INIT_LIST_HEAD(&bf_head);
+	list_add_tail(&bf->list, &bf_head);
 
 	/* setup descriptor */
+
 	ds = bf->bf_desc;
 	ds->ds_link = 0;
 	ds->ds_data = bf->bf_buf_addr;
 
-	/*
-	 * Save the DMA context in the first ath_buf
-	 */
-	bf->bf_dmacontext = txctl->dmacontext;
+	/* Formulate first tx descriptor with tx controls */
 
-	/*
-	 * Formulate first tx descriptor with tx controls.
-	 */
-	ath9k_hw_set11n_txdesc(ah,
-			       ds,
-			       bf->bf_frmlen, /* frame length */
-			       txctl->atype, /* Atheros packet type */
-			       min(txctl->txpower, (u16)60), /* txpower */
-			       txctl->keyix,            /* key cache index */
-			       txctl->keytype,          /* key type */
-			       txctl->flags);           /* flags */
-	ath9k_hw_filltxdesc(ah,
-			    ds,
-			    sg_dma_len(sg),     /* segment length */
-			    true,            /* first segment */
-			    (n_sg == 1) ? true : false, /* last segment */
-			    ds);                /* first descriptor */
+	ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
+			       bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
+
+	ath9k_hw_filltxdesc(ah, ds,
+			    sg_dma_len(sg),		/* segment length */
+			    true,			/* first segment */
+			    (n_sg == 1) ? true : false,	/* last segment */
+			    ds);			/* first descriptor */
 
 	bf->bf_lastfrm = bf;
-	(txctl->ht) ?
-		(bf->bf_state.bf_type |= BUF_HT) :
-		(bf->bf_state.bf_type &= ~BUF_HT);
 
-	spin_lock_bh(&txq->axq_lock);
+	spin_lock_bh(&txctl->txq->axq_lock);
 
-	if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
-		struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno);
-		if (ath_aggr_query(sc, an, txctl->tidno)) {
+	if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
+	    tx_info->control.sta) {
+		an = (struct ath_node *)tx_info->control.sta->drv_priv;
+		tid = ATH_AN_2_TID(an, bf->bf_tidno);
+
+		if (ath_aggr_query(sc, an, bf->bf_tidno)) {
 			/*
 			 * Try aggregation if it's a unicast data frame
 			 * and the destination is HT capable.
 			 */
-			ath_tx_send_ampdu(sc, txq, tid, &bf_head, txctl);
+			ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
 		} else {
 			/*
-			 * Send this frame as regular when ADDBA exchange
-			 * is neither complete nor pending.
+			 * Send this frame as regular when ADDBA
+			 * exchange is neither complete nor pending.
 			 */
-			ath_tx_send_normal(sc, txq, tid, &bf_head);
+			ath_tx_send_normal(sc, txctl->txq,
+					   tid, &bf_head);
 		}
 	} else {
 		bf->bf_lastbf = bf;
 		bf->bf_nframes = 1;
+
 		ath_buf_set_rate(sc, bf);
-
-		if (ieee80211_is_back_req(fc)) {
-			/* This is required for resuming tid
-			 * during BAR completion */
-			bf->bf_tidno = txctl->tidno;
-		}
-
-		ath_tx_txqaddbuf(sc, txq, &bf_head);
+		ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
 	}
-	spin_unlock_bh(&txq->axq_lock);
-	return 0;
+
+	spin_unlock_bh(&txctl->txq->axq_lock);
 }
 
-static void xmit_map_sg(struct ath_softc *sc,
-			struct sk_buff *skb,
-			struct ath_tx_control *txctl)
+int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
+		 struct ath_tx_control *txctl)
 {
-	struct ath_xmit_status tx_status;
-	struct ath_atx_tid *tid;
+	struct ath_buf *bf;
 	struct scatterlist sg;
 
-	txctl->dmacontext = pci_map_single(sc->pdev, skb->data,
-					   skb->len, PCI_DMA_TODEVICE);
+	/* Check if a tx buffer is available */
 
-	/* setup S/G list */
+	bf = ath_tx_get_buffer(sc);
+	if (!bf) {
+		DPRINTF(sc, ATH_DBG_XMIT, "%s: TX buffers are full\n",
+			__func__);
+		return -1;
+	}
+
+	ath_tx_setup_buffer(sc, bf, skb, &sg, txctl);
+
+	/* Setup S/G */
+
 	memset(&sg, 0, sizeof(struct scatterlist));
-	sg_dma_address(&sg) = txctl->dmacontext;
+	sg_dma_address(&sg) = bf->bf_dmacontext;
 	sg_dma_len(&sg) = skb->len;
 
-	if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) {
-		/*
-		 *  We have to do drop frame here.
-		 */
-		pci_unmap_single(sc->pdev, txctl->dmacontext,
-				 skb->len, PCI_DMA_TODEVICE);
+	ath_tx_start_dma(sc, bf, &sg, 1, txctl);
 
-		tx_status.retries = 0;
-		tx_status.flags = ATH_TX_ERROR;
-
-		if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
-			/* Reclaim the seqno. */
-			tid = ATH_AN_2_TID((struct ath_node *)
-				txctl->an, txctl->tidno);
-			DECR(tid->seq_next, IEEE80211_SEQ_MAX);
-		}
-		ath_tx_complete(sc, skb, &tx_status, txctl->an);
-	}
+	return 0;
 }
 
 /* Initialize TX queue and h/w */
@@ -2151,7 +2057,6 @@
 		txq->axq_depth = 0;
 		txq->axq_aggr_depth = 0;
 		txq->axq_totalqueued = 0;
-		txq->axq_intrcnt = 0;
 		txq->axq_linkbuf = NULL;
 		sc->sc_txqsetup |= 1<<qnum;
 	}
@@ -2221,6 +2126,34 @@
 	return qnum;
 }
 
+/* Get a transmit queue, if available */
+
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
+{
+	struct ath_txq *txq = NULL;
+	int qnum;
+
+	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+	txq = &sc->sc_txq[qnum];
+
+	spin_lock_bh(&txq->axq_lock);
+
+	/* Try to avoid running out of descriptors */
+	if (txq->axq_depth >= (ATH_TXBUF - 20)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: TX queue: %d is full, depth: %d\n",
+			__func__, qnum, txq->axq_depth);
+		ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
+		txq->stopped = 1;
+		spin_unlock_bh(&txq->axq_lock);
+		return NULL;
+	}
+
+	spin_unlock_bh(&txq->axq_lock);
+
+	return txq;
+}
+
 /* Update parameters for a transmit queue */
 
 int ath_txq_update(struct ath_softc *sc, int qnum,
@@ -2284,27 +2217,6 @@
 	return 0;
 }
 
-int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ath_tx_control txctl;
-	int error = 0;
-
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	error = ath_tx_prepare(sc, skb, &txctl);
-	if (error == 0)
-		/*
-		 * Start DMA mapping.
-		 * ath_tx_start_dma() will be called either synchronously
-		 * or asynchrounsly once DMA is complete.
-		 */
-		xmit_map_sg(sc, skb, &txctl);
-	else
-		ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
-
-	/* failed packets will be dropped by the caller */
-	return error;
-}
-
 /* Deferred processing of transmit interrupt */
 
 void ath_tx_tasklet(struct ath_softc *sc)
@@ -2378,8 +2290,7 @@
 	if (sc->sc_flags & SC_OP_TXAGGR) {
 		if (!retry_tx) {
 			spin_lock_bh(&txq->axq_lock);
-			ath_txq_drain_pending_buffers(sc, txq,
-				ATH9K_BH_STATUS_CHANGE);
+			ath_txq_drain_pending_buffers(sc, txq);
 			spin_unlock_bh(&txq->axq_lock);
 		}
 	}
@@ -2410,64 +2321,39 @@
 	return sc->sc_txq[qnum].axq_aggr_depth;
 }
 
-/* Check if an ADDBA is required. A valid node must be passed. */
-enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
-				      struct ath_node *an,
-				      u8 tidno)
+bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
 {
 	struct ath_atx_tid *txtid;
-	DECLARE_MAC_BUF(mac);
 
 	if (!(sc->sc_flags & SC_OP_TXAGGR))
-		return AGGR_NOT_REQUIRED;
+		return false;
 
-	/* ADDBA exchange must be completed before sending aggregates */
 	txtid = ATH_AN_2_TID(an, tidno);
 
-	if (txtid->addba_exchangecomplete)
-		return AGGR_EXCHANGE_DONE;
-
-	if (txtid->cleanup_inprogress)
-		return AGGR_CLEANUP_PROGRESS;
-
-	if (txtid->addba_exchangeinprogress)
-		return AGGR_EXCHANGE_PROGRESS;
-
-	if (!txtid->addba_exchangecomplete) {
-		if (!txtid->addba_exchangeinprogress &&
+	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+		if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
 		    (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
 			txtid->addba_exchangeattempts++;
-			return AGGR_REQUIRED;
+			return true;
 		}
 	}
 
-	return AGGR_NOT_REQUIRED;
+	return false;
 }
 
 /* Start TX aggregation */
 
-int ath_tx_aggr_start(struct ath_softc *sc,
-		      const u8 *addr,
-		      u16 tid,
-		      u16 *ssn)
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn)
 {
 	struct ath_atx_tid *txtid;
 	struct ath_node *an;
 
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, (u8 *) addr);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (!an) {
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: Node not found to initialize "
-			"TX aggregation\n", __func__);
-		return -1;
-	}
+	an = (struct ath_node *)sta->drv_priv;
 
 	if (sc->sc_flags & SC_OP_TXAGGR) {
 		txtid = ATH_AN_2_TID(an, tid);
-		txtid->addba_exchangeinprogress = 1;
+		txtid->state |= AGGR_ADDBA_PROGRESS;
 		ath_tx_pause_tid(sc, txtid);
 	}
 
@@ -2476,26 +2362,33 @@
 
 /* Stop tx aggregation */
 
-int ath_tx_aggr_stop(struct ath_softc *sc,
-		     const u8 *addr,
-		     u16 tid)
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 {
-	struct ath_node *an;
-
-	spin_lock_bh(&sc->node_lock);
-	an = ath_node_find(sc, (u8 *) addr);
-	spin_unlock_bh(&sc->node_lock);
-
-	if (!an) {
-		DPRINTF(sc, ATH_DBG_AGGR,
-			"%s: TX aggr stop for non-existent node\n", __func__);
-		return -1;
-	}
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 
 	ath_tx_aggr_teardown(sc, an, tid);
 	return 0;
 }
 
+/* Resume tx aggregation */
+
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+	struct ath_atx_tid *txtid;
+	struct ath_node *an;
+
+	an = (struct ath_node *)sta->drv_priv;
+
+	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);
+	}
+}
+
 /*
  * Performs transmit side cleanup when TID changes from aggregated to
  * unaggregated.
@@ -2503,8 +2396,7 @@
  * - Discard all retry frames from the s/w queue.
  */
 
-void ath_tx_aggr_teardown(struct ath_softc *sc,
-	struct ath_node *an, u8 tid)
+void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
 {
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
 	struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
@@ -2514,10 +2406,10 @@
 
 	DPRINTF(sc, ATH_DBG_AGGR, "%s: teardown TX aggregation\n", __func__);
 
-	if (txtid->cleanup_inprogress) /* cleanup is in progress */
+	if (txtid->state & AGGR_CLEANUP) /* cleanup is in progress */
 		return;
 
-	if (!txtid->addba_exchangecomplete) {
+	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
 		txtid->addba_exchangeattempts = 0;
 		return;
 	}
@@ -2547,9 +2439,9 @@
 
 	if (txtid->baw_head != txtid->baw_tail) {
 		spin_unlock_bh(&txq->axq_lock);
-		txtid->cleanup_inprogress = true;
+		txtid->state |= AGGR_CLEANUP;
 	} else {
-		txtid->addba_exchangecomplete = 0;
+		txtid->state &= ~AGGR_ADDBA_COMPLETE;
 		txtid->addba_exchangeattempts = 0;
 		spin_unlock_bh(&txq->axq_lock);
 		ath_tx_flush_tid(sc, txtid);
@@ -2591,10 +2483,8 @@
 		if (tid->paused)    /* check next tid to keep h/w busy */
 			continue;
 
-		if (!(tid->an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) ||
-		    ((txq->axq_depth % 2) == 0)) {
+		if ((txq->axq_depth % 2) == 0)
 			ath_tx_sched_aggr(sc, txq, tid);
-		}
 
 		/*
 		 * add tid to round-robin queue if more frames
@@ -2625,72 +2515,67 @@
 
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 {
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		struct ath_atx_tid *tid;
-		struct ath_atx_ac *ac;
-		int tidno, acno;
+	struct ath_atx_tid *tid;
+	struct ath_atx_ac *ac;
+	int tidno, acno;
 
-		sc->sc_ht_info.maxampdu = ATH_AMPDU_LIMIT_DEFAULT;
+	/*
+	 * Init per tid tx state
+	 */
+	for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
+	     tidno < WME_NUM_TID;
+	     tidno++, tid++) {
+		tid->an        = an;
+		tid->tidno     = tidno;
+		tid->seq_start = tid->seq_next = 0;
+		tid->baw_size  = WME_MAX_BA;
+		tid->baw_head  = tid->baw_tail = 0;
+		tid->sched     = false;
+		tid->paused = false;
+		tid->state &= ~AGGR_CLEANUP;
+		INIT_LIST_HEAD(&tid->buf_q);
 
-		/*
-		 * Init per tid tx state
-		 */
-		for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
-				tidno < WME_NUM_TID;
-				tidno++, tid++) {
-			tid->an        = an;
-			tid->tidno     = tidno;
-			tid->seq_start = tid->seq_next = 0;
-			tid->baw_size  = WME_MAX_BA;
-			tid->baw_head  = tid->baw_tail = 0;
-			tid->sched     = false;
-			tid->paused = false;
-			tid->cleanup_inprogress = false;
-			INIT_LIST_HEAD(&tid->buf_q);
+		acno = TID_TO_WME_AC(tidno);
+		tid->ac = &an->an_aggr.tx.ac[acno];
 
-			acno = TID_TO_WME_AC(tidno);
-			tid->ac = &an->an_aggr.tx.ac[acno];
+		/* ADDBA state */
+		tid->state &= ~AGGR_ADDBA_COMPLETE;
+		tid->state &= ~AGGR_ADDBA_PROGRESS;
+		tid->addba_exchangeattempts = 0;
+	}
 
-			/* ADDBA state */
-			tid->addba_exchangecomplete     = 0;
-			tid->addba_exchangeinprogress   = 0;
-			tid->addba_exchangeattempts     = 0;
-		}
+	/*
+	 * Init per ac tx state
+	 */
+	for (acno = 0, ac = &an->an_aggr.tx.ac[acno];
+	     acno < WME_NUM_AC; acno++, ac++) {
+		ac->sched    = false;
+		INIT_LIST_HEAD(&ac->tid_q);
 
-		/*
-		 * Init per ac tx state
-		 */
-		for (acno = 0, ac = &an->an_aggr.tx.ac[acno];
-				acno < WME_NUM_AC; acno++, ac++) {
-			ac->sched    = false;
-			INIT_LIST_HEAD(&ac->tid_q);
-
-			switch (acno) {
-			case WME_AC_BE:
-				ac->qnum = ath_tx_get_qnum(sc,
-					ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
-				break;
-			case WME_AC_BK:
-				ac->qnum = ath_tx_get_qnum(sc,
-					ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
-				break;
-			case WME_AC_VI:
-				ac->qnum = ath_tx_get_qnum(sc,
-					ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
-				break;
-			case WME_AC_VO:
-				ac->qnum = ath_tx_get_qnum(sc,
-					ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
-				break;
-			}
+		switch (acno) {
+		case WME_AC_BE:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
+			break;
+		case WME_AC_BK:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
+			break;
+		case WME_AC_VI:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
+			break;
+		case WME_AC_VO:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
+			break;
 		}
 	}
 }
 
 /* Cleanupthe pending buffers for the node. */
 
-void ath_tx_node_cleanup(struct ath_softc *sc,
-	struct ath_node *an, bool bh_flag)
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 {
 	int i;
 	struct ath_atx_ac *ac, *ac_tmp;
@@ -2700,10 +2585,7 @@
 		if (ATH_TXQ_SETUP(sc, i)) {
 			txq = &sc->sc_txq[i];
 
-			if (likely(bh_flag))
-				spin_lock_bh(&txq->axq_lock);
-			else
-				spin_lock(&txq->axq_lock);
+			spin_lock(&txq->axq_lock);
 
 			list_for_each_entry_safe(ac,
 					ac_tmp, &txq->axq_acq, list) {
@@ -2718,36 +2600,14 @@
 						tid_tmp, &ac->tid_q, list) {
 					list_del(&tid->list);
 					tid->sched = false;
-					ath_tid_drain(sc, txq, tid, bh_flag);
-					tid->addba_exchangecomplete = 0;
+					ath_tid_drain(sc, txq, tid);
+					tid->state &= ~AGGR_ADDBA_COMPLETE;
 					tid->addba_exchangeattempts = 0;
-					tid->cleanup_inprogress = false;
+					tid->state &= ~AGGR_CLEANUP;
 				}
 			}
 
-			if (likely(bh_flag))
-				spin_unlock_bh(&txq->axq_lock);
-			else
-				spin_unlock(&txq->axq_lock);
-		}
-	}
-}
-
-/* Cleanup per node transmit state */
-
-void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
-{
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		struct ath_atx_tid *tid;
-		int tidno, i;
-
-		/* Init per tid rx state */
-		for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
-			tidno < WME_NUM_TID;
-		     tidno++, tid++) {
-
-			for (i = 0; i < ATH_TID_MAX_BUFS; i++)
-				ASSERT(tid->tx_buf[i] == NULL);
+			spin_unlock(&txq->axq_lock);
 		}
 	}
 }
@@ -2758,6 +2618,8 @@
 	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
@@ -2785,23 +2647,18 @@
 		memmove(skb->data, skb->data + padsize, hdrlen);
 	}
 
+	txctl.txq = sc->sc_cabq;
+
 	DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n",
 		__func__,
 		skb);
 
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	txctl.flags = ATH9K_TXDESC_CAB;
-	if (ath_tx_prepare(sc, skb, &txctl) == 0) {
-		/*
-		 * Start DMA mapping.
-		 * ath_tx_start_dma() will be called either synchronously
-		 * or asynchrounsly once DMA is complete.
-		 */
-		xmit_map_sg(sc, skb, &txctl);
-	} else {
-		ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
-		DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
-		dev_kfree_skb_any(skb);
+	if (ath_tx_start(sc, skb, &txctl) != 0) {
+		DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
+		goto exit;
 	}
-}
 
+	return;
+exit:
+	dev_kfree_skb_any(skb);
+}
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index ecb02bd..3962b55 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -67,7 +67,7 @@
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
-#include <net/ieee80211.h>
+#include <linux/ieee80211.h>
 #include "atmel.h"
 
 #define DRIVER_MAJOR 0
@@ -569,7 +569,7 @@
 static void atmel_command_irq(struct atmel_private *priv);
 static int atmel_validate_channel(struct atmel_private *priv, int channel);
 static void atmel_management_frame(struct atmel_private *priv,
-				   struct ieee80211_hdr_4addr *header,
+				   struct ieee80211_hdr *header,
 				   u16 frame_len, u8 rssi);
 static void atmel_management_timer(u_long a);
 static void atmel_send_command(struct atmel_private *priv, int command,
@@ -577,7 +577,7 @@
 static int atmel_send_command_wait(struct atmel_private *priv, int command,
 				   void *cmd, int cmd_size);
 static void atmel_transmit_management_frame(struct atmel_private *priv,
-					    struct ieee80211_hdr_4addr *header,
+					    struct ieee80211_hdr *header,
 					    u8 *body, int body_len);
 
 static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -785,7 +785,7 @@
 {
 	static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 	struct atmel_private *priv = netdev_priv(dev);
-	struct ieee80211_hdr_4addr header;
+	struct ieee80211_hdr header;
 	unsigned long flags;
 	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
@@ -823,7 +823,7 @@
 
 	frame_ctl = IEEE80211_FTYPE_DATA;
 	header.duration_id = 0;
-	header.seq_ctl = 0;
+	header.seq_ctrl = 0;
 	if (priv->wep_is_on)
 		frame_ctl |= IEEE80211_FCTL_PROTECTED;
 	if (priv->operating_mode == IW_MODE_ADHOC) {
@@ -840,7 +840,7 @@
 	if (priv->use_wpa)
 		memcpy(&header.addr4, SNAP_RFC1024, 6);
 
-	header.frame_ctl = cpu_to_le16(frame_ctl);
+	header.frame_control = cpu_to_le16(frame_ctl);
 	/* Copy the wireless header into the card */
 	atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
 	/* Copy the packet sans its 802.3 header addresses which have been replaced */
@@ -860,7 +860,7 @@
 }
 
 static void atmel_transmit_management_frame(struct atmel_private *priv,
-					    struct ieee80211_hdr_4addr *header,
+					    struct ieee80211_hdr *header,
 					    u8 *body, int body_len)
 {
 	u16 buff;
@@ -876,7 +876,7 @@
 }
 
 static void fast_rx_path(struct atmel_private *priv,
-			 struct ieee80211_hdr_4addr *header,
+			 struct ieee80211_hdr *header,
 			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
 {
 	/* fast path: unfragmented packet copy directly into skbuf */
@@ -914,12 +914,11 @@
 	}
 
 	memcpy(skbp, header->addr1, 6); /* destination address */
-	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
 		memcpy(&skbp[6], header->addr3, 6);
 	else
 		memcpy(&skbp[6], header->addr2, 6); /* source address */
 
-	priv->dev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, priv->dev);
 	skb->ip_summed = CHECKSUM_NONE;
 	netif_rx(skb);
@@ -950,7 +949,7 @@
 }
 
 static void frag_rx_path(struct atmel_private *priv,
-			 struct ieee80211_hdr_4addr *header,
+			 struct ieee80211_hdr *header,
 			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
 			 u8 frag_no, int more_frags)
 {
@@ -958,7 +957,7 @@
 	u8 source[6];
 	struct sk_buff *skb;
 
-	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
 		memcpy(source, header->addr3, 6);
 	else
 		memcpy(source, header->addr2, 6);
@@ -1026,7 +1025,6 @@
 				memcpy(skb_put(skb, priv->frag_len + 12),
 				       priv->rx_buf,
 				       priv->frag_len + 12);
-				priv->dev->last_rx = jiffies;
 				skb->protocol = eth_type_trans(skb, priv->dev);
 				skb->ip_summed = CHECKSUM_NONE;
 				netif_rx(skb);
@@ -1041,7 +1039,7 @@
 static void rx_done_irq(struct atmel_private *priv)
 {
 	int i;
-	struct ieee80211_hdr_4addr header;
+	struct ieee80211_hdr header;
 
 	for (i = 0;
 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -1068,10 +1066,10 @@
 			goto next;
 		}
 
-		/* Get header as far as end of seq_ctl */
+		/* Get header as far as end of seq_ctrl */
 		atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
-		frame_ctl = le16_to_cpu(header.frame_ctl);
-		seq_control = le16_to_cpu(header.seq_ctl);
+		frame_ctl = le16_to_cpu(header.frame_control);
+		seq_control = le16_to_cpu(header.seq_ctrl);
 
 		/* probe for CRC use here if needed  once five packets have
 		   arrived with the same crc status, we assume we know what's
@@ -1479,7 +1477,6 @@
 	struct net_device *dev;
 	struct atmel_private *priv;
 	int rc;
-	DECLARE_MAC_BUF(mac);
 
 	/* Create the network device object. */
         dev = alloc_etherdev(sizeof(*priv));
@@ -1591,8 +1588,8 @@
 	if (!ent)
 		printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
 
-	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %s\n",
-	       dev->name, DRIVER_MAJOR, DRIVER_MINOR, print_mac(mac, dev->dev_addr));
+	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
+	       dev->name, DRIVER_MAJOR, DRIVER_MINOR, dev->dev_addr);
 
 	return dev;
 
@@ -1822,7 +1819,7 @@
 	/* Determine and validate the key index */
 	idx = encoding->flags & IW_ENCODE_INDEX;
 	if (idx) {
-		if (idx < 1 || idx > WEP_KEYS)
+		if (idx < 1 || idx > 4)
 			return -EINVAL;
 		idx--;
 	} else
@@ -1885,7 +1882,7 @@
 
 	idx = encoding->flags & IW_ENCODE_INDEX;
 	if (idx) {
-		if (idx < 1 || idx > WEP_KEYS)
+		if (idx < 1 || idx > 4)
 			return -EINVAL;
 		idx--;
 	} else
@@ -2800,7 +2797,7 @@
 				u8 channel)
 {
 	int rejoin = 0;
-	int new = capability & MFIE_TYPE_POWER_CONSTRAINT ?
+	int new = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
 		SHORT_PREAMBLE : LONG_PREAMBLE;
 
 	if (priv->preamble != new) {
@@ -2829,19 +2826,19 @@
 static void send_authentication_request(struct atmel_private *priv, u16 system,
 					u8 *challenge, int challenge_len)
 {
-	struct ieee80211_hdr_4addr header;
+	struct ieee80211_hdr header;
 	struct auth_body auth;
 
-	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+	header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
 	header.duration_id = cpu_to_le16(0x8000);
-	header.seq_ctl = 0;
+	header.seq_ctrl = 0;
 	memcpy(header.addr1, priv->CurrentBSSID, 6);
 	memcpy(header.addr2, priv->dev->dev_addr, 6);
 	memcpy(header.addr3, priv->CurrentBSSID, 6);
 
 	if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
 		/* no WEP for authentication frames with TrSeqNo 1 */
-                header.frame_ctl |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+                header.frame_control |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
 	auth.alg = cpu_to_le16(system);
 
@@ -2864,7 +2861,7 @@
 {
 	u8 *ssid_el_p;
 	int bodysize;
-	struct ieee80211_hdr_4addr header;
+	struct ieee80211_hdr header;
 	struct ass_req_format {
 		__le16 capability;
 		__le16 listen_interval;
@@ -2877,10 +2874,10 @@
 		u8 rates[4];
 	} body;
 
-	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+	header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 		(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
 	header.duration_id = cpu_to_le16(0x8000);
-	header.seq_ctl = 0;
+	header.seq_ctrl = 0;
 
 	memcpy(header.addr1, priv->CurrentBSSID, 6);
 	memcpy(header.addr2, priv->dev->dev_addr, 6);
@@ -2890,7 +2887,7 @@
 	if (priv->wep_is_on)
 		body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 	if (priv->preamble == SHORT_PREAMBLE)
-		body.capability |= cpu_to_le16(MFIE_TYPE_POWER_CONSTRAINT);
+		body.capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
 
 	body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
 
@@ -2904,10 +2901,10 @@
 		bodysize = 12 + priv->SSID_size;
 	}
 
-	ssid_el_p[0] = MFIE_TYPE_SSID;
+	ssid_el_p[0] = WLAN_EID_SSID;
 	ssid_el_p[1] = priv->SSID_size;
 	memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
-	ssid_el_p[2 + priv->SSID_size] = MFIE_TYPE_RATES;
+	ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
 	ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
 	memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
 
@@ -2915,9 +2912,9 @@
 }
 
 static int is_frame_from_current_bss(struct atmel_private *priv,
-				     struct ieee80211_hdr_4addr *header)
+				     struct ieee80211_hdr *header)
 {
-	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
 		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
 	else
 		return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
@@ -2965,7 +2962,7 @@
 }
 
 static void store_bss_info(struct atmel_private *priv,
-			   struct ieee80211_hdr_4addr *header, u16 capability,
+			   struct ieee80211_hdr *header, u16 capability,
 			   u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
 			   u8 *ssid, int is_beacon)
 {
@@ -3004,7 +3001,7 @@
 	else if (capability & WLAN_CAPABILITY_ESS)
 		priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
 
-	priv->BSSinfo[index].preamble = capability & MFIE_TYPE_POWER_CONSTRAINT ?
+	priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
 		SHORT_PREAMBLE : LONG_PREAMBLE;
 }
 
@@ -3040,7 +3037,7 @@
 			}
 		} else if (system == WLAN_AUTH_SHARED_KEY) {
 			if (trans_seq_no == 0x0002 &&
-			    auth->el_id == MFIE_TYPE_CHALLENGE) {
+			    auth->el_id == WLAN_EID_CHALLENGE) {
 				send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
 				return;
 			} else if (trans_seq_no == 0x0004) {
@@ -3291,12 +3288,12 @@
 
 /* deals with incoming managment frames. */
 static void atmel_management_frame(struct atmel_private *priv,
-				   struct ieee80211_hdr_4addr *header,
+				   struct ieee80211_hdr *header,
 				   u16 frame_len, u8 rssi)
 {
 	u16 subtype;
 
-	subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
+	subtype = le16_to_cpu(header->frame_control) & IEEE80211_FCTL_STYPE;
 	switch (subtype) {
 	case IEEE80211_STYPE_BEACON:
 	case IEEE80211_STYPE_PROBE_RESP:
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 427b820..a53c378 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -718,7 +718,6 @@
 
 	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
-	bool short_slot;	/* TRUE, if short slot timing is enabled. */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
 
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 098f886..6d65a02 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1387,13 +1387,11 @@
 
 			info = IEEE80211_SKB_CB(meta->skb);
 
-			memset(&info->status, 0, sizeof(info->status));
-
 			/*
 			 * Call back to inform the ieee80211 subsystem about
 			 * the status of the transmission.
 			 */
-			frame_succeed = b43_fill_txstatus_report(info, status);
+			frame_succeed = b43_fill_txstatus_report(dev, info, status);
 #ifdef CONFIG_B43_DEBUG
 			if (frame_succeed)
 				ring->nr_succeed_tx_packets++;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 14c44df..ba7a5ab 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -703,13 +703,11 @@
 static void b43_short_slot_timing_enable(struct b43_wldev *dev)
 {
 	b43_set_slot_time(dev, 9);
-	dev->short_slot = 1;
 }
 
 static void b43_short_slot_timing_disable(struct b43_wldev *dev)
 {
 	b43_set_slot_time(dev, 20);
-	dev->short_slot = 0;
 }
 
 /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
@@ -1339,25 +1337,6 @@
 	return antenna_nr;
 }
 
-static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
-{
-	antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
-	switch (antenna) {
-	case 0:		/* default/diversity */
-		return B43_ANTENNA_DEFAULT;
-	case 1:		/* Antenna 0 */
-		return B43_ANTENNA0;
-	case 2:		/* Antenna 1 */
-		return B43_ANTENNA1;
-	case 3:		/* Antenna 2 */
-		return B43_ANTENNA2;
-	case 4:		/* Antenna 3 */
-		return B43_ANTENNA3;
-	default:
-		return B43_ANTENNA_DEFAULT;
-	}
-}
-
 /* Convert a b43 antenna number value to the PHY TX control value. */
 static u16 b43_antenna_to_phyctl(int antenna)
 {
@@ -1399,7 +1378,7 @@
 				  len, ram_offset, shm_size_offset, rate);
 
 	/* Write the PHY TX control parameters. */
-	antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx);
+	antenna = B43_ANTENNA_DEFAULT;
 	antenna = b43_antenna_to_phyctl(antenna);
 	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
 	/* We can't send beacons with short preamble. Would get PHY errors. */
@@ -1693,25 +1672,6 @@
 	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
 }
 
-static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
-{
-	u32 tmp;
-	u16 i, len;
-
-	len = min((u16) ssid_len, (u16) 0x100);
-	for (i = 0; i < len; i += sizeof(u32)) {
-		tmp = (u32) (ssid[i + 0]);
-		if (i + 1 < len)
-			tmp |= (u32) (ssid[i + 1]) << 8;
-		if (i + 2 < len)
-			tmp |= (u32) (ssid[i + 2]) << 16;
-		if (i + 3 < len)
-			tmp |= (u32) (ssid[i + 3]) << 24;
-		b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp);
-	}
-	b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len);
-}
-
 static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
 {
 	b43_time_lock(dev);
@@ -3339,11 +3299,28 @@
 	return err;
 }
 
-static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+/* Write the short and long frame retry limit values. */
+static void b43_set_retry_limits(struct b43_wldev *dev,
+				 unsigned int short_retry,
+				 unsigned int long_retry)
+{
+	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+	 * the chip-internal counter. */
+	short_retry = min(short_retry, (unsigned int)0xF);
+	long_retry = min(long_retry, (unsigned int)0xF);
+
+	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
+			short_retry);
+	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
+			long_retry);
+}
+
+static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev;
 	struct b43_phy *phy;
+	struct ieee80211_conf *conf = &hw->conf;
 	unsigned long flags;
 	int antenna;
 	int err = 0;
@@ -3358,6 +3335,13 @@
 	dev = wl->current_dev;
 	phy = &dev->phy;
 
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
+					  conf->long_frame_max_tx_count);
+	changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+	if (!changed)
+		goto out_unlock_mutex;
+
 	/* Disable IRQs while reconfiguring the device.
 	 * This makes it possible to drop the spinlock throughout
 	 * the reconfiguration process. */
@@ -3375,16 +3359,6 @@
 	if (conf->channel->hw_value != phy->channel)
 		b43_switch_channel(dev, conf->channel->hw_value);
 
-	/* Enable/Disable ShortSlot timing. */
-	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
-	    dev->short_slot) {
-		B43_WARN_ON(phy->type != B43_PHYTYPE_G);
-		if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
-			b43_short_slot_timing_enable(dev);
-		else
-			b43_short_slot_timing_disable(dev);
-	}
-
 	dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
 
 	/* Adjust the desired TX power level. */
@@ -3399,9 +3373,9 @@
 	}
 
 	/* Antennas for RX and management frame TX. */
-	antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
+	antenna = B43_ANTENNA_DEFAULT;
 	b43_mgmtframe_txantenna(dev, antenna);
-	antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
+	antenna = B43_ANTENNA_DEFAULT;
 	if (phy->ops->set_rx_antenna)
 		phy->ops->set_rx_antenna(dev, antenna);
 
@@ -3435,6 +3409,104 @@
 	return err;
 }
 
+static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates)
+{
+	struct ieee80211_supported_band *sband =
+		dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
+	struct ieee80211_rate *rate;
+	int i;
+	u16 basic, direct, offset, basic_offset, rateptr;
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = &sband->bitrates[i];
+
+		if (b43_is_cck_rate(rate->hw_value)) {
+			direct = B43_SHM_SH_CCKDIRECT;
+			basic = B43_SHM_SH_CCKBASIC;
+			offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+			offset &= 0xF;
+		} else {
+			direct = B43_SHM_SH_OFDMDIRECT;
+			basic = B43_SHM_SH_OFDMBASIC;
+			offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+			offset &= 0xF;
+		}
+
+		rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+		if (b43_is_cck_rate(rate->hw_value)) {
+			basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+			basic_offset &= 0xF;
+		} else {
+			basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+			basic_offset &= 0xF;
+		}
+
+		/*
+		 * Get the pointer that we need to point to
+		 * from the direct map
+		 */
+		rateptr = b43_shm_read16(dev, B43_SHM_SHARED,
+					 direct + 2 * basic_offset);
+		/* and write it to the basic map */
+		b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset,
+				rateptr);
+	}
+}
+
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *conf,
+				    u32 changed)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	struct b43_phy *phy;
+	unsigned long flags;
+	u32 savedirqs;
+
+	mutex_lock(&wl->mutex);
+
+	dev = wl->current_dev;
+	phy = &dev->phy;
+
+	/* Disable IRQs while reconfiguring the device.
+	 * This makes it possible to drop the spinlock throughout
+	 * the reconfiguration process. */
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	if (b43_status(dev) < B43_STAT_STARTED) {
+		spin_unlock_irqrestore(&wl->irq_lock, flags);
+		goto out_unlock_mutex;
+	}
+	savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+	b43_synchronize_irq(dev);
+
+	b43_mac_suspend(dev);
+
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		b43_update_basic_rates(dev, conf->basic_rates);
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (conf->use_short_slot)
+			b43_short_slot_timing_enable(dev);
+		else
+			b43_short_slot_timing_disable(dev);
+	}
+
+	b43_mac_enable(dev);
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43_interrupt_enable(dev, savedirqs);
+	/* XXX: why? */
+	mmiowb();
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ out_unlock_mutex:
+	mutex_unlock(&wl->mutex);
+
+	return;
+}
+
 static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			   const u8 *local_addr, const u8 *addr,
 			   struct ieee80211_key_conf *key)
@@ -3445,7 +3517,6 @@
 	u8 algorithm;
 	u8 index;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	if (modparam_nohwcrypt)
 		return -ENOSPC; /* User disabled HW-crypto */
@@ -3533,9 +3604,9 @@
 	mutex_unlock(&wl->mutex);
 	if (!err) {
 		b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
-		       "mac: %s\n",
+		       "mac: %pM\n",
 		       cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
-		       print_mac(mac, addr));
+		       addr);
 	}
 	return err;
 }
@@ -3598,8 +3669,6 @@
 		if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
 		    b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
 			B43_WARN_ON(vif->type != wl->if_type);
-			if (conf->changed & IEEE80211_IFCC_SSID)
-				b43_set_ssid(dev, conf->ssid, conf->ssid_len);
 			if (conf->changed & IEEE80211_IFCC_BEACON)
 				b43_update_templates(wl);
 		} else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
@@ -3878,22 +3947,6 @@
 #endif /* CONFIG_SSB_DRIVER_PCICORE */
 }
 
-/* Write the short and long frame retry limit values. */
-static void b43_set_retry_limits(struct b43_wldev *dev,
-				 unsigned int short_retry,
-				 unsigned int long_retry)
-{
-	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
-	 * the chip-internal counter. */
-	short_retry = min(short_retry, (unsigned int)0xF);
-	long_retry = min(long_retry, (unsigned int)0xF);
-
-	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
-			short_retry);
-	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
-			long_retry);
-}
-
 static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
 {
 	u16 pu_delay;
@@ -4214,26 +4267,6 @@
 	cancel_work_sync(&(wl->txpower_adjust_work));
 }
 
-static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
-				  u32 short_retry_limit, u32 long_retry_limit)
-{
-	struct b43_wl *wl = hw_to_b43_wl(hw);
-	struct b43_wldev *dev;
-	int err = 0;
-
-	mutex_lock(&wl->mutex);
-	dev = wl->current_dev;
-	if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) {
-		err = -ENODEV;
-		goto out_unlock;
-	}
-	b43_set_retry_limits(dev, short_retry_limit, long_retry_limit);
-out_unlock:
-	mutex_unlock(&wl->mutex);
-
-	return err;
-}
-
 static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
 				 struct ieee80211_sta *sta, bool set)
 {
@@ -4263,6 +4296,7 @@
 	.add_interface		= b43_op_add_interface,
 	.remove_interface	= b43_op_remove_interface,
 	.config			= b43_op_config,
+	.bss_info_changed	= b43_op_bss_info_changed,
 	.config_interface	= b43_op_config_interface,
 	.configure_filter	= b43_op_configure_filter,
 	.set_key		= b43_op_set_key,
@@ -4270,7 +4304,6 @@
 	.get_tx_stats		= b43_op_get_tx_stats,
 	.start			= b43_op_start,
 	.stop			= b43_op_stop,
-	.set_retry_limit	= b43_op_set_retry_limit,
 	.set_tim		= b43_op_beacon_set_tim,
 	.sta_notify		= b43_op_sta_notify,
 };
@@ -4588,7 +4621,7 @@
 		BIT(NL80211_IFTYPE_ADHOC);
 
 	hw->queues = b43_modparam_qos ? 4 : 1;
-	hw->max_altrates = 1;
+	hw->max_rates = 2;
 	SET_IEEE80211_DEV(hw, dev->dev);
 	if (is_valid_ether_addr(sprom->et1mac))
 		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 40159126..1036bef 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -587,9 +587,8 @@
 	spin_lock(&q->lock); /* IRQs are already disabled. */
 
 	info = IEEE80211_SKB_CB(pack->skb);
-	memset(&info->status, 0, sizeof(info->status));
 
-	b43_fill_txstatus_report(info, status);
+	b43_fill_txstatus_report(dev, info, status);
 
 	total_len = pack->skb->len + b43_txhdr_size(dev);
 	total_len = roundup(total_len, 4);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 2fabcf8..adba89b 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -185,7 +185,7 @@
 		       u8 *_txhdr,
 		       const unsigned char *fragment_data,
 		       unsigned int fragment_len,
-		       const struct ieee80211_tx_info *info,
+		       struct ieee80211_tx_info *info,
 		       u16 cookie)
 {
 	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
@@ -202,6 +202,7 @@
 	u16 phy_ctl = 0;
 	u8 extra_ft = 0;
 	struct ieee80211_rate *txrate;
+	struct ieee80211_tx_rate *rates;
 
 	memset(txhdr, 0, sizeof(*txhdr));
 
@@ -291,7 +292,7 @@
 		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
 	else
 		phy_ctl |= B43_TXH_PHY_ENC_CCK;
-	if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
 
 	switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
@@ -314,6 +315,7 @@
 		B43_WARN_ON(1);
 	}
 
+	rates = info->control.rates;
 	/* MAC control */
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
 		mac_ctl |= B43_TXH_MAC_ACK;
@@ -324,12 +326,22 @@
 		mac_ctl |= B43_TXH_MAC_STMSDU;
 	if (phy->type == B43_PHYTYPE_A)
 		mac_ctl |= B43_TXH_MAC_5GHZ;
-	if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+
+	/* Overwrite rates[0].count to make the retry calculation
+	 * in the tx status easier. need the actual retry limit to
+	 * detect whether the fallback rate was used.
+	 */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
 		mac_ctl |= B43_TXH_MAC_LONGFRAME;
+	} else {
+		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+	}
 
 	/* Generate the RTS or CTS-to-self frame */
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
 		unsigned int len;
 		struct ieee80211_hdr *hdr;
 		int rts_rate, rts_rate_fb;
@@ -344,7 +356,7 @@
 		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
 
-		if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 			struct ieee80211_cts *cts;
 
 			if (b43_is_old_txhdr_format(dev)) {
@@ -687,10 +699,18 @@
 /* Fill out the mac80211 TXstatus report based on the b43-specific
  * txstatus report data. This returns a boolean whether the frame was
  * successfully transmitted. */
-bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+			      struct ieee80211_tx_info *report,
 			      const struct b43_txstatus *status)
 {
 	bool frame_success = 1;
+	int retry_limit;
+
+	/* preserve the confiured retry limit before clearing the status
+	 * The xmit function has overwritten the rc's value with the actual
+	 * retry limit done by the hardware */
+	retry_limit = report->status.rates[0].count;
+	ieee80211_tx_info_clear_status(report);
 
 	if (status->acked) {
 		/* The frame was ACKed. */
@@ -700,14 +720,32 @@
 		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
 			/* ...but we expected an ACK. */
 			frame_success = 0;
-			report->status.excessive_retries = 1;
 		}
 	}
 	if (status->frame_count == 0) {
 		/* The frame was not transmitted at all. */
-		report->status.retry_count = 0;
-	} else
-		report->status.retry_count = status->frame_count - 1;
+		report->status.rates[0].count = 0;
+	} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+		/*
+		 * If the short retries (RTS, not data frame) have exceeded
+		 * the limit, the hw will not have tried the selected rate,
+		 * but will have used the fallback rate instead.
+		 * Don't let the rate control count attempts for the selected
+		 * rate in this case, otherwise the statistics will be off.
+		 */
+		report->status.rates[0].count = 0;
+		report->status.rates[1].count = status->frame_count;
+	} else {
+		if (status->frame_count > retry_limit) {
+			report->status.rates[0].count = retry_limit;
+			report->status.rates[1].count = status->frame_count -
+					retry_limit;
+
+		} else {
+			report->status.rates[0].count = status->frame_count;
+			report->status.rates[1].idx = -1;
+		}
+	}
 
 	return frame_success;
 }
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 0215faf..4fb2a19 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -178,7 +178,7 @@
 		       u8 * txhdr,
 		       const unsigned char *fragment_data,
 		       unsigned int fragment_len,
-		       const struct ieee80211_tx_info *txctl, u16 cookie);
+		       struct ieee80211_tx_info *txctl, u16 cookie);
 
 /* Transmit Status */
 struct b43_txstatus {
@@ -294,7 +294,8 @@
 
 void b43_handle_txstatus(struct b43_wldev *dev,
 			 const struct b43_txstatus *status);
-bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+			      struct ieee80211_tx_info *report,
 			      const struct b43_txstatus *status);
 
 void b43_tx_suspend(struct b43_wldev *dev);
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index fb6819e..3649fc3 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -919,7 +919,7 @@
 			if (!ring->txhdr_cache)
 				goto err_kfree_meta;
 
-				dma_test = ssb_dma_map_single(dev->dev,
+			dma_test = ssb_dma_map_single(dev->dev,
 					ring->txhdr_cache,
 					sizeof(struct b43legacy_txhdr_fw3),
 					DMA_TO_DEVICE);
@@ -1411,6 +1411,7 @@
 	struct b43legacy_dmaring *ring;
 	struct b43legacy_dmadesc_generic *desc;
 	struct b43legacy_dmadesc_meta *meta;
+	int retry_limit;
 	int slot;
 
 	ring = parse_cookie(dev, status->cookie, &slot);
@@ -1437,25 +1438,42 @@
 			struct ieee80211_tx_info *info;
 			BUG_ON(!meta->skb);
 			info = IEEE80211_SKB_CB(meta->skb);
+
+			/* preserve the confiured retry limit before clearing the status
+			 * The xmit function has overwritten the rc's value with the actual
+			 * retry limit done by the hardware */
+			retry_limit = info->status.rates[0].count;
+			ieee80211_tx_info_clear_status(info);
+
+			if (status->acked)
+				info->flags |= IEEE80211_TX_STAT_ACK;
+
+			if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+				/*
+				 * If the short retries (RTS, not data frame) have exceeded
+				 * the limit, the hw will not have tried the selected rate,
+				 * but will have used the fallback rate instead.
+				 * Don't let the rate control count attempts for the selected
+				 * rate in this case, otherwise the statistics will be off.
+				 */
+				info->status.rates[0].count = 0;
+				info->status.rates[1].count = status->frame_count;
+			} else {
+				if (status->frame_count > retry_limit) {
+					info->status.rates[0].count = retry_limit;
+					info->status.rates[1].count = status->frame_count -
+							retry_limit;
+
+				} else {
+					info->status.rates[0].count = status->frame_count;
+					info->status.rates[1].idx = -1;
+				}
+			}
+
 			/* Call back to inform the ieee80211 subsystem about the
 			 * status of the transmission.
 			 * Some fields of txstat are already filled in dma_tx().
 			 */
-
-			memset(&info->status, 0, sizeof(info->status));
-
-			if (status->acked) {
-				info->flags |= IEEE80211_TX_STAT_ACK;
-			} else {
-				if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
-					 info->status.excessive_retries = 1;
-			}
-			if (status->frame_count == 0) {
-				/* The frame was not transmitted at all. */
-				info->status.retry_count = 0;
-			} else
-				info->status.retry_count = status->frame_count
-							   - 1;
 			ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
 			/* skb is freed by ieee80211_tx_status_irqsafe() */
 			meta->skb = NULL;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c66d575..6c8eb4d 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1160,29 +1160,6 @@
 	wl->beacon1_uploaded = 0;
 }
 
-static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
-			       const u8 *ssid, u8 ssid_len)
-{
-	u32 tmp;
-	u16 i;
-	u16 len;
-
-	len = min((u16)ssid_len, (u16)0x100);
-	for (i = 0; i < len; i += sizeof(u32)) {
-		tmp = (u32)(ssid[i + 0]);
-		if (i + 1 < len)
-			tmp |= (u32)(ssid[i + 1]) << 8;
-		if (i + 2 < len)
-			tmp |= (u32)(ssid[i + 2]) << 16;
-		if (i + 3 < len)
-			tmp |= (u32)(ssid[i + 3]) << 24;
-		b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
-				      0x380 + i, tmp);
-	}
-	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
-			      0x48, len);
-}
-
 static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
 				     u16 beacon_int)
 {
@@ -2556,26 +2533,27 @@
 	return err;
 }
 
-static int b43legacy_antenna_from_ieee80211(u8 antenna)
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+				       unsigned int short_retry,
+				       unsigned int long_retry)
 {
-	switch (antenna) {
-	case 0: /* default/diversity */
-		return B43legacy_ANTENNA_DEFAULT;
-	case 1: /* Antenna 0 */
-		return B43legacy_ANTENNA0;
-	case 2: /* Antenna 1 */
-		return B43legacy_ANTENNA1;
-	default:
-		return B43legacy_ANTENNA_DEFAULT;
-	}
+	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+	 * the chip-internal counter. */
+	short_retry = min(short_retry, (unsigned int)0xF);
+	long_retry = min(long_retry, (unsigned int)0xF);
+
+	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
 }
 
 static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
-				   struct ieee80211_conf *conf)
+				   u32 changed)
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev;
 	struct b43legacy_phy *phy;
+	struct ieee80211_conf *conf = &hw->conf;
 	unsigned long flags;
 	unsigned int new_phymode = 0xFFFF;
 	int antenna_tx;
@@ -2583,13 +2561,21 @@
 	int err = 0;
 	u32 savedirqs;
 
-	antenna_tx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_tx);
-	antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
+	antenna_tx = B43legacy_ANTENNA_DEFAULT;
+	antenna_rx = B43legacy_ANTENNA_DEFAULT;
 
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	phy = &dev->phy;
 
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		b43legacy_set_retry_limits(dev,
+					   conf->short_frame_max_tx_count,
+					   conf->long_frame_max_tx_count);
+	changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+	if (!changed)
+		goto out_unlock_mutex;
+
 	/* Switch the PHY mode (if necessary). */
 	switch (conf->channel->band) {
 	case IEEE80211_BAND_2GHZ:
@@ -2735,7 +2721,6 @@
 	if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
 		if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
 			B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
-			b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
 			if (conf->changed & IEEE80211_IFCC_BEACON)
 				b43legacy_update_templates(wl);
 		} else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
@@ -3002,20 +2987,6 @@
 #endif /* CONFIG_SSB_DRIVER_PCICORE */
 }
 
-/* Write the short and long frame retry limit values. */
-static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
-				       unsigned int short_retry,
-				       unsigned int long_retry)
-{
-	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
-	 * the chip-internal counter. */
-	short_retry = min(short_retry, (unsigned int)0xF);
-	long_retry = min(long_retry, (unsigned int)0xF);
-
-	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
-	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
-}
-
 static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
 					  bool idle) {
 	u16 pu_delay = 1050;
@@ -3380,28 +3351,6 @@
 	mutex_unlock(&wl->mutex);
 }
 
-static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
-					u32 short_retry_limit,
-					u32 long_retry_limit)
-{
-	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
-	struct b43legacy_wldev *dev;
-	int err = 0;
-
-	mutex_lock(&wl->mutex);
-	dev = wl->current_dev;
-	if (unlikely(!dev ||
-		     (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
-		err = -ENODEV;
-		goto out_unlock;
-	}
-	b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
-out_unlock:
-	mutex_unlock(&wl->mutex);
-
-	return err;
-}
-
 static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
 				       struct ieee80211_sta *sta, bool set)
 {
@@ -3427,7 +3376,6 @@
 	.get_tx_stats		= b43legacy_op_get_tx_stats,
 	.start			= b43legacy_op_start,
 	.stop			= b43legacy_op_stop,
-	.set_retry_limit	= b43legacy_op_set_retry_limit,
 	.set_tim		= b43legacy_op_beacon_set_tim,
 };
 
@@ -3710,7 +3658,7 @@
 		BIT(NL80211_IFTYPE_WDS) |
 		BIT(NL80211_IFTYPE_ADHOC);
 	hw->queues = 1; /* FIXME: hardware has more queues */
-	hw->max_altrates = 1;
+	hw->max_rates = 2;
 	SET_IEEE80211_DEV(hw, dev->dev);
 	if (is_valid_ether_addr(sprom->et1mac))
 		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index a86c764..746d536 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -491,6 +491,7 @@
 	struct b43legacy_pioqueue *queue;
 	struct b43legacy_pio_txpacket *packet;
 	struct ieee80211_tx_info *info;
+	int retry_limit;
 
 	queue = parse_cookie(dev, status->cookie, &packet);
 	B43legacy_WARN_ON(!queue);
@@ -503,11 +504,37 @@
 				sizeof(struct b43legacy_txhdr_fw3));
 
 	info = IEEE80211_SKB_CB(packet->skb);
-	memset(&info->status, 0, sizeof(info->status));
+
+	/* preserve the confiured retry limit before clearing the status
+	 * The xmit function has overwritten the rc's value with the actual
+	 * retry limit done by the hardware */
+	retry_limit = info->status.rates[0].count;
+	ieee80211_tx_info_clear_status(info);
 
 	if (status->acked)
 		info->flags |= IEEE80211_TX_STAT_ACK;
-	info->status.retry_count = status->frame_count - 1;
+
+	if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+		/*
+		 * If the short retries (RTS, not data frame) have exceeded
+		 * the limit, the hw will not have tried the selected rate,
+		 * but will have used the fallback rate instead.
+		 * Don't let the rate control count attempts for the selected
+		 * rate in this case, otherwise the statistics will be off.
+		 */
+		info->status.rates[0].count = 0;
+		info->status.rates[1].count = status->frame_count;
+	} else {
+		if (status->frame_count > retry_limit) {
+			info->status.rates[0].count = retry_limit;
+			info->status.rates[1].count = status->frame_count -
+					retry_limit;
+
+		} else {
+			info->status.rates[0].count = status->frame_count;
+			info->status.rates[1].idx = -1;
+		}
+	}
 	ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb);
 	packet->skb = NULL;
 
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 65e8337..12fca99 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -188,7 +188,7 @@
 			       struct b43legacy_txhdr_fw3 *txhdr,
 			       const unsigned char *fragment_data,
 			       unsigned int fragment_len,
-			       const struct ieee80211_tx_info *info,
+			       struct ieee80211_tx_info *info,
 			       u16 cookie)
 {
 	const struct ieee80211_hdr *wlhdr;
@@ -201,6 +201,7 @@
 	u32 mac_ctl = 0;
 	u16 phy_ctl = 0;
 	struct ieee80211_rate *tx_rate;
+	struct ieee80211_tx_rate *rates;
 
 	wlhdr = (const struct ieee80211_hdr *)fragment_data;
 
@@ -274,7 +275,7 @@
 	/* PHY TX Control word */
 	if (rate_ofdm)
 		phy_ctl |= B43legacy_TX4_PHY_OFDM;
-	if (dev->short_preamble)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 		phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
 	switch (info->antenna_sel_tx) {
 	case 0:
@@ -291,6 +292,7 @@
 	}
 
 	/* MAC control */
+	rates = info->control.rates;
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
 		mac_ctl |= B43legacy_TX4_MAC_ACK;
 	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
@@ -299,12 +301,22 @@
 		mac_ctl |= B43legacy_TX4_MAC_STMSDU;
 	if (rate_fb_ofdm)
 		mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
-	if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+
+	/* Overwrite rates[0].count to make the retry calculation
+	 * in the tx status easier. need the actual retry limit to
+	 * detect whether the fallback rate was used.
+	 */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
 		mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
+	} else {
+		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+	}
 
 	/* Generate the RTS or CTS-to-self frame */
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
 		unsigned int len;
 		struct ieee80211_hdr *hdr;
 		int rts_rate;
@@ -319,7 +331,7 @@
 		if (rts_rate_fb_ofdm)
 			mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
 
-		if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 			ieee80211_ctstoself_get(dev->wl->hw,
 						info->control.vif,
 						fragment_data,
@@ -362,7 +374,7 @@
 			      u8 *txhdr,
 			      const unsigned char *fragment_data,
 			      unsigned int fragment_len,
-			      const struct ieee80211_tx_info *info,
+			      struct ieee80211_tx_info *info,
 			      u16 cookie)
 {
 	return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h
index e56777e0f..62e09d0 100644
--- a/drivers/net/wireless/b43legacy/xmit.h
+++ b/drivers/net/wireless/b43legacy/xmit.h
@@ -80,7 +80,7 @@
 			      u8 *txhdr,
 			      const unsigned char *fragment_data,
 			      unsigned int fragment_len,
-			      const struct ieee80211_tx_info *info,
+			      struct ieee80211_tx_info *info,
 			      u16 cookie);
 
 
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index f106bc1..5f64461 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -19,7 +19,6 @@
 {
 	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
-	DECLARE_MAC_BUF(mac);
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
@@ -45,11 +44,11 @@
 	printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
 	       le16_to_cpu(hdr->seq_ctl));
 
-	printk(KERN_DEBUG "   A1=%s", print_mac(mac, hdr->addr1));
-	printk(" A2=%s", print_mac(mac, hdr->addr2));
-	printk(" A3=%s", print_mac(mac, hdr->addr3));
+	printk(KERN_DEBUG "   A1=%pM", hdr->addr1);
+	printk(" A2=%pM", hdr->addr2);
+	printk(" A3=%pM", hdr->addr3);
 	if (skb->len >= 30)
-		printk(" A4=%s", print_mac(mac, hdr->addr4));
+		printk(" A4=%pM", hdr->addr4);
 	printk("\n");
 }
 
@@ -68,7 +67,6 @@
 
 	iface = netdev_priv(dev);
 	local = iface->local;
-	dev->last_rx = jiffies;
 
 	if (dev->type == ARPHRD_IEEE80211_PRISM) {
 		if (local->monitor_type == PRISM2_MONITOR_PRISM) {
@@ -557,7 +555,6 @@
 hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
 		    u16 fc, struct net_device **wds)
 {
-	DECLARE_MAC_BUF(mac);
 	/* FIX: is this really supposed to accept WDS frames only in Master
 	 * mode? What about Repeater or Managed with WDS frames? */
 	if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=
@@ -573,10 +570,10 @@
 	     hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
 		/* RA (or BSSID) is not ours - drop */
 		PDEBUG(DEBUG_EXTRA2, "%s: received WDS frame with "
-		       "not own or broadcast %s=%s\n",
+		       "not own or broadcast %s=%pM\n",
 		       local->dev->name,
 		       fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
-		       print_mac(mac, hdr->addr1));
+		       hdr->addr1);
 		return -1;
 	}
 
@@ -589,8 +586,8 @@
 		/* require that WDS link has been registered with TA or the
 		 * frame is from current AP when using 'AP client mode' */
 		PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
-		       "from unknown TA=%s\n",
-		       local->dev->name, print_mac(mac, hdr->addr2));
+		       "from unknown TA=%pM\n",
+		       local->dev->name, hdr->addr2);
 		if (local->ap && local->ap->autom_ap_wds)
 			hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
 		return -1;
@@ -667,10 +664,8 @@
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       local->dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+			       "received packet from %pM\n",
+			       local->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -679,12 +674,8 @@
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
-		printk(KERN_DEBUG "%s: decryption failed (SA=" MAC_FMT
-		       ") res=%d\n",
-		       local->dev->name,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
-		       res);
+		printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n",
+		       local->dev->name, hdr->addr2, res);
 		local->comm_tallies.rx_discards_wep_undecryptable++;
 		return -1;
 	}
@@ -700,7 +691,6 @@
 {
 	struct ieee80211_hdr_4addr *hdr;
 	int res, hdrlen;
-	DECLARE_MAC_BUF(mac);
 
 	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 		return 0;
@@ -713,8 +703,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=%s keyidx=%d)\n",
-		       local->dev->name, print_mac(mac, hdr->addr2), keyidx);
+		       " (SA=%pM keyidx=%d)\n",
+		       local->dev->name, hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -822,10 +812,8 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			printk(KERN_DEBUG "%s: WEP decryption failed (not set)"
-			       " (SA=" MAC_FMT ")\n",
-			       local->dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+			       " (SA=%pM)\n",
+			       local->dev->name, hdr->addr2);
 #endif
 			local->comm_tallies.rx_discards_wep_undecryptable++;
 			goto rx_dropped;
@@ -839,9 +827,7 @@
 		    (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
 		{
 			printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
-			       "from " MAC_FMT "\n", dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+			       "from %pM\n", dev->name, hdr->addr2);
 			/* TODO: could inform hostapd about this so that it
 			 * could send auth failure report */
 			goto rx_dropped;
@@ -896,8 +882,6 @@
 		from_assoc_ap = 1;
 	}
 
-	dev->last_rx = jiffies;
-
 	if ((local->iw_mode == IW_MODE_MASTER ||
 	     local->iw_mode == IW_MODE_REPEAT) &&
 	    !from_assoc_ap) {
@@ -1009,10 +993,8 @@
 			       "unencrypted EAPOL frame\n", local->dev->name);
 		} else {
 			printk(KERN_DEBUG "%s: encryption configured, but RX "
-			       "frame not encrypted (SA=" MAC_FMT ")\n",
-			       local->dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+			       "frame not encrypted (SA=%pM)\n",
+			       local->dev->name, hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -1021,10 +1003,8 @@
 	    !hostap_is_eapol_frame(local, skb)) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: dropped unencrypted RX data "
-			       "frame from " MAC_FMT " (drop_unencrypted=1)\n",
-			       dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+			       "frame from %pM (drop_unencrypted=1)\n",
+			       dev->name, hdr->addr2);
 		}
 		goto rx_dropped;
 	}
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 921c984..0752471 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -17,7 +17,6 @@
 {
 	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
-	DECLARE_MAC_BUF(mac);
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
@@ -41,11 +40,11 @@
 	printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
 	       le16_to_cpu(hdr->seq_ctl));
 
-	printk(KERN_DEBUG "   A1=%s", print_mac(mac, hdr->addr1));
-	printk(" A2=%s", print_mac(mac, hdr->addr2));
-	printk(" A3=%s", print_mac(mac, hdr->addr3));
+	printk(KERN_DEBUG "   A1=%pM", hdr->addr1);
+	printk(" A2=%pM", hdr->addr2);
+	printk(" A3=%pM", hdr->addr3);
 	if (skb->len >= 30)
-		printk(" A4=%s", print_mac(mac, hdr->addr4));
+		printk(" A4=%pM", hdr->addr4);
 	printk("\n");
 }
 
@@ -328,10 +327,8 @@
 		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       local->dev->name,
-			       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-			       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+			       "TX packet to %pM\n",
+			       local->dev->name, hdr->addr1);
 		}
 		kfree_skb(skb);
 		return NULL;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index af3d4ef..dec3dbe 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -94,7 +94,6 @@
 static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
 {
 	struct sta_info *s;
-	DECLARE_MAC_BUF(mac);
 
 	s = ap->sta_hash[STA_HASH(sta->addr)];
 	if (s == NULL) return;
@@ -109,20 +108,18 @@
 	if (s->hnext != NULL)
 		s->hnext = s->hnext->hnext;
 	else
-		printk("AP: could not remove STA %s"
-		       " from hash table\n",
-		       print_mac(mac, sta->addr));
+		printk("AP: could not remove STA %pM from hash table\n",
+		       sta->addr);
 }
 
 static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
 {
-	DECLARE_MAC_BUF(mac);
 	if (sta->ap && sta->local)
 		hostap_event_expired_sta(sta->local->dev, sta);
 
 	if (ap->proc != NULL) {
 		char name[20];
-		sprintf(name, "%s", print_mac(mac, sta->addr));
+		sprintf(name, "%pM", sta->addr);
 		remove_proc_entry(name, ap->proc);
 	}
 
@@ -185,7 +182,6 @@
 	struct ap_data *ap;
 	unsigned long next_time = 0;
 	int was_assoc;
-	DECLARE_MAC_BUF(mac);
 
 	if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) {
 		PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n");
@@ -242,8 +238,8 @@
 	if (sta->ap) {
 		if (ap->autom_ap_wds) {
 			PDEBUG(DEBUG_AP, "%s: removing automatic WDS "
-			       "connection to AP %s\n",
-			       local->dev->name, print_mac(mac, sta->addr));
+			       "connection to AP %pM\n",
+			       local->dev->name, sta->addr);
 			hostap_wds_link_oper(local, sta->addr, WDS_DEL);
 		}
 	} else if (sta->timeout_next == STA_NULLFUNC) {
@@ -259,11 +255,11 @@
 	} else {
 		int deauth = sta->timeout_next == STA_DEAUTH;
 		__le16 resp;
-		PDEBUG(DEBUG_AP, "%s: sending %s info to STA %s"
+		PDEBUG(DEBUG_AP, "%s: sending %s info to STA %pM"
 		       "(last=%lu, jiffies=%lu)\n",
 		       local->dev->name,
 		       deauth ? "deauthentication" : "disassociation",
-		       print_mac(mac, sta->addr), sta->last_rx, jiffies);
+		       sta->addr, sta->last_rx, jiffies);
 
 		resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID :
 				   WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
@@ -275,10 +271,10 @@
 
 	if (sta->timeout_next == STA_DEAUTH) {
 		if (sta->flags & WLAN_STA_PERM) {
-			PDEBUG(DEBUG_AP, "%s: STA %s"
+			PDEBUG(DEBUG_AP, "%s: STA %pM"
 			       " would have been removed, "
 			       "but it has 'perm' flag\n",
-			       local->dev->name, print_mac(mac, sta->addr));
+			       local->dev->name, sta->addr);
 		} else
 			ap_free_sta(ap, sta);
 		return;
@@ -332,7 +328,6 @@
 	struct ap_data *ap = (struct ap_data *) data;
 	char *policy_txt;
 	struct mac_entry *entry;
-	DECLARE_MAC_BUF(mac);
 
 	if (off != 0) {
 		*eof = 1;
@@ -363,7 +358,7 @@
 			break;
 		}
 
-		p += sprintf(p, "%s\n", print_mac(mac, entry->addr));
+		p += sprintf(p, "%pM\n", entry->addr);
 	}
 	spin_unlock_bh(&ap->mac_restrictions.lock);
 
@@ -520,7 +515,6 @@
 	struct ap_data *ap = (struct ap_data *) data;
 	struct sta_info *sta;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	if (off > PROC_LIMIT) {
 		*eof = 1;
@@ -533,8 +527,8 @@
 		if (!sta->ap)
 			continue;
 
-		p += sprintf(p, "%s %d %d %d %d '",
-			     print_mac(mac, sta->addr),
+		p += sprintf(p, "%pM %d %d %d %d '",
+			     sta->addr,
 			     sta->u.ap.channel, sta->last_rx_signal,
 			     sta->last_rx_silence, sta->last_rx_rate);
 		for (i = 0; i < sta->u.ap.ssid_len; i++)
@@ -683,11 +677,9 @@
 	if (sta)
 		atomic_dec(&sta->users);
 	if (txt) {
-		PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth_cb - alg=%d "
+		PDEBUG(DEBUG_AP, "%s: %pM auth_cb - alg=%d "
 		       "trans#=%d status=%d - %s\n",
-		       dev->name,
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
+		       dev->name, hdr->addr1,
 		       auth_alg, auth_transaction, status, txt);
 	}
 	dev_kfree_skb(skb);
@@ -754,11 +746,8 @@
 	if (sta)
 		atomic_dec(&sta->users);
 	if (txt) {
-		PDEBUG(DEBUG_AP, "%s: " MAC_FMT " assoc_cb - %s\n",
-		       dev->name,
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
-		       txt);
+		PDEBUG(DEBUG_AP, "%s: %pM assoc_cb - %s\n",
+		       dev->name, hdr->addr1, txt);
 	}
 	dev_kfree_skb(skb);
 }
@@ -781,11 +770,9 @@
 			sta->flags &= ~WLAN_STA_PENDING_POLL;
 		spin_unlock(&ap->sta_table_lock);
 	} else {
-		PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
-		       " did not ACK activity poll frame\n",
-		       ap->local->dev->name,
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+		PDEBUG(DEBUG_AP,
+		       "%s: STA %pM did not ACK activity poll frame\n",
+		       ap->local->dev->name, hdr->addr1);
 	}
 
  fail:
@@ -1002,7 +989,6 @@
 	char *p = page;
 	struct sta_info *sta = (struct sta_info *) data;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	/* FIX: possible race condition.. the STA data could have just expired,
 	 * but proc entry was still here so that the read could have started;
@@ -1013,11 +999,11 @@
 		return 0;
 	}
 
-	p += sprintf(p, "%s=%s\nusers=%d\naid=%d\n"
+	p += sprintf(p, "%s=%pM\nusers=%d\naid=%d\n"
 		     "flags=0x%04x%s%s%s%s%s%s%s\n"
 		     "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
 		     sta->ap ? "AP" : "STA",
-		     print_mac(mac, sta->addr), atomic_read(&sta->users), sta->aid,
+		     sta->addr, atomic_read(&sta->users), sta->aid,
 		     sta->flags,
 		     sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
 		     sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
@@ -1078,7 +1064,6 @@
 	struct sta_info *sta;
 	char name[20];
 	struct add_sta_proc_data *entry, *prev;
-	DECLARE_MAC_BUF(mac);
 
 	entry = ap->add_sta_proc_entries;
 	ap->add_sta_proc_entries = NULL;
@@ -1091,7 +1076,7 @@
 		spin_unlock_bh(&ap->sta_table_lock);
 
 		if (sta) {
-			sprintf(name, "%s", print_mac(mac, sta->addr));
+			sprintf(name, "%pM", sta->addr);
 			sta->proc = create_proc_read_entry(
 				name, 0, ap->proc,
 				prism2_sta_proc_read, sta);
@@ -1318,9 +1303,7 @@
 
 	if (len < 6) {
 		PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "
-		       "(len=%d) from " MAC_FMT "\n", dev->name, len,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+		       "(len=%d) from %pM\n", dev->name, len, hdr->addr2);
 		return;
 	}
 
@@ -1385,10 +1368,8 @@
 		if (time_after(jiffies, sta->u.ap.last_beacon +
 			       (10 * sta->listen_interval * HZ) / 1024)) {
 			PDEBUG(DEBUG_AP, "%s: no beacons received for a while,"
-			       " assuming AP " MAC_FMT " is now STA\n",
-			       dev->name,
-			       sta->addr[0], sta->addr[1], sta->addr[2],
-			       sta->addr[3], sta->addr[4], sta->addr[5]);
+			       " assuming AP %pM is now STA\n",
+			       dev->name, sta->addr);
 			sta->ap = 0;
 			sta->flags = 0;
 			sta->u.sta.challenge = NULL;
@@ -1503,11 +1484,9 @@
 	}
 
 	if (resp) {
-		PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth (alg=%d "
+		PDEBUG(DEBUG_AP, "%s: %pM auth (alg=%d "
 		       "trans#=%d stat=%d len=%d fc=%04x) ==> %d (%s)\n",
-		       dev->name,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+		       dev->name, hdr->addr2,
 		       auth_alg, auth_transaction, status_code, len,
 		       fc, resp, txt);
 	}
@@ -1533,10 +1512,8 @@
 
 	if (len < (reassoc ? 10 : 4)) {
 		PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload "
-		       "(len=%d, reassoc=%d) from " MAC_FMT "\n",
-		       dev->name, len, reassoc,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+		       "(len=%d, reassoc=%d) from %pM\n",
+		       dev->name, len, reassoc, hdr->addr2);
 		return;
 	}
 
@@ -1613,12 +1590,9 @@
 		}
 
 		if (left > 0) {
-			PDEBUG(DEBUG_AP, "%s: assoc from " MAC_FMT
+			PDEBUG(DEBUG_AP, "%s: assoc from %pM"
 			       " with extra data (%d bytes) [",
-			       dev->name,
-			       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-			       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
-			       left);
+			       dev->name, hdr->addr2, left);
 			while (left > 0) {
 				PDEBUG2(DEBUG_AP, "<%02x>", *u);
 				u++; left--;
@@ -1717,14 +1691,12 @@
 	}
 
 #if 0
-	PDEBUG(DEBUG_AP, "%s: " MAC_FMT" %sassoc (len=%d "
-	       "prev_ap=" MAC_FMT") => %d(%d) (%s)\n",
+	PDEBUG(DEBUG_AP, "%s: %pM %sassoc (len=%d "
+	       "prev_ap=%pM) => %d(%d) (%s)\n",
 	       dev->name,
-	       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-	       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+	       hdr->addr2,
 	       reassoc ? "re" : "", len,
-	       prev_ap[0], prev_ap[1], prev_ap[2],
-	       prev_ap[3], prev_ap[4], prev_ap[5],
+	       prev_ap,
 	       resp, send_deauth, txt);
 #endif
 }
@@ -1741,7 +1713,6 @@
 	u16 reason_code;
 	__le16 *pos;
 	struct sta_info *sta = NULL;
-	DECLARE_MAC_BUF(mac);
 
 	len = skb->len - IEEE80211_MGMT_HDR_LEN;
 
@@ -1753,10 +1724,8 @@
 	pos = (__le16 *) body;
 	reason_code = le16_to_cpu(*pos);
 
-	PDEBUG(DEBUG_AP, "%s: deauthentication: " MAC_FMT " len=%d, "
-	       "reason_code=%d\n", dev->name,
-	       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-	       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+	PDEBUG(DEBUG_AP, "%s: deauthentication: %pM len=%d, "
+	       "reason_code=%d\n", dev->name, hdr->addr2,
 	       len, reason_code);
 
 	spin_lock_bh(&local->ap->sta_table_lock);
@@ -1768,11 +1737,9 @@
 	}
 	spin_unlock_bh(&local->ap->sta_table_lock);
 	if (sta == NULL) {
-		printk("%s: deauthentication from " MAC_FMT ", "
+		printk("%s: deauthentication from %pM, "
 	       "reason_code=%d, but STA not authenticated\n", dev->name,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
-		       reason_code);
+		       hdr->addr2, reason_code);
 	}
 }
 
@@ -1799,10 +1766,8 @@
 	pos = (__le16 *) body;
 	reason_code = le16_to_cpu(*pos);
 
-	PDEBUG(DEBUG_AP, "%s: disassociation: " MAC_FMT " len=%d, "
-	       "reason_code=%d\n", dev->name,
-	       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-	       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+	PDEBUG(DEBUG_AP, "%s: disassociation: %pM len=%d, "
+	       "reason_code=%d\n", dev->name, hdr->addr2,
 	       len, reason_code);
 
 	spin_lock_bh(&local->ap->sta_table_lock);
@@ -1814,12 +1779,9 @@
 	}
 	spin_unlock_bh(&local->ap->sta_table_lock);
 	if (sta == NULL) {
-		printk("%s: disassociation from " MAC_FMT ", "
+		printk("%s: disassociation from %pM, "
 		       "reason_code=%d, but STA not authenticated\n",
-		       dev->name,
-		       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-		       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
-		       reason_code);
+		       dev->name, hdr->addr2, reason_code);
 	}
 }
 
@@ -1909,19 +1871,14 @@
 	u16 aid;
 	struct sk_buff *skb;
 
-	PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MAC_FMT
-	       ", TA=" MAC_FMT " PWRMGT=%d\n",
-	       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-	       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
-	       hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
-	       hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+	PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%pM, TA=%pM PWRMGT=%d\n",
+	       hdr->addr1, hdr->addr2,
 	       !!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM));
 
 	if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
-		PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MAC_FMT
-		       " not own MAC\n",
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+		PDEBUG(DEBUG_AP,
+		       "handle_pspoll - addr1(BSSID)=%pM not own MAC\n",
+		       hdr->addr1);
 		return;
 	}
 
@@ -2007,11 +1964,10 @@
 
 	while (entry) {
 		PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection "
-		       "to AP " MAC_FMT "\n",
+		       "to AP %pM\n",
 		       local->dev->name,
 		       entry->type == WDS_ADD ? "adding" : "removing",
-		       entry->addr[0], entry->addr[1], entry->addr[2],
-		       entry->addr[3], entry->addr[4], entry->addr[5]);
+		       entry->addr);
 		if (entry->type == WDS_ADD)
 			prism2_wds_add(local, entry->addr, 0);
 		else if (entry->type == WDS_DEL)
@@ -2215,10 +2171,8 @@
 		}
 
 		if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
-			PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)="
-			       MAC_FMT " not own MAC\n",
-			       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-			       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+			PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=%pM"
+			       " not own MAC\n", hdr->addr1);
 			goto done;
 		}
 
@@ -2254,18 +2208,14 @@
 	}
 
 	if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
-		PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MAC_FMT
-		       " not own MAC\n",
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+		PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=%pM"
+		       " not own MAC\n", hdr->addr1);
 		goto done;
 	}
 
 	if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) {
-		PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MAC_FMT
-		       " not own MAC\n",
-		       hdr->addr3[0], hdr->addr3[1], hdr->addr3[2],
-		       hdr->addr3[3], hdr->addr3[4], hdr->addr3[5]);
+		PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=%pM"
+		       " not own MAC\n", hdr->addr3);
 		goto done;
 	}
 
@@ -2366,10 +2316,9 @@
 	memcpy(hdr->addr2, sta->addr, ETH_ALEN);
 	hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14));
 
-	PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for STA "
-	       MAC_FMT "\n", local->dev->name,
-	       sta->addr[0], sta->addr[1], sta->addr[2],
-	       sta->addr[3], sta->addr[4], sta->addr[5]);
+	PDEBUG(DEBUG_PS2,
+	       "%s: Scheduling buffered packet delivery for STA %pM\n",
+	       local->dev->name, sta->addr);
 
 	skb->dev = local->dev;
 
@@ -2723,12 +2672,8 @@
 			case 3: sta->tx_rate = 110; break;
 			default: sta->tx_rate = 0; break;
 			}
-			PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
-			       " TX rate raised to %d\n",
-			       dev->name,
-			       sta->addr[0], sta->addr[1], sta->addr[2],
-			       sta->addr[3], sta->addr[4], sta->addr[5],
-			       sta->tx_rate);
+			PDEBUG(DEBUG_AP, "%s: STA %pM TX rate raised to %d\n",
+			       dev->name, sta->addr, sta->tx_rate);
 		}
 		sta->tx_since_last_failure = 0;
 	}
@@ -2781,9 +2726,7 @@
 		 * print out any errors here. */
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "AP: drop packet to non-associated "
-			       "STA " MAC_FMT "\n",
-			       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-			       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+			       "STA %pM\n", hdr->addr1);
 		}
 #endif
 		local->ap->tx_drop_nonassoc++;
@@ -2821,11 +2764,9 @@
 	}
 
 	if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) {
-		PDEBUG(DEBUG_PS, "%s: No more space in STA (" MAC_FMT
-		       ")'s PS mode buffer\n",
-		       local->dev->name,
-		       sta->addr[0], sta->addr[1], sta->addr[2],
-		       sta->addr[3], sta->addr[4], sta->addr[5]);
+		PDEBUG(DEBUG_PS, "%s: No more space in STA (%pM)'s"
+		       "PS mode buffer\n",
+		       local->dev->name, sta->addr);
 		/* Make sure that TIM is set for the station (it might not be
 		 * after AP wlan hw reset). */
 		/* FIX: should fix hw reset to restore bits based on STA
@@ -2897,12 +2838,9 @@
 	sta = ap_get_sta(local->ap, hdr->addr1);
 	if (!sta) {
 		spin_unlock(&local->ap->sta_table_lock);
-		PDEBUG(DEBUG_AP, "%s: Could not find STA " MAC_FMT
+		PDEBUG(DEBUG_AP, "%s: Could not find STA %pM"
 		       " for this TX error (@%lu)\n",
-		       local->dev->name,
-		       hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
-		       hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
-		       jiffies);
+		       local->dev->name, hdr->addr1, jiffies);
 		return;
 	}
 
@@ -2929,12 +2867,9 @@
 			case 3: sta->tx_rate = 110; break;
 			default: sta->tx_rate = 0; break;
 			}
-			PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
-			       " TX rate lowered to %d\n",
-			       local->dev->name,
-			       sta->addr[0], sta->addr[1], sta->addr[2],
-			       sta->addr[3], sta->addr[4], sta->addr[5],
-			       sta->tx_rate);
+			PDEBUG(DEBUG_AP,
+			       "%s: STA %pM TX rate lowered to %d\n",
+			       local->dev->name, sta->addr, sta->tx_rate);
 		}
 		sta->tx_consecutive_exc = 0;
 	}
@@ -2945,17 +2880,16 @@
 static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
 				  int pwrmgt, int type, int stype)
 {
-	DECLARE_MAC_BUF(mac);
 	if (pwrmgt && !(sta->flags & WLAN_STA_PS)) {
 		sta->flags |= WLAN_STA_PS;
-		PDEBUG(DEBUG_PS2, "STA %s changed to use PS "
+		PDEBUG(DEBUG_PS2, "STA %pM changed to use PS "
 		       "mode (type=0x%02X, stype=0x%02X)\n",
-		       print_mac(mac, sta->addr), type >> 2, stype >> 4);
+		       sta->addr, type >> 2, stype >> 4);
 	} else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) {
 		sta->flags &= ~WLAN_STA_PS;
-		PDEBUG(DEBUG_PS2, "STA %s changed to not use "
+		PDEBUG(DEBUG_PS2, "STA %pM changed to not use "
 		       "PS mode (type=0x%02X, stype=0x%02X)\n",
-		       print_mac(mac, sta->addr), type >> 2, stype >> 4);
+		       sta->addr, type >> 2, stype >> 4);
 		if (type != IEEE80211_FTYPE_CTL ||
 		    stype != IEEE80211_STYPE_PSPOLL)
 			schedule_packet_send(local, sta);
@@ -3029,13 +2963,9 @@
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
 			} else {
 				printk(KERN_DEBUG "%s: dropped received packet"
-				       " from non-associated STA "
-				       MAC_FMT
+				       " from non-associated STA %pM"
 				       " (type=0x%02x, subtype=0x%02x)\n",
-				       dev->name,
-				       hdr->addr2[0], hdr->addr2[1],
-				       hdr->addr2[2], hdr->addr2[3],
-				       hdr->addr2[4], hdr->addr2[5],
+				       dev->name, hdr->addr2,
 				       type >> 2, stype >> 4);
 				hostap_rx(dev, skb, rx_stats);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
@@ -3068,13 +2998,9 @@
 			 * after being unavailable for some time. Speed up
 			 * re-association by informing the station about it not
 			 * being associated. */
-			printk(KERN_DEBUG "%s: rejected received nullfunc "
-			       "frame without ToDS from not associated STA "
-			       MAC_FMT "\n",
-			       dev->name,
-			       hdr->addr2[0], hdr->addr2[1],
-			       hdr->addr2[2], hdr->addr2[3],
-			       hdr->addr2[4], hdr->addr2[5]);
+			printk(KERN_DEBUG "%s: rejected received nullfunc frame"
+			       " without ToDS from not associated STA %pM\n",
+			       dev->name, hdr->addr2);
 			hostap_rx(dev, skb, rx_stats);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 		}
@@ -3090,13 +3016,10 @@
 		 * broadcast frame from an IBSS network. Drop it silently.
 		 * If BSSID is own, report the dropping of this frame. */
 		if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
-			printk(KERN_DEBUG "%s: dropped received packet from "
-			       MAC_FMT " with no ToDS flag "
+			printk(KERN_DEBUG "%s: dropped received packet from %pM"
+			       " with no ToDS flag "
 			       "(type=0x%02x, subtype=0x%02x)\n", dev->name,
-			       hdr->addr2[0], hdr->addr2[1],
-			       hdr->addr2[2], hdr->addr2[3],
-			       hdr->addr2[4], hdr->addr2[5],
-			       type >> 2, stype >> 4);
+			       hdr->addr2, type >> 2, stype >> 4);
 			hostap_dump_rx_80211(dev->name, skb, rx_stats);
 		}
 		ret = AP_RX_DROP;
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index b470c74..90b64b0 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -6,19 +6,6 @@
 
 /* IEEE 802.11 defines */
 
-/* Information Element IDs */
-#define WLAN_EID_SSID 0
-#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
-#define WLAN_EID_DS_PARAMS 3
-#define WLAN_EID_CF_PARAMS 4
-#define WLAN_EID_TIM 5
-#define WLAN_EID_IBSS_PARAMS 6
-#define WLAN_EID_CHALLENGE 16
-#define WLAN_EID_RSN 48
-#define WLAN_EID_GENERIC 221
-
-
 /* HFA384X Configuration RIDs */
 #define HFA384X_RID_CNFPORTTYPE 0xFC00
 #define HFA384X_RID_CNFOWNMACADDR 0xFC01
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 3153fe9..fd7f7ce 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2335,10 +2335,6 @@
 	int show_dump, res;
 	char *payload = NULL;
 	struct hfa384x_tx_frame txdesc;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
-	DECLARE_MAC_BUF(mac4);
 
 	show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR;
 	local->stats.tx_errors++;
@@ -2404,9 +2400,9 @@
 	       WLAN_FC_GET_STYPE(fc) >> 4,
 	       fc & IEEE80211_FCTL_TODS ? " ToDS" : "",
 	       fc & IEEE80211_FCTL_FROMDS ? " FromDS" : "");
-	PDEBUG(DEBUG_EXTRA, "   A1=%s A2=%s A3=%s A4=%s\n",
-	       print_mac(mac, txdesc.addr1), print_mac(mac2, txdesc.addr2),
-	       print_mac(mac3, txdesc.addr3), print_mac(mac4, txdesc.addr4));
+	PDEBUG(DEBUG_EXTRA, "   A1=%pM A2=%pM A3=%pM A4=%pM\n",
+	       txdesc.addr1, txdesc.addr2,
+	       txdesc.addr3, txdesc.addr4);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 7cd3fb7..99b4cf4 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -166,7 +166,6 @@
 	struct hfa384x_hostscan_result *selected, *entry;
 	int i;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	if (local->last_join_time &&
 	    time_before(jiffies, local->last_join_time + 10 * HZ)) {
@@ -199,9 +198,8 @@
 	    local->preferred_ap[2] || local->preferred_ap[3] ||
 	    local->preferred_ap[4] || local->preferred_ap[5]) {
 		/* Try to find preferred AP */
-		PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID "
-		       "%s\n",
-		       dev->name, print_mac(mac, local->preferred_ap));
+		PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID %pM\n",
+		       dev->name, local->preferred_ap);
 		for (i = 0; i < local->last_scan_results_count; i++) {
 			entry = &local->last_scan_results[i];
 			if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
@@ -218,9 +216,9 @@
 	req.channel = selected->chid;
 	spin_unlock_irqrestore(&local->lock, flags);
 
-	PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%s"
+	PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%pM"
 	       " channel=%d\n",
-	       dev->name, print_mac(mac, req.bssid), le16_to_cpu(req.channel));
+	       dev->name, req.bssid, le16_to_cpu(req.channel));
 	if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
 				 sizeof(req))) {
 		printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
@@ -413,7 +411,6 @@
 	int val = local->prev_link_status;
 	int connected;
 	union iwreq_data wrqu;
-	DECLARE_MAC_BUF(mac);
 
 	connected =
 		val == HFA384X_LINKSTATUS_CONNECTED ||
@@ -425,10 +422,9 @@
 		printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
 		       "LinkStatus event\n", local->dev->name);
 	} else {
-		PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID="
-		       "%s\n",
+		PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=%pM\n",
 		       local->dev->name,
-		       print_mac(mac, (unsigned char *) local->bssid));
+		       (unsigned char *) local->bssid);
 		if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
 			hostap_add_sta(local->ap, local->bssid);
 	}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 3f8b1d7..2318c5d 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -664,7 +664,6 @@
 	unsigned long flags;
 	int i;
 	struct hfa384x_hostscan_result *entry;
-	DECLARE_MAC_BUF(mac);
 
 	iface = netdev_priv(dev);
 	local = iface->local;
@@ -686,14 +685,13 @@
 
 	if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
 				 sizeof(req))) {
-		printk(KERN_DEBUG "%s: JoinRequest %s"
-		       " failed\n",
-		       dev->name, print_mac(mac, local->preferred_ap));
+		printk(KERN_DEBUG "%s: JoinRequest %pM failed\n",
+		       dev->name, local->preferred_ap);
 		return -1;
 	}
 
-	printk(KERN_DEBUG "%s: Trying to join BSSID %s\n",
-	       dev->name, print_mac(mac, local->preferred_ap));
+	printk(KERN_DEBUG "%s: Trying to join BSSID %pM\n",
+	       dev->name, local->preferred_ap);
 
 	return 0;
 }
@@ -3701,10 +3699,8 @@
 					  struct prism2_hostapd_param *param,
 					  int param_len)
 {
-	DECLARE_MAC_BUF(mac);
-	printk(KERN_DEBUG "%ssta: associated as client with AP "
-	       "%s\n",
-	       local->dev->name, print_mac(mac, param->sta_addr));
+	printk(KERN_DEBUG "%ssta: associated as client with AP %pM\n",
+	       local->dev->name, param->sta_addr);
 	memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
 	return 0;
 }
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 756ab56..4c36eb2 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -530,10 +530,6 @@
 void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
 {
 	u16 status, fc;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
-	DECLARE_MAC_BUF(mac4);
 
 	status = __le16_to_cpu(rx->status);
 
@@ -552,12 +548,11 @@
 	       fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
 	       fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
 
-	printk(KERN_DEBUG "   A1=%s A2=%s A3=%s A4=%s\n",
-	       print_mac(mac, rx->addr1), print_mac(mac2, rx->addr2),
-	       print_mac(mac3, rx->addr3), print_mac(mac4, rx->addr4));
+	printk(KERN_DEBUG "   A1=%pM A2=%pM A3=%pM A4=%pM\n",
+	       rx->addr1, rx->addr2, rx->addr3, rx->addr4);
 
-	printk(KERN_DEBUG "   dst=%s src=%s len=%d\n",
-	       print_mac(mac, rx->dst_addr), print_mac(mac2, rx->src_addr),
+	printk(KERN_DEBUG "   dst=%pM src=%pM len=%d\n",
+	       rx->dst_addr, rx->src_addr,
 	       __be16_to_cpu(rx->len));
 }
 
@@ -565,10 +560,6 @@
 void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
 {
 	u16 fc;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
-	DECLARE_MAC_BUF(mac4);
 
 	printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d "
 	       "tx_control=0x%04x; jiffies=%ld\n",
@@ -584,12 +575,11 @@
 	       fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
 	       fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
 
-	printk(KERN_DEBUG "   A1=%s A2=%s A3=%s A4=%s\n",
-	       print_mac(mac, tx->addr1), print_mac(mac2, tx->addr2),
-	       print_mac(mac3, tx->addr3), print_mac(mac4, tx->addr4));
+	printk(KERN_DEBUG "   A1=%pM A2=%pM A3=%pM A4=%pM\n",
+	       tx->addr1, tx->addr2, tx->addr3, tx->addr4);
 
-	printk(KERN_DEBUG "   dst=%s src=%s len=%d\n",
-	       print_mac(mac, tx->dst_addr), print_mac(mac2, tx->src_addr),
+	printk(KERN_DEBUG "   dst=%pM src=%pM len=%d\n",
+	       tx->dst_addr, tx->src_addr,
 	       __be16_to_cpu(tx->len));
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 3a874fc..8fdd41f 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -312,7 +312,7 @@
 		goto err_out_disable;
 	}
 
-	mem = ioremap(phymem, pci_resource_len(pdev, 0));
+	mem = pci_ioremap_bar(pdev, 0);
 	if (mem == NULL) {
 		printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
 		goto fail;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index b035360..ae7d3ca 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -106,7 +106,6 @@
 	local_info_t *local = (local_info_t *) data;
 	struct list_head *ptr;
 	struct hostap_interface *iface;
-	DECLARE_MAC_BUF(mac);
 
 	if (off > PROC_LIMIT) {
 		*eof = 1;
@@ -118,9 +117,9 @@
 		iface = list_entry(ptr, struct hostap_interface, list);
 		if (iface->type != HOSTAP_INTERFACE_WDS)
 			continue;
-		p += sprintf(p, "%s\t%s\n",
+		p += sprintf(p, "%s\t%pM\n",
 			     iface->dev->name,
-			     print_mac(mac, iface->u.wds.remote_addr));
+			     iface->u.wds.remote_addr);
 		if ((p - page) > PROC_LIMIT) {
 			printk(KERN_DEBUG "%s: wds proc did not fit\n",
 			       local->dev->name);
@@ -148,7 +147,6 @@
 	struct list_head *ptr;
 	struct hostap_bss_info *bss;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	if (off > PROC_LIMIT) {
 		*eof = 1;
@@ -160,8 +158,8 @@
 	spin_lock_bh(&local->lock);
 	list_for_each(ptr, &local->bss_list) {
 		bss = list_entry(ptr, struct hostap_bss_info, list);
-		p += sprintf(p, "%s\t%lu\t%u\t0x%x\t",
-			     print_mac(mac, bss->bssid), bss->last_update,
+		p += sprintf(p, "%pM\t%lu\t%u\t0x%x\t",
+			     bss->bssid, bss->last_update,
 			     bss->count, bss->capab_info);
 		for (i = 0; i < bss->ssid_len; i++) {
 			p += sprintf(p, "%c",
@@ -314,7 +312,6 @@
 	int entry, i, len, total = 0;
 	struct hfa384x_hostscan_result *scanres;
 	u8 *pos;
-	DECLARE_MAC_BUF(mac);
 
 	p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
 		     "SSID\n");
@@ -332,14 +329,14 @@
 		if ((p - page) > (PAGE_SIZE - 200))
 			break;
 
-		p += sprintf(p, "%d %d %d %d 0x%02x %d %s %d ",
+		p += sprintf(p, "%d %d %d %d 0x%02x %d %pM %d ",
 			     le16_to_cpu(scanres->chid),
 			     (s16) le16_to_cpu(scanres->anl),
 			     (s16) le16_to_cpu(scanres->sl),
 			     le16_to_cpu(scanres->beacon_interval),
 			     le16_to_cpu(scanres->capability),
 			     le16_to_cpu(scanres->rate),
-			     print_mac(mac, scanres->bssid),
+			     scanres->bssid,
 			     le16_to_cpu(scanres->atim));
 
 		pos = scanres->sup_rates;
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index ffdf487..8431030 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -822,7 +822,7 @@
 	int last_scan_results_count;
 	enum { PRISM2_SCAN, PRISM2_HOSTSCAN } last_scan_type;
 	struct work_struct info_queue;
-	long pending_info; /* bit field of pending info_queue items */
+	unsigned long pending_info; /* bit field of pending info_queue items */
 #define PRISM2_INFO_PENDING_LINKSTATUS 0
 #define PRISM2_INFO_PENDING_SCANRESULTS 1
 	int prev_link_status; /* previous received LinkStatus info */
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index bca7481..062c9f2 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -163,6 +163,8 @@
 #include <linux/ctype.h>
 #include <linux/pm_qos_params.h>
 
+#include <net/lib80211.h>
+
 #include "ipw2100.h"
 
 #define IPW2100_VERSION "git-1.2.2"
@@ -185,7 +187,7 @@
 static int debug = 0;
 static int mode = 0;
 static int channel = 0;
-static int associate = 1;
+static int associate = 0;
 static int disable = 0;
 #ifdef CONFIG_PM
 static struct ipw2100_fw ipw2100_firmware;
@@ -201,7 +203,7 @@
 MODULE_PARM_DESC(debug, "debug level");
 MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
 MODULE_PARM_DESC(channel, "channel");
-MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default off)");
 MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 
 static u32 ipw2100_debug_level = IPW_DL_NONE;
@@ -1914,7 +1916,7 @@
 	u32 chan;
 	char *txratename;
 	u8 bssid[ETH_ALEN];
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	/*
 	 * TBD: BSSID is usually 00:00:00:00:00:00 here and not
@@ -1975,10 +1977,9 @@
 		break;
 	}
 
-	IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="
-		       "%s)\n",
-		       priv->net_dev->name, escape_essid(essid, essid_len),
-		       txratename, chan, print_mac(mac, bssid));
+	IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
+		       priv->net_dev->name, print_ssid(ssid, essid, essid_len),
+		       txratename, chan, bssid);
 
 	/* now we copy read ssid into dev */
 	if (!(priv->config & CFG_STATIC_ESSID)) {
@@ -2004,8 +2005,9 @@
 		.host_command_length = ssid_len
 	};
 	int err;
+	DECLARE_SSID_BUF(ssid);
 
-	IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len));
+	IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
 
 	if (ssid_len)
 		memcpy(cmd.host_command_parameters, essid, ssid_len);
@@ -2046,12 +2048,12 @@
 
 static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
 {
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
-		  "disassociated: '%s' %s \n",
-		  escape_essid(priv->essid, priv->essid_len),
-		  print_mac(mac, priv->bssid));
+		  "disassociated: '%s' %pM \n",
+		  print_ssid(ssid, priv->essid, priv->essid_len),
+		  priv->bssid);
 
 	priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
 
@@ -4058,7 +4060,6 @@
 	char *out = buf;
 	int length;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	if (priv->status & STATUS_RF_KILL_MASK)
 		return 0;
@@ -4086,7 +4087,7 @@
 			       __LINE__);
 
 	out += sprintf(out, "ESSID: %s\n", essid);
-	out += sprintf(out, "BSSID:   %s\n", print_mac(mac, bssid));
+	out += sprintf(out, "BSSID:   %pM\n", bssid);
 	out += sprintf(out, "Channel: %d\n", chan);
 
 	return out - buf;
@@ -4662,7 +4663,6 @@
 {
 	u32 length = ETH_ALEN;
 	u8 addr[ETH_ALEN];
-	DECLARE_MAC_BUF(mac);
 
 	int err;
 
@@ -4673,8 +4673,7 @@
 	}
 
 	memcpy(priv->net_dev->dev_addr, addr, ETH_ALEN);
-	IPW_DEBUG_INFO("card MAC is %s\n",
-		       print_mac(mac, priv->net_dev->dev_addr));
+	IPW_DEBUG_INFO("card MAC is %pM\n", priv->net_dev->dev_addr);
 
 	return 0;
 }
@@ -5053,10 +5052,8 @@
 	int err;
 
 #ifdef CONFIG_IPW2100_DEBUG
-	DECLARE_MAC_BUF(mac);
 	if (bssid != NULL)
-		IPW_DEBUG_HC("MANDATORY_BSSID: %s\n",
-			     print_mac(mac, bssid));
+		IPW_DEBUG_HC("MANDATORY_BSSID: %pM\n", bssid);
 	else
 		IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n");
 #endif
@@ -6905,7 +6902,6 @@
 	static const unsigned char off[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 	};
-	DECLARE_MAC_BUF(mac);
 
 	// sanity checks
 	if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
@@ -6931,8 +6927,7 @@
 
 	err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0);
 
-	IPW_DEBUG_WX("SET BSSID -> %s\n",
-		     print_mac(mac, wrqu->ap_addr.sa_data));
+	IPW_DEBUG_WX("SET BSSID -> %pM\n", wrqu->ap_addr.sa_data);
 
       done:
 	mutex_unlock(&priv->action_mutex);
@@ -6948,7 +6943,6 @@
 	 */
 
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	/* If we are associated, trying to associate, or have a statically
 	 * configured BSSID then return that; otherwise return ANY */
@@ -6958,8 +6952,7 @@
 	} else
 		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
 
-	IPW_DEBUG_WX("Getting WAP BSSID: %s\n",
-		     print_mac(mac, wrqu->ap_addr.sa_data));
+	IPW_DEBUG_WX("Getting WAP BSSID: %pM\n", wrqu->ap_addr.sa_data);
 	return 0;
 }
 
@@ -6971,6 +6964,7 @@
 	char *essid = "";	/* ANY */
 	int length = 0;
 	int err = 0;
+	DECLARE_SSID_BUF(ssid);
 
 	mutex_lock(&priv->action_mutex);
 	if (!(priv->status & STATUS_INITIALIZED)) {
@@ -7000,8 +6994,8 @@
 		goto done;
 	}
 
-	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
-		     length);
+	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
+		     print_ssid(ssid, essid, length), length);
 
 	priv->essid_len = length;
 	memcpy(priv->essid, essid, priv->essid_len);
@@ -7022,12 +7016,13 @@
 	 */
 
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
+	DECLARE_SSID_BUF(ssid);
 
 	/* If we are associated, trying to associate, or have a statically
 	 * configured ESSID then return that; otherwise return ANY */
 	if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
 		IPW_DEBUG_WX("Getting essid: '%s'\n",
-			     escape_essid(priv->essid, priv->essid_len));
+			     print_ssid(ssid, priv->essid, priv->essid_len));
 		memcpy(extra, priv->essid, priv->essid_len);
 		wrqu->essid.length = priv->essid_len;
 		wrqu->essid.flags = 1;	/* active */
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index dcce3542..051ae92 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -87,7 +87,7 @@
 static int mode = 0;
 
 static u32 ipw_debug_level;
-static int associate = 1;
+static int associate;
 static int auto_create = 1;
 static int led = 0;
 static int disable = 0;
@@ -2265,8 +2265,8 @@
 		return -1;
 	}
 
-	IPW_DEBUG_INFO("%s: Setting MAC to %s\n",
-		       priv->net_dev->name, print_mac(mac, mac));
+	IPW_DEBUG_INFO("%s: Setting MAC to %pM\n",
+		       priv->net_dev->name, mac);
 
 	return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
 }
@@ -3812,7 +3812,6 @@
 {
 	struct ipw_station_entry entry;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	for (i = 0; i < priv->num_stations; i++) {
 		if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) {
@@ -3829,7 +3828,7 @@
 	if (i == MAX_STATIONS)
 		return IPW_INVALID_STATION;
 
-	IPW_DEBUG_SCAN("Adding AdHoc station: %s\n", print_mac(mac, bssid));
+	IPW_DEBUG_SCAN("Adding AdHoc station: %pM\n", bssid);
 
 	entry.reserved = 0;
 	entry.support_mode = 0;
@@ -3856,7 +3855,6 @@
 static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
 {
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	if (priv->status & STATUS_ASSOCIATING) {
 		IPW_DEBUG_ASSOC("Disassociating while associating.\n");
@@ -3869,9 +3867,9 @@
 		return;
 	}
 
-	IPW_DEBUG_ASSOC("Disassocation attempt from %s "
+	IPW_DEBUG_ASSOC("Disassocation attempt from %pM "
 			"on channel %d.\n",
-			print_mac(mac, priv->assoc_request.bssid),
+			priv->assoc_request.bssid,
 			priv->assoc_request.channel);
 
 	priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
@@ -4397,7 +4395,7 @@
 static void ipw_rx_notification(struct ipw_priv *priv,
 				       struct ipw_rx_notification *notif)
 {
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 	u16 size = le16_to_cpu(notif->size);
 	notif->size = le16_to_cpu(notif->size);
 
@@ -4411,11 +4409,10 @@
 			case CMAS_ASSOCIATED:{
 					IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
 						  IPW_DL_ASSOC,
-						  "associated: '%s' %s"
-						  " \n",
-						  escape_essid(priv->essid,
-							       priv->essid_len),
-						  print_mac(mac, priv->bssid));
+						  "associated: '%s' %pM \n",
+						  print_ssid(ssid, priv->essid,
+							     priv->essid_len),
+						  priv->bssid);
 
 					switch (priv->ieee->iw_mode) {
 					case IW_MODE_INFRA:
@@ -4449,7 +4446,7 @@
 
 #ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
-			 le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl))
+			 le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_control))
 					if ((priv->status & STATUS_AUTH) &&
 					    (IPW_GET_PACKET_STYPE(&notif->u.raw)
 					     == IEEE80211_STYPE_ASSOC_RESP)) {
@@ -4492,13 +4489,14 @@
 							  IPW_DL_STATE |
 							  IPW_DL_ASSOC,
 							  "deauthenticated: '%s' "
-							  "%s"
+							  "%pM"
 							  ": (0x%04X) - %s \n",
-							  escape_essid(priv->
-								       essid,
-								       priv->
-								       essid_len),
-							  print_mac(mac, priv->bssid),
+							  print_ssid(ssid,
+								     priv->
+								     essid,
+								     priv->
+								     essid_len),
+							  priv->bssid,
 							  le16_to_cpu(auth->status),
 							  ipw_get_status_code
 							  (le16_to_cpu
@@ -4515,11 +4513,10 @@
 
 					IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
 						  IPW_DL_ASSOC,
-						  "authenticated: '%s' %s"
-						  "\n",
-						  escape_essid(priv->essid,
-							       priv->essid_len),
-						  print_mac(mac, priv->bssid));
+						  "authenticated: '%s' %pM\n",
+						  print_ssid(ssid, priv->essid,
+							     priv->essid_len),
+						  priv->bssid);
 					break;
 				}
 
@@ -4544,11 +4541,10 @@
 
 					IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
 						  IPW_DL_ASSOC,
-						  "disassociated: '%s' %s"
-						  " \n",
-						  escape_essid(priv->essid,
-							       priv->essid_len),
-						  print_mac(mac, priv->bssid));
+						  "disassociated: '%s' %pM \n",
+						  print_ssid(ssid, priv->essid,
+							     priv->essid_len),
+						  priv->bssid);
 
 					priv->status &=
 					    ~(STATUS_DISASSOCIATING |
@@ -4583,10 +4579,10 @@
 			switch (auth->state) {
 			case CMAS_AUTHENTICATED:
 				IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
-					  "authenticated: '%s' %s \n",
-					  escape_essid(priv->essid,
-						       priv->essid_len),
-					  print_mac(mac, priv->bssid));
+					  "authenticated: '%s' %pM \n",
+					  print_ssid(ssid, priv->essid,
+						     priv->essid_len),
+					  priv->bssid);
 				priv->status |= STATUS_AUTH;
 				break;
 
@@ -4602,10 +4598,10 @@
 				}
 				IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
 					  IPW_DL_ASSOC,
-					  "deauthenticated: '%s' %s\n",
-					  escape_essid(priv->essid,
-						       priv->essid_len),
-					  print_mac(mac, priv->bssid));
+					  "deauthenticated: '%s' %pM\n",
+					  print_ssid(ssid, priv->essid,
+						     priv->essid_len),
+					  priv->bssid);
 
 				priv->status &= ~(STATUS_ASSOCIATING |
 						  STATUS_AUTH |
@@ -5429,27 +5425,17 @@
 				  int roaming)
 {
 	struct ipw_supported_rates rates;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
+	DECLARE_SSID_BUF(ssid);
 
 	/* Verify that this network's capability is compatible with the
 	 * current mode (AdHoc or Infrastructure) */
 	if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
 	     !(network->capability & WLAN_CAPABILITY_IBSS))) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded due to "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
 				"capability mismatch.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
-		return 0;
-	}
-
-	/* If we do not have an ESSID for this AP, we can not associate with
-	 * it */
-	if (network->flags & NETWORK_EMPTY_ESSID) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
-				"because of hidden ESSID.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
@@ -5459,11 +5445,11 @@
 		if ((network->ssid_len != match->network->ssid_len) ||
 		    memcmp(network->ssid, match->network->ssid,
 			   network->ssid_len)) {
-			IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+			IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 					"because of non-network ESSID.\n",
-					escape_essid(network->ssid,
-						     network->ssid_len),
-					print_mac(mac, network->bssid));
+					print_ssid(ssid, network->ssid,
+						   network->ssid_len),
+					network->bssid);
 			return 0;
 		}
 	} else {
@@ -5476,13 +5462,14 @@
 			char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
 
 			strncpy(escaped,
-				escape_essid(network->ssid, network->ssid_len),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
 				sizeof(escaped));
-			IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+			IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 					"because of ESSID mismatch: '%s'.\n",
-					escaped, print_mac(mac, network->bssid),
-					escape_essid(priv->essid,
-						     priv->essid_len));
+					escaped, network->bssid,
+					print_ssid(ssid, priv->essid,
+						   priv->essid_len));
 			return 0;
 		}
 	}
@@ -5493,24 +5480,25 @@
 	if (network->time_stamp[0] < match->network->time_stamp[0]) {
 		IPW_DEBUG_MERGE("Network '%s excluded because newer than "
 				"current network.\n",
-				escape_essid(match->network->ssid,
-					     match->network->ssid_len));
+				print_ssid(ssid, match->network->ssid,
+					   match->network->ssid_len));
 		return 0;
 	} else if (network->time_stamp[1] < match->network->time_stamp[1]) {
 		IPW_DEBUG_MERGE("Network '%s excluded because newer than "
 				"current network.\n",
-				escape_essid(match->network->ssid,
-					     match->network->ssid_len));
+				print_ssid(ssid, match->network->ssid,
+					   match->network->ssid_len));
 		return 0;
 	}
 
 	/* Now go through and see if the requested network is valid... */
 	if (priv->ieee->scan_age != 0 &&
 	    time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because of age: %ums.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				jiffies_to_msecs(jiffies -
 						 network->last_scanned));
 		return 0;
@@ -5518,10 +5506,11 @@
 
 	if ((priv->config & CFG_STATIC_CHANNEL) &&
 	    (network->channel != priv->channel)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because of channel mismatch: %d != %d.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				network->channel, priv->channel);
 		return 0;
 	}
@@ -5529,10 +5518,11 @@
 	/* Verify privacy compatability */
 	if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
 	    ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because of privacy mismatch: %s != %s.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				priv->
 				capability & CAP_PRIVACY_ON ? "on" : "off",
 				network->
@@ -5542,41 +5532,44 @@
 	}
 
 	if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
-				"because of the same BSSID match: %s"
-				".\n", escape_essid(network->ssid,
-						    network->ssid_len),
-				print_mac(mac, network->bssid),
-				print_mac(mac2, priv->bssid));
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
+				"because of the same BSSID match: %pM"
+				".\n", print_ssid(ssid, network->ssid,
+						  network->ssid_len),
+				network->bssid,
+				priv->bssid);
 		return 0;
 	}
 
 	/* Filter out any incompatible freq / mode combinations */
 	if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because of invalid frequency/mode "
 				"combination.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
 	/* Ensure that the rates supported by the driver are compatible with
 	 * this AP, including verification of basic rates (mandatory) */
 	if (!ipw_compatible_rates(priv, network, &rates)) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because configured rate mask excludes "
 				"AP mandatory rate.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
 	if (rates.num_rates == 0) {
-		IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
 				"because of no compatible rates.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
@@ -5587,15 +5580,16 @@
 	/* Set up 'new' AP to this network */
 	ipw_copy_rates(&match->rates, &rates);
 	match->network = network;
-	IPW_DEBUG_MERGE("Network '%s (%s)' is a viable match.\n",
-			escape_essid(network->ssid, network->ssid_len),
-			print_mac(mac, network->bssid));
+	IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
+			print_ssid(ssid, network->ssid, network->ssid_len),
+			network->bssid);
 
 	return 1;
 }
 
 static void ipw_merge_adhoc_network(struct work_struct *work)
 {
+	DECLARE_SSID_BUF(ssid);
 	struct ipw_priv *priv =
 		container_of(work, struct ipw_priv, merge_networks);
 	struct ieee80211_network *network = NULL;
@@ -5626,8 +5620,8 @@
 		mutex_lock(&priv->mutex);
 		if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
 			IPW_DEBUG_MERGE("remove network %s\n",
-					escape_essid(priv->essid,
-						     priv->essid_len));
+					print_ssid(ssid, priv->essid,
+						   priv->essid_len));
 			ipw_remove_current_network(priv);
 		}
 
@@ -5643,7 +5637,7 @@
 			    struct ieee80211_network *network, int roaming)
 {
 	struct ipw_supported_rates rates;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	/* Verify that this network's capability is compatible with the
 	 * current mode (AdHoc or Infrastructure) */
@@ -5651,20 +5645,11 @@
 	     !(network->capability & WLAN_CAPABILITY_ESS)) ||
 	    (priv->ieee->iw_mode == IW_MODE_ADHOC &&
 	     !(network->capability & WLAN_CAPABILITY_IBSS))) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded due to "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
 				"capability mismatch.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
-		return 0;
-	}
-
-	/* If we do not have an ESSID for this AP, we can not associate with
-	 * it */
-	if (network->flags & NETWORK_EMPTY_ESSID) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
-				"because of hidden ESSID.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
@@ -5674,11 +5659,11 @@
 		if ((network->ssid_len != match->network->ssid_len) ||
 		    memcmp(network->ssid, match->network->ssid,
 			   network->ssid_len)) {
-			IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+			IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 					"because of non-network ESSID.\n",
-					escape_essid(network->ssid,
-						     network->ssid_len),
-					print_mac(mac, network->bssid));
+					print_ssid(ssid, network->ssid,
+						   network->ssid_len),
+					network->bssid);
 			return 0;
 		}
 	} else {
@@ -5690,13 +5675,14 @@
 			    min(network->ssid_len, priv->essid_len)))) {
 			char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
 			strncpy(escaped,
-				escape_essid(network->ssid, network->ssid_len),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
 				sizeof(escaped));
-			IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+			IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 					"because of ESSID mismatch: '%s'.\n",
-					escaped, print_mac(mac, network->bssid),
-					escape_essid(priv->essid,
-						     priv->essid_len));
+					escaped, network->bssid,
+					print_ssid(ssid, priv->essid,
+						   priv->essid_len));
 			return 0;
 		}
 	}
@@ -5706,14 +5692,14 @@
 	if (match->network && match->network->stats.rssi > network->stats.rssi) {
 		char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
 		strncpy(escaped,
-			escape_essid(network->ssid, network->ssid_len),
+			print_ssid(ssid, network->ssid, network->ssid_len),
 			sizeof(escaped));
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded because "
-				"'%s (%s)' has a stronger signal.\n",
-				escaped, print_mac(mac, network->bssid),
-				escape_essid(match->network->ssid,
-					     match->network->ssid_len),
-				print_mac(mac, match->network->bssid));
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
+				"'%s (%pM)' has a stronger signal.\n",
+				escaped, network->bssid,
+				print_ssid(ssid, match->network->ssid,
+					   match->network->ssid_len),
+				match->network->bssid);
 		return 0;
 	}
 
@@ -5721,11 +5707,12 @@
 	 * last 3 seconds, do not try and associate again... */
 	if (network->last_associate &&
 	    time_after(network->last_associate + (HZ * 3UL), jiffies)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of storming (%ums since last "
 				"assoc attempt).\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				jiffies_to_msecs(jiffies -
 						 network->last_associate));
 		return 0;
@@ -5734,10 +5721,11 @@
 	/* Now go through and see if the requested network is valid... */
 	if (priv->ieee->scan_age != 0 &&
 	    time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of age: %ums.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				jiffies_to_msecs(jiffies -
 						 network->last_scanned));
 		return 0;
@@ -5745,10 +5733,11 @@
 
 	if ((priv->config & CFG_STATIC_CHANNEL) &&
 	    (network->channel != priv->channel)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of channel mismatch: %d != %d.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				network->channel, priv->channel);
 		return 0;
 	}
@@ -5756,10 +5745,11 @@
 	/* Verify privacy compatability */
 	if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
 	    ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of privacy mismatch: %s != %s.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid),
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid,
 				priv->capability & CAP_PRIVACY_ON ? "on" :
 				"off",
 				network->capability &
@@ -5769,48 +5759,53 @@
 
 	if ((priv->config & CFG_STATIC_BSSID) &&
 	    memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
-				"because of BSSID mismatch: %s.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid), print_mac(mac, priv->bssid));
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
+				"because of BSSID mismatch: %pM.\n",
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid, priv->bssid);
 		return 0;
 	}
 
 	/* Filter out any incompatible freq / mode combinations */
 	if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of invalid frequency/mode "
 				"combination.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
 	/* Filter out invalid channel in current GEO */
 	if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of invalid channel in current GEO\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
 	/* Ensure that the rates supported by the driver are compatible with
 	 * this AP, including verification of basic rates (mandatory) */
 	if (!ipw_compatible_rates(priv, network, &rates)) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because configured rate mask excludes "
 				"AP mandatory rate.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
 	if (rates.num_rates == 0) {
-		IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
 				"because of no compatible rates.\n",
-				escape_essid(network->ssid, network->ssid_len),
-				print_mac(mac, network->bssid));
+				print_ssid(ssid, network->ssid,
+					   network->ssid_len),
+				network->bssid);
 		return 0;
 	}
 
@@ -5822,9 +5817,9 @@
 	ipw_copy_rates(&match->rates, &rates);
 	match->network = network;
 
-	IPW_DEBUG_ASSOC("Network '%s (%s)' is a viable match.\n",
-			escape_essid(network->ssid, network->ssid_len),
-			print_mac(mac, network->bssid));
+	IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
+			print_ssid(ssid, network->ssid, network->ssid_len),
+			network->bssid);
 
 	return 1;
 }
@@ -6066,7 +6061,7 @@
 
 static void ipw_debug_config(struct ipw_priv *priv)
 {
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 	IPW_DEBUG_INFO("Scan completed, no valid APs matched "
 		       "[CFG 0x%08X]\n", priv->config);
 	if (priv->config & CFG_STATIC_CHANNEL)
@@ -6075,12 +6070,11 @@
 		IPW_DEBUG_INFO("Channel unlocked.\n");
 	if (priv->config & CFG_STATIC_ESSID)
 		IPW_DEBUG_INFO("ESSID locked to '%s'\n",
-			       escape_essid(priv->essid, priv->essid_len));
+			       print_ssid(ssid, priv->essid, priv->essid_len));
 	else
 		IPW_DEBUG_INFO("ESSID unlocked.\n");
 	if (priv->config & CFG_STATIC_BSSID)
-		IPW_DEBUG_INFO("BSSID locked to %s\n",
-			       print_mac(mac, priv->bssid));
+		IPW_DEBUG_INFO("BSSID locked to %pM\n", priv->bssid);
 	else
 		IPW_DEBUG_INFO("BSSID unlocked.\n");
 	if (priv->capability & CAP_PRIVACY_ON)
@@ -6892,8 +6886,7 @@
 	if ((priv->status & STATUS_ASSOCIATED) &&
 	    (priv->ieee->iw_mode == IW_MODE_ADHOC) && (active_network == 0)) {
 		if (memcmp(network->bssid, priv->bssid, ETH_ALEN))
-			if ((network->capability & WLAN_CAPABILITY_IBSS) &&
-			    !(network->flags & NETWORK_EMPTY_ESSID))
+			if (network->capability & WLAN_CAPABILITY_IBSS)
 				if ((network->ssid_len ==
 				     priv->assoc_network->ssid_len) &&
 				    !memcmp(network->ssid,
@@ -7295,7 +7288,7 @@
 				 struct ipw_supported_rates *rates, int roaming)
 {
 	int err;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	if (priv->config & CFG_FIXED_RATE)
 		ipw_set_fixed_rate(priv, network->mode);
@@ -7364,7 +7357,7 @@
 	IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, "
 			"802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
 			roaming ? "Rea" : "A",
-			escape_essid(priv->essid, priv->essid_len),
+			print_ssid(ssid, priv->essid, priv->essid_len),
 			network->channel,
 			ipw_modes[priv->assoc_request.ieee_mode],
 			rates->num_rates,
@@ -7463,9 +7456,9 @@
 		return err;
 	}
 
-	IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %s \n",
-		  escape_essid(priv->essid, priv->essid_len),
-		  print_mac(mac, priv->bssid));
+	IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n",
+		  print_ssid(ssid, priv->essid, priv->essid_len),
+		  priv->bssid);
 
 	return 0;
 }
@@ -7555,6 +7548,7 @@
 	struct ipw_supported_rates *rates;
 	struct list_head *element;
 	unsigned long flags;
+	DECLARE_SSID_BUF(ssid);
 
 	if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
 		IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
@@ -7604,7 +7598,6 @@
 		if (list_empty(&priv->ieee->network_free_list)) {
 			struct ieee80211_network *oldest = NULL;
 			struct ieee80211_network *target;
-			DECLARE_MAC_BUF(mac);
 
 			list_for_each_entry(target, &priv->ieee->network_list, list) {
 				if ((oldest == NULL) ||
@@ -7615,11 +7608,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IPW_DEBUG_ASSOC("Expired '%s' (%s) from "
+			IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
 					"network list.\n",
-					escape_essid(target->ssid,
-						     target->ssid_len),
-					print_mac(mac, target->bssid));
+					print_ssid(ssid, target->ssid,
+						   target->ssid_len),
+					target->bssid);
 			list_add_tail(&target->list,
 				      &priv->ieee->network_free_list);
 		}
@@ -7672,12 +7665,12 @@
 	u16 fc;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = le16_to_cpu(hdr->frame_ctl);
+	fc = le16_to_cpu(hdr->frame_control);
 	if (!(fc & IEEE80211_FCTL_PROTECTED))
 		return;
 
 	fc &= ~IEEE80211_FCTL_PROTECTED;
-	hdr->frame_ctl = cpu_to_le16(fc);
+	hdr->frame_control = cpu_to_le16(fc);
 	switch (priv->ieee->sec.level) {
 	case SEC_LEVEL_3:
 		/* Remove CCMP HDR */
@@ -7989,17 +7982,17 @@
 	}
 
 	hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
-	if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
+	if (ieee80211_is_management(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_MGMT)
 			return;
 		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
+	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_CTL)
 			return;
 		if (filter & IPW_PROM_CTL_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
+	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_DATA)
 			return;
 		if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -8017,7 +8010,7 @@
 	ipw_rt = (void *)skb->data;
 
 	if (hdr_only)
-		len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+		len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
 
 	memcpy(ipw_rt->payload, hdr, len);
 
@@ -8237,7 +8230,7 @@
 	/* Comment this line now since we observed the card receives
 	 * duplicate packets but the FCTL_RETRY bit is not set in the
 	 * IBSS mode with fragmentation enabled.
-	 BUG_ON(!(le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_RETRY)); */
+	 BUG_ON(!(le16_to_cpu(header->frame_control) & IEEE80211_FCTL_RETRY)); */
 	return 1;
 }
 
@@ -8301,9 +8294,6 @@
 	u32 r, w, i;
 	u8 network_packet;
 	u8 fill_rx = 0;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
 
 	r = ipw_read32(priv, IPW_RX_READ_INDEX);
 	w = ipw_read32(priv, IPW_RX_WRITE_INDEX);
@@ -8433,18 +8423,12 @@
 									 header)))
 					{
 						IPW_DEBUG_DROP("Dropping: "
-							       "%s, "
-							       "%s, "
-							       "%s\n",
-							       print_mac(mac,
-									 header->
-								       addr1),
-							       print_mac(mac2,
-									 header->
-								       addr2),
-							       print_mac(mac3,
-									 header->
-								       addr3));
+							       "%pM, "
+							       "%pM, "
+							       "%pM\n",
+							       header->addr1,
+							       header->addr2,
+							       header->addr3);
 						break;
 					}
 
@@ -8983,7 +8967,6 @@
 			  union iwreq_data *wrqu, char *extra)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	static const unsigned char any[] = {
 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
@@ -9014,8 +8997,8 @@
 		return 0;
 	}
 
-	IPW_DEBUG_WX("Setting mandatory BSSID to %s\n",
-		     print_mac(mac, wrqu->ap_addr.sa_data));
+	IPW_DEBUG_WX("Setting mandatory BSSID to %pM\n",
+		     wrqu->ap_addr.sa_data);
 
 	memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
 
@@ -9033,7 +9016,6 @@
 			  union iwreq_data *wrqu, char *extra)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
 	/* If we are associated, trying to associate, or have a statically
 	 * configured BSSID then return that; otherwise return ANY */
@@ -9045,8 +9027,8 @@
 	} else
 		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
 
-	IPW_DEBUG_WX("Getting WAP BSSID: %s\n",
-		     print_mac(mac, wrqu->ap_addr.sa_data));
+	IPW_DEBUG_WX("Getting WAP BSSID: %pM\n",
+		     wrqu->ap_addr.sa_data);
 	mutex_unlock(&priv->mutex);
 	return 0;
 }
@@ -9057,6 +9039,7 @@
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
         int length;
+	DECLARE_SSID_BUF(ssid);
 
         mutex_lock(&priv->mutex);
 
@@ -9081,8 +9064,8 @@
 		return 0;
 	}
 
-	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(extra, length),
-		     length);
+	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
+		     print_ssid(ssid, extra, length), length);
 
 	priv->essid_len = length;
 	memcpy(priv->essid, extra, priv->essid_len);
@@ -9101,6 +9084,7 @@
 			    union iwreq_data *wrqu, char *extra)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
+	DECLARE_SSID_BUF(ssid);
 
 	/* If we are associated, trying to associate, or have a statically
 	 * configured ESSID then return that; otherwise return ANY */
@@ -9108,7 +9092,7 @@
 	if (priv->config & CFG_STATIC_ESSID ||
 	    priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
 		IPW_DEBUG_WX("Getting essid: '%s'\n",
-			     escape_essid(priv->essid, priv->essid_len));
+			     print_ssid(ssid, priv->essid, priv->essid_len));
 		memcpy(extra, priv->essid, priv->essid_len);
 		wrqu->essid.length = priv->essid_len;
 		wrqu->essid.flags = 1;	/* active */
@@ -10199,10 +10183,8 @@
 			id = ipw_add_station(priv, hdr->addr1);
 			if (id == IPW_INVALID_STATION) {
 				IPW_WARNING("Attempt to send data to "
-					    "invalid cell: " MAC_FMT "\n",
-					    hdr->addr1[0], hdr->addr1[1],
-					    hdr->addr1[2], hdr->addr1[3],
-					    hdr->addr1[4], hdr->addr1[5]);
+					    "invalid cell: %pM\n",
+					    hdr->addr1);
 				goto drop;
 			}
 		}
@@ -10399,17 +10381,17 @@
 
 	/* Filtering of fragment chains is done agains the first fragment */
 	hdr = (void *)txb->fragments[0]->data;
-	if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
+	if (ieee80211_is_management(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_MGMT)
 			return;
 		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
+	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_CTL)
 			return;
 		if (filter & IPW_PROM_CTL_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
+	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_DATA)
 			return;
 		if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -10424,7 +10406,7 @@
 
 		if (hdr_only) {
 			hdr = (void *)src->data;
-			len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+			len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
 		} else
 			len = src->len;
 
@@ -10505,15 +10487,14 @@
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	struct sockaddr *addr = p;
-	DECLARE_MAC_BUF(mac);
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 	mutex_lock(&priv->mutex);
 	priv->config |= CFG_CUSTOM_MAC;
 	memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
-	printk(KERN_INFO "%s: Setting MAC to %s\n",
-	       priv->net_dev->name, print_mac(mac, priv->mac_addr));
+	printk(KERN_INFO "%s: Setting MAC to %pM\n",
+	       priv->net_dev->name, priv->mac_addr);
 	queue_work(priv->workqueue, &priv->adapter_restart);
 	mutex_unlock(&priv->mutex);
 	return 0;
@@ -11648,7 +11629,7 @@
 	length = pci_resource_len(pdev, 0);
 	priv->hw_len = length;
 
-	base = ioremap_nocache(pci_resource_start(pdev, 0), length);
+	base = pci_ioremap_bar(pdev, 0);
 	if (!base) {
 		err = -ENODEV;
 		goto out_pci_release_regions;
@@ -11940,7 +11921,7 @@
 MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 
 module_param(associate, int, 0444);
-MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default off)");
 
 module_param(auto_create, int, 0444);
 MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 0bad1ec..0a84d52 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -48,6 +48,7 @@
 #include <linux/jiffies.h>
 #include <asm/io.h>
 
+#include <net/lib80211.h>
 #include <net/ieee80211.h>
 #include <net/ieee80211_radiotap.h>
 
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index b0ac0ce..47bee0e 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -4,6 +4,7 @@
 config IWLCORE
 	tristate "Intel Wireless Wifi Core"
 	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+	select LIB80211
 	select IWLWIFI
 	select MAC80211_LEDS if IWLWIFI_LEDS
 	select LEDS_CLASS if IWLWIFI_LEDS
@@ -105,6 +106,7 @@
 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
 	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
 	select FW_LOADER
+	select LIB80211
 	select IWLWIFI
 	select MAC80211_LEDS if IWL3945_LEDS
 	select LEDS_CLASS if IWL3945_LEDS
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
index 817ece7..8772d9d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
@@ -121,7 +121,7 @@
 	REPLY_TX_PWR_TABLE_CMD = 0x97,
 	MEASURE_ABORT_NOTIFICATION = 0x99,	/* not used */
 
-	/* Bluetooth device coexistance config command */
+	/* Bluetooth device coexistence config command */
 	REPLY_BT_CONFIG = 0x9b,
 
 	/* Statistics */
@@ -158,7 +158,7 @@
 	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
 	u8 flags;	/* IWL_CMD_* */
 	/*
-	 * The driver sets up the sequence number to values of its chosing.
+	 * The driver sets up the sequence number to values of its choosing.
 	 * uCode does not use this value, but passes it back to the driver
 	 * when sending the response to each driver-originated command, so
 	 * the driver can match the response to the command.  Since the values
@@ -991,7 +991,7 @@
  *
  * 3945 and 4965 support hardware handshake with Bluetooth device on
  * same platform.  Bluetooth device alerts wireless device when it will Tx;
- * wireless device can delay or kill its own Tx to accomodate.
+ * wireless device can delay or kill its own Tx to accommodate.
  */
 struct iwl3945_bt_cmd {
 	u8 flags;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
index b3fe48d..1daa3f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
@@ -53,7 +53,7 @@
  * _iwl3945_read32.)
  *
  * These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguring of the hardware I/O.  In combination with
+ * which result in misconfiguration of the hardware I/O.  In combination with
  * git-bisect and the IO debug level you can quickly determine the specific
  * commit which breaks the IO sequence to the hardware.
  *
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 6fc5e73..bfeef70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -355,12 +355,6 @@
 	return;
 }
 
-static void rs_clear(void *priv)
-{
-	return;
-}
-
-
 static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 {
 	struct iwl3945_rs_sta *rs_sta;
@@ -422,34 +416,6 @@
 }
 
 
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
-{
-	int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
-	switch (priv->band) {
-	case IEEE80211_BAND_5GHZ:
-		if (rate == IWL_RATE_12M_INDEX)
-			next_rate = IWL_RATE_9M_INDEX;
-		else if (rate == IWL_RATE_6M_INDEX)
-			next_rate = IWL_RATE_6M_INDEX;
-		break;
-/* XXX cannot be invoked in current mac80211 so not a regression
-	case MODE_IEEE80211B:
-		if (rate == IWL_RATE_11M_INDEX_TABLE)
-			next_rate = IWL_RATE_5M_INDEX_TABLE;
-		break;
- */
-	default:
-		break;
-	}
-
-	return next_rate;
-}
 /**
  * rs_tx_status - Update rate control values based on Tx results
  *
@@ -460,17 +426,21 @@
 			 struct ieee80211_sta *sta, void *priv_sta,
 			 struct sk_buff *skb)
 {
-	u8 retries, current_count;
+	u8 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 iwl3945_rs_sta *rs_sta = priv_sta;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	int i;
 
 	IWL_DEBUG_RATE("enter\n");
 
-	retries = info->status.retry_count;
-	first_index = sband->bitrates[info->tx_rate_idx].hw_value;
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++)
+		retries += info->status.rates[i].count;
+	retries--;
+
+	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
 	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
 		IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
 		return;
@@ -502,7 +472,7 @@
 			last_index = scale_rate_index;
 		} else {
 			current_count = priv->retry_rate;
-			last_index = rs_adjust_next_rate(priv,
+			last_index = iwl3945_rs_next_rate(priv,
 							 scale_rate_index);
 		}
 
@@ -518,7 +488,7 @@
 
 		if (retries)
 			scale_rate_index =
-			    rs_adjust_next_rate(priv, scale_rate_index);
+			    iwl3945_rs_next_rate(priv, scale_rate_index);
 	}
 
 
@@ -630,10 +600,11 @@
  * rate table and must reference the driver allocated rate table
  *
  */
-static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
-			struct ieee80211_sta *sta, void *priv_sta,
-			struct sk_buff *skb, struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
+			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
 {
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct sk_buff *skb = txrc->skb;
 	u8 low = IWL_RATE_INVALID;
 	u8 high = IWL_RATE_INVALID;
 	u16 high_low;
@@ -649,7 +620,7 @@
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	u16 fc, rate_mask;
 	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
-	DECLARE_MAC_BUF(mac);
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 	IWL_DEBUG_RATE("enter\n");
 
@@ -660,7 +631,7 @@
 	    is_multicast_ether_addr(hdr->addr1) ||
 	    !sta || !priv_sta) {
 		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
-		sel->rate_idx = rate_lowest_index(sband, sta);
+		info->control.rates[0].idx = rate_lowest_index(sband, sta);
 		return;
 	}
 
@@ -675,8 +646,8 @@
 		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
 
 		if (sta_id == IWL_INVALID_STATION) {
-			IWL_DEBUG_RATE("LQ: ADD station %s\n",
-				       print_mac(mac, hdr->addr1));
+			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
+				       hdr->addr1);
 			sta_id = iwl3945_add_station(priv,
 				    hdr->addr1, 0, CMD_ASYNC);
 		}
@@ -793,9 +764,10 @@
 
 	rs_sta->last_txrate_idx = index;
 	if (sband->band == IEEE80211_BAND_5GHZ)
-		sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+		info->control.rates[0].idx = rs_sta->last_txrate_idx -
+				IWL_FIRST_OFDM_RATE;
 	else
-		sel->rate_idx = rs_sta->last_txrate_idx;
+		info->control.rates[0].idx = rs_sta->last_txrate_idx;
 
 	IWL_DEBUG_RATE("leave: %d\n", index);
 }
@@ -806,7 +778,6 @@
 	.tx_status = rs_tx_status,
 	.get_rate = rs_get_rate,
 	.rate_init = rs_rate_init,
-	.clear = rs_clear,
 	.alloc = rs_alloc,
 	.free = rs_free,
 	.alloc_sta = rs_alloc_sta,
@@ -827,13 +798,12 @@
 	rcu_read_lock();
 
 	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
-	psta = (void *) sta->drv_priv;
-	if (!sta || !psta) {
-		IWL_DEBUG_RATE("leave - no private rate data!\n");
+	if (!sta) {
 		rcu_read_unlock();
 		return;
 	}
 
+	psta = (void *) sta->drv_priv;
 	rs_sta = psta->rs_sta;
 
 	spin_lock_irqsave(&rs_sta->lock, flags);
@@ -857,7 +827,6 @@
 		break;
 	}
 
-	rcu_read_unlock();
 	spin_unlock_irqrestore(&rs_sta->lock, flags);
 
 	rssi = priv->last_rx_rssi;
@@ -871,6 +840,7 @@
 	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
 		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
 		       iwl3945_rates[rs_sta->start_rate].plcp);
+	rcu_read_unlock();
 }
 
 int iwl3945_rate_control_register(void)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 7ca5627..af77ea7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -200,7 +200,7 @@
  * priv->eeprom  is used to determine if antenna AUX/MAIN are reversed
  * priv->antenna specifies the antenna diversity mode:
  *
- * IWL_ANTENNA_DIVERISTY - NIC selects best antenna by itself
+ * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
  * IWL_ANTENNA_MAIN      - Force MAIN antenna
  * IWL_ANTENNA_AUX       - Force AUX antenna
  */
@@ -261,6 +261,35 @@
 }
 #endif
 
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate)
+{
+	int next_rate = iwl3945_get_prev_ieee_rate(rate);
+
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
+		if (rate == IWL_RATE_12M_INDEX)
+			next_rate = IWL_RATE_9M_INDEX;
+		else if (rate == IWL_RATE_6M_INDEX)
+			next_rate = IWL_RATE_6M_INDEX;
+		break;
+/* XXX cannot be invoked in current mac80211 so not a regression
+	case MODE_IEEE80211B:
+		if (rate == IWL_RATE_11M_INDEX_TABLE)
+			next_rate = IWL_RATE_5M_INDEX_TABLE;
+		break;
+ */
+	default:
+		break;
+	}
+
+	return next_rate;
+}
+
 
 /**
  * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
@@ -308,6 +337,7 @@
 	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32  status = le32_to_cpu(tx_resp->status);
 	int rate_idx;
+	int fail, i;
 
 	if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
 		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
@@ -318,9 +348,36 @@
 	}
 
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
-	memset(&info->status, 0, sizeof(info->status));
+	ieee80211_tx_info_clear_status(info);
 
-	info->status.retry_count = tx_resp->failure_frame;
+	/* Fill the MRR chain with some info about on-chip retransmissions */
+	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate_idx -= IWL_FIRST_OFDM_RATE;
+
+	fail = tx_resp->failure_frame;
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		int next = iwl3945_rs_next_rate(priv, rate_idx);
+
+		info->status.rates[i].idx = rate_idx;
+
+		/*
+		 * Put remaining into the last count as best approximation
+		 * of saying exactly what the hardware would have done...
+		 */
+		if ((rate_idx == next) || (i == IEEE80211_TX_MAX_RATES - 1)) {
+			info->status.rates[i].count = fail;
+			break;
+		}
+
+		info->status.rates[i].count = priv->retry_rate;
+		fail -= priv->retry_rate;
+		rate_idx = next;
+		if (fail <= 0)
+			break;
+	}
+	info->status.rates[i].count++; /* add final attempt */
+
 	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
 	info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
 				IEEE80211_TX_STAT_ACK : 0;
@@ -329,10 +386,6 @@
 			txq_id, iwl3945_get_tx_fail_reason(status), status,
 			tx_resp->rate, tx_resp->failure_frame);
 
-	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
-	if (info->band == IEEE80211_BAND_5GHZ)
-		rate_idx -= IWL_FIRST_OFDM_RATE;
-	info->tx_rate_idx = rate_idx;
 	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
 	iwl3945_tx_queue_reclaim(priv, txq_id, index);
 
@@ -759,7 +812,6 @@
 	int i;
 	int ret = IWL_INVALID_STATION;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
@@ -770,8 +822,8 @@
 			goto out;
 		}
 
-	IWL_DEBUG_INFO("can not find STA %s (total %d)\n",
-		       print_mac(mac, addr), priv->num_stations);
+	IWL_DEBUG_INFO("can not find STA %pM (total %d)\n",
+		       addr, priv->num_stations);
  out:
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	return ret;
@@ -1830,7 +1882,7 @@
 		ref_temp = (s16)priv->eeprom.groups[ch_info->group_index].
 		    temperature;
 
-		/* get power index adjustment based on curr and factory
+		/* get power index adjustment based on current and factory
 		 * temps */
 		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
 							      ref_temp);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bdd3247..7187925 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -828,8 +828,6 @@
 	unsigned long last_statistics_time;
 
 	/* context information */
-	u8 essid[IW_ESSID_MAX_SIZE];
-	u8 essid_len;
 	u16 rates_mask;
 
 	u32 power_mode;
@@ -954,6 +952,8 @@
 extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
 	const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
 
+extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate);
+
 /* Requires full declaration of iwl3945_priv before including */
 #include "iwl-3945-io.h"
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index f4793a6..9da7c7b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -71,7 +71,7 @@
 
 #include "iwl-fh.h"
 
-/* EERPROM */
+/* EEPROM */
 #define IWL4965_EEPROM_IMG_SIZE			1024
 
 /*
@@ -111,7 +111,6 @@
 #define PCI_CFG_CMD_REG_INT_DIS_MSK	0x04
 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
 
-#define TFD_QUEUE_SIZE_MAX      (256)
 
 #define IWL_NUM_SCAN_RATES         (2)
 
@@ -287,13 +286,13 @@
  *     that target txpower.
  *
  *
- * 3)  Determine (EEPROM) calibration subband for the target channel, by
- *     comparing against first and last channels in each subband
+ * 3)  Determine (EEPROM) calibration sub band for the target channel, by
+ *     comparing against first and last channels in each sub band
  *     (see struct iwl4965_eeprom_calib_subband_info).
  *
  *
  * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
- *     referencing the 2 factory-measured (sample) channels within the subband.
+ *     referencing the 2 factory-measured (sample) channels within the sub band.
  *
  *     Interpolation is based on difference between target channel's frequency
  *     and the sample channels' frequencies.  Since channel numbers are based
@@ -301,7 +300,7 @@
  *     to interpolating based on channel number differences.
  *
  *     Note that the sample channels may or may not be the channels at the
- *     edges of the subband.  The target channel may be "outside" of the
+ *     edges of the sub band.  The target channel may be "outside" of the
  *     span of the sampled channels.
  *
  *     Driver may choose the pair (for 2 Tx chains) of measurements (see
@@ -345,7 +344,7 @@
  *     "4965 temperature calculation".
  *
  *     If current temperature is higher than factory temperature, driver must
- *     increase gain (lower gain table index), and vice versa.
+ *     increase gain (lower gain table index), and vice verse.
  *
  *     Temperature affects gain differently for different channels:
  *
@@ -815,125 +814,72 @@
  * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
  * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
  */
-#define IWL49_MAX_WIN_SIZE	64
-#define IWL49_QUEUE_SIZE	256
 #define IWL49_NUM_FIFOS 	7
 #define IWL49_CMD_FIFO_NUM	4
 #define IWL49_NUM_QUEUES	16
 #define IWL49_NUM_AMPDU_QUEUES	8
 
+#define IWL_TX_DMA_MASK        (DMA_BIT_MASK(36) & ~0x3)
+#define IWL_NUM_OF_TBS		20
+
+static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
+{
+	return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
 /**
- * struct iwl_tfd_frame_data
+ * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
  *
- * Describes up to 2 buffers containing (contiguous) portions of a Tx frame.
- * Each buffer must be on dword boundary.
- * Up to 10 iwl_tfd_frame_data structures, describing up to 20 buffers,
- * may be filled within a TFD (iwl_tfd_frame).
+ * This structure contains dma address and length of transmission address
  *
- * Bit fields in tb1_addr:
- * 31- 0: Tx buffer 1 address bits [31:0]
- *
- * Bit fields in val1:
- * 31-16: Tx buffer 2 address bits [15:0]
- * 15- 4: Tx buffer 1 length (bytes)
- *  3- 0: Tx buffer 1 address bits [32:32]
- *
- * Bit fields in val2:
- * 31-20: Tx buffer 2 length (bytes)
- * 19- 0: Tx buffer 2 address bits [35:16]
+ * @lo: low [31:0] portion of the dma address of TX buffer
+ * 	every even is unaligned on 16 bit boundary
+ * @hi_n_len 0-3 [35:32] portion of dma
+ *	     4-16 length of the tx buffer
  */
-struct iwl_tfd_frame_data {
-	__le32 tb1_addr;
-
-	__le32 val1;
-	/* __le32 ptb1_32_35:4; */
-#define IWL_tb1_addr_hi_POS 0
-#define IWL_tb1_addr_hi_LEN 4
-#define IWL_tb1_addr_hi_SYM val1
-	/* __le32 tb_len1:12; */
-#define IWL_tb1_len_POS 4
-#define IWL_tb1_len_LEN 12
-#define IWL_tb1_len_SYM val1
-	/* __le32 ptb2_0_15:16; */
-#define IWL_tb2_addr_lo16_POS 16
-#define IWL_tb2_addr_lo16_LEN 16
-#define IWL_tb2_addr_lo16_SYM val1
-
-	__le32 val2;
-	/* __le32 ptb2_16_35:20; */
-#define IWL_tb2_addr_hi20_POS 0
-#define IWL_tb2_addr_hi20_LEN 20
-#define IWL_tb2_addr_hi20_SYM val2
-	/* __le32 tb_len2:12; */
-#define IWL_tb2_len_POS 20
-#define IWL_tb2_len_LEN 12
-#define IWL_tb2_len_SYM val2
-} __attribute__ ((packed));
-
+struct iwl_tfd_tb {
+	__le32 lo;
+	__le16 hi_n_len;
+} __attribute__((packed));
 
 /**
- * struct iwl_tfd_frame
+ * struct iwl_tfd
  *
  * Transmit Frame Descriptor (TFD)
  *
- * 4965 supports up to 16 Tx queues resident in host DRAM.
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-5 number of active tbs
+ * 	     6-7 padding (not used)
+ * @ tbs[20]	transmit frame buffer descriptors
+ * @ __pad 	padding
+ *
  * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
  * Both driver and device share these circular buffers, each of which must be
- * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes for 4965.
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
  *
  * Driver must indicate the physical address of the base of each
- * circular buffer via the 4965's FH_MEM_CBBC_QUEUE registers.
+ * circular buffer via the FH_MEM_CBBC_QUEUE registers.
  *
  * Each TFD contains pointer/size information for up to 20 data buffers
  * in host DRAM.  These buffers collectively contain the (one) frame described
  * by the TFD.  Each buffer must be a single contiguous block of memory within
  * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
- * of (4K - 4).  The 4965 concatenates all of a TFD's buffers into a single
+ * of (4K - 4).  The concatenates all of a TFD's buffers into a single
  * Tx frame, up to 8 KBytes in size.
  *
- * Bit fields in the control dword (val0):
- * 31-30: # dwords (0-3) of padding required at end of frame for 16-byte bound
- *    29: reserved
- * 28-24: # Transmit Buffer Descriptors in TFD
- * 23- 0: reserved
- *
  * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ *
+ * Bit fields in the control dword (val0):
  */
-struct iwl_tfd_frame {
-	__le32 val0;
-	/* __le32 rsvd1:24; */
-	/* __le32 num_tbs:5; */
-#define IWL_num_tbs_POS 24
-#define IWL_num_tbs_LEN 5
-#define IWL_num_tbs_SYM val0
-	/* __le32 rsvd2:1; */
-	/* __le32 padding:2; */
-	struct iwl_tfd_frame_data pa[10];
-	__le32 reserved;
+struct iwl_tfd {
+	u8 __reserved1[3];
+	u8 num_tbs;
+	struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
+	__le32 __pad;
 } __attribute__ ((packed));
 
 
 /**
- * struct iwl4965_queue_byte_cnt_entry
- *
- * Byte Count Table Entry
- *
- * Bit fields:
- * 15-12: reserved
- * 11- 0: total to-be-transmitted byte count of frame (does not include command)
- */
-struct iwl4965_queue_byte_cnt_entry {
-	__le16 val;
-	/* __le16 byte_cnt:12; */
-#define IWL_byte_cnt_POS 0
-#define IWL_byte_cnt_LEN 12
-#define IWL_byte_cnt_SYM val
-	/* __le16 rsvd:4; */
-} __attribute__ ((packed));
-
-
-/**
- * struct iwl4965_sched_queue_byte_cnt_tbl
+ * struct iwl4965_schedq_bc_tbl
  *
  * Byte Count table
  *
@@ -947,15 +893,12 @@
  * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
  * must duplicate the byte count entry in corresponding index 256-319.
  *
- * "dont_care" padding puts each byte count table on a 1024-byte boundary;
+ * padding puts each byte count table on a 1024-byte boundary;
  * 4965 assumes tables are separated by 1024 bytes.
  */
-struct iwl4965_sched_queue_byte_cnt_tbl {
-	struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL49_QUEUE_SIZE +
-						       IWL49_MAX_WIN_SIZE];
-	u8 dont_care[1024 -
-		     (IWL49_QUEUE_SIZE + IWL49_MAX_WIN_SIZE) *
-		     sizeof(__le16)];
+struct iwl4965_schedq_bc_tbl {
+	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+	u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
 } __attribute__ ((packed));
 
 
@@ -983,8 +926,7 @@
  * 31- 0:  Not used
  */
 struct iwl4965_shared {
-	struct iwl4965_sched_queue_byte_cnt_tbl
-	 queues_byte_cnt_tbls[IWL49_NUM_QUEUES];
+	struct iwl4965_schedq_bc_tbl queues_bc_tbls[IWL49_NUM_QUEUES];
 	__le32 rb_closed;
 
 	/* __le32 rb_closed_stts_rb_num:12; */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 9838de5..157cad4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -246,7 +246,7 @@
 	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
 				 priv->ucode_data.len);
 
-	/* Inst bytecount must be last to set up, bit 31 signals uCode
+	/* Inst byte count must be last to set up, bit 31 signals uCode
 	 *   that all new ptr/size info is in place */
 	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
 				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -318,31 +318,13 @@
 /*
  * EEPROM handlers
  */
-
-static int iwl4965_eeprom_check_version(struct iwl_priv *priv)
+static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv)
 {
-	u16 eeprom_ver;
-	u16 calib_ver;
-
-	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-
-	calib_ver = iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
-
-	if (eeprom_ver < EEPROM_4965_EEPROM_VERSION ||
-	    calib_ver < EEPROM_4965_TX_POWER_VERSION)
-		goto err;
-
-	return 0;
-err:
-	IWL_ERROR("Unsuported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
-		  eeprom_ver, EEPROM_4965_EEPROM_VERSION,
-		  calib_ver, EEPROM_4965_TX_POWER_VERSION);
-	return -EINVAL;
-
+	return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
 }
 
 /*
- * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
  * must be called under priv->lock and mac access
  */
 static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
@@ -414,7 +396,7 @@
 
 	/* L1 is enabled by BIOS */
 	if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
-		/* diable L0S disabled L1A enabled */
+		/* disable L0S disabled L1A enabled */
 		iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
 	else
 		/* L0S enabled L1A disabled */
@@ -537,10 +519,10 @@
 	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
 
 	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
-		struct iwl4965_calibration_cmd cmd;
+		struct iwl_calib_diff_gain_cmd cmd;
 
 		memset(&cmd, 0, sizeof(cmd));
-		cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.opCode = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
 		cmd.diff_gain_a = 0;
 		cmd.diff_gain_b = 0;
 		cmd.diff_gain_c = 0;
@@ -587,11 +569,11 @@
 
 	/* Differential gain gets sent to uCode only once */
 	if (!data->radio_write) {
-		struct iwl4965_calibration_cmd cmd;
+		struct iwl_calib_diff_gain_cmd cmd;
 		data->radio_write = 1;
 
 		memset(&cmd, 0, sizeof(cmd));
-		cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.opCode = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
 		cmd.diff_gain_a = data->delta_gain_code[0];
 		cmd.diff_gain_b = data->delta_gain_code[1];
 		cmd.diff_gain_c = data->delta_gain_code[2];
@@ -619,10 +601,10 @@
 static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
 			__le32 *tx_flags)
 {
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		*tx_flags |= TX_CMD_FLG_RTS_MSK;
 		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-	} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+	} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
 		*tx_flags |= TX_CMD_FLG_CTS_MSK;
 	}
@@ -643,7 +625,7 @@
 
 	mutex_lock(&priv->mutex);
 
-	/* Regardless of if we are assocaited, we must reconfigure the
+	/* Regardless of if we are associated, we must reconfigure the
 	 * TX power since frames can be sent on non-radar channels while
 	 * not associated */
 	iwl4965_send_tx_power(priv);
@@ -734,7 +716,7 @@
 	/* Tel 4965 where to find Tx byte count tables */
 	iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
 		(priv->shared_phys +
-		 offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
+		 offsetof(struct iwl4965_shared, queues_bc_tbls)) >> 10);
 
 	/* Disable chain mode for all queues */
 	iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
@@ -822,7 +804,6 @@
 	}
 
 	priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
-	priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE;
 	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
 	priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
 	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
@@ -1687,21 +1668,22 @@
 					    struct iwl_tx_queue *txq,
 					    u16 byte_cnt)
 {
-	int len;
-	int txq_id = txq->q.id;
 	struct iwl4965_shared *shared_data = priv->shared_virt;
+	int txq_id = txq->q.id;
+	int write_ptr = txq->q.write_ptr;
+	int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	__le16 bc_ent;
 
-	len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
 
+	bc_ent = cpu_to_le16(len & 0xFFF);
 	/* Set up byte count within first 256 entries */
-	IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-		       tfd_offset[txq->q.write_ptr], byte_cnt, len);
+	shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent;
 
 	/* If within first 64 entries, duplicate at end */
-	if (txq->q.write_ptr < IWL49_MAX_WIN_SIZE)
-		IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-			tfd_offset[IWL49_QUEUE_SIZE + txq->q.write_ptr],
-			byte_cnt, len);
+	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		shared_data->queues_bc_tbls[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
 /**
@@ -2037,7 +2019,7 @@
 }
 
 /**
- * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+ * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
  */
 static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
 				      struct iwl_ht_agg *agg,
@@ -2059,7 +2041,7 @@
 	agg->rate_n_flags = rate_n_flags;
 	agg->bitmap = 0;
 
-	/* # frames attempted by Tx command */
+	/* num frames attempted by Tx command */
 	if (agg->frame_count == 1) {
 		/* Only one frame was attempted; no block-ack will arrive */
 		status = le16_to_cpu(frame_status[0].status);
@@ -2070,7 +2052,7 @@
 				   agg->frame_count, agg->start_idx, idx);
 
 		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
-		info->status.retry_count = tx_resp->failure_frame;
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
 		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
 		info->flags |= iwl_is_tx_success(status)?
 			IEEE80211_TX_STAT_ACK : 0;
@@ -2158,12 +2140,13 @@
 	int txq_id = SEQ_TO_QUEUE(sequence);
 	int index = SEQ_TO_INDEX(sequence);
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *info;
 	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32  status = le32_to_cpu(tx_resp->u.status);
-	int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
-	__le16 fc;
-	struct ieee80211_hdr *hdr;
+	int tid = MAX_TID_COUNT;
+	int sta_id;
+	int freed;
 	u8 *qc = NULL;
 
 	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
@@ -2178,8 +2161,7 @@
 	memset(&info->status, 0, sizeof(info->status));
 
 	hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
-	fc = hdr->frame_control;
-	if (ieee80211_is_data_qos(fc)) {
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
 		qc = ieee80211_get_qos_ctl(hdr);
 		tid = qc[0] & 0xf;
 	}
@@ -2194,8 +2176,7 @@
 		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
 		struct iwl_ht_agg *agg = NULL;
 
-		if (!qc)
-			return;
+		WARN_ON(!qc);
 
 		agg = &priv->stations[sta_id].tid[tid].agg;
 
@@ -2206,54 +2187,49 @@
 			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
 		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-			int freed, ampdu_q;
 			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
 			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
 					   "%d index %d\n", scd_ssn , index);
 			freed = iwl_tx_queue_reclaim(priv, txq_id, index);
 			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
 
-			if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-			    txq_id >= 0 && priv->mac80211_registered &&
-			    agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
-				/* calculate mac80211 ampdu sw queue to wake */
-				ampdu_q = txq_id - IWL49_FIRST_AMPDU_QUEUE +
-					  priv->hw->queues;
+			if (priv->mac80211_registered &&
+			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
 				if (agg->state == IWL_AGG_OFF)
 					ieee80211_wake_queue(priv->hw, txq_id);
 				else
-					ieee80211_wake_queue(priv->hw, ampdu_q);
+					ieee80211_wake_queue(priv->hw,
+							     txq->swq_id);
 			}
-			iwl_txq_check_empty(priv, sta_id, tid, txq_id);
 		}
 	} else {
-		info->status.retry_count = tx_resp->failure_frame;
-		info->flags |=
-			iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0;
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags |= iwl_is_tx_success(status) ?
+					IEEE80211_TX_STAT_ACK : 0;
 		iwl_hwrate_to_tx_control(priv,
 					le32_to_cpu(tx_resp->rate_n_flags),
 					info);
 
-		IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags "
-			     "0x%x retries %d\n", txq_id,
-				iwl_get_tx_fail_reason(status),
-				status, le32_to_cpu(tx_resp->rate_n_flags),
-				tx_resp->failure_frame);
+		IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) "
+				   "rate_n_flags 0x%x retries %d\n",
+				   txq_id,
+				   iwl_get_tx_fail_reason(status), status,
+				   le32_to_cpu(tx_resp->rate_n_flags),
+				   tx_resp->failure_frame);
 
-		IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-
-		if (index != -1) {
-		    int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-		    if (tid != MAX_TID_COUNT)
+		freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+		if (qc && likely(sta_id != IWL_INVALID_STATION))
 			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-		    if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-			(txq_id >= 0) && priv->mac80211_registered)
+
+		if (priv->mac80211_registered &&
+		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
 			ieee80211_wake_queue(priv->hw, txq_id);
-		    if (tid != MAX_TID_COUNT)
-			iwl_txq_check_empty(priv, sta_id, tid, txq_id);
-		}
 	}
 
+	if (qc && likely(sta_id != IWL_INVALID_STATION))
+		iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+
 	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
 		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
@@ -2347,7 +2323,7 @@
 		.reset = iwl4965_apm_reset,
 		.stop = iwl4965_apm_stop,
 		.config = iwl4965_nic_config,
-		.set_pwr_src = iwl4965_set_pwr_src,
+		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -2362,11 +2338,11 @@
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
-		.check_version = iwl4965_eeprom_check_version,
+		.calib_version = iwl4965_eeprom_calib_version,
 		.query_addr = iwlcore_eeprom_query_addr,
 	},
 	.send_tx_power	= iwl4965_send_tx_power,
-	.update_chain_flags = iwl4965_update_chain_flags,
+	.update_chain_flags = iwl_update_chain_flags,
 	.temperature = iwl4965_temperature_calib,
 };
 
@@ -2381,6 +2357,8 @@
 	.fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
 	.ops = &iwl4965_ops,
 	.mod_params = &iwl4965_mod_params,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index c479ee2..12c7404 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -73,33 +73,34 @@
 #define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
 #define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
 
-/* EERPROM */
+/* EEPROM */
 #define IWL_5000_EEPROM_IMG_SIZE			2048
 
-
-#define IWL50_MAX_WIN_SIZE                64
-#define IWL50_QUEUE_SIZE                 256
 #define IWL50_CMD_FIFO_NUM                 7
 #define IWL50_NUM_QUEUES                  20
 #define IWL50_NUM_AMPDU_QUEUES		  10
 #define IWL50_FIRST_AMPDU_QUEUE		  10
 
-#define IWL_sta_id_POS 12
-#define IWL_sta_id_LEN 4
-#define IWL_sta_id_SYM val
-
 /* Fixed (non-configurable) rx data from phy */
 
-/* Base physical address of iwl5000_shared is provided to SCD_DRAM_BASE_ADDR
- * and &iwl5000_shared.val0 is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG */
-struct iwl5000_sched_queue_byte_cnt_tbl {
-	struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL50_QUEUE_SIZE +
-						       IWL50_MAX_WIN_SIZE];
+/**
+ * struct iwl5000_schedq_bc_tbl scheduler byte count table
+ * 	base physical address of iwl5000_shared
+ * 	is provided to SCD_DRAM_BASE_ADDR
+ * @tfd_offset  0-12 - tx command byte count
+ *	       12-16 - station index
+ */
+struct iwl5000_schedq_bc_tbl {
+	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
 } __attribute__ ((packed));
 
+/**
+ * struct iwl5000_shared
+ * @rb_closed
+ * 	address is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG
+ */
 struct iwl5000_shared {
-	struct iwl5000_sched_queue_byte_cnt_tbl
-	 queues_byte_cnt_tbls[IWL50_NUM_QUEUES];
+	struct iwl5000_schedq_bc_tbl queues_bc_tbls[IWL50_NUM_QUEUES];
 	__le32 rb_closed;
 
 	/* __le32 rb_closed_stts_rb_num:12; */
@@ -129,13 +130,5 @@
 	__le32 padding2;
 } __attribute__ ((packed));
 
-/* calibrations defined for 5000 */
-/* defines the order in which results should be sent to the runtime uCode */
-enum iwl5000_calib {
-	IWL5000_CALIB_LO,
-	IWL5000_CALIB_TX_IQ,
-	IWL5000_CALIB_TX_IQ_PERD,
-};
-
 #endif /* __iwl_5000_hw_h__ */
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 5155b8a..31e62a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -46,6 +46,8 @@
 
 #define IWL5000_UCODE_API  "-1"
 
+#define IWL5000_MODULE_FIRMWARE "iwlwifi-5000" IWL5000_UCODE_API ".ucode"
+
 static const u16 iwl5000_default_queue_to_tx_fifo[] = {
 	IWL_TX_FIFO_AC3,
 	IWL_TX_FIFO_AC2,
@@ -92,7 +94,7 @@
 	iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
 		    CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
 
-	/* Set FH wait treshold to maximum (HW error during stress W/A) */
+	/* Set FH wait threshold to maximum (HW error during stress W/A) */
 	iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
 
 	/* enable HAP INTA to move device L1a -> L0s */
@@ -132,7 +134,7 @@
 	return ret;
 }
 
-/* FIXME: this is indentical to 4965 */
+/* FIXME: this is identical to 4965 */
 static void iwl5000_apm_stop(struct iwl_priv *priv)
 {
 	unsigned long flags;
@@ -217,7 +219,7 @@
 
 	/* L1 is enabled by BIOS */
 	if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
-		/* diable L0S disabled L1A enabled */
+		/* disable L0S disabled L1A enabled */
 		iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
 	else
 		/* L0S enabled L1A disabled */
@@ -291,30 +293,17 @@
 	return (address & ADDRESS_MSK) + (offset << 1);
 }
 
-static int iwl5000_eeprom_check_version(struct iwl_priv *priv)
+static u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
 {
-	u16 eeprom_ver;
 	struct iwl_eeprom_calib_hdr {
 		u8 version;
 		u8 pa_type;
 		u16 voltage;
 	} *hdr;
 
-	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-
 	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
 							EEPROM_5000_CALIB_ALL);
-
-	if (eeprom_ver < EEPROM_5000_EEPROM_VERSION ||
-	    hdr->version < EEPROM_5000_TX_POWER_VERSION)
-		goto err;
-
-	return 0;
-err:
-	IWL_ERROR("Unsuported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
-		  eeprom_ver, EEPROM_5000_EEPROM_VERSION,
-		  hdr->version, EEPROM_5000_TX_POWER_VERSION);
-	return -EINVAL;
+	return hdr->version;
 
 }
 
@@ -348,10 +337,10 @@
 			data->delta_gain_code[1], data->delta_gain_code[2]);
 
 	if (!data->radio_write) {
-		struct iwl5000_calibration_chain_noise_gain_cmd cmd;
+		struct iwl_calib_chain_noise_gain_cmd cmd;
 		memset(&cmd, 0, sizeof(cmd));
 
-		cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
+		cmd.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
 		cmd.delta_gain_1 = data->delta_gain_code[1];
 		cmd.delta_gain_2 = data->delta_gain_code[2];
 		iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
@@ -375,10 +364,10 @@
 	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
 
 	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
-		struct iwl5000_calibration_chain_noise_reset_cmd cmd;
+		struct iwl_calib_chain_noise_reset_cmd cmd;
 
 		memset(&cmd, 0, sizeof(cmd));
-		cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
+		cmd.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
 		if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
 			sizeof(cmd), &cmd))
 			IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
@@ -390,8 +379,8 @@
 static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
 			__le32 *tx_flags)
 {
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
+	if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
 		*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
 	else
 		*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
@@ -429,28 +418,27 @@
 /*
  *  Calibration
  */
-static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
+static int iwl5000_set_Xtal_calib(struct iwl_priv *priv)
 {
+	u8 data[sizeof(struct iwl_calib_hdr) +
+		sizeof(struct iwl_cal_xtal_freq)];
+	struct iwl_calib_cmd *cmd = (struct iwl_calib_cmd *)data;
+	struct iwl_cal_xtal_freq *xtal = (struct iwl_cal_xtal_freq *)cmd->data;
 	u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
 
-	struct iwl5000_calibration cal_cmd = {
-		.op_code = IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD,
-		.data = {
-			(u8)xtal_calib[0],
-			(u8)xtal_calib[1],
-		}
-	};
-
-	return iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-				sizeof(cal_cmd), &cal_cmd);
+	cmd->hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
+	xtal->cap_pin1 = (u8)xtal_calib[0];
+	xtal->cap_pin2 = (u8)xtal_calib[1];
+	return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
+			     data, sizeof(data));
 }
 
 static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
 {
-	struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
+	struct iwl_calib_cfg_cmd calib_cfg_cmd;
 	struct iwl_host_cmd cmd = {
 		.id = CALIBRATION_CFG_CMD,
-		.len = sizeof(struct iwl5000_calib_cfg_cmd),
+		.len = sizeof(struct iwl_calib_cfg_cmd),
 		.data = &calib_cfg_cmd,
 	};
 
@@ -467,7 +455,7 @@
 			     struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-	struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
+	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
 	int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
 	int index;
 
@@ -478,14 +466,14 @@
 	 * uCode. iwl_send_calib_results sends them in a row according to their
 	 * index. We sort them here */
 	switch (hdr->op_code) {
-	case IWL5000_PHY_CALIBRATE_LO_CMD:
-		index = IWL5000_CALIB_LO;
+	case IWL_PHY_CALIBRATE_LO_CMD:
+		index = IWL_CALIB_LO;
 		break;
-	case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
-		index = IWL5000_CALIB_TX_IQ;
+	case IWL_PHY_CALIBRATE_TX_IQ_CMD:
+		index = IWL_CALIB_TX_IQ;
 		break;
-	case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
-		index = IWL5000_CALIB_TX_IQ_PERD;
+	case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD:
+		index = IWL_CALIB_TX_IQ_PERD;
 		break;
 	default:
 		IWL_ERROR("Unknown calibration notification %d\n",
@@ -535,7 +523,7 @@
 
 	iwl_write_direct32(priv,
 		FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
-		(iwl_get_dma_hi_address(phy_addr)
+		(iwl_get_dma_hi_addr(phy_addr)
 			<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
 
 	iwl_write_direct32(priv,
@@ -547,7 +535,7 @@
 	iwl_write_direct32(priv,
 		FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
 		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE	|
-		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL |
+		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|
 		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
 	iwl_release_nic_access(priv);
@@ -561,14 +549,13 @@
 {
 	int ret = 0;
 
-	ret = iwl5000_load_section(
-		priv, inst_image, RTC_INST_LOWER_BOUND);
+	ret = iwl5000_load_section(priv, inst_image, RTC_INST_LOWER_BOUND);
 	if (ret)
 		return ret;
 
 	IWL_DEBUG_INFO("INST uCode section being loaded...\n");
 	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-				priv->ucode_write_complete, 5 * HZ);
+					priv->ucode_write_complete, 5 * HZ);
 	if (ret == -ERESTARTSYS) {
 		IWL_ERROR("Could not load the INST uCode section due "
 			"to interrupt\n");
@@ -682,7 +669,7 @@
 					int tx_fifo_id, int scd_retry)
 {
 	int txq_id = txq->q.id;
-	int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
 
 	iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
 			(active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
@@ -735,7 +722,7 @@
 
 	iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
 		(priv->shared_phys +
-		 offsetof(struct iwl5000_shared, queues_byte_cnt_tbls)) >> 10);
+		 offsetof(struct iwl5000_shared, queues_bc_tbls)) >> 10);
 	iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
 		IWL50_SCD_QUEUECHAIN_SEL_ALL(
 			priv->hw_params.max_txq_num));
@@ -765,6 +752,7 @@
 	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
 
 	iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+
 	/* map qos queues to fifos one-to-one */
 	for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
 		int ac = iwl5000_default_queue_to_tx_fifo[i];
@@ -784,10 +772,8 @@
 
 	iwl5000_send_wimax_coex(priv);
 
-	iwl5000_send_Xtal_calib(priv);
-
-	if (priv->ucode_type == UCODE_RT)
-		iwl_send_calib_results(priv);
+	iwl5000_set_Xtal_calib(priv);
+	iwl_send_calib_results(priv);
 
 	return 0;
 }
@@ -802,7 +788,6 @@
 	}
 
 	priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
-	priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE;
 	priv->hw_params.max_stations = IWL5000_STATION_COUNT;
 	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
 	priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
@@ -814,10 +799,14 @@
 
 	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
 	case CSR_HW_REV_TYPE_5100:
+		priv->hw_params.tx_chains_num = 1;
+		priv->hw_params.rx_chains_num = 2;
+		priv->hw_params.valid_tx_ant = ANT_B;
+		priv->hw_params.valid_rx_ant = ANT_AB;
+		break;
 	case CSR_HW_REV_TYPE_5150:
 		priv->hw_params.tx_chains_num = 1;
 		priv->hw_params.rx_chains_num = 2;
-		/* FIXME: move to ANT_A, ANT_B, ANT_C enum */
 		priv->hw_params.valid_tx_ant = ANT_A;
 		priv->hw_params.valid_rx_ant = ANT_AB;
 		break;
@@ -844,6 +833,23 @@
 		break;
 	}
 
+	/* Set initial calibration set */
+	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+	case CSR_HW_REV_TYPE_5100:
+	case CSR_HW_REV_TYPE_5300:
+	case CSR_HW_REV_TYPE_5350:
+		priv->hw_params.calib_init_cfg =
+			BIT(IWL_CALIB_XTAL)		|
+			BIT(IWL_CALIB_LO)		|
+			BIT(IWL_CALIB_TX_IQ) 	|
+			BIT(IWL_CALIB_TX_IQ_PERD);
+		break;
+	case CSR_HW_REV_TYPE_5150:
+		priv->hw_params.calib_init_cfg = 0;
+		break;
+	}
+
+
 	return 0;
 }
 
@@ -885,15 +891,17 @@
 					    u16 byte_cnt)
 {
 	struct iwl5000_shared *shared_data = priv->shared_virt;
+	int write_ptr = txq->q.write_ptr;
 	int txq_id = txq->q.id;
 	u8 sec_ctl = 0;
-	u8 sta = 0;
-	int len;
+	u8 sta_id = 0;
+	u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	__le16 bc_ent;
 
-	len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
 
 	if (txq_id != IWL_CMD_QUEUE_NUM) {
-		sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
+		sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
 		sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
 
 		switch (sec_ctl & TX_CMD_SEC_MSK) {
@@ -909,40 +917,36 @@
 		}
 	}
 
-	IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-		       tfd_offset[txq->q.write_ptr], byte_cnt, len);
+	bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
 
-	IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-		       tfd_offset[txq->q.write_ptr], sta_id, sta);
+	shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent;
 
-	if (txq->q.write_ptr < IWL50_MAX_WIN_SIZE) {
-		IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-			tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr],
-			byte_cnt, len);
-		IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-			tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr],
-			sta_id, sta);
-	}
+	if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		shared_data->queues_bc_tbls[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
 static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
 					   struct iwl_tx_queue *txq)
 {
-	int txq_id = txq->q.id;
 	struct iwl5000_shared *shared_data = priv->shared_virt;
-	u8 sta = 0;
+	int txq_id = txq->q.id;
+	int read_ptr = txq->q.read_ptr;
+	u8 sta_id = 0;
+	__le16 bc_ent;
+
+	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
 
 	if (txq_id != IWL_CMD_QUEUE_NUM)
-		sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id;
+		sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
 
-	shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr].
-					val = cpu_to_le16(1 | (sta << 12));
+	bc_ent =  cpu_to_le16(1 | (sta_id << 12));
+	shared_data->queues_bc_tbls[txq_id].
+			tfd_offset[read_ptr] = bc_ent;
 
-	if (txq->q.write_ptr < IWL50_MAX_WIN_SIZE) {
-		shared_data->queues_byte_cnt_tbls[txq_id].
-			tfd_offset[IWL50_QUEUE_SIZE + txq->q.read_ptr].
-				val = cpu_to_le16(1 | (sta << 12));
-	}
+	if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		shared_data->queues_bc_tbls[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =  bc_ent;
 }
 
 static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
@@ -1089,7 +1093,7 @@
 
 
 /*
- * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
  * must be called under priv->lock and mac access
  */
 static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
@@ -1136,10 +1140,10 @@
 				   agg->frame_count, agg->start_idx, idx);
 
 		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
-		info->status.retry_count = tx_resp->failure_frame;
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
 		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
 		info->flags |= iwl_is_tx_success(status)?
-			IEEE80211_TX_STAT_ACK : 0;
+					IEEE80211_TX_STAT_ACK : 0;
 		iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
 
 		/* FIXME: code repetition end */
@@ -1225,9 +1229,9 @@
 	struct ieee80211_tx_info *info;
 	struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32  status = le16_to_cpu(tx_resp->status.status);
-	int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
-	struct ieee80211_hdr *hdr;
-	u8 *qc = NULL;
+	int tid;
+	int sta_id;
+	int freed;
 
 	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
 		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
@@ -1240,25 +1244,13 @@
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
 	memset(&info->status, 0, sizeof(info->status));
 
-	hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
-	if (ieee80211_is_data_qos(hdr->frame_control)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & 0xf;
-	}
-
-	sta_id = iwl_get_ra_sta_id(priv, hdr);
-	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-		IWL_ERROR("Station not known\n");
-		return;
-	}
+	tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
+	sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
 
 	if (txq->sched_retry) {
 		const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
 		struct iwl_ht_agg *agg = NULL;
 
-		if (!qc)
-			return;
-
 		agg = &priv->stations[sta_id].tid[tid].agg;
 
 		iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
@@ -1268,58 +1260,58 @@
 			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
 		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-			int freed, ampdu_q;
 			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
-					   "%d index %d\n", scd_ssn , index);
+			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim "
+					"scd_ssn=%d idx=%d txq=%d swq=%d\n",
+					scd_ssn , index, txq_id, txq->swq_id);
+
 			freed = iwl_tx_queue_reclaim(priv, txq_id, index);
 			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
 
-			if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-			    txq_id >= 0 && priv->mac80211_registered &&
-			    agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
-				/* calculate mac80211 ampdu sw queue to wake */
-				ampdu_q = txq_id - IWL50_FIRST_AMPDU_QUEUE +
-					  priv->hw->queues;
+			if (priv->mac80211_registered &&
+			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
 				if (agg->state == IWL_AGG_OFF)
 					ieee80211_wake_queue(priv->hw, txq_id);
 				else
-					ieee80211_wake_queue(priv->hw, ampdu_q);
+					ieee80211_wake_queue(priv->hw,
+							     txq->swq_id);
 			}
-			iwl_txq_check_empty(priv, sta_id, tid, txq_id);
 		}
 	} else {
-		info->status.retry_count = tx_resp->failure_frame;
-		info->flags =
-			iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0;
+		BUG_ON(txq_id != txq->swq_id);
+
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags |= iwl_is_tx_success(status) ?
+					IEEE80211_TX_STAT_ACK : 0;
 		iwl_hwrate_to_tx_control(priv,
 					le32_to_cpu(tx_resp->rate_n_flags),
 					info);
 
-		IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags "
-			     "0x%x retries %d\n", txq_id,
-				iwl_get_tx_fail_reason(status),
-				status, le32_to_cpu(tx_resp->rate_n_flags),
-				tx_resp->failure_frame);
+		IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) rate_n_flags "
+				   "0x%x retries %d\n",
+				   txq_id,
+				   iwl_get_tx_fail_reason(status), status,
+				   le32_to_cpu(tx_resp->rate_n_flags),
+				   tx_resp->failure_frame);
 
-		IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-		if (index != -1) {
-		    int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-		    if (tid != MAX_TID_COUNT)
+		freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+		if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
 			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-		    if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-			(txq_id >= 0) && priv->mac80211_registered)
+
+		if (priv->mac80211_registered &&
+		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
 			ieee80211_wake_queue(priv->hw, txq_id);
-		    if (tid != MAX_TID_COUNT)
-			iwl_txq_check_empty(priv, sta_id, tid, txq_id);
-		}
 	}
 
+	if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
+		iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+
 	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
 		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
 
-/* Currently 5000 is the supperset of everything */
+/* Currently 5000 is the superset of everything */
 static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
 {
 	return len;
@@ -1482,13 +1474,13 @@
 	.alive_notify = iwl5000_alive_notify,
 	.send_tx_power = iwl5000_send_tx_power,
 	.temperature = iwl5000_temperature,
-	.update_chain_flags = iwl4965_update_chain_flags,
+	.update_chain_flags = iwl_update_chain_flags,
 	.apm_ops = {
 		.init =	iwl5000_apm_init,
 		.reset = iwl5000_apm_reset,
 		.stop = iwl5000_apm_stop,
 		.config = iwl5000_nic_config,
-		.set_pwr_src = iwl4965_set_pwr_src,
+		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -1503,7 +1495,7 @@
 		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
-		.check_version	= iwl5000_eeprom_check_version,
+		.calib_version	= iwl5000_eeprom_calib_version,
 		.query_addr = iwl5000_eeprom_query_addr,
 	},
 };
@@ -1526,50 +1518,60 @@
 
 struct iwl_cfg iwl5300_agn_cfg = {
 	.name = "5300AGN",
-	.fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+	.fw_name = IWL5000_MODULE_FIRMWARE,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 };
 
 struct iwl_cfg iwl5100_bg_cfg = {
 	.name = "5100BG",
-	.fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+	.fw_name = IWL5000_MODULE_FIRMWARE,
 	.sku = IWL_SKU_G,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 };
 
 struct iwl_cfg iwl5100_abg_cfg = {
 	.name = "5100ABG",
-	.fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+	.fw_name = IWL5000_MODULE_FIRMWARE,
 	.sku = IWL_SKU_A|IWL_SKU_G,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
 	.name = "5100AGN",
-	.fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+	.fw_name = IWL5000_MODULE_FIRMWARE,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 };
 
 struct iwl_cfg iwl5350_agn_cfg = {
 	.name = "5350AGN",
-	.fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+	.fw_name = IWL5000_MODULE_FIRMWARE,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 };
 
-MODULE_FIRMWARE("iwlwifi-5000" IWL5000_UCODE_API ".ucode");
+MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE);
 
 module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
 MODULE_PARM_DESC(disable50,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index e2a58e4..0332805 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -188,7 +188,7 @@
  * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
  * "G" is the only table that supports CCK (the first 4 rates).
  */
-/*FIXME:RS:need to spearate tables for MIMO2/MIMO3*/
+/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/
 static s32 expected_tpt_A[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
 };
@@ -357,11 +357,9 @@
 				      struct iwl_lq_sta *lq_data, u8 tid,
 				      struct ieee80211_sta *sta)
 {
-	DECLARE_MAC_BUF(mac);
-
 	if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
-		IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
-				print_mac(mac, sta->addr), tid);
+		IWL_DEBUG_HT("Starting Tx agg: STA: %pM tid: %d\n",
+				sta->addr, tid);
 		ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
 	}
 }
@@ -800,7 +798,7 @@
 	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
 		return;
 
-	retries = info->status.retry_count;
+	retries = info->status.rates[0].count - 1;
 
 	if (retries > 15)
 		retries = 15;
@@ -832,20 +830,15 @@
 	if (priv->band == IEEE80211_BAND_5GHZ)
 		rs_index -= IWL_FIRST_OFDM_RATE;
 
-	if ((info->tx_rate_idx < 0) ||
-	    (tbl_type.is_SGI ^
-		!!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) ||
-	    (tbl_type.is_fat ^
-		!!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) ||
-	    (tbl_type.is_dup ^
-		!!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) ||
-	    (tbl_type.ant_type ^ info->antenna_sel_tx) ||
-	    (!!(tx_rate & RATE_MCS_HT_MSK) ^
-		!!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) ||
-	    (!!(tx_rate & RATE_MCS_GF_MSK) ^
-		!!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) ||
+	if ((info->status.rates[0].idx < 0) ||
+	    (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
+	    (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+	    (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
+	    (tbl_type.ant_type != info->antenna_sel_tx) ||
+	    (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
+	    (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
 	    (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
-	     hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) {
+	     hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) {
 		IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate);
 		goto out;
 	}
@@ -1135,11 +1128,10 @@
 	s32 rate;
 	s8 is_green = lq_sta->is_green;
 
-	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
-	    !sta->ht_info.ht_supported)
+	if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
 		return -1;
 
-	if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+	if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
 						== WLAN_HT_CAP_SM_PS_STATIC)
 		return -1;
 
@@ -1203,8 +1195,7 @@
 	u8 is_green = lq_sta->is_green;
 	s32 rate;
 
-	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
-	    !sta->ht_info.ht_supported)
+	if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
 		return -1;
 
 	IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@@ -2003,9 +1994,8 @@
 		 * stay with best antenna legacy modulation for a while
 		 * before next round of mode comparisons. */
 		tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
-		if (is_legacy(tbl1->lq_type) &&
-		   (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) &&
-		    (lq_sta->action_counter >= 1)) {
+		if (is_legacy(tbl1->lq_type) && !conf->ht.enabled &&
+		    lq_sta->action_counter >= 1) {
 			lq_sta->action_counter = 0;
 			IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
 			rs_set_stay_in_table(priv, 1, lq_sta);
@@ -2081,15 +2071,13 @@
 	if ((i < 0) || (i >= IWL_RATE_COUNT))
 		i = 0;
 
-	/* FIXME:RS: This is also wrong in 4965 */
 	rate = iwl_rates[i].plcp;
-	rate |= RATE_MCS_ANT_B_MSK;
-	rate &= ~RATE_MCS_ANT_A_MSK;
+	tbl->ant_type = first_antenna(valid_tx_ant);
+	rate |= tbl->ant_type << RATE_MCS_ANT_POS;
 
 	if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
 		rate |= RATE_MCS_CCK_MSK;
 
-	tbl->ant_type = ANT_B;
 	rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
 	if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
 	    rs_toggle_antenna(valid_tx_ant, &rate, tbl);
@@ -2103,15 +2091,17 @@
 	return;
 }
 
-static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
-			struct ieee80211_sta *sta, void *priv_sta,
-			struct sk_buff *skb, struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
+			struct ieee80211_tx_rate_control *txrc)
 {
 
 	int i;
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_supported_band *sband = txrc->sband;
 	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
 	struct ieee80211_conf *conf = &priv->hw->conf;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	__le16 fc;
 	struct iwl_lq_sta *lq_sta;
 
@@ -2122,7 +2112,7 @@
 	fc = hdr->frame_control;
 	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
 	    !sta || !priv_sta) {
-		sel->rate_idx = rate_lowest_index(sband, sta);
+		info->control.rates[0].idx = rate_lowest_index(sband, sta);
 		return;
 	}
 
@@ -2132,11 +2122,10 @@
 	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
 	    !lq_sta->ibss_sta_added) {
 		u8 sta_id = iwl_find_station(priv, hdr->addr1);
-		DECLARE_MAC_BUF(mac);
 
 		if (sta_id == IWL_INVALID_STATION) {
-			IWL_DEBUG_RATE("LQ: ADD station %s\n",
-				       print_mac(mac, hdr->addr1));
+			IWL_DEBUG_RATE("LQ: ADD station %pM\n",
+				       hdr->addr1);
 			sta_id = iwl_add_station_flags(priv, hdr->addr1,
 							0, CMD_ASYNC, NULL);
 		}
@@ -2149,13 +2138,13 @@
 	}
 
 	if ((i < 0) || (i > IWL_RATE_COUNT)) {
-		sel->rate_idx = rate_lowest_index(sband, sta);
+		info->control.rates[0].idx = rate_lowest_index(sband, sta);
 		return;
 	}
 
 	if (sband->band == IEEE80211_BAND_5GHZ)
 		i -= IWL_FIRST_OFDM_RATE;
-	sel->rate_idx = i;
+	info->control.rates[0].idx = i;
 }
 
 static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
@@ -2205,15 +2194,12 @@
 	lq_sta->ibss_sta_added = 0;
 	if (priv->iw_mode == NL80211_IFTYPE_AP) {
 		u8 sta_id = iwl_find_station(priv, sta->addr);
-		DECLARE_MAC_BUF(mac);
 
 		/* for IBSS the call are from tasklet */
-		IWL_DEBUG_RATE("LQ: ADD station %s\n",
-			     print_mac(mac, sta->addr));
+		IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr);
 
 		if (sta_id == IWL_INVALID_STATION) {
-			IWL_DEBUG_RATE("LQ: ADD station %s\n",
-				       print_mac(mac, sta->addr));
+			IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr);
 			sta_id = iwl_add_station_flags(priv, sta->addr,
 							0, CMD_ASYNC, NULL);
 		}
@@ -2244,19 +2230,19 @@
 	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
 	 * supp_rates[] does not; shift to convert format, force 9 MBits off.
 	 */
-	lq_sta->active_siso_rate = conf->ht_conf.supp_mcs_set[0] << 1;
-	lq_sta->active_siso_rate |= conf->ht_conf.supp_mcs_set[0] & 0x1;
+	lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1;
+	lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1;
 	lq_sta->active_siso_rate &= ~((u16)0x2);
 	lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
 
 	/* Same here */
-	lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1;
-	lq_sta->active_mimo2_rate |= conf->ht_conf.supp_mcs_set[1] & 0x1;
+	lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1;
+	lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1;
 	lq_sta->active_mimo2_rate &= ~((u16)0x2);
 	lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
 
-	lq_sta->active_mimo3_rate = conf->ht_conf.supp_mcs_set[2] << 1;
-	lq_sta->active_mimo3_rate |= conf->ht_conf.supp_mcs_set[2] & 0x1;
+	lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1;
+	lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1;
 	lq_sta->active_mimo3_rate &= ~((u16)0x2);
 	lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
 
@@ -2265,7 +2251,7 @@
 		     lq_sta->active_mimo2_rate,
 		     lq_sta->active_mimo3_rate);
 
-	/* These values will be overriden later */
+	/* These values will be overridden later */
 	lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
 	lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
 
@@ -2405,19 +2391,6 @@
 	return;
 }
 
-static void rs_clear(void *priv_rate)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
-
-	IWL_DEBUG_RATE("enter\n");
-
-	/* TODO - add rate scale state reset */
-
-	IWL_DEBUG_RATE("leave\n");
-#endif /* CONFIG_IWLWIFI_DEBUG */
-}
-
 static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
 			void *priv_sta)
 {
@@ -2605,7 +2578,6 @@
 	.tx_status = rs_tx_status,
 	.get_rate = rs_get_rate,
 	.rate_init = rs_rate_init,
-	.clear = rs_clear,
 	.alloc = rs_alloc,
 	.free = rs_free,
 	.alloc_sta = rs_alloc_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index d148d73..adcbf53 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -229,7 +229,7 @@
 #define IWL_MIMO2_SWITCH_SISO_C         4
 #define IWL_MIMO2_SWITCH_GI             5
 
-/*FIXME:RS:add posible acctions for MIMO3*/
+/*FIXME:RS:add possible actions for MIMO3*/
 
 #define IWL_ACTION_LIMIT		3	/* # possible actions */
 
@@ -284,7 +284,17 @@
 		!!((mask) & ANT_C);
 }
 
-static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
+static inline u8 first_antenna(u8 mask)
+{
+	if (mask & ANT_A)
+		return ANT_A;
+	if (mask & ANT_B)
+		return ANT_B;
+	return ANT_C;
+}
+
+
+static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
 {
 	u8 rate = iwl_rates[rate_index].prev_ieee;
 
@@ -294,11 +304,11 @@
 }
 
 /**
- * iwl4965_rate_control_register - Register the rate control algorithm callbacks
+ * iwl_rate_control_register - Register the rate control algorithm callbacks
  *
  * Since the rate control algorithm is hardware specific, there is no need
  * or reason to place it as a stand alone module.  The driver can call
- * iwl4965_rate_control_register in order to register the rate control callbacks
+ * iwl_rate_control_register in order to register the rate control callbacks
  * with the mac80211 subsystem.  This should be performed prior to calling
  * ieee80211_register_hw
  *
@@ -306,7 +316,7 @@
 extern int iwlagn_rate_control_register(void);
 
 /**
- * iwl4965_rate_control_unregister - Unregister the rate control callbacks
+ * iwl_rate_control_unregister - Unregister the rate control callbacks
  *
  * This should be called after calling ieee80211_unregister_hw, but before
  * the driver is unloaded.
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8d690a0..8264d37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -96,7 +96,7 @@
 
 
 
-static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
 {
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 
@@ -108,13 +108,13 @@
 }
 
 /**
- * iwl4965_check_rxon_cmd - validate RXON structure is valid
+ * iwl_check_rxon_cmd - validate RXON structure is valid
  *
  * NOTE:  This is really only useful during development and can eventually
  * be #ifdef'd out once the driver is stable and folks aren't actively
  * making changes
  */
-static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
+static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
 {
 	int error = 0;
 	int counter = 1;
@@ -174,7 +174,7 @@
 			    le16_to_cpu(rxon->channel));
 
 	if (error) {
-		IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
+		IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
 		return -1;
 	}
 	return 0;
@@ -228,18 +228,17 @@
 }
 
 /**
- * iwl4965_commit_rxon - commit staging_rxon to hardware
+ * iwl_commit_rxon - commit staging_rxon to hardware
  *
  * The RXON command in staging_rxon is committed to the hardware and
  * the active_rxon structure is updated with the new data.  This
  * function correctly transitions out of the RXON_ASSOC_MSK state if
  * a HW tune is required based on the RXON structure changes.
  */
-static int iwl4965_commit_rxon(struct iwl_priv *priv)
+static int iwl_commit_rxon(struct iwl_priv *priv)
 {
 	/* cast away the const for active_rxon in this function */
 	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
-	DECLARE_MAC_BUF(mac);
 	int ret;
 	bool new_assoc =
 		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
@@ -253,14 +252,14 @@
 	 * 5000, but will not damage 4965 */
 	priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
 
-	ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
+	ret = iwl_check_rxon_cmd(&priv->staging_rxon);
 	if (ret) {
 		IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
 		return -EINVAL;
 	}
 
 	/* If we don't need to send a full RXON, we can use
-	 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
 	 * and other flags for the current radio configuration. */
 	if (!iwl_full_rxon_required(priv)) {
 		ret = iwl_send_rxon_assoc(priv);
@@ -300,12 +299,12 @@
 	IWL_DEBUG_INFO("Sending RXON\n"
 		       "* with%s RXON_FILTER_ASSOC_MSK\n"
 		       "* channel = %d\n"
-		       "* bssid = %s\n",
+		       "* bssid = %pM\n",
 		       (new_assoc ? "" : "out"),
 		       le16_to_cpu(priv->staging_rxon.channel),
-		       print_mac(mac, priv->staging_rxon.bssid_addr));
+		       priv->staging_rxon.bssid_addr);
 
-	iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
 
 	/* Apply the new configuration
 	 * RXON unassoc clears the station table in uCode, send it before
@@ -375,14 +374,14 @@
 	return 0;
 }
 
-void iwl4965_update_chain_flags(struct iwl_priv *priv)
+void iwl_update_chain_flags(struct iwl_priv *priv)
 {
 
 	iwl_set_rxon_chain(priv);
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 }
 
-static int iwl4965_send_bt_config(struct iwl_priv *priv)
+static int iwl_send_bt_config(struct iwl_priv *priv)
 {
 	struct iwl4965_bt_cmd bt_cmd = {
 		.flags = 3,
@@ -460,7 +459,7 @@
 	return priv->ibss_beacon->len;
 }
 
-static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
+static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
 {
 	int i;
 	int rate_mask;
@@ -485,7 +484,7 @@
 		return IWL_RATE_6M_PLCP;
 }
 
-static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
 				       struct iwl_frame *frame, u8 rate)
 {
 	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
@@ -517,7 +516,7 @@
 
 	return sizeof(*tx_beacon_cmd) + frame_size;
 }
-static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+static int iwl_send_beacon_cmd(struct iwl_priv *priv)
 {
 	struct iwl_frame *frame;
 	unsigned int frame_size;
@@ -532,9 +531,9 @@
 		return -ENOMEM;
 	}
 
-	rate = iwl4965_rate_get_lowest_plcp(priv);
+	rate = iwl_rate_get_lowest_plcp(priv);
 
-	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
+	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
 
 	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
 			      &frame->u.cmd[0]);
@@ -550,20 +549,33 @@
  *
  ******************************************************************************/
 
-static void iwl4965_ht_conf(struct iwl_priv *priv,
+static void iwl_ht_conf(struct iwl_priv *priv,
 			    struct ieee80211_bss_conf *bss_conf)
 {
-	struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
-	struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
+	struct ieee80211_sta_ht_cap *ht_conf;
 	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
 
 	IWL_DEBUG_MAC80211("enter: \n");
 
-	iwl_conf->is_ht = bss_conf->assoc_ht;
-
 	if (!iwl_conf->is_ht)
 		return;
 
+
+	/*
+	 * It is totally wrong to base global information on something
+	 * that is valid only when associated, alas, this driver works
+	 * that way and I don't know how to fix it.
+	 */
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(priv->hw, priv->bssid);
+	if (!sta) {
+		rcu_read_unlock();
+		return;
+	}
+	ht_conf = &sta->ht_cap;
+
 	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
 		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
 	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
@@ -574,29 +586,28 @@
 		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
 
 	iwl_conf->supported_chan_width =
-		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
-	iwl_conf->extension_chan_offset =
-		ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
+		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+
+	iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset;
 	/* If no above or below channel supplied disable FAT channel */
-	if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE &&
-	    iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) {
-		iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE;
+	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
+	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) {
+		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
 		iwl_conf->supported_chan_width = 0;
 	}
 
 	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
 
-	memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
+	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
 
-	iwl_conf->control_channel = ht_bss_conf->primary_channel;
-	iwl_conf->tx_chan_width =
-		!!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
+	iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok;
 	iwl_conf->ht_protection =
-		ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
+		bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
 	iwl_conf->non_GF_STA_present =
-		!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
+		!!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 
-	IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
+	rcu_read_unlock();
+
 	IWL_DEBUG_MAC80211("leave\n");
 }
 
@@ -637,23 +648,22 @@
 
 #define MAX_UCODE_BEACON_INTERVAL	4096
 
-static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
+static u16 iwl_adjust_beacon_interval(u16 beacon_val)
 {
 	u16 new_val = 0;
 	u16 beacon_factor = 0;
 
-	beacon_factor =
-	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
-		/ MAX_UCODE_BEACON_INTERVAL;
+	beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL)
+					/ MAX_UCODE_BEACON_INTERVAL;
 	new_val = beacon_val / beacon_factor;
 
-	return cpu_to_le16(new_val);
+	return new_val;
 }
 
-static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
+static void iwl_setup_rxon_timing(struct iwl_priv *priv)
 {
-	u64 interval_tm_unit;
-	u64 tsf, result;
+	u64 tsf;
+	s32 interval_tm, rem;
 	unsigned long flags;
 	struct ieee80211_conf *conf = NULL;
 	u16 beacon_int = 0;
@@ -661,49 +671,32 @@
 	conf = ieee80211_get_hw_conf(priv->hw);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
-	priv->rxon_timing.timestamp.dw[0] =
-				cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
-
+	priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
 	priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
 
-	tsf = priv->timestamp;
-
-	beacon_int = priv->beacon_int;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
-		if (beacon_int == 0) {
-			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
-			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
-		} else {
-			priv->rxon_timing.beacon_interval =
-				cpu_to_le16(beacon_int);
-			priv->rxon_timing.beacon_interval =
-			    iwl4965_adjust_beacon_interval(
-				le16_to_cpu(priv->rxon_timing.beacon_interval));
-		}
-
+		beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
 		priv->rxon_timing.atim_window = 0;
 	} else {
-		priv->rxon_timing.beacon_interval =
-			iwl4965_adjust_beacon_interval(conf->beacon_int);
+		beacon_int = iwl_adjust_beacon_interval(conf->beacon_int);
+
 		/* TODO: we need to get atim_window from upper stack
 		 * for now we set to 0 */
 		priv->rxon_timing.atim_window = 0;
 	}
 
-	interval_tm_unit =
-		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
-	result = do_div(tsf, interval_tm_unit);
-	priv->rxon_timing.beacon_init_val =
-	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));
+	priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
 
-	IWL_DEBUG_ASSOC
-	    ("beacon interval %d beacon timer %d beacon tim %d\n",
-		le16_to_cpu(priv->rxon_timing.beacon_interval),
-		le32_to_cpu(priv->rxon_timing.beacon_init_val),
-		le16_to_cpu(priv->rxon_timing.atim_window));
+	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+	interval_tm = beacon_int * 1024;
+	rem = do_div(tsf, interval_tm);
+	priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	IWL_DEBUG_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n",
+			le16_to_cpu(priv->rxon_timing.beacon_interval),
+			le32_to_cpu(priv->rxon_timing.beacon_init_val),
+			le16_to_cpu(priv->rxon_timing.atim_window));
 }
 
 static void iwl_set_flags_for_band(struct iwl_priv *priv,
@@ -715,7 +708,7 @@
 		      | RXON_FLG_CCK_MSK);
 		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
 	} else {
-		/* Copied from iwl4965_post_associate() */
+		/* Copied from iwl_post_associate() */
 		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
 			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
@@ -733,13 +726,13 @@
 /*
  * initialize rxon structure with default values from eeprom
  */
-static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
+static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
 {
 	const struct iwl_channel_info *ch_info;
 
 	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
 
-	switch (priv->iw_mode) {
+	switch (mode) {
 	case NL80211_IFTYPE_AP:
 		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
 		break;
@@ -762,7 +755,7 @@
 		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
 		break;
 	default:
-		IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+		IWL_ERROR("Unsupported interface type %d\n", mode);
 		break;
 	}
 
@@ -808,11 +801,9 @@
 	iwl_set_rxon_chain(priv);
 }
 
-static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
+static int iwl_set_mode(struct iwl_priv *priv, int mode)
 {
-	priv->iw_mode = mode;
-
-	iwl4965_connection_init_rx_config(priv);
+	iwl_connection_init_rx_config(priv, mode);
 	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 
 	iwl_clear_stations_table(priv);
@@ -828,12 +819,12 @@
 		return -EAGAIN;
 	}
 
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 
 	return 0;
 }
 
-static void iwl4965_set_rate(struct iwl_priv *priv)
+static void iwl_set_rate(struct iwl_priv *priv)
 {
 	const struct ieee80211_supported_band *hw = NULL;
 	struct ieee80211_rate *rate;
@@ -895,7 +886,7 @@
  * the lower 3 bytes is the time in usec within one beacon interval
  */
 
-static u32 iwl4965_usecs_to_beacons(u32 usec, u32 beacon_interval)
+static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
 {
 	u32 quot;
 	u32 rem;
@@ -914,7 +905,7 @@
  * the same as HW timer counter counting down
  */
 
-static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
 {
 	u32 base_low = base & BEACON_TIME_MASK_LOW;
 	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
@@ -933,7 +924,7 @@
 	return cpu_to_le32(res);
 }
 
-static int iwl4965_get_measurement(struct iwl_priv *priv,
+static int iwl_get_measurement(struct iwl_priv *priv,
 			       struct ieee80211_measurement_params *params,
 			       u8 type)
 {
@@ -951,7 +942,7 @@
 
 	if (iwl_is_associated(priv))
 		add_time =
-		    iwl4965_usecs_to_beacons(
+		    iwl_usecs_to_beacons(
 			le64_to_cpu(params->start_time) - priv->last_tsf,
 			le16_to_cpu(priv->rxon_timing.beacon_interval));
 
@@ -966,7 +957,7 @@
 
 	if (iwl_is_associated(priv))
 		spectrum.start_time =
-		    iwl4965_add_beacon_time(priv->last_beacon_time,
+		    iwl_add_beacon_time(priv->last_beacon_time,
 				add_time,
 				le16_to_cpu(priv->rxon_timing.beacon_interval));
 	else
@@ -1054,7 +1045,7 @@
 		IWL_WARNING("uCode did not respond OK.\n");
 }
 
-static void iwl4965_rx_reply_error(struct iwl_priv *priv,
+static void iwl_rx_reply_error(struct iwl_priv *priv,
 				   struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1070,7 +1061,7 @@
 
 #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
 
-static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
@@ -1081,7 +1072,7 @@
 	priv->staging_rxon.channel = csa->channel;
 }
 
-static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb)
 {
 #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
@@ -1099,7 +1090,7 @@
 #endif
 }
 
-static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
+static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
 				      struct iwl_rx_mem_buffer *rxb)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -1110,7 +1101,7 @@
 #endif
 }
 
-static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
 					     struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1120,7 +1111,7 @@
 	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
 }
 
-static void iwl4965_bg_beacon_update(struct work_struct *work)
+static void iwl_bg_beacon_update(struct work_struct *work)
 {
 	struct iwl_priv *priv =
 		container_of(work, struct iwl_priv, beacon_update);
@@ -1142,11 +1133,11 @@
 	priv->ibss_beacon = beacon;
 	mutex_unlock(&priv->mutex);
 
-	iwl4965_send_beacon_cmd(priv);
+	iwl_send_beacon_cmd(priv);
 }
 
 /**
- * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+ * iwl_bg_statistics_periodic - Timer callback to queue statistics
  *
  * This callback is provided in order to send a statistics request.
  *
@@ -1155,17 +1146,21 @@
  * was received.  We need to ensure we receive the statistics in order
  * to update the temperature used for calibrating the TXPOWER.
  */
-static void iwl4965_bg_statistics_periodic(unsigned long data)
+static void iwl_bg_statistics_periodic(unsigned long data)
 {
 	struct iwl_priv *priv = (struct iwl_priv *)data;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	/* dont send host command if rf-kill is on */
+	if (!iwl_is_ready_rf(priv))
+		return;
+
 	iwl_send_statistics_request(priv, CMD_ASYNC);
 }
 
-static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+static void iwl_rx_beacon_notif(struct iwl_priv *priv,
 				struct iwl_rx_mem_buffer *rxb)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -1189,7 +1184,7 @@
 
 /* Handle notification from uCode that card's power state is changing
  * due to software, hardware, or critical temperature RFKILL */
-static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+static void iwl_rx_card_state_notif(struct iwl_priv *priv,
 				    struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1258,7 +1253,7 @@
 		wake_up_interruptible(&priv->wait_command_queue);
 }
 
-int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
+int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
 {
 	int ret;
 	unsigned long flags;
@@ -1290,7 +1285,7 @@
 }
 
 /**
- * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
+ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
  *
  * Setup the RX handlers for each of the reply types sent from the uCode
  * to the host.
@@ -1301,14 +1296,14 @@
 static void iwl_setup_rx_handlers(struct iwl_priv *priv)
 {
 	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
-	priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
-	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
+	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
 	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-	    iwl4965_rx_spectrum_measure_notif;
-	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl4965_rx_pm_sleep_notif;
+	    iwl_rx_spectrum_measure_notif;
+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
 	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-	    iwl4965_rx_pm_debug_statistics_notif;
-	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+	    iwl_rx_pm_debug_statistics_notif;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
 
 	/*
 	 * The same handler is used for both the REPLY to a discrete
@@ -1321,7 +1316,7 @@
 	iwl_setup_rx_scan_handlers(priv);
 
 	/* status change handler */
-	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
+	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
 
 	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
 	    iwl_rx_missed_beacon_notif;
@@ -1398,13 +1393,14 @@
 		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
 			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
 			(pkt->hdr.cmd != REPLY_RX) &&
+			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
 			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
 			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
 			(pkt->hdr.cmd != REPLY_TX);
 
 		/* Based on type of command response or notification,
 		 *   handle those that need handling via function in
-		 *   rx_handlers table.  See iwl4965_setup_rx_handlers() */
+		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
 		if (priv->rx_handlers[pkt->hdr.cmd]) {
 			IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r,
 				i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
@@ -1461,10 +1457,9 @@
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
+static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 {
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-	DECLARE_MAC_BUF(mac);
 
 	IWL_DEBUG_RADIO("RX CONFIG:\n");
 	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
@@ -1476,15 +1471,13 @@
 	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
 			rxon->ofdm_basic_rates);
 	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
-	IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
-			print_mac(mac, rxon->node_addr));
-	IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
-			print_mac(mac, rxon->bssid_addr));
+	IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+	IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
 #endif
 
-static void iwl4965_enable_interrupts(struct iwl_priv *priv)
+static void iwl_enable_interrupts(struct iwl_priv *priv)
 {
 	IWL_DEBUG_ISR("Enabling interrupts\n");
 	set_bit(STATUS_INT_ENABLED, &priv->status);
@@ -1494,12 +1487,12 @@
 /* call this function to flush any scheduled tasklet */
 static inline void iwl_synchronize_irq(struct iwl_priv *priv)
 {
-	/* wait to make sure we flush pedding tasklet*/
+	/* wait to make sure we flush pending tasklet*/
 	synchronize_irq(priv->pci_dev->irq);
 	tasklet_kill(&priv->irq_tasklet);
 }
 
-static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
+static inline void iwl_disable_interrupts(struct iwl_priv *priv)
 {
 	clear_bit(STATUS_INT_ENABLED, &priv->status);
 
@@ -1515,11 +1508,11 @@
 
 
 /**
- * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
+ * iwl_irq_handle_error - called for HW or SW error interrupt from card
  */
-static void iwl4965_irq_handle_error(struct iwl_priv *priv)
+static void iwl_irq_handle_error(struct iwl_priv *priv)
 {
-	/* Set the FW error flag -- cleared on iwl4965_down */
+	/* Set the FW error flag -- cleared on iwl_down */
 	set_bit(STATUS_FW_ERROR, &priv->status);
 
 	/* Cancel currently queued command. */
@@ -1529,7 +1522,7 @@
 	if (priv->debug_level & IWL_DL_FW_ERRORS) {
 		iwl_dump_nic_error_log(priv);
 		iwl_dump_nic_event_log(priv);
-		iwl4965_print_rx_config_cmd(priv);
+		iwl_print_rx_config_cmd(priv);
 	}
 #endif
 
@@ -1553,14 +1546,14 @@
 	}
 }
 
-static void iwl4965_error_recovery(struct iwl_priv *priv)
+static void iwl_error_recovery(struct iwl_priv *priv)
 {
 	unsigned long flags;
 
 	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
 	       sizeof(priv->staging_rxon));
 	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 
 	iwl_rxon_add_station(priv, priv->bssid, 1);
 
@@ -1570,7 +1563,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+static void iwl_irq_tasklet(struct iwl_priv *priv)
 {
 	u32 inta, handled = 0;
 	u32 inta_fh;
@@ -1616,9 +1609,9 @@
 		IWL_ERROR("Microcode HW error detected.  Restarting.\n");
 
 		/* Tell the device to stop sending interrupts */
-		iwl4965_disable_interrupts(priv);
+		iwl_disable_interrupts(priv);
 
-		iwl4965_irq_handle_error(priv);
+		iwl_irq_handle_error(priv);
 
 		handled |= CSR_INT_BIT_HW_ERR;
 
@@ -1672,7 +1665,7 @@
 	if (inta & CSR_INT_BIT_SW_ERR) {
 		IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
 			  inta);
-		iwl4965_irq_handle_error(priv);
+		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
 
@@ -1718,7 +1711,7 @@
 	/* Re-enable all interrupts */
 	/* only Re-enable if diabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl4965_enable_interrupts(priv);
+		iwl_enable_interrupts(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (priv->debug_level & (IWL_DL_ISR)) {
@@ -1732,7 +1725,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static irqreturn_t iwl4965_isr(int irq, void *data)
+static irqreturn_t iwl_isr(int irq, void *data)
 {
 	struct iwl_priv *priv = data;
 	u32 inta, inta_mask;
@@ -1773,7 +1766,7 @@
 
 	inta &= ~CSR_INT_BIT_SCD;
 
-	/* iwl4965_irq_tasklet() will service interrupts and re-enable them */
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
 	if (likely(inta || inta_fh))
 		tasklet_schedule(&priv->irq_tasklet);
 
@@ -1785,7 +1778,7 @@
 	/* re-enable interrupts here since we don't have anything to service. */
 	/* only Re-enable if diabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl4965_enable_interrupts(priv);
+		iwl_enable_interrupts(priv);
 	spin_unlock(&priv->lock);
 	return IRQ_NONE;
 }
@@ -1796,7 +1789,7 @@
  *
  ******************************************************************************/
 
-static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
 {
 	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
 	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
@@ -1806,7 +1799,7 @@
 	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
 }
 
-static void iwl4965_nic_start(struct iwl_priv *priv)
+static void iwl_nic_start(struct iwl_priv *priv)
 {
 	/* Remove all resets to allow NIC to operate */
 	iwl_write32(priv, CSR_RESET, 0);
@@ -1814,11 +1807,11 @@
 
 
 /**
- * iwl4965_read_ucode - Read uCode images from disk file.
+ * iwl_read_ucode - Read uCode images from disk file.
  *
  * Copy into buffers for card to fetch via bus-mastering
  */
-static int iwl4965_read_ucode(struct iwl_priv *priv)
+static int iwl_read_ucode(struct iwl_priv *priv)
 {
 	struct iwl_ucode *ucode;
 	int ret;
@@ -1962,7 +1955,7 @@
 		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
 
 	/* Runtime data (2nd block)
-	 * NOTE:  Copy into backup buffer will be done in iwl4965_up()  */
+	 * NOTE:  Copy into backup buffer will be done in iwl_up()  */
 	src = &ucode->data[inst_size];
 	len = priv->ucode_data.len;
 	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
@@ -2000,7 +1993,7 @@
  err_pci_alloc:
 	IWL_ERROR("failed to allocate pci memory\n");
 	ret = -ENOMEM;
-	iwl4965_dealloc_ucode_pci(priv);
+	iwl_dealloc_ucode_pci(priv);
 
  err_release:
 	release_firmware(ucode_raw);
@@ -2045,7 +2038,7 @@
 		goto restart;
 	}
 
-	/* After the ALIVE response, we can send host commands to 4965 uCode */
+	/* After the ALIVE response, we can send host commands to the uCode */
 	set_bit(STATUS_ALIVE, &priv->status);
 
 	if (iwl_is_rfkill(priv))
@@ -2065,17 +2058,17 @@
 		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	} else {
 		/* Initialize our rx_config data */
-		iwl4965_connection_init_rx_config(priv);
+		iwl_connection_init_rx_config(priv, priv->iw_mode);
 		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 	}
 
 	/* Configure Bluetooth device coexistence support */
-	iwl4965_send_bt_config(priv);
+	iwl_send_bt_config(priv);
 
 	iwl_reset_run_time_calib(priv);
 
 	/* Configure the adapter for unassociated operation */
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 
 	/* At this point, the NIC is initialized and operational */
 	iwl_rf_kill_ct_config(priv);
@@ -2087,12 +2080,12 @@
 	wake_up_interruptible(&priv->wait_command_queue);
 
 	if (priv->error_recovering)
-		iwl4965_error_recovery(priv);
+		iwl_error_recovery(priv);
 
 	iwl_power_update_mode(priv, 1);
 
 	if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
-		iwl4965_set_mode(priv, priv->iw_mode);
+		iwl_set_mode(priv, priv->iw_mode);
 
 	return;
 
@@ -2102,7 +2095,7 @@
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv);
 
-static void __iwl4965_down(struct iwl_priv *priv)
+static void __iwl_down(struct iwl_priv *priv)
 {
 	unsigned long flags;
 	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -2129,14 +2122,14 @@
 
 	/* tell the device to stop sending interrupts */
 	spin_lock_irqsave(&priv->lock, flags);
-	iwl4965_disable_interrupts(priv);
+	iwl_disable_interrupts(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 	iwl_synchronize_irq(priv);
 
 	if (priv->mac80211_registered)
 		ieee80211_stop_queues(priv->hw);
 
-	/* If we have not previously called iwl4965_init() then
+	/* If we have not previously called iwl_init() then
 	 * clear all bits but the RF Kill and SUSPEND bits and return */
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
@@ -2203,10 +2196,10 @@
 	iwl_clear_free_frames(priv);
 }
 
-static void iwl4965_down(struct iwl_priv *priv)
+static void iwl_down(struct iwl_priv *priv)
 {
 	mutex_lock(&priv->mutex);
-	__iwl4965_down(priv);
+	__iwl_down(priv);
 	mutex_unlock(&priv->mutex);
 
 	iwl_cancel_deferred_work(priv);
@@ -2214,7 +2207,7 @@
 
 #define MAX_HW_RESTARTS 5
 
-static int __iwl4965_up(struct iwl_priv *priv)
+static int __iwl_up(struct iwl_priv *priv)
 {
 	int i;
 	int ret;
@@ -2236,7 +2229,7 @@
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
 	if (iwl_is_rfkill(priv)) {
-		iwl4965_enable_interrupts(priv);
+		iwl_enable_interrupts(priv);
 		IWL_WARNING("Radio disabled by %s RF Kill switch\n",
 		    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
 		return 0;
@@ -2263,7 +2256,7 @@
 
 	/* clear (again), then enable host interrupts */
 	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl4965_enable_interrupts(priv);
+	iwl_enable_interrupts(priv);
 
 	/* really make sure rfkill handshake bits are cleared */
 	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
@@ -2293,7 +2286,7 @@
 		clear_bit(STATUS_FW_ERROR, &priv->status);
 
 		/* start card; "initialize" will load runtime ucode */
-		iwl4965_nic_start(priv);
+		iwl_nic_start(priv);
 
 		IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
 
@@ -2301,7 +2294,7 @@
 	}
 
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
-	__iwl4965_down(priv);
+	__iwl_down(priv);
 	clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	/* tried to restart and config the device for as long as our
@@ -2344,7 +2337,7 @@
 	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
 }
 
-static void iwl4965_bg_rf_kill(struct work_struct *work)
+static void iwl_bg_rf_kill(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
 
@@ -2378,7 +2371,7 @@
 	iwl_rfkill_set_hw_state(priv);
 }
 
-static void iwl4965_bg_set_monitor(struct work_struct *work)
+static void iwl_bg_set_monitor(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work,
 				struct iwl_priv, set_monitor);
@@ -2388,16 +2381,16 @@
 
 	mutex_lock(&priv->mutex);
 
-	ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR);
-
+	ret = iwl_set_mode(priv, NL80211_IFTYPE_MONITOR);
 	if (ret) {
 		if (ret == -EAGAIN)
 			IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
 		else
-			IWL_ERROR("iwl4965_set_mode() failed ret = %d\n", ret);
+			IWL_ERROR("iwl_set_mode() failed ret = %d\n", ret);
 	}
 
 	mutex_unlock(&priv->mutex);
+	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
 }
 
 static void iwl_bg_run_time_calib_work(struct work_struct *work)
@@ -2423,7 +2416,7 @@
 	return;
 }
 
-static void iwl4965_bg_up(struct work_struct *data)
+static void iwl_bg_up(struct work_struct *data)
 {
 	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
 
@@ -2431,23 +2424,23 @@
 		return;
 
 	mutex_lock(&priv->mutex);
-	__iwl4965_up(priv);
+	__iwl_up(priv);
 	mutex_unlock(&priv->mutex);
 	iwl_rfkill_set_hw_state(priv);
 }
 
-static void iwl4965_bg_restart(struct work_struct *data)
+static void iwl_bg_restart(struct work_struct *data)
 {
 	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	iwl4965_down(priv);
+	iwl_down(priv);
 	queue_work(priv->workqueue, &priv->up);
 }
 
-static void iwl4965_bg_rx_replenish(struct work_struct *data)
+static void iwl_bg_rx_replenish(struct work_struct *data)
 {
 	struct iwl_priv *priv =
 	    container_of(data, struct iwl_priv, rx_replenish);
@@ -2462,11 +2455,10 @@
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl4965_post_associate(struct iwl_priv *priv)
+static void iwl_post_associate(struct iwl_priv *priv)
 {
 	struct ieee80211_conf *conf = NULL;
 	int ret = 0;
-	DECLARE_MAC_BUF(mac);
 	unsigned long flags;
 
 	if (priv->iw_mode == NL80211_IFTYPE_AP) {
@@ -2474,9 +2466,8 @@
 		return;
 	}
 
-	IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
-			priv->assoc_id,
-			print_mac(mac, priv->active_rxon.bssid_addr));
+	IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+			priv->assoc_id, priv->active_rxon.bssid_addr);
 
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -2492,10 +2483,9 @@
 	conf = ieee80211_get_hw_conf(priv->hw);
 
 	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 
-	memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
-	iwl4965_setup_rxon_timing(priv);
+	iwl_setup_rxon_timing(priv);
 	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
 			      sizeof(priv->rxon_timing), &priv->rxon_timing);
 	if (ret)
@@ -2528,7 +2518,7 @@
 
 	}
 
-	iwl4965_commit_rxon(priv);
+	iwl_commit_rxon(priv);
 
 	switch (priv->iw_mode) {
 	case NL80211_IFTYPE_STATION:
@@ -2540,7 +2530,7 @@
 		priv->assoc_id = 1;
 
 		iwl_rxon_add_station(priv, priv->bssid, 0);
-		iwl4965_send_beacon_cmd(priv);
+		iwl_send_beacon_cmd(priv);
 
 		break;
 
@@ -2577,7 +2567,7 @@
 
 #define UCODE_READY_TIMEOUT	(4 * HZ)
 
-static int iwl4965_mac_start(struct ieee80211_hw *hw)
+static int iwl_mac_start(struct ieee80211_hw *hw)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret;
@@ -2599,7 +2589,7 @@
 		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
 	}
 
-	ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
+	ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
 			  DRV_NAME, priv);
 	if (ret) {
 		IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -2614,7 +2604,7 @@
 	 * ucode filename and max sizes are card-specific. */
 
 	if (!priv->ucode_code.len) {
-		ret = iwl4965_read_ucode(priv);
+		ret = iwl_read_ucode(priv);
 		if (ret) {
 			IWL_ERROR("Could not read microcode: %d\n", ret);
 			mutex_unlock(&priv->mutex);
@@ -2622,7 +2612,7 @@
 		}
 	}
 
-	ret = __iwl4965_up(priv);
+	ret = __iwl_up(priv);
 
 	mutex_unlock(&priv->mutex);
 
@@ -2668,7 +2658,7 @@
 	return ret;
 }
 
-static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+static void iwl_mac_stop(struct ieee80211_hw *hw)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -2690,7 +2680,7 @@
 		mutex_unlock(&priv->mutex);
 	}
 
-	iwl4965_down(priv);
+	iwl_down(priv);
 
 	flush_workqueue(priv->workqueue);
 	free_irq(priv->pci_dev->irq, priv);
@@ -2701,7 +2691,7 @@
 	IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -2717,12 +2707,11 @@
 	return 0;
 }
 
-static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+static int iwl_mac_add_interface(struct ieee80211_hw *hw,
 				 struct ieee80211_if_init_conf *conf)
 {
 	struct iwl_priv *priv = hw->priv;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
 
@@ -2733,17 +2722,18 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->vif = conf->vif;
+	priv->iw_mode = conf->type;
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	mutex_lock(&priv->mutex);
 
 	if (conf->mac_addr) {
-		IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr));
+		IWL_DEBUG_MAC80211("Set %pM\n", conf->mac_addr);
 		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
 	}
 
-	if (iwl4965_set_mode(priv, conf->type) == -EAGAIN)
+	if (iwl_set_mode(priv, conf->type) == -EAGAIN)
 		/* we are not ready, will run again when ready */
 		set_bit(STATUS_MODE_PENDING, &priv->status);
 
@@ -2754,16 +2744,17 @@
 }
 
 /**
- * iwl4965_mac_config - mac80211 config callback
+ * iwl_mac_config - mac80211 config callback
  *
  * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
  * be set inappropriately and the driver currently sets the hardware up to
  * use it whenever needed.
  */
-static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct iwl_priv *priv = hw->priv;
 	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
 	unsigned long flags;
 	int ret = 0;
 	u16 channel;
@@ -2771,6 +2762,8 @@
 	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
 
+	priv->current_ht_config.is_ht = conf->ht.enabled;
+
 	if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
 		IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
 		goto out;
@@ -2828,13 +2821,13 @@
 	/* The list of supported rates and rate mask can be different
 	 * for each band; since the band may have changed, reset
 	 * the rate mask to what mac80211 lists */
-	iwl4965_set_rate(priv);
+	iwl_set_rate(priv);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 #ifdef IEEE80211_CONF_CHANNEL_SWITCH
 	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
-		iwl4965_hw_channel_switch(priv, conf->channel);
+		iwl_hw_channel_switch(priv, conf->channel);
 		goto out;
 	}
 #endif
@@ -2862,11 +2855,11 @@
 
 	iwl_set_tx_power(priv, conf->power_level, false);
 
-	iwl4965_set_rate(priv);
+	iwl_set_rate(priv);
 
 	if (memcmp(&priv->active_rxon,
 		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 	else
 		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
 
@@ -2877,7 +2870,7 @@
 	return ret;
 }
 
-static void iwl4965_config_ap(struct iwl_priv *priv)
+static void iwl_config_ap(struct iwl_priv *priv)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -2886,15 +2879,14 @@
 		return;
 
 	/* The following should be done only at AP bring up */
-	if (!(iwl_is_associated(priv))) {
+	if (!iwl_is_associated(priv)) {
 
 		/* RXON - unassoc (to set timing command) */
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 
 		/* RXON Timing */
-		memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
-		iwl4965_setup_rxon_timing(priv);
+		iwl_setup_rxon_timing(priv);
 		ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
 				sizeof(priv->rxon_timing), &priv->rxon_timing);
 		if (ret)
@@ -2927,13 +2919,13 @@
 		}
 		/* restore RXON assoc */
 		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 		spin_lock_irqsave(&priv->lock, flags);
 		iwl_activate_qos(priv, 1);
 		spin_unlock_irqrestore(&priv->lock, flags);
 		iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
 	}
-	iwl4965_send_beacon_cmd(priv);
+	iwl_send_beacon_cmd(priv);
 
 	/* FIXME - we need to add code here to detect a totally new
 	 * configuration, reset the AP, unassoc, rxon timing, assoc,
@@ -2941,15 +2933,13 @@
 }
 
 /* temporary */
-static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
 
-static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+static int iwl_mac_config_interface(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif,
 				    struct ieee80211_if_conf *conf)
 {
 	struct iwl_priv *priv = hw->priv;
-	DECLARE_MAC_BUF(mac);
-	unsigned long flags;
 	int rc;
 
 	if (conf == NULL)
@@ -2965,26 +2955,18 @@
 		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
 		if (!beacon)
 			return -ENOMEM;
-		rc = iwl4965_mac_beacon_update(hw, beacon);
+		rc = iwl_mac_beacon_update(hw, beacon);
 		if (rc)
 			return rc;
 	}
 
-	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
-	    (!conf->ssid_len)) {
-		IWL_DEBUG_MAC80211
-		    ("Leaving in AP mode because HostAPD is not ready.\n");
-		return 0;
-	}
-
 	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	mutex_lock(&priv->mutex);
 
 	if (conf->bssid)
-		IWL_DEBUG_MAC80211("bssid: %s\n",
-				   print_mac(mac, conf->bssid));
+		IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
 
 /*
  * very dubious code was here; the probe filtering flag is never set:
@@ -2997,8 +2979,8 @@
 		if (!conf->bssid) {
 			conf->bssid = priv->mac_addr;
 			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-			IWL_DEBUG_MAC80211("bssid was set to: %s\n",
-					   print_mac(mac, conf->bssid));
+			IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+					   conf->bssid);
 		}
 		if (priv->ibss_beacon)
 			dev_kfree_skb(priv->ibss_beacon);
@@ -3029,9 +3011,9 @@
 		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 
 		if (priv->iw_mode == NL80211_IFTYPE_AP)
-			iwl4965_config_ap(priv);
+			iwl_config_ap(priv);
 		else {
-			rc = iwl4965_commit_rxon(priv);
+			rc = iwl_commit_rxon(priv);
 			if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
 				iwl_rxon_add_station(
 					priv, priv->active_rxon.bssid_addr, 1);
@@ -3040,26 +3022,17 @@
 	} else {
 		iwl_scan_cancel_timeout(priv, 100);
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 	}
 
  done:
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!conf->ssid_len)
-		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-	else
-		memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
-	priv->essid_len = conf->ssid_len;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	IWL_DEBUG_MAC80211("leave\n");
 	mutex_unlock(&priv->mutex);
 
 	return 0;
 }
 
-static void iwl4965_configure_filter(struct ieee80211_hw *hw,
+static void iwl_configure_filter(struct ieee80211_hw *hw,
 				 unsigned int changed_flags,
 				 unsigned int *total_flags,
 				 int mc_count, struct dev_addr_list *mc_list)
@@ -3078,7 +3051,7 @@
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
-static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 				     struct ieee80211_if_init_conf *conf)
 {
 	struct iwl_priv *priv = hw->priv;
@@ -3090,13 +3063,11 @@
 	if (iwl_is_ready_rf(priv)) {
 		iwl_scan_cancel_timeout(priv, 100);
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 	}
 	if (priv->vif == conf->vif) {
 		priv->vif = NULL;
 		memset(priv->bssid, 0, ETH_ALEN);
-		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-		priv->essid_len = 0;
 	}
 	mutex_unlock(&priv->mutex);
 
@@ -3105,7 +3076,7 @@
 }
 
 #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+static void iwl_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *bss_conf,
 				     u32 changes)
@@ -3132,8 +3103,7 @@
 	}
 
 	if (changes & BSS_CHANGED_HT) {
-		IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
-		iwl4965_ht_conf(priv, bss_conf);
+		iwl_ht_conf(priv, bss_conf);
 		iwl_set_rxon_chain(priv);
 	}
 
@@ -3156,7 +3126,7 @@
 			priv->next_scan_jiffies = jiffies +
 					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
 			mutex_lock(&priv->mutex);
-			iwl4965_post_associate(priv);
+			iwl_post_associate(priv);
 			mutex_unlock(&priv->mutex);
 		} else {
 			priv->assoc_id = 0;
@@ -3232,7 +3202,7 @@
 	return ret;
 }
 
-static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
 			struct ieee80211_key_conf *keyconf, const u8 *addr,
 			u32 iv32, u16 *phase1key)
 {
@@ -3241,14 +3211,13 @@
 	unsigned long flags;
 	__le16 key_flags = 0;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	IWL_DEBUG_MAC80211("enter\n");
 
 	sta_id = iwl_find_station(priv, addr);
 	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
-				   print_mac(mac, addr));
+		IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+				   addr);
 		return;
 	}
 
@@ -3284,12 +3253,11 @@
 	IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			   const u8 *local_addr, const u8 *addr,
 			   struct ieee80211_key_conf *key)
 {
 	struct iwl_priv *priv = hw->priv;
-	DECLARE_MAC_BUF(mac);
 	int ret = 0;
 	u8 sta_id = IWL_INVALID_STATION;
 	u8 is_default_wep_key = 0;
@@ -3307,8 +3275,8 @@
 
 	sta_id = iwl_find_station(priv, addr);
 	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
-				   print_mac(mac, addr));
+		IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+				   addr);
 		return -EINVAL;
 
 	}
@@ -3356,7 +3324,7 @@
 	return ret;
 }
 
-static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 			   const struct ieee80211_tx_queue_params *params)
 {
 	struct iwl_priv *priv = hw->priv;
@@ -3404,15 +3372,14 @@
 	return 0;
 }
 
-static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 			     enum ieee80211_ampdu_mlme_action action,
 			     struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	struct iwl_priv *priv = hw->priv;
-	DECLARE_MAC_BUF(mac);
 
-	IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
-		     print_mac(mac, sta->addr), tid);
+	IWL_DEBUG_HT("A-MPDU action on addr %pM tid %d\n",
+		     sta->addr, tid);
 
 	if (!(priv->cfg->sku & IWL_SKU_N))
 		return -EACCES;
@@ -3437,7 +3404,7 @@
 	}
 	return 0;
 }
-static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
 				struct ieee80211_tx_queue_stats *stats)
 {
 	struct iwl_priv *priv = hw->priv;
@@ -3472,7 +3439,7 @@
 	return 0;
 }
 
-static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
+static int iwl_mac_get_stats(struct ieee80211_hw *hw,
 			     struct ieee80211_low_level_stats *stats)
 {
 	struct iwl_priv *priv = hw->priv;
@@ -3484,7 +3451,7 @@
 	return 0;
 }
 
-static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
 {
 	struct iwl_priv *priv = hw->priv;
 	unsigned long flags;
@@ -3528,7 +3495,7 @@
 	if (priv->iw_mode != NL80211_IFTYPE_AP) {
 		iwl_scan_cancel_timeout(priv, 100);
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl4965_commit_rxon(priv);
+		iwl_commit_rxon(priv);
 	}
 
 	iwl_power_update_mode(priv, 0);
@@ -3551,14 +3518,14 @@
 		return;
 	}
 
-	iwl4965_set_rate(priv);
+	iwl_set_rate(priv);
 
 	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct iwl_priv *priv = hw->priv;
 	unsigned long flags;
@@ -3595,7 +3562,7 @@
 
 	iwl_reset_qos(priv);
 
-	iwl4965_post_associate(priv);
+	iwl_post_associate(priv);
 
 	mutex_unlock(&priv->mutex);
 
@@ -3749,7 +3716,7 @@
 		else {
 			IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags);
 			priv->staging_rxon.flags = cpu_to_le32(flags);
-			iwl4965_commit_rxon(priv);
+			iwl_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3790,7 +3757,7 @@
 				       "0x%04X\n", filter_flags);
 			priv->staging_rxon.filter_flags =
 				cpu_to_le32(filter_flags);
-			iwl4965_commit_rxon(priv);
+			iwl_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3865,7 +3832,7 @@
 
 	IWL_DEBUG_INFO("Invoking measurement of type %d on "
 		       "channel %d (for '%s')\n", type, params.channel, buf);
-	iwl4965_get_measurement(priv, &params, type);
+	iwl_get_measurement(priv, &params, type);
 
 	return count;
 }
@@ -4085,12 +4052,12 @@
 
 	init_waitqueue_head(&priv->wait_command_queue);
 
-	INIT_WORK(&priv->up, iwl4965_bg_up);
-	INIT_WORK(&priv->restart, iwl4965_bg_restart);
-	INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
-	INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
-	INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
+	INIT_WORK(&priv->up, iwl_bg_up);
+	INIT_WORK(&priv->restart, iwl_bg_restart);
+	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
+	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
+	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
+	INIT_WORK(&priv->set_monitor, iwl_bg_set_monitor);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
@@ -4103,10 +4070,10 @@
 
 	init_timer(&priv->statistics_periodic);
 	priv->statistics_periodic.data = (unsigned long)priv;
-	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+	priv->statistics_periodic.function = iwl_bg_statistics_periodic;
 
 	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-		     iwl4965_irq_tasklet, (unsigned long)priv);
+		     iwl_irq_tasklet, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -4122,7 +4089,7 @@
 	del_timer_sync(&priv->statistics_periodic);
 }
 
-static struct attribute *iwl4965_sysfs_entries[] = {
+static struct attribute *iwl_sysfs_entries[] = {
 	&dev_attr_channels.attr,
 	&dev_attr_flags.attr,
 	&dev_attr_filter_flags.attr,
@@ -4143,39 +4110,38 @@
 	NULL
 };
 
-static struct attribute_group iwl4965_attribute_group = {
+static struct attribute_group iwl_attribute_group = {
 	.name = NULL,		/* put in device directory */
-	.attrs = iwl4965_sysfs_entries,
+	.attrs = iwl_sysfs_entries,
 };
 
-static struct ieee80211_ops iwl4965_hw_ops = {
-	.tx = iwl4965_mac_tx,
-	.start = iwl4965_mac_start,
-	.stop = iwl4965_mac_stop,
-	.add_interface = iwl4965_mac_add_interface,
-	.remove_interface = iwl4965_mac_remove_interface,
-	.config = iwl4965_mac_config,
-	.config_interface = iwl4965_mac_config_interface,
-	.configure_filter = iwl4965_configure_filter,
-	.set_key = iwl4965_mac_set_key,
-	.update_tkip_key = iwl4965_mac_update_tkip_key,
-	.get_stats = iwl4965_mac_get_stats,
-	.get_tx_stats = iwl4965_mac_get_tx_stats,
-	.conf_tx = iwl4965_mac_conf_tx,
-	.reset_tsf = iwl4965_mac_reset_tsf,
-	.bss_info_changed = iwl4965_bss_info_changed,
-	.ampdu_action = iwl4965_mac_ampdu_action,
+static struct ieee80211_ops iwl_hw_ops = {
+	.tx = iwl_mac_tx,
+	.start = iwl_mac_start,
+	.stop = iwl_mac_stop,
+	.add_interface = iwl_mac_add_interface,
+	.remove_interface = iwl_mac_remove_interface,
+	.config = iwl_mac_config,
+	.config_interface = iwl_mac_config_interface,
+	.configure_filter = iwl_configure_filter,
+	.set_key = iwl_mac_set_key,
+	.update_tkip_key = iwl_mac_update_tkip_key,
+	.get_stats = iwl_mac_get_stats,
+	.get_tx_stats = iwl_mac_get_tx_stats,
+	.conf_tx = iwl_mac_conf_tx,
+	.reset_tsf = iwl_mac_reset_tsf,
+	.bss_info_changed = iwl_bss_info_changed,
+	.ampdu_action = iwl_mac_ampdu_action,
 	.hw_scan = iwl_mac_hw_scan
 };
 
-static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err = 0;
 	struct iwl_priv *priv;
 	struct ieee80211_hw *hw;
 	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	/************************
 	 * 1. Allocating HW data
@@ -4187,10 +4153,10 @@
 		if (cfg->mod_params->debug & IWL_DL_INFO)
 			dev_printk(KERN_DEBUG, &(pdev->dev),
 				   "Disabling hw_scan\n");
-		iwl4965_hw_ops.hw_scan = NULL;
+		iwl_hw_ops.hw_scan = NULL;
 	}
 
-	hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
+	hw = iwl_alloc_all(cfg, &iwl_hw_ops);
 	if (!hw) {
 		err = -ENOMEM;
 		goto out;
@@ -4284,7 +4250,7 @@
 
 	/* extract MAC Address */
 	iwl_eeprom_get_mac(priv, priv->mac_addr);
-	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+	IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
 	/************************
@@ -4318,10 +4284,10 @@
 	 * 8. Setup services
 	 ********************/
 	spin_lock_irqsave(&priv->lock, flags);
-	iwl4965_disable_interrupts(priv);
+	iwl_disable_interrupts(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+	err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
 	if (err) {
 		IWL_ERROR("failed to create sysfs device attributes\n");
 		goto out_uninit_drv;
@@ -4357,7 +4323,7 @@
 	return 0;
 
  out_remove_sysfs:
-	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
  out_uninit_drv:
 	iwl_uninit_drv(priv);
  out_free_eeprom:
@@ -4375,7 +4341,7 @@
 	return err;
 }
 
-static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 {
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	unsigned long flags;
@@ -4386,10 +4352,10 @@
 	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
 
 	iwl_dbgfs_unregister(priv);
-	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
 
-	/* ieee80211_unregister_hw call wil cause iwl4965_mac_stop to
-	 * to be called and iwl4965_down since we are removing the device
+	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
+	 * to be called and iwl_down since we are removing the device
 	 * we need to set STATUS_EXIT_PENDING bit.
 	 */
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -4397,20 +4363,20 @@
 		ieee80211_unregister_hw(priv->hw);
 		priv->mac80211_registered = 0;
 	} else {
-		iwl4965_down(priv);
+		iwl_down(priv);
 	}
 
 	/* make sure we flush any pending irq or
 	 * tasklet for the driver
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
-	iwl4965_disable_interrupts(priv);
+	iwl_disable_interrupts(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	iwl_synchronize_irq(priv);
 
 	iwl_rfkill_unregister(priv);
-	iwl4965_dealloc_ucode_pci(priv);
+	iwl_dealloc_ucode_pci(priv);
 
 	if (priv->rxq.bd)
 		iwl_rx_queue_free(priv, &priv->rxq);
@@ -4423,7 +4389,7 @@
 	/*netif_stop_queue(dev); */
 	flush_workqueue(priv->workqueue);
 
-	/* ieee80211_unregister_hw calls iwl4965_mac_stop, which flushes
+	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
 	 * priv->workqueue... so we can't take down the workqueue
 	 * until now... */
 	destroy_workqueue(priv->workqueue);
@@ -4444,13 +4410,13 @@
 
 #ifdef CONFIG_PM
 
-static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 
 	if (priv->is_open) {
 		set_bit(STATUS_IN_SUSPEND, &priv->status);
-		iwl4965_mac_stop(priv->hw);
+		iwl_mac_stop(priv->hw);
 		priv->is_open = 1;
 	}
 
@@ -4459,14 +4425,14 @@
 	return 0;
 }
 
-static int iwl4965_pci_resume(struct pci_dev *pdev)
+static int iwl_pci_resume(struct pci_dev *pdev)
 {
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 
 	pci_set_power_state(pdev, PCI_D0);
 
 	if (priv->is_open)
-		iwl4965_mac_start(priv->hw);
+		iwl_mac_start(priv->hw);
 
 	clear_bit(STATUS_IN_SUSPEND, &priv->status);
 	return 0;
@@ -4509,15 +4475,15 @@
 static struct pci_driver iwl_driver = {
 	.name = DRV_NAME,
 	.id_table = iwl_hw_card_ids,
-	.probe = iwl4965_pci_probe,
-	.remove = __devexit_p(iwl4965_pci_remove),
+	.probe = iwl_pci_probe,
+	.remove = __devexit_p(iwl_pci_remove),
 #ifdef CONFIG_PM
-	.suspend = iwl4965_pci_suspend,
-	.resume = iwl4965_pci_resume,
+	.suspend = iwl_pci_suspend,
+	.resume = iwl_pci_resume,
 #endif
 };
 
-static int __init iwl4965_init(void)
+static int __init iwl_init(void)
 {
 
 	int ret;
@@ -4543,11 +4509,11 @@
 	return ret;
 }
 
-static void __exit iwl4965_exit(void)
+static void __exit iwl_exit(void)
 {
 	pci_unregister_driver(&iwl_driver);
 	iwlagn_rate_control_unregister();
 }
 
-module_exit(iwl4965_exit);
-module_init(iwl4965_init);
+module_exit(iwl_exit);
+module_init(iwl_init);
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 72fbf47..25f4658 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -70,7 +70,7 @@
  * INIT calibrations framework
  *****************************************************************************/
 
- int iwl_send_calib_results(struct iwl_priv *priv)
+int iwl_send_calib_results(struct iwl_priv *priv)
 {
 	int ret = 0;
 	int i = 0;
@@ -80,14 +80,16 @@
 		.meta.flags = CMD_SIZE_HUGE,
 	};
 
-	for (i = 0; i < IWL_CALIB_MAX; i++)
-		if (priv->calib_results[i].buf) {
+	for (i = 0; i < IWL_CALIB_MAX; i++) {
+		if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
+		    priv->calib_results[i].buf) {
 			hcmd.len = priv->calib_results[i].buf_len;
 			hcmd.data = priv->calib_results[i].buf;
 			ret = iwl_send_cmd_sync(priv, &hcmd);
 			if (ret)
 				goto err;
 		}
+	}
 
 	return 0;
 err:
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 8d04e96..8aade00 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -66,8 +66,8 @@
  * Please use iwl-dev.h for driver implementation definitions.
  */
 
-#ifndef __iwl4965_commands_h__
-#define __iwl4965_commands_h__
+#ifndef __iwl_commands_h__
+#define __iwl_commands_h__
 
 enum {
 	REPLY_ALIVE = 0x1,
@@ -98,6 +98,11 @@
 	COEX_MEDIUM_NOTIFICATION = 0x5b,
 	COEX_EVENT_CMD = 0x5c,
 
+	/* Calibration */
+	CALIBRATION_CFG_CMD = 0x65,
+	CALIBRATION_RES_NOTIFICATION = 0x66,
+	CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
+
 	/* 802.11h related */
 	RADAR_NOTIFICATION = 0x70,	/* not used */
 	REPLY_QUIET_CMD = 0x71,		/* not used */
@@ -129,7 +134,7 @@
 	REPLY_TX_POWER_DBM_CMD = 0x98,
 	MEASURE_ABORT_NOTIFICATION = 0x99,	/* not used */
 
-	/* Bluetooth device coexistance config command */
+	/* Bluetooth device coexistence config command */
 	REPLY_BT_CONFIG = 0x9b,
 
 	/* Statistics */
@@ -180,7 +185,7 @@
 	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
 	u8 flags;	/* 0:5 reserved, 6 abort, 7 internal */
 	/*
-	 * The driver sets up the sequence number to values of its chosing.
+	 * The driver sets up the sequence number to values of its choosing.
 	 * uCode does not use this value, but passes it back to the driver
 	 * when sending the response to each driver-originated command, so
 	 * the driver can match the response to the command.  Since the values
@@ -278,18 +283,20 @@
 #define RATE_MCS_SGI_MSK 0x2000
 
 /**
- * rate_n_flags Tx antenna masks (4965 has 2 transmitters):
- * bit14:15 01 B inactive, A active
- *          10 B active, A inactive
- *          11 Both active
+ * rate_n_flags Tx antenna masks
+ * 4965 has 2 transmitters
+ * 5100 has 1 transmitter B
+ * 5150 has 1 transmitter A
+ * 5300 has 3 transmitters
+ * 5350 has 3 transmitters
+ * bit14:16
  */
 #define RATE_MCS_ANT_POS      14
 #define RATE_MCS_ANT_A_MSK    0x04000
 #define RATE_MCS_ANT_B_MSK    0x08000
 #define RATE_MCS_ANT_C_MSK    0x10000
 #define RATE_MCS_ANT_ABC_MSK  0x1C000
-
-#define RATE_MCS_ANT_INIT_IND   1
+#define RATE_ANT_NUM 3
 
 #define POWER_TABLE_NUM_ENTRIES			33
 #define POWER_TABLE_NUM_HT_OFDM_ENTRIES		32
@@ -340,7 +347,7 @@
 } __attribute__ ((packed));
 
 /**
- * Commad REPLY_TX_POWER_DBM_CMD = 0x98
+ * Command REPLY_TX_POWER_DBM_CMD = 0x98
  * struct iwl5000_tx_power_dbm_cmd
  */
 #define IWL50_TX_POWER_AUTO 0x7f
@@ -376,7 +383,7 @@
  * calculating txpower settings:
  *
  * 1)  Power supply voltage indication.  The voltage sensor outputs higher
- *     values for lower voltage, and vice versa.
+ *     values for lower voltage, and vice verse.
  *
  * 2)  Temperature measurement parameters, for each of two channel widths
  *     (20 MHz and 40 MHz) supported by the radios.  Temperature sensing
@@ -477,11 +484,6 @@
 } __attribute__ ((packed));
 
 
-union tsf {
-	u8 byte[8];
-	__le16 word[4];
-	__le32 dw[2];
-};
 
 /*
  * REPLY_ERROR = 0x2 (response only, not a command)
@@ -492,7 +494,7 @@
 	u8 reserved1;
 	__le16 bad_cmd_seq_num;
 	__le32 error_info;
-	union tsf timestamp;
+	__le64 timestamp;
 } __attribute__ ((packed));
 
 /******************************************************************************
@@ -620,7 +622,7 @@
 	u8 ofdm_ht_dual_stream_basic_rates;
 } __attribute__ ((packed));
 
-/* 5000 HW just extend this cmmand */
+/* 5000 HW just extend this command */
 struct iwl_rxon_cmd {
 	u8 node_addr[6];
 	__le16 reserved1;
@@ -679,8 +681,8 @@
 /*
  * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
  */
-struct iwl4965_rxon_time_cmd {
-	union tsf timestamp;
+struct iwl_rxon_time_cmd {
+	__le64 timestamp;
 	__le16 beacon_interval;
 	__le16 atim_window;
 	__le32 beacon_init_val;
@@ -1111,7 +1113,7 @@
 #define IWL50_OFDM_RSSI_C_BIT_POS 0
 
 struct iwl5000_non_cfg_phy {
-	__le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT];  /* upto 8 phy entries */
+	__le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT];  /* up to 8 phy entries */
 } __attribute__ ((packed));
 
 
@@ -1167,7 +1169,7 @@
 
 /* REPLY_TX Tx flags field */
 
-/* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it
+/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
  * before this frame. if CTS-to-self required check
  * RXON_FLG_SELF_CTS_EN status. */
 #define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0)
@@ -1411,21 +1413,21 @@
 };
 
 enum {
-	TX_STATUS_MSK = 0x000000ff,	/* bits 0:7 */
+	TX_STATUS_MSK = 0x000000ff,		/* bits 0:7 */
 	TX_STATUS_DELAY_MSK = 0x00000040,
 	TX_STATUS_ABORT_MSK = 0x00000080,
 	TX_PACKET_MODE_MSK = 0x0000ff00,	/* bits 8:15 */
 	TX_FIFO_NUMBER_MSK = 0x00070000,	/* bits 16:18 */
-	TX_RESERVED = 0x00780000,	/* bits 19:22 */
+	TX_RESERVED = 0x00780000,		/* bits 19:22 */
 	TX_POWER_PA_DETECT_MSK = 0x7f800000,	/* bits 23:30 */
 	TX_ABORT_REQUIRED_MSK = 0x80000000,	/* bits 31:31 */
 };
 
-static inline int iwl_is_tx_success(u32 status)
+static inline bool iwl_is_tx_success(u32 status)
 {
 	status &= TX_STATUS_MSK;
-	return (status == TX_STATUS_SUCCESS)
-	    || (status == TX_STATUS_DIRECT_DONE);
+	return (status == TX_STATUS_SUCCESS) ||
+	       (status == TX_STATUS_DIRECT_DONE);
 }
 
 
@@ -1450,10 +1452,9 @@
 	AGG_TX_STATE_DELAY_TX_MSK = 0x400
 };
 
-#define AGG_TX_STATE_LAST_SENT_MSK \
-(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
- AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
- AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
+#define AGG_TX_STATE_LAST_SENT_MSK  (AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+				     AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
+				     AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
 
 /* # tx attempts for first frame in aggregation */
 #define AGG_TX_STATE_TRY_CNT_POS 12
@@ -1526,6 +1527,28 @@
 	} u;
 } __attribute__ ((packed));
 
+/*
+ * definitions for initial rate index field
+ * bits [3:0] initial rate index
+ * bits [6:4] rate table color, used for the initial rate
+ * bit-7 invalid rate indication
+ *   i.e. rate was not chosen from rate table
+ *   or rate table color was changed during frame retries
+ * refer tlc rate info
+ */
+
+#define IWL50_TX_RES_INIT_RATE_INDEX_POS	0
+#define IWL50_TX_RES_INIT_RATE_INDEX_MSK	0x0f
+#define IWL50_TX_RES_RATE_TABLE_COLOR_POS	4
+#define IWL50_TX_RES_RATE_TABLE_COLOR_MSK	0x70
+#define IWL50_TX_RES_INV_RATE_INDEX_MSK	0x80
+
+/* refer to ra_tid */
+#define IWL50_TX_RES_TID_POS	0
+#define IWL50_TX_RES_TID_MSK	0x0f
+#define IWL50_TX_RES_RA_POS	4
+#define IWL50_TX_RES_RA_MSK	0xf0
+
 struct iwl5000_tx_resp {
 	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
 	u8 bt_kill_count;	/* # blocked by bluetooth (unused for agg) */
@@ -1540,14 +1563,17 @@
 	 * For agg:  RTS + CTS + aggregation tx time + block-ack time. */
 	__le16 wireless_media_time;	/* uSecs */
 
-	__le16 reserved;
-	__le32 pa_power1;	/* RF power amplifier measurement (not used) */
-	__le32 pa_power2;
+	u8 pa_status;		/* RF power amplifier measurement (not used) */
+	u8 pa_integ_res_a[3];
+	u8 pa_integ_res_b[3];
+	u8 pa_integ_res_C[3];
 
 	__le32 tfd_info;
 	__le16 seq_ctl;
 	__le16 byte_cnt;
-	__le32 tlc_info;
+	u8 tlc_info;
+	u8 ra_tid;		/* tid (0:3), sta_id (4:7) */
+	__le16 frame_ctrl;
 	/*
 	 * For non-agg:  frame status TX_STATUS_*
 	 * For agg:  status of 1st frame, AGG_TX_STATE_*; other frame status
@@ -1742,7 +1768,7 @@
  * match the modulation characteristics of the history set.
  *
  * When using block-ack (aggregation), all frames are transmitted at the same
- * rate, since there is no per-attempt acknowledgement from the destination
+ * rate, since there is no per-attempt acknowledgment from the destination
  * station.  The Tx response struct iwl_tx_resp indicates the Tx rate in
  * rate_n_flags field.  After receiving a block-ack, the driver can update
  * history for the entire block all at once.
@@ -1881,7 +1907,7 @@
  *
  * 3945 and 4965 support hardware handshake with Bluetooth device on
  * same platform.  Bluetooth device alerts wireless device when it will Tx;
- * wireless device can delay or kill its own Tx to accomodate.
+ * wireless device can delay or kill its own Tx to accommodate.
  */
 struct iwl4965_bt_cmd {
 	u8 flags;
@@ -2043,7 +2069,7 @@
  *              '11' Illegal set
  *
  * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
- * ucode assume sleep over DTIM is allowed and we don't need to wakeup
+ * ucode assume sleep over DTIM is allowed and we don't need to wake up
  * for every DTIM.
  */
 #define IWL_POWER_VEC_SIZE 5
@@ -2849,55 +2875,30 @@
  * 1-0: amount of gain, units of 1.5 dB
  */
 
-/* "Differential Gain" opcode used in REPLY_PHY_CALIBRATION_CMD. */
-#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
-
-struct iwl4965_calibration_cmd {
-	u8 opCode;		/* PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
-	u8 flags;		/* not used */
-	__le16 reserved;
-	s8 diff_gain_a;		/* see above */
-	s8 diff_gain_b;
-	s8 diff_gain_c;
-	u8 reserved1;
-} __attribute__ ((packed));
-
-/* Phy calibration command for 5000 series */
+/* Phy calibration command for series */
 
 enum {
-	IWL5000_PHY_CALIBRATE_DC_CMD		= 8,
-	IWL5000_PHY_CALIBRATE_LO_CMD		= 9,
-	IWL5000_PHY_CALIBRATE_RX_BB_CMD		= 10,
-	IWL5000_PHY_CALIBRATE_TX_IQ_CMD		= 11,
-	IWL5000_PHY_CALIBRATE_RX_IQ_CMD		= 12,
-	IWL5000_PHY_CALIBRATION_NOISE_CMD	= 13,
-	IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD	= 14,
-	IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD	= 15,
-	IWL5000_PHY_CALIBRATE_BASE_BAND_CMD	= 16,
-	IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD	= 17,
-	IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
-	IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
+	IWL_PHY_CALIBRATE_DIFF_GAIN_CMD		= 7,
+	IWL_PHY_CALIBRATE_DC_CMD		= 8,
+	IWL_PHY_CALIBRATE_LO_CMD		= 9,
+	IWL_PHY_CALIBRATE_RX_BB_CMD		= 10,
+	IWL_PHY_CALIBRATE_TX_IQ_CMD		= 11,
+	IWL_PHY_CALIBRATE_RX_IQ_CMD		= 12,
+	IWL_PHY_CALIBRATION_NOISE_CMD		= 13,
+	IWL_PHY_CALIBRATE_AGC_TABLE_CMD		= 14,
+	IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD	= 15,
+	IWL_PHY_CALIBRATE_BASE_BAND_CMD		= 16,
+	IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD	= 17,
+	IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD	= 18,
+	IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD	= 19,
 };
 
-enum {
-	CALIBRATION_CFG_CMD = 0x65,
-	CALIBRATION_RES_NOTIFICATION = 0x66,
-	CALIBRATION_COMPLETE_NOTIFICATION = 0x67
-};
 
-struct iwl_cal_crystal_freq_cmd {
+struct iwl_cal_xtal_freq {
 	u8 cap_pin1;
 	u8 cap_pin2;
 } __attribute__ ((packed));
 
-struct iwl5000_calibration {
-	u8 op_code;
-	u8 first_group;
-	u8 num_groups;
-	u8 all_data_valid;
-	struct iwl_cal_crystal_freq_cmd data;
-} __attribute__ ((packed));
-
 #define IWL_CALIB_INIT_CFG_ALL	__constant_cpu_to_le32(0xffffffff)
 
 struct iwl_calib_cfg_elmnt_s {
@@ -2914,27 +2915,44 @@
 	__le32 flags;
 } __attribute__ ((packed));
 
-struct iwl5000_calib_cfg_cmd {
+struct iwl_calib_cfg_cmd {
 	struct iwl_calib_cfg_status_s ucd_calib_cfg;
 	struct iwl_calib_cfg_status_s drv_calib_cfg;
 	__le32 reserved1;
 } __attribute__ ((packed));
 
-struct iwl5000_calib_hdr {
+struct iwl_calib_hdr {
 	u8 op_code;
 	u8 first_group;
 	u8 groups_num;
 	u8 data_valid;
 } __attribute__ ((packed));
 
-struct iwl5000_calibration_chain_noise_reset_cmd {
-	u8 op_code;	/* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
+struct iwl_calib_cmd {
+	struct iwl_calib_hdr hdr;
+	u8 data[0];
+} __attribute__ ((packed));
+
+/* "Differential Gain" opcode used in REPLY_PHY_CALIBRATION_CMD. */
+
+struct iwl_calib_diff_gain_cmd {
+	u8 opCode;		/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+	u8 flags;		/* not used */
+	__le16 reserved;
+	s8 diff_gain_a;		/* see above */
+	s8 diff_gain_b;
+	s8 diff_gain_c;
+	u8 reserved1;
+} __attribute__ ((packed));
+
+struct iwl_calib_chain_noise_reset_cmd {
+	u8 op_code;	/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
 	u8 flags;	/* not used */
 	__le16 reserved;
 } __attribute__ ((packed));
 
-struct iwl5000_calibration_chain_noise_gain_cmd {
-	u8 op_code;	/* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */
+struct iwl_calib_chain_noise_gain_cmd {
+	u8 op_code;	/* IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */
 	u8 flags;	/* not used */
 	__le16 reserved;
 	u8 delta_gain_1;
@@ -2999,11 +3017,11 @@
 
 /* COEX flag masks */
 
-/* Staion table is valid */
+/* Station table is valid */
 #define COEX_FLAGS_STA_TABLE_VALID_MSK      (0x1)
-/* UnMask wakeup src at unassociated sleep */
+/* UnMask wake up src at unassociated sleep */
 #define COEX_FLAGS_UNASSOC_WA_UNMASK_MSK    (0x4)
-/* UnMask wakeup src at associated sleep */
+/* UnMask wake up src at associated sleep */
 #define COEX_FLAGS_ASSOC_WA_UNMASK_MSK      (0x8)
 /* Enable CoEx feature. */
 #define COEX_FLAGS_COEX_ENABLE_MSK          (0x80)
@@ -3039,7 +3057,6 @@
 		struct iwl_notif_statistics stats;
 		struct iwl_compressed_ba_resp compressed_ba;
 		struct iwl4965_missed_beacon_notif missed_beacon;
-		struct iwl5000_calibration calib;
 		__le32 status;
 		u8 raw[0];
 	} u;
@@ -3047,4 +3064,4 @@
 
 #define IWL_RX_FRAME_SIZE        (4 + sizeof(struct iwl4965_rx_frame))
 
-#endif				/* __iwl4965_commands_h__ */
+#endif				/* __iwl_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 4c312c5..8eb0203 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -88,26 +88,27 @@
  * translate ucode response to mac80211 tx status control values
  */
 void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
-				  struct ieee80211_tx_info *control)
+				  struct ieee80211_tx_info *info)
 {
 	int rate_index;
+	struct ieee80211_tx_rate *r = &info->control.rates[0];
 
-	control->antenna_sel_tx =
+	info->antenna_sel_tx =
 		((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
 	if (rate_n_flags & RATE_MCS_HT_MSK)
-		control->flags |= IEEE80211_TX_CTL_OFDM_HT;
+		r->flags |= IEEE80211_TX_RC_MCS;
 	if (rate_n_flags & RATE_MCS_GF_MSK)
-		control->flags |= IEEE80211_TX_CTL_GREEN_FIELD;
+		r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
 	if (rate_n_flags & RATE_MCS_FAT_MSK)
-		control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH;
+		r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 	if (rate_n_flags & RATE_MCS_DUP_MSK)
-		control->flags |= IEEE80211_TX_CTL_DUP_DATA;
+		r->flags |= IEEE80211_TX_RC_DUP_DATA;
 	if (rate_n_flags & RATE_MCS_SGI_MSK)
-		control->flags |= IEEE80211_TX_CTL_SHORT_GI;
+		r->flags |= IEEE80211_TX_RC_SHORT_GI;
 	rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags);
-	if (control->band == IEEE80211_BAND_5GHZ)
+	if (info->band == IEEE80211_BAND_5GHZ)
 		rate_index -= IWL_FIRST_OFDM_RATE;
-	control->tx_rate_idx = rate_index;
+	r->idx = rate_index;
 }
 EXPORT_SYMBOL(iwl_hwrate_to_tx_control);
 
@@ -119,7 +120,9 @@
 	if (rate_n_flags & RATE_MCS_HT_MSK) {
 		idx = (rate_n_flags & 0xff);
 
-		if (idx >= IWL_RATE_MIMO2_6M_PLCP)
+		if (idx >= IWL_RATE_MIMO3_6M_PLCP)
+			idx = idx - IWL_RATE_MIMO3_6M_PLCP;
+		else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
 			idx = idx - IWL_RATE_MIMO2_6M_PLCP;
 
 		idx += IWL_FIRST_OFDM_RATE;
@@ -140,7 +143,17 @@
 }
 EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
 
-
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
+{
+	int i;
+	u8 ind = ant;
+	for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+		ind = (ind + 1) < RATE_ANT_NUM ?  ind + 1 : 0;
+		if (priv->hw_params.valid_tx_ant & BIT(ind))
+			return ind;
+	}
+	return ant;
+}
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 EXPORT_SYMBOL(iwl_bcast_addr);
@@ -382,10 +395,10 @@
 }
 EXPORT_SYMBOL(iwl_reset_qos);
 
-#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */
-#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */
+#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
 static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
-			      struct ieee80211_ht_info *ht_info,
+			      struct ieee80211_sta_ht_cap *ht_info,
 			      enum ieee80211_band band)
 {
 	u16 max_bit_rate = 0;
@@ -393,45 +406,46 @@
 	u8 tx_chains_num = priv->hw_params.tx_chains_num;
 
 	ht_info->cap = 0;
-	memset(ht_info->supp_mcs_set, 0, 16);
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
 
-	ht_info->ht_supported = 1;
+	ht_info->ht_supported = true;
 
-	ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
-	ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
-	ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS &
+	ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+	ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
 			     (WLAN_HT_CAP_SM_PS_DISABLED << 2));
 
 	max_bit_rate = MAX_BIT_RATE_20_MHZ;
 	if (priv->hw_params.fat_channel & BIT(band)) {
-		ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
-		ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
-		ht_info->supp_mcs_set[4] = 0x01;
+		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+		ht_info->mcs.rx_mask[4] = 0x01;
 		max_bit_rate = MAX_BIT_RATE_40_MHZ;
 	}
 
 	if (priv->cfg->mod_params->amsdu_size_8K)
-		ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
+		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
 	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
 	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
 
-	ht_info->supp_mcs_set[0] = 0xFF;
+	ht_info->mcs.rx_mask[0] = 0xFF;
 	if (rx_chains_num >= 2)
-		ht_info->supp_mcs_set[1] = 0xFF;
+		ht_info->mcs.rx_mask[1] = 0xFF;
 	if (rx_chains_num >= 3)
-		ht_info->supp_mcs_set[2] = 0xFF;
+		ht_info->mcs.rx_mask[2] = 0xFF;
 
 	/* Highest supported Rx data rate */
 	max_bit_rate *= rx_chains_num;
-	ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF);
-	ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8);
+	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
+	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
 
 	/* Tx MCS capabilities */
-	ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 	if (tx_chains_num != rx_chains_num) {
-		ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF;
-		ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2);
+		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+		ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
+				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
 	}
 }
 
@@ -495,7 +509,7 @@
 	sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
 
 	if (priv->cfg->sku & IWL_SKU_N)
-		iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_5GHZ);
 
 	sband = &priv->bands[IEEE80211_BAND_2GHZ];
@@ -505,7 +519,7 @@
 	sband->n_bitrates = IWL_RATE_COUNT;
 
 	if (priv->cfg->sku & IWL_SKU_N)
-		iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_2GHZ);
 
 	priv->ieee_channels = channels;
@@ -595,8 +609,8 @@
 static bool is_single_rx_stream(struct iwl_priv *priv)
 {
 	return !priv->current_ht_config.is_ht ||
-	       ((priv->current_ht_config.supp_mcs_set[1] == 0) &&
-		(priv->current_ht_config.supp_mcs_set[2] == 0));
+	       ((priv->current_ht_config.mcs.rx_mask[1] == 0) &&
+		(priv->current_ht_config.mcs.rx_mask[2] == 0));
 }
 
 static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -609,10 +623,10 @@
 	if (!is_channel_valid(ch_info))
 		return 0;
 
-	if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE)
+	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
 		return !(ch_info->fat_extension_channel &
 					IEEE80211_CHAN_NO_FAT_ABOVE);
-	else if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW)
+	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
 		return !(ch_info->fat_extension_channel &
 					IEEE80211_CHAN_NO_FAT_BELOW);
 
@@ -620,24 +634,24 @@
 }
 
 u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
-			     struct ieee80211_ht_info *sta_ht_inf)
+			 struct ieee80211_sta_ht_cap *sta_ht_inf)
 {
 	struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
 
 	if ((!iwl_ht_conf->is_ht) ||
 	   (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
-	   (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE))
+	   (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
 		return 0;
 
 	if (sta_ht_inf) {
 		if ((!sta_ht_inf->ht_supported) ||
-		   (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
+		   (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
 			return 0;
 	}
 
 	return iwl_is_channel_extension(priv, priv->band,
-					 iwl_ht_conf->control_channel,
-					 iwl_ht_conf->extension_chan_offset);
+					le16_to_cpu(priv->staging_rxon.channel),
+					iwl_ht_conf->extension_chan_offset);
 }
 EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
 
@@ -662,22 +676,15 @@
 		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
 				 RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
 
-	if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
-		IWL_DEBUG_ASSOC("control diff than current %d %d\n",
-				le16_to_cpu(rxon->channel),
-				ht_info->control_channel);
-		return;
-	}
-
 	/* Note: control channel is opposite of extension channel */
 	switch (ht_info->extension_chan_offset) {
-	case IEEE80211_HT_IE_CHA_SEC_ABOVE:
+	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 		rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
 		break;
-	case IEEE80211_HT_IE_CHA_SEC_BELOW:
+	case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 		rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
 		break;
-	case IEEE80211_HT_IE_CHA_SEC_NONE:
+	case IEEE80211_HT_PARAM_CHA_SEC_NONE:
 	default:
 		rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
 		break;
@@ -691,14 +698,12 @@
 
 	IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
 			"rxon flags 0x%X operation mode :0x%X "
-			"extension channel offset 0x%x "
-			"control chan %d\n",
-			ht_info->supp_mcs_set[0],
-			ht_info->supp_mcs_set[1],
-			ht_info->supp_mcs_set[2],
+			"extension channel offset 0x%x\n",
+			ht_info->mcs.rx_mask[0],
+			ht_info->mcs.rx_mask[1],
+			ht_info->mcs.rx_mask[2],
 			le32_to_cpu(rxon->flags), ht_info->ht_protection,
-			ht_info->extension_chan_offset,
-			ht_info->control_channel);
+			ht_info->extension_chan_offset);
 	return;
 }
 EXPORT_SYMBOL(iwl_set_rxon_ht);
@@ -742,7 +747,7 @@
 		break;
 	case WLAN_HT_CAP_SM_PS_INVALID:
 	default:
-		IWL_ERROR("invalide mimo ps mode %d\n",
+		IWL_ERROR("invalid mimo ps mode %d\n",
 			   priv->current_ht_config.sm_ps);
 		WARN_ON(1);
 		idle_cnt = -1;
@@ -868,7 +873,8 @@
 
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM;
+		    IEEE80211_HW_NOISE_DBM |
+		    IEEE80211_HW_AMPDU_AGGREGATION;
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_STATION) |
@@ -945,7 +951,6 @@
 
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 
-	priv->use_ant_b_for_management_frame = 1; /* start with ant B */
 	priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
 
 	/* Choose which receivers/antennas to use */
@@ -1169,24 +1174,47 @@
 }
 EXPORT_SYMBOL(iwl_verify_ucode);
 
+
+static const char *desc_lookup_text[] = {
+	"OK",
+	"FAIL",
+	"BAD_PARAM",
+	"BAD_CHECKSUM",
+	"NMI_INTERRUPT_WDG",
+	"SYSASSERT",
+	"FATAL_ERROR",
+	"BAD_COMMAND",
+	"HW_ERROR_TUNE_LOCK",
+	"HW_ERROR_TEMPERATURE",
+	"ILLEGAL_CHAN_FREQ",
+	"VCC_NOT_STABLE",
+	"FH_ERROR",
+	"NMI_INTERRUPT_HOST",
+	"NMI_INTERRUPT_ACTION_PT",
+	"NMI_INTERRUPT_UNKNOWN",
+	"UCODE_VERSION_MISMATCH",
+	"HW_ERROR_ABS_LOCK",
+	"HW_ERROR_CAL_LOCK_FAIL",
+	"NMI_INTERRUPT_INST_ACTION_PT",
+	"NMI_INTERRUPT_DATA_ACTION_PT",
+	"NMI_TRM_HW_ER",
+	"NMI_INTERRUPT_TRM",
+	"NMI_INTERRUPT_BREAK_POINT"
+	"DEBUG_0",
+	"DEBUG_1",
+	"DEBUG_2",
+	"DEBUG_3",
+	"UNKNOWN"
+};
+
 static const char *desc_lookup(int i)
 {
-	switch (i) {
-	case 1:
-		return "FAIL";
-	case 2:
-		return "BAD_PARAM";
-	case 3:
-		return "BAD_CHECKSUM";
-	case 4:
-		return "NMI_INTERRUPT";
-	case 5:
-		return "SYSASSERT";
-	case 6:
-		return "FATAL_ERROR";
-	}
+	int max = ARRAY_SIZE(desc_lookup_text) - 1;
 
-	return "UNKNOWN";
+	if (i < 0 || i > max)
+		i = max;
+
+	return desc_lookup_text[i];
 }
 
 #define ERROR_START_OFFSET  (1 * sizeof(u32))
@@ -1232,9 +1260,9 @@
 	line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
 	time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
 
-	IWL_ERROR("Desc        Time       "
+	IWL_ERROR("Desc                               Time       "
 		"data1      data2      line\n");
-	IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
+	IWL_ERROR("%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
 		desc_lookup(desc), desc, time, data1, data2, line);
 	IWL_ERROR("blink1  blink2  ilink1  ilink2\n");
 	IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 288b6a8..10f07f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -100,7 +100,7 @@
 };
 
 struct iwl_lib_ops {
-	/* set hw dependant perameters */
+	/* set hw dependent parameters */
 	int (*set_hw_params)(struct iwl_priv *priv);
 	/* ucode shared memory */
 	int (*alloc_shared_mem)(struct iwl_priv *priv);
@@ -173,6 +173,8 @@
 	const char *fw_name;
 	unsigned int sku;
 	int eeprom_size;
+	u16  eeprom_ver;
+	u16  eeprom_calib_ver;
 	const struct iwl_ops *ops;
 	const struct iwl_mod_params *mod_params;
 };
@@ -190,7 +192,7 @@
 int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
 u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
-			 struct ieee80211_ht_info *sta_ht_inf);
+			 struct ieee80211_sta_ht_cap *sta_ht_inf);
 int iwl_hw_nic_init(struct iwl_priv *priv);
 int iwl_setup_mac(struct iwl_priv *priv);
 int iwl_set_hw_params(struct iwl_priv *priv);
@@ -237,7 +239,6 @@
 int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
 int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
 int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
-
 /*****************************************************
  * TX power
  ****************************************************/
@@ -259,6 +260,13 @@
 			      struct ieee80211_tx_info *info);
 int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
 
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
+
+static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
+{
+	return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
 static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
 {
 	return le32_to_cpu(rate_n_flags) & 0xFF;
@@ -313,6 +321,7 @@
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 void iwl_dump_nic_event_log(struct iwl_priv *priv);
 
+
 /*************** DRIVER STATUS FUNCTIONS   *****/
 
 #define STATUS_HCMD_ACTIVE	0	/* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 662edf4..84f56a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -60,6 +60,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
+#ifndef __iwl_csr_h__
+#define __iwl_csr_h__
 /*=== CSR (control and status registers) ===*/
 #define CSR_BASE    (0x000)
 
@@ -286,4 +288,4 @@
 #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
 
 
-
+#endif /* !__iwl_csr_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index e548d67..84b7772 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -101,13 +101,12 @@
  *
  * To add your debug level to the list of levels seen when you perform
  *
- * % cat /proc/net/iwl/debug_level
+ * % cat /sys/class/net/wlanX/device/debug_level
  *
  * you simply need to add your entry to the iwl_debug_levels array.
  *
- * If you do not see debug_level in /proc/net/iwl then you do not have
- * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
- *
+ * If you do not see debug_level in  /sys/class/net/wlanX/device/debug_level
+ * then you do not have CONFIG_IWLWIFI_DEBUG defined in your kernel config file
  */
 
 #define IWL_DL_INFO		(1 << 0)
@@ -183,6 +182,8 @@
 #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
 #define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
 #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_TX_REPLY_LIMIT(f, a...) \
+	IWL_DEBUG_LIMIT(IWL_DL_TX_REPLY, f, ## a)
 #define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
 #define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
 #define IWL_DEBUG_POWER(f, a...)  IWL_DEBUG(IWL_DL_POWER, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 20db0eb..c3df5aa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -58,7 +58,8 @@
 #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                        \
 	dbgfs->dbgfs_##parent##_files.file_##name =                     \
 	debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr);     \
-	if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name))          \
+	if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)		\
+			|| !dbgfs->dbgfs_##parent##_files.file_##name)	\
 		goto err;                                               \
 } while (0)
 
@@ -228,7 +229,6 @@
 	ssize_t ret;
 	/* Add 30 for initial string */
 	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
-	DECLARE_MAC_BUF(mac);
 
 	buf = kmalloc(bufsz, GFP_KERNEL);
 	if (!buf)
@@ -242,7 +242,6 @@
 		if (station->used) {
 			pos += scnprintf(buf + pos, bufsz - pos,
 					"station %d:\ngeneral data:\n", i+1);
-			print_mac(mac, station->sta.sta.addr);
 			pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
 					station->sta.sta.sta_id);
 			pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c018121..eb396f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -112,11 +112,9 @@
 				* space less than this */
 } __attribute__ ((packed));
 
-#define MAX_NUM_OF_TBS          (20)
-
 /* One for each TFD */
 struct iwl_tx_info {
-	struct sk_buff *skb[MAX_NUM_OF_TBS];
+	struct sk_buff *skb[IWL_NUM_OF_TBS - 1];
 };
 
 /**
@@ -134,12 +132,13 @@
  */
 struct iwl_tx_queue {
 	struct iwl_queue q;
-	struct iwl_tfd_frame *bd;
+	struct iwl_tfd *tfds;
 	struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
 	struct iwl_tx_info *txb;
-	int need_update;
-	int sched_retry;
-	int active;
+	u8 need_update;
+	u8 sched_retry;
+	u8 active;
+	u8 swq_id;
 };
 
 #define IWL_NUM_SCAN_RATES         (2)
@@ -252,7 +251,8 @@
 	/* The CMD_SIZE_HUGE flag bit indicates that the command
 	 * structure is stored at the end of the shared queue memory. */
 	u32 flags;
-
+	DECLARE_PCI_UNMAP_ADDR(mapping)
+	DECLARE_PCI_UNMAP_LEN(len)
 } __attribute__ ((packed));
 
 #define IWL_CMD_MAX_PAYLOAD 320
@@ -268,24 +268,16 @@
 	struct iwl_cmd_meta meta;	/* driver data */
 	struct iwl_cmd_header hdr;	/* uCode API */
 	union {
-		struct iwl_addsta_cmd addsta;
-		struct iwl_led_cmd led;
 		u32 flags;
 		u8 val8;
 		u16 val16;
 		u32 val32;
-		struct iwl4965_bt_cmd bt;
-		struct iwl4965_rxon_time_cmd rxon_time;
-		struct iwl_powertable_cmd powertable;
-		struct iwl_qosparam_cmd qosparam;
 		struct iwl_tx_cmd tx;
-		struct iwl4965_rxon_assoc_cmd rxon_assoc;
-		struct iwl_rem_sta_cmd rm_sta;
-		u8 *indirect;
 		u8 payload[IWL_CMD_MAX_PAYLOAD];
 	} __attribute__ ((packed)) cmd;
 } __attribute__ ((packed));
 
+
 struct iwl_host_cmd {
 	u8 id;
 	u16 len;
@@ -412,9 +404,8 @@
 	u8 max_amsdu_size;
 	u8 ampdu_factor;
 	u8 mpdu_density;
-	u8 supp_mcs_set[16];
+	struct ieee80211_mcs_info mcs;
 	/* BSS related data */
-	u8 control_channel;
 	u8 extension_chan_offset;
 	u8 tx_chan_width;
 	u8 ht_protection;
@@ -527,8 +518,8 @@
  * @sw_crypto: 0 for hw, 1 for sw
  * @max_xxx_size: for ucode uses
  * @ct_kill_threshold: temperature threshold
+ * @calib_init_cfg: setup initial calibrations for the hw
  * @struct iwl_sensitivity_ranges: range of sensitivity values
- * @first_ampdu_q: first HW queue available for ampdu
  */
 struct iwl_hw_params {
 	u16 max_txq_num;
@@ -548,8 +539,8 @@
 	u32 max_data_size;
 	u32 max_bsm_size;
 	u32 ct_kill_threshold; /* value in hw-dependent units */
+	u32 calib_init_cfg;
 	const struct iwl_sensitivity_ranges *sens;
-	u8 first_ampdu_q;
 };
 
 #define HT_SHORT_GI_20MHZ	(1 << 0)
@@ -584,9 +575,9 @@
 extern int iwl_send_add_sta(struct iwl_priv *priv,
 			    struct iwl_addsta_cmd *sta, u8 flags);
 extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
-			int is_ap, u8 flags, struct ieee80211_ht_info *ht_info);
-extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
-extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
+			int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
+extern void iwl_update_chain_flags(struct iwl_priv *priv);
+extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
 extern const u8 iwl_bcast_addr[ETH_ALEN];
 extern int iwl_rxq_stop(struct iwl_priv *priv);
 extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
@@ -699,6 +690,20 @@
 	u32 beacon_energy_c;
 };
 
+
+/*
+ * enum iwl_calib
+ * defines the order in which results of initial calibrations
+ * should be sent to the runtime uCode
+ */
+enum iwl_calib {
+	IWL_CALIB_XTAL,
+	IWL_CALIB_LO,
+	IWL_CALIB_TX_IQ,
+	IWL_CALIB_TX_IQ_PERD,
+	IWL_CALIB_MAX
+};
+
 /* Opaque calibration results */
 struct iwl_calib_result {
 	void *buf;
@@ -765,7 +770,6 @@
 
 
 #define IWL_MAX_NUM_QUEUES	20 /* FIXME: do dynamic allocation */
-#define IWL_CALIB_MAX  3
 
 struct iwl_priv {
 
@@ -817,12 +821,13 @@
 	unsigned long scan_start;
 	unsigned long scan_pass_start;
 	unsigned long scan_start_tsf;
+	struct iwl_scan_cmd *scan;
 	int scan_bands;
 	int one_direct_scan;
 	u8 direct_ssid_len;
 	u8 direct_ssid[IW_ESSID_MAX_SIZE];
-	struct iwl_scan_cmd *scan;
-	u32 scan_tx_ant[IEEE80211_NUM_BANDS];
+	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
+	u8 mgmt_tx_ant;
 
 	/* spinlock */
 	spinlock_t lock;	/* protect general shared data */
@@ -849,7 +854,7 @@
 	u8 ucode_write_complete;	/* the image write is complete */
 
 
-	struct iwl4965_rxon_time_cmd rxon_timing;
+	struct iwl_rxon_time_cmd rxon_timing;
 
 	/* We declare this const so it can only be
 	 * changed via explicit cast within the
@@ -881,7 +886,6 @@
 	u16 active_rate_basic;
 
 	u8 assoc_station_added;
-	u8 use_ant_b_for_management_frame;	/* Tx antenna selection */
 	u8 start_calib;
 	struct iwl_sensitivity_data sensitivity_data;
 	struct iwl_chain_noise_data chain_noise_data;
@@ -907,7 +911,7 @@
 
 	unsigned long status;
 
-	int last_rx_rssi;	/* From Rx packet statisitics */
+	int last_rx_rssi;	/* From Rx packet statistics */
 	int last_rx_noise;	/* From beacon statistics */
 
 	/* counts mgmt, ctl, and data packets */
@@ -922,8 +926,6 @@
 	unsigned long last_statistics_time;
 
 	/* context information */
-	u8 essid[IW_ESSID_MAX_SIZE];
-	u8 essid_len;
 	u16 rates_mask;
 
 	u32 power_mode;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 3715575..792a3c1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -279,7 +279,23 @@
 
 int iwl_eeprom_check_version(struct iwl_priv *priv)
 {
-	return priv->cfg->ops->lib->eeprom_ops.check_version(priv);
+	u16 eeprom_ver;
+	u16 calib_ver;
+
+	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+	calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
+
+	if (eeprom_ver < priv->cfg->eeprom_ver ||
+	    calib_ver < priv->cfg->eeprom_calib_ver)
+		goto err;
+
+	return 0;
+err:
+	IWL_ERROR("Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
+		  eeprom_ver, priv->cfg->eeprom_ver,
+		  calib_ver,  priv->cfg->eeprom_calib_ver);
+	return -EINVAL;
+
 }
 EXPORT_SYMBOL(iwl_eeprom_check_version);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index d3a2a5b..997f23c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -174,6 +174,9 @@
 #define EEPROM_5000_REG_BAND_52_FAT_CHANNELS  ((0x92)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22  bytes */
 
+/* 5050 Specific */
+#define EEPROM_5050_TX_POWER_VERSION    (4)
+#define EEPROM_5050_EEPROM_VERSION	(0x21E)
 
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];
@@ -371,7 +374,7 @@
 	int (*verify_signature) (struct iwl_priv *priv);
 	int (*acquire_semaphore) (struct iwl_priv *priv);
 	void (*release_semaphore) (struct iwl_priv *priv);
-	int (*check_version) (struct iwl_priv *priv);
+	u16 (*calib_version) (struct iwl_priv *priv);
 	const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
 };
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index a72efdf..97e2cf4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -60,6 +60,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
+#ifndef __iwl_fh_h__
+#define __iwl_fh_h__
 
 /****************************/
 /* Flow Handler Definitions */
@@ -316,34 +318,40 @@
 #define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
 
 /* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
-	(FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
+#define FH49_TCSR_CHNL_NUM                            (7)
+#define FH50_TCSR_CHNL_NUM                            (8)
 
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL    (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL     (0x00000008)
+#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
+#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
 
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE            (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF        (0x40000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE           (0x80000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV		(0x00000001)
 
-#define FH_TCSR_CHNL_NUM                            (7)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE	(0x00000008)
 
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY          (0x00000000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT           (0x00002000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID          (0x00000003)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD	(0x00100000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD	(0x00200000)
 
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT           (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD          (0x00100000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD           (0x00200000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD	(0x00400000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD	(0x00800000)
 
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM      (20)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX      (12)
-#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
-	(FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
-#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
-	  (FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x4)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
-	 (FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x8)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF	(0x40000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE	(0x80000000)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY	(0x00000000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT	(0x00002000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID	(0x00000003)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM		(20)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX		(12)
 
 /**
  * Tx Shared Status Registers (TSSR)
@@ -360,7 +368,7 @@
 #define FH_TSSR_LOWER_BOUND		(FH_MEM_LOWER_BOUND + 0xEA0)
 #define FH_TSSR_UPPER_BOUND		(FH_MEM_LOWER_BOUND + 0xEC0)
 
-#define FH_TSSR_TX_STATUS_REG	(FH_TSSR_LOWER_BOUND + 0x010)
+#define FH_TSSR_TX_STATUS_REG		(FH_TSSR_LOWER_BOUND + 0x010)
 
 #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24)
 #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16)
@@ -391,3 +399,9 @@
 /* TCSR: tx_config register values */
 #define FH_RSCSR_FRAME_SIZE_MSK	(0x00003FFF)	/* bits 0-13 */
 
+#define TFD_QUEUE_SIZE_MAX      (256)
+#define TFD_QUEUE_SIZE_BC_DUP	(64)
+#define TFD_QUEUE_BC_SIZE	(TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
+
+
+#endif /* !__iwl_fh_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 41eed67..4f0fa21 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -32,108 +32,6 @@
 
 #include <linux/ctype.h>
 
-/*
- * The structures defined by the hardware/uCode interface
- * have bit-wise operations.  For each bit-field there is
- * a data symbol in the structure, the start bit position
- * and the length of the bit-field.
- *
- * iwl_get_bits and iwl_set_bits will return or set the
- * appropriate bits on a 32-bit value.
- *
- * IWL_GET_BITS and IWL_SET_BITS use symbol expansion to
- * expand out to the appropriate call to iwl_get_bits
- * and iwl_set_bits without having to reference all of the
- * numerical constants and defines provided in the hardware
- * definition
- */
-
-/**
- * iwl_get_bits - Extract a hardware bit-field value
- * @src: source hardware value (__le32)
- * @pos: bit-position (0-based) of first bit of value
- * @len: length of bit-field
- *
- * iwl_get_bits will return the bit-field in cpu endian ordering.
- *
- * NOTE:  If used from IWL_GET_BITS then pos and len are compile-constants and
- *        will collapse to minimal code by the compiler.
- */
-static inline u32 iwl_get_bits(__le32 src, u8 pos, u8 len)
-{
-	u32 tmp = le32_to_cpu(src);
-
-	tmp >>= pos;
-	tmp &= (1UL << len) - 1;
-	return tmp;
-}
-
-/**
- * iwl_set_bits - Set a hardware bit-field value
- * @dst: Address of __le32 hardware value
- * @pos: bit-position (0-based) of first bit of value
- * @len: length of bit-field
- * @val: cpu endian value to encode into the bit-field
- *
- * iwl_set_bits will encode val into dst, masked to be len bits long at bit
- * position pos.
- *
- * NOTE:  If used IWL_SET_BITS pos and len will be compile-constants and
- *        will collapse to minimal code by the compiler.
- */
-static inline void iwl_set_bits(__le32 *dst, u8 pos, u8 len, int val)
-{
-	u32 tmp = le32_to_cpu(*dst);
-
-	tmp &= ~(((1UL << len) - 1) << pos);
-	tmp |= (val & ((1UL << len) - 1)) << pos;
-	*dst = cpu_to_le32(tmp);
-}
-
-static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)
-{
-	u16 tmp = le16_to_cpu(*dst);
-
-	tmp &= ~((1UL << (pos + len)) - (1UL << pos));
-	tmp |= (val & ((1UL << len) - 1)) << pos;
-	*dst = cpu_to_le16(tmp);
-}
-
-/*
- * The bit-field definitions in iwl-xxxx-hw.h are in the form of:
- *
- * struct example {
- *         __le32 val1;
- * #define IWL_name_POS 8
- * #define IWL_name_LEN 4
- * #define IWL_name_SYM val1
- * };
- *
- * The IWL_SET_BITS and IWL_GET_BITS macros are provided to allow the driver
- * to call:
- *
- * struct example bar;
- * u32 val = IWL_GET_BITS(bar, name);
- * val = val * 2;
- * IWL_SET_BITS(bar, name, val);
- *
- * All cpu / host ordering, masking, and shifts are performed by the macros
- * and iwl_{get,set}_bits.
- *
- */
-#define IWL_SET_BITS(s, sym, v) \
-	iwl_set_bits(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-		     IWL_ ## sym ## _LEN, (v))
-
-#define IWL_SET_BITS16(s, sym, v) \
-	iwl_set_bits16(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-		       IWL_ ## sym ## _LEN, (v))
-
-#define IWL_GET_BITS(s, sym) \
-	iwl_get_bits((s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-		      IWL_ ## sym ## _LEN)
-
-
 #define KELVIN_TO_CELSIUS(x) ((x)-273)
 #define CELSIUS_TO_KELVIN(x) ((x)+273)
 #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
@@ -159,11 +57,6 @@
 	return end + (MAX_JIFFY_OFFSET - start) + 1;
 }
 
-static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
-{
-	return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
-}
-
 /**
  * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
  * @index -- current index
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 9740fcc..40e0050 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -55,7 +55,7 @@
  * _iwl_read32.)
  *
  * These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguring of the hardware I/O.  In combination with
+ * which result in misconfiguration of the hardware I/O.  In combination with
  * git-bisect and the IO debug level you can quickly determine the specific
  * commit which breaks the IO sequence to the hardware.
  *
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 4eee1b1..ffb428a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -278,7 +278,7 @@
 	/* FIXME: + priv->rx_stats[2].bytes; */
 	s64 tpt = current_tpt - priv->led_tpt;
 
-	if (tpt < 0) /* wrapparound */
+	if (tpt < 0) /* wraparound */
 		tpt = -tpt;
 
 	IWL_DEBUG_LED("tpt %lld current_tpt %llu\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 60a03d2..07a5f60 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -80,7 +80,7 @@
 #define IWL_REDUCED_POWER_TEMPERATURE	95
 
 /* default power management (not Tx power) table values */
-/* for tim  0-10 */
+/* for TIM  0-10 */
 static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
@@ -91,7 +91,7 @@
 };
 
 
-/* for tim = 3-10 */
+/* for TIM = 3-10 */
 static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -101,7 +101,7 @@
 	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
 };
 
-/* for tim > 11 */
+/* for TIM > 11 */
 static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
@@ -183,7 +183,7 @@
 	return 0;
 }
 
-/* adjust power command according to dtim period and power level*/
+/* adjust power command according to DTIM period and power level*/
 static int iwl_update_power_command(struct iwl_priv *priv,
 				    struct iwl_powertable_cmd *cmd,
 				    u16 mode)
@@ -325,7 +325,7 @@
 EXPORT_SYMBOL(iwl_power_update_mode);
 
 /* Allow other iwl code to disable/enable power management active
- * this will be usefull for rate scale to disable PM during heavy
+ * this will be useful for rate scale to disable PM during heavy
  * Tx/Rx activities
  */
 int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
@@ -352,8 +352,8 @@
 EXPORT_SYMBOL(iwl_power_disable_management);
 
 /* Allow other iwl code to disable/enable power management active
- * this will be usefull for rate scale to disable PM during hight
- * valume activities
+ * this will be useful for rate scale to disable PM during high
+ * volume activities
  */
 int iwl_power_enable_management(struct iwl_priv *priv)
 {
@@ -391,7 +391,7 @@
 }
 EXPORT_SYMBOL(iwl_power_set_system_mode);
 
-/* initilize to default */
+/* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
 
@@ -443,7 +443,7 @@
 
 	mutex_lock(&priv->mutex);
 
-	/* on starting association we disable power managment
+	/* on starting association we disable power management
 	 * until association, if association failed then this
 	 * timer will expire and enable PM again.
 	 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index ee5afd4..b0ffb89 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -158,9 +158,9 @@
  *
  * 4)  Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
  *     images in host DRAM.  The last register loaded must be the instruction
- *     bytecount register ("1" in MSbit tells initialization uCode to load
+ *     byte count register ("1" in MSbit tells initialization uCode to load
  *     the runtime uCode):
- *     BSM_DRAM_INST_BYTECOUNT_REG = bytecount | BSM_DRAM_INST_LOAD
+ *     BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD
  *
  * 5)  Wait for "alive" notification, then issue normal runtime commands.
  *
@@ -244,7 +244,7 @@
 /**
  * Tx Scheduler
  *
- * The Tx Scheduler selects the next frame to be transmitted, chosing TFDs
+ * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
  * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
  * host DRAM.  It steers each frame's Tx command (which contains the frame
  * data) into one of up to 7 prioritized Tx DMA FIFO channels within the
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 5d64229..618841a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -64,7 +64,7 @@
 		iwl_radio_kill_sw_disable_radio(priv);
 		break;
 	default:
-		IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+		IWL_WARNING("we received unexpected RFKILL state %d\n", state);
 		break;
 	}
 out_unlock:
@@ -83,7 +83,7 @@
 	IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
 	priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
 	if (!priv->rfkill) {
-		IWL_ERROR("Unable to allocate rfkill device.\n");
+		IWL_ERROR("Unable to allocate RFKILL device.\n");
 		ret = -ENOMEM;
 		goto error;
 	}
@@ -99,7 +99,7 @@
 
 	ret = rfkill_register(priv->rfkill);
 	if (ret) {
-		IWL_ERROR("Unable to register rfkill: %d\n", ret);
+		IWL_ERROR("Unable to register RFKILL: %d\n", ret);
 		goto free_rfkill;
 	}
 
@@ -127,7 +127,7 @@
 }
 EXPORT_SYMBOL(iwl_rfkill_unregister);
 
-/* set rf-kill to the right state. */
+/* set RFKILL to the right state. */
 void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
 {
 	if (!priv->rfkill)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 7cde9d7..b86f9586 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -407,7 +407,7 @@
 			   (priv->shared_phys + priv->rb_closed_offset) >> 4);
 
 	/* Enable Rx DMA
-	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set becuase of HW bug in
+	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
 	 *      the credit mechanism in 5000 HW RX FIFO
 	 * Direct rx interrupts to hosts
 	 * Rx buffer size 4 or 8k
@@ -1149,7 +1149,7 @@
 		priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
 
 	/* Set "1" to report good data frames in groups of 100 */
-	/* FIXME: need to optimze the call: */
+	/* FIXME: need to optimize the call: */
 	iwl_dbg_report_frame(priv, pkt, header, 1);
 
 	IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
@@ -1160,12 +1160,12 @@
 	 * "antenna number"
 	 *
 	 * It seems that the antenna field in the phy flags value
-	 * is actually a bitfield. This is undefined by radiotap,
+	 * is actually a bit field. This is undefined by radiotap,
 	 * it wants an actual antenna number but I always get "7"
 	 * for most legacy frames I receive indicating that the
 	 * same frame was received on all three RX chains.
 	 *
-	 * I think this field should be removed in favour of a
+	 * I think this field should be removed in favor of a
 	 * new 802.11n radiotap field "RX chains" that is defined
 	 * as a bitmask.
 	 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index c89365e..c4b9030 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -25,8 +25,10 @@
  * Tomas Winkler <tomas.winkler@intel.com>
  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
-#include <net/mac80211.h>
+#include <linux/types.h>
 #include <linux/etherdevice.h>
+#include <net/lib80211.h>
+#include <net/mac80211.h>
 
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
@@ -64,54 +66,6 @@
 #define IWL_SCAN_PROBE_MASK(n) 	cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
 
 
-static int scan_tx_ant[3] = {
-	RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK
-};
-
-
-
-static int iwl_is_empty_essid(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
-
-
-static const char *iwl_escape_essid(const char *essid, u8 essid_len)
-{
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (iwl_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else
-			*d++ = *s++;
-	}
-	*d = '\0';
-	return escaped;
-}
-
 /**
  * iwl_scan_cancel - Cancel any currently executing HW scan
  *
@@ -455,10 +409,11 @@
 
 void iwl_init_scan_params(struct iwl_priv *priv)
 {
+	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
 	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
-		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = RATE_MCS_ANT_INIT_IND;
+		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
 	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
-		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = RATE_MCS_ANT_INIT_IND;
+		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
 }
 
 int iwl_scan_initiate(struct iwl_priv *priv)
@@ -550,7 +505,7 @@
 {
 	struct ieee80211_ht_cap *ht_cap;
 
-	if (!sband || !sband->ht_info.ht_supported)
+	if (!sband || !sband->ht_cap.ht_supported)
 		return;
 
 	if (*left < sizeof(struct ieee80211_ht_cap))
@@ -559,12 +514,12 @@
 	*pos++ = sizeof(struct ieee80211_ht_cap);
 	ht_cap = (struct ieee80211_ht_cap *) pos;
 
-	ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
-	memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
+	ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
+	memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
 	ht_cap->ampdu_params_info =
-		(sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
-		((sband->ht_info.ampdu_density << 2) &
-			IEEE80211_HT_CAP_AMPDU_DENSITY);
+		(sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
+		((sband->ht_cap.ampdu_density << 2) &
+			IEEE80211_HT_AMPDU_PARM_DENSITY);
 	*left -= sizeof(struct ieee80211_ht_cap);
 }
 
@@ -670,23 +625,6 @@
 	return (u16)len;
 }
 
-static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
-{
-	int i, ind;
-
-	ind = priv->scan_tx_ant[band];
-	for (i = 0; i < priv->hw_params.tx_chains_num; i++) {
-		ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1;
-		if (priv->hw_params.valid_tx_ant & (1 << ind)) {
-			priv->scan_tx_ant[band] = ind;
-			break;
-		}
-	}
-	IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
-	return scan_tx_ant[ind];
-}
-
-
 static void iwl_bg_request_scan(struct work_struct *data)
 {
 	struct iwl_priv *priv =
@@ -699,11 +637,13 @@
 	struct iwl_scan_cmd *scan;
 	struct ieee80211_conf *conf = NULL;
 	int ret = 0;
-	u32 tx_ant;
+	u32 rate_flags = 0;
 	u16 cmd_len;
 	enum ieee80211_band band;
 	u8 n_probes = 2;
 	u8 rx_chain = priv->hw_params.valid_rx_ant;
+	u8 rate;
+	DECLARE_SSID_BUF(ssid);
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -714,7 +654,7 @@
 		goto done;
 	}
 
-	/* Make sure the scan wasn't cancelled before this queued work
+	/* Make sure the scan wasn't canceled before this queued work
 	 * was given the chance to run... */
 	if (!test_bit(STATUS_SCANNING, &priv->status))
 		goto done;
@@ -796,20 +736,13 @@
 	/* We should add the ability for user to lock to PASSIVE ONLY */
 	if (priv->one_direct_scan) {
 		IWL_DEBUG_SCAN("Start direct scan for '%s'\n",
-				iwl_escape_essid(priv->direct_ssid,
-				priv->direct_ssid_len));
+				print_ssid(ssid, priv->direct_ssid,
+					   priv->direct_ssid_len));
 		scan->direct_scan[0].id = WLAN_EID_SSID;
 		scan->direct_scan[0].len = priv->direct_ssid_len;
 		memcpy(scan->direct_scan[0].ssid,
 		       priv->direct_ssid, priv->direct_ssid_len);
 		n_probes++;
-	} else if (!iwl_is_associated(priv) && priv->essid_len) {
-		IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n",
-				iwl_escape_essid(priv->essid, priv->essid_len));
-		scan->direct_scan[0].id = WLAN_EID_SSID;
-		scan->direct_scan[0].len = priv->essid_len;
-		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
-		n_probes++;
 	} else {
 		IWL_DEBUG_SCAN("Start indirect scan.\n");
 	}
@@ -822,23 +755,16 @@
 	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
 		band = IEEE80211_BAND_2GHZ;
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-		tx_ant = iwl_scan_tx_ant(priv, band);
-		if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK)
-			scan->tx_cmd.rate_n_flags =
-				iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
-							tx_ant);
-		else
-			scan->tx_cmd.rate_n_flags =
-				iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
-							tx_ant |
-							RATE_MCS_CCK_MSK);
+		if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) {
+			rate = IWL_RATE_6M_PLCP;
+		} else {
+			rate = IWL_RATE_1M_PLCP;
+			rate_flags = RATE_MCS_CCK_MSK;
+		}
 		scan->good_CRC_th = 0;
 	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
 		band = IEEE80211_BAND_5GHZ;
-		tx_ant = iwl_scan_tx_ant(priv, band);
-		scan->tx_cmd.rate_n_flags =
-				iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
-							tx_ant);
+		rate = IWL_RATE_6M_PLCP;
 		scan->good_CRC_th = IWL_GOOD_CRC_TH;
 
 		/* Force use of chains B and C (0x6) for scan Rx for 4965
@@ -851,6 +777,11 @@
 		goto done;
 	}
 
+	priv->scan_tx_ant[band] =
+			 iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
+	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
+	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
+
 	/* MIMO is not used here, but value is required */
 	scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
 				cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 61797f3..0c5f122 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -45,7 +45,6 @@
 	int start = 0;
 	int ret = IWL_INVALID_STATION;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
 	    (priv->iw_mode == NL80211_IFTYPE_AP))
@@ -63,8 +62,8 @@
 			goto out;
 		}
 
-	IWL_DEBUG_ASSOC_LIMIT("can not find STA %s total %d\n",
-			      print_mac(mac, addr), priv->num_stations);
+	IWL_DEBUG_ASSOC_LIMIT("can not find STA %pM total %d\n",
+			      addr, priv->num_stations);
 
  out:
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -86,7 +85,6 @@
 static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 {
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
@@ -94,8 +92,8 @@
 		IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
 
 	priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
-	IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n",
-			print_mac(mac, priv->stations[sta_id].sta.sta.addr));
+	IWL_DEBUG_ASSOC("Added STA to Ucode: %pM\n",
+			priv->stations[sta_id].sta.sta.addr);
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
@@ -104,7 +102,9 @@
 				   struct iwl_cmd *cmd, struct sk_buff *skb)
 {
 	struct iwl_rx_packet *res = NULL;
-	u8 sta_id = cmd->cmd.addsta.sta.sta_id;
+	struct iwl_addsta_cmd *addsta =
+		(struct iwl_addsta_cmd *)cmd->cmd.payload;
+	u8 sta_id = addsta->sta.sta_id;
 
 	if (!skb) {
 		IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
@@ -183,7 +183,7 @@
 EXPORT_SYMBOL(iwl_send_add_sta);
 
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
-				   struct ieee80211_ht_info *sta_ht_inf)
+				   struct ieee80211_sta_ht_cap *sta_ht_inf)
 {
 	__le32 sta_flags;
 	u8 mimo_ps_mode;
@@ -231,13 +231,12 @@
  * iwl_add_station_flags - Add station to tables in driver and device
  */
 u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
-			 u8 flags, struct ieee80211_ht_info *ht_info)
+			 u8 flags, struct ieee80211_sta_ht_cap *ht_info)
 {
 	int i;
 	int sta_id = IWL_INVALID_STATION;
 	struct iwl_station_entry *station;
 	unsigned long flags_spin;
-	DECLARE_MAC_BUF(mac);
 
 	spin_lock_irqsave(&priv->sta_lock, flags_spin);
 	if (is_ap)
@@ -273,8 +272,8 @@
 
 	station = &priv->stations[sta_id];
 	station->used = IWL_STA_DRIVER_ACTIVE;
-	IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n",
-			sta_id, print_mac(mac, addr));
+	IWL_DEBUG_ASSOC("Add STA to driver ID %d: %pM\n",
+			sta_id, addr);
 	priv->num_stations++;
 
 	/* Set up the REPLY_ADD_STA command to send to device */
@@ -301,14 +300,11 @@
 static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
 {
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
-
 	u8 sta_id = iwl_find_station(priv, addr);
 
 	BUG_ON(sta_id == IWL_INVALID_STATION);
 
-	IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
-			print_mac(mac, addr));
+	IWL_DEBUG_ASSOC("Removed STA from Ucode: %pM\n", addr);
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
@@ -326,7 +322,9 @@
 				   struct iwl_cmd *cmd, struct sk_buff *skb)
 {
 	struct iwl_rx_packet *res = NULL;
-	const char *addr = cmd->cmd.rm_sta.addr;
+	struct iwl_rem_sta_cmd *rm_sta =
+		 (struct iwl_rem_sta_cmd *)cmd->cmd.payload;
+	const char *addr = rm_sta->addr;
 
 	if (!skb) {
 		IWL_ERROR("Error: Response NULL in REPLY_REMOVE_STA.\n");
@@ -415,7 +413,6 @@
 	int sta_id = IWL_INVALID_STATION;
 	int i, ret = -EINVAL;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
@@ -435,18 +432,18 @@
 	if (unlikely(sta_id == IWL_INVALID_STATION))
 		goto out;
 
-	IWL_DEBUG_ASSOC("Removing STA from driver:%d  %s\n",
-		sta_id, print_mac(mac, addr));
+	IWL_DEBUG_ASSOC("Removing STA from driver:%d  %pM\n",
+		sta_id, addr);
 
 	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-		IWL_ERROR("Removing %s but non DRIVER active\n",
-				print_mac(mac, addr));
+		IWL_ERROR("Removing %pM but non DRIVER active\n",
+				addr);
 		goto out;
 	}
 
 	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
-		IWL_ERROR("Removing %s but non UCODE active\n",
-				print_mac(mac, addr));
+		IWL_ERROR("Removing %pM but non UCODE active\n",
+				addr);
 		goto out;
 	}
 
@@ -696,7 +693,7 @@
 	/* else, we are overriding an existing key => no need to allocated room
 	 * in uCode. */
 
-	/* This copy is acutally not needed: we get the key with each TX */
+	/* This copy is actually not needed: we get the key with each TX */
 	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
 
 	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
@@ -791,7 +788,7 @@
 {
 	int i;
 	IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
-	IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
+	IWL_DEBUG_RATE("lq ant 0x%X 0x%X\n",
 		       lq->general_params.single_stream_ant_msk,
 		       lq->general_params.dual_stream_ant_msk);
 
@@ -852,7 +849,7 @@
 	struct iwl_link_quality_cmd link_cmd = {
 		.reserved1 = 0,
 	};
-	u16 rate_flags;
+	u32 rate_flags;
 
 	/* Set up the rate scaling to start at selected rate, fall back
 	 * all the way down to 1M in IEEE order, and then spin on 1M */
@@ -868,15 +865,16 @@
 		if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
 			rate_flags |= RATE_MCS_CCK_MSK;
 
-		/* Use Tx antenna B only */
-		rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
+		rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
+				RATE_MCS_ANT_POS;
 
 		link_cmd.rs_table[i].rate_n_flags =
 			iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
-		r = iwl4965_get_prev_ieee_rate(r);
+		r = iwl_get_prev_ieee_rate(r);
 	}
 
-	link_cmd.general_params.single_stream_ant_msk = 2;
+	link_cmd.general_params.single_stream_ant_msk =
+				first_antenna(priv->hw_params.valid_tx_ant);
 	link_cmd.general_params.dual_stream_ant_msk = 3;
 	link_cmd.agg_params.agg_dis_start_th = 3;
 	link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
@@ -892,24 +890,35 @@
  * iwl_rxon_add_station - add station into station table.
  *
  * there is only one AP station with id= IWL_AP_ID
- * NOTE: mutex must be held before calling this fnction
+ * NOTE: mutex must be held before calling this function
  */
 int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
 {
+	struct ieee80211_sta *sta;
+	struct ieee80211_sta_ht_cap ht_config;
+	struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
 	u8 sta_id;
 
 	/* Add station to device's station table */
-	struct ieee80211_conf *conf = &priv->hw->conf;
-	struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
 
-	if ((is_ap) &&
-	    (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
-	    (priv->iw_mode == NL80211_IFTYPE_STATION))
-		sta_id = iwl_add_station_flags(priv, addr, is_ap,
-						   0, cur_ht_config);
-	else
-		sta_id = iwl_add_station_flags(priv, addr, is_ap,
-						   0, NULL);
+	/*
+	 * XXX: This check is definitely not correct, if we're an AP
+	 *	it'll always be false which is not what we want, but
+	 *	it doesn't look like iwlagn is prepared to be an HT
+	 *	AP anyway.
+	 */
+	if (priv->current_ht_config.is_ht) {
+		rcu_read_lock();
+		sta = ieee80211_find_sta(priv->hw, addr);
+		if (sta) {
+			memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
+			cur_ht_config = &ht_config;
+		}
+		rcu_read_unlock();
+	}
+
+	sta_id = iwl_add_station_flags(priv, addr, is_ap,
+				       0, cur_ht_config);
 
 	/* Set up default rate scaling table in device's station table */
 	iwl_sta_init_lq(priv, addr, is_ap);
@@ -927,7 +936,6 @@
 {
 	int sta_id;
 	u16 fc = le16_to_cpu(hdr->frame_control);
-	DECLARE_MAC_BUF(mac);
 
 	/* If this frame is broadcast or management, use broadcast station id */
 	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
@@ -962,9 +970,9 @@
 		if (sta_id != IWL_INVALID_STATION)
 			return sta_id;
 
-		IWL_DEBUG_DROP("Station %s not in station map. "
+		IWL_DEBUG_DROP("Station %pM not in station map. "
 			       "Defaulting to broadcast...\n",
-			       print_mac(mac, hdr->addr1));
+			       hdr->addr1);
 		iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
 		return priv->hw_params.bcast_sta_id;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 907a53e..7d8b4e2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -56,96 +56,112 @@
 	IWL_TX_FIFO_AC3
 };
 
+static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	dma_addr_t addr = get_unaligned_le32(&tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		addr |=
+		((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+	return addr;
+}
+
+static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+				  dma_addr_t addr, u16 len)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+	u16 hi_n_len = len << 4;
+
+	put_unaligned_le32(addr, &tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+	tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+	tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+	return tfd->num_tbs & 0x1f;
+}
 
 /**
  * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
  *
  * Does NOT advance any TFD circular buffer read/write indexes
  * Does NOT free the TFD itself (which is within circular buffer)
  */
-static int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 {
-	struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
-	struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+	struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0];
+	struct iwl_tfd *tfd;
 	struct pci_dev *dev = priv->pci_dev;
+	int index = txq->q.read_ptr;
 	int i;
-	int counter = 0;
-	int index, is_odd;
+	int num_tbs;
 
-	/* Host command buffers stay mapped in memory, nothing to clean */
-	if (txq->q.id == IWL_CMD_QUEUE_NUM)
-		return 0;
+	tfd = &tfd_tmp[index];
 
 	/* Sanity check on number of chunks */
-	counter = IWL_GET_BITS(*bd, num_tbs);
-	if (counter > MAX_NUM_OF_TBS) {
-		IWL_ERROR("Too many chunks: %i\n", counter);
+	num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERROR("Too many chunks: %i\n", num_tbs);
 		/* @todo issue fatal error, it is quite serious situation */
-		return 0;
+		return;
 	}
 
-	/* Unmap chunks, if any.
-	 * TFD info for odd chunks is different format than for even chunks. */
-	for (i = 0; i < counter; i++) {
-		index = i / 2;
-		is_odd = i & 0x1;
-
-		if (is_odd)
-			pci_unmap_single(
-				dev,
-				IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
-				(IWL_GET_BITS(bd->pa[index],
-					      tb2_addr_hi20) << 16),
-				IWL_GET_BITS(bd->pa[index], tb2_len),
+	/* Unmap tx_cmd */
+	if (num_tbs)
+		pci_unmap_single(dev,
+				pci_unmap_addr(&txq->cmd[index]->meta, mapping),
+				pci_unmap_len(&txq->cmd[index]->meta, len),
 				PCI_DMA_TODEVICE);
 
-		else if (i > 0)
-			pci_unmap_single(dev,
-					 le32_to_cpu(bd->pa[index].tb1_addr),
-					 IWL_GET_BITS(bd->pa[index], tb1_len),
-					 PCI_DMA_TODEVICE);
+	/* Unmap chunks, if any. */
+	for (i = 1; i < num_tbs; i++) {
+		pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
+				iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
 
-		/* Free SKB, if any, for this chunk */
-		if (txq->txb[txq->q.read_ptr].skb[i]) {
-			struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
-
-			dev_kfree_skb(skb);
-			txq->txb[txq->q.read_ptr].skb[i] = NULL;
+		if (txq->txb) {
+			dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]);
+			txq->txb[txq->q.read_ptr].skb[i - 1] = NULL;
 		}
 	}
-	return 0;
 }
 
-static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
-				 dma_addr_t addr, u16 len)
+static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+					struct iwl_tfd *tfd,
+					dma_addr_t addr, u16 len)
 {
-	int index, is_odd;
-	struct iwl_tfd_frame *tfd = ptr;
-	u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
+
+	u32 num_tbs = iwl_tfd_get_num_tbs(tfd);
 
 	/* Each TFD can point to a maximum 20 Tx buffers */
-	if (num_tbs >= MAX_NUM_OF_TBS) {
+	if (num_tbs >= IWL_NUM_OF_TBS) {
 		IWL_ERROR("Error can not send more than %d chunks\n",
-			  MAX_NUM_OF_TBS);
+			  IWL_NUM_OF_TBS);
 		return -EINVAL;
 	}
 
-	index = num_tbs / 2;
-	is_odd = num_tbs & 0x1;
+	BUG_ON(addr & ~DMA_BIT_MASK(36));
+	if (unlikely(addr & ~IWL_TX_DMA_MASK))
+		IWL_ERROR("Unaligned address = %llx\n",
+			  (unsigned long long)addr);
 
-	if (!is_odd) {
-		tfd->pa[index].tb1_addr = cpu_to_le32(addr);
-		IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
-			     iwl_get_dma_hi_address(addr));
-		IWL_SET_BITS(tfd->pa[index], tb1_len, len);
-	} else {
-		IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
-			     (u32) (addr & 0xffff));
-		IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
-		IWL_SET_BITS(tfd->pa[index], tb2_len, len);
-	}
-
-	IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
+	iwl_tfd_set_tb(tfd, num_tbs, addr, len);
 
 	return 0;
 }
@@ -210,7 +226,7 @@
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
 	struct iwl_queue *q = &txq->q;
 	struct pci_dev *dev = priv->pci_dev;
-	int i, slots_num, len;
+	int i, len;
 
 	if (q->n_bd == 0)
 		return;
@@ -221,21 +237,15 @@
 		iwl_hw_txq_free_tfd(priv, txq);
 
 	len = sizeof(struct iwl_cmd) * q->n_window;
-	if (q->id == IWL_CMD_QUEUE_NUM)
-		len += IWL_MAX_SCAN_SIZE;
 
 	/* De-alloc array of command/tx buffers */
-	slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
-			TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-	for (i = 0; i < slots_num; i++)
+	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
 		kfree(txq->cmd[i]);
-	if (txq_id == IWL_CMD_QUEUE_NUM)
-		kfree(txq->cmd[slots_num]);
 
 	/* De-alloc circular buffer of TFDs */
 	if (txq->q.n_bd)
-		pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
-				    txq->q.n_bd, txq->bd, txq->q.dma_addr);
+		pci_free_consistent(dev, sizeof(struct iwl_tfd) *
+				    txq->q.n_bd, txq->tfds, txq->q.dma_addr);
 
 	/* De-alloc array of per-TFD driver data */
 	kfree(txq->txb);
@@ -245,6 +255,40 @@
 	memset(txq, 0, sizeof(*txq));
 }
 
+
+/**
+ * iwl_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_cmd_queue_free(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+	struct iwl_queue *q = &txq->q;
+	struct pci_dev *dev = priv->pci_dev;
+	int i, len;
+
+	if (q->n_bd == 0)
+		return;
+
+	len = sizeof(struct iwl_cmd) * q->n_window;
+	len += IWL_MAX_SCAN_SIZE;
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i <= TFD_CMD_SLOTS; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd)
+		pci_free_consistent(dev, sizeof(struct iwl_tfd) *
+				    txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
 /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
  * DMA services
  *
@@ -340,13 +384,13 @@
 
 	/* Circular buffer of transmit frame descriptors (TFDs),
 	 * shared with device */
-	txq->bd = pci_alloc_consistent(dev,
-			sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
+	txq->tfds = pci_alloc_consistent(dev,
+			sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX,
 			&txq->q.dma_addr);
 
-	if (!txq->bd) {
+	if (!txq->tfds) {
 		IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
-			  sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
+			  sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX);
 		goto error;
 	}
 	txq->q.id = id;
@@ -370,15 +414,15 @@
 static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
 				struct iwl_tx_queue *txq)
 {
-	int rc;
+	int ret;
 	unsigned long flags;
 	int txq_id = txq->q.id;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
+	ret = iwl_grab_nic_access(priv);
+	if (ret) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
+		return ret;
 	}
 
 	/* Circular buffer (TFD queue in DRAM) physical base address */
@@ -386,10 +430,10 @@
 			     txq->q.dma_addr >> 8);
 
 	/* Enable DMA channel, using same id as for TFD queue */
-	iwl_write_direct32(
-		priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
-		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
+	iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+			FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+			FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
 	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -468,7 +512,10 @@
 
 	/* Tx queues */
 	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-		iwl_tx_queue_free(priv, txq_id);
+		if (txq_id == IWL_CMD_QUEUE_NUM)
+			iwl_cmd_queue_free(priv);
+		else
+			iwl_tx_queue_free(priv, txq_id);
 
 	/* Keep-warm buffer */
 	iwl_kw_free(priv);
@@ -477,7 +524,7 @@
 
 /**
  * iwl_txq_ctx_reset - Reset TX queue context
- * Destroys all DMA structures and initialise them again
+ * Destroys all DMA structures and initialize them again
  *
  * @param priv
  * @return error code
@@ -647,11 +694,11 @@
 			      __le16 fc, int sta_id,
 			      int is_hcca)
 {
+	u32 rate_flags = 0;
+	int rate_idx;
 	u8 rts_retry_limit = 0;
 	u8 data_retry_limit = 0;
 	u8 rate_plcp;
-	u16 rate_flags = 0;
-	int rate_idx;
 
 	rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
 			IWL_RATE_COUNT - 1);
@@ -694,14 +741,8 @@
 			break;
 		}
 
-		/* Alternate between antenna A and B for successive frames */
-		if (priv->use_ant_b_for_management_frame) {
-			priv->use_ant_b_for_management_frame = 0;
-			rate_flags |= RATE_MCS_ANT_B_MSK;
-		} else {
-			priv->use_ant_b_for_management_frame = 1;
-			rate_flags |= RATE_MCS_ANT_A_MSK;
-		}
+		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
+		rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
 	}
 
 	tx_cmd->rts_retry_limit = rts_retry_limit;
@@ -723,7 +764,7 @@
 		memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
 		if (info->flags & IEEE80211_TX_CTL_AMPDU)
 			tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
-		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+		IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
 		break;
 
 	case ALG_TKIP:
@@ -767,7 +808,7 @@
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct iwl_tfd_frame *tfd;
+	struct iwl_tfd *tfd;
 	struct iwl_tx_queue *txq;
 	struct iwl_queue *q;
 	struct iwl_cmd *out_cmd;
@@ -776,7 +817,7 @@
 	dma_addr_t phys_addr;
 	dma_addr_t txcmd_phys;
 	dma_addr_t scratch_phys;
-	u16 len, idx, len_org;
+	u16 len, len_org;
 	u16 seq_number = 0;
 	__le16 fc;
 	u8 hdr_len, unicast;
@@ -830,10 +871,8 @@
 	/* Find (or create) index into station table for destination station */
 	sta_id = iwl_get_sta_id(priv, hdr);
 	if (sta_id == IWL_INVALID_STATION) {
-		DECLARE_MAC_BUF(mac);
-
-		IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
-			       print_mac(mac, hdr->addr1));
+		IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+			       hdr->addr1);
 		goto drop;
 	}
 
@@ -856,23 +895,22 @@
 		priv->stations[sta_id].tid[tid].tfds_in_queue++;
 	}
 
-	/* Descriptor for chosen Tx queue */
 	txq = &priv->txq[txq_id];
 	q = &txq->q;
+	txq->swq_id = swq_id;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
 	/* Set up first empty TFD within this queue's circular TFD buffer */
-	tfd = &txq->bd[q->write_ptr];
+	tfd = &txq->tfds[q->write_ptr];
 	memset(tfd, 0, sizeof(*tfd));
-	idx = get_cmd_index(q, q->write_ptr, 0);
 
 	/* Set up driver data for this TFD */
 	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
 	txq->txb[q->write_ptr].skb[0] = skb;
 
 	/* Set up first empty entry in queue's array of Tx/cmd buffers */
-	out_cmd = txq->cmd[idx];
+	out_cmd = txq->cmd[q->write_ptr];
 	tx_cmd = &out_cmd->cmd.tx;
 	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
 	memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
@@ -912,12 +950,14 @@
 
 	/* Physical address of this Tx command's header (not MAC header!),
 	 * within command buffer array. */
-	txcmd_phys = pci_map_single(priv->pci_dev, out_cmd,
-				sizeof(struct iwl_cmd), PCI_DMA_TODEVICE);
-	txcmd_phys += offsetof(struct iwl_cmd, hdr);
-
+	txcmd_phys = pci_map_single(priv->pci_dev,
+				    out_cmd, sizeof(struct iwl_cmd),
+				    PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
+	pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
 	/* Add buffer containing Tx command and MAC(!) header to TFD's
 	 * first entry */
+	txcmd_phys += offsetof(struct iwl_cmd, hdr);
 	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 
 	if (info->control.hw_key)
@@ -950,7 +990,7 @@
 	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
 		offsetof(struct iwl_tx_cmd, scratch);
 	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
 	if (!ieee80211_has_morefrags(hdr->frame_control)) {
 		txq->need_update = 1;
@@ -983,7 +1023,7 @@
 			iwl_txq_update_write_ptr(priv, txq);
 			spin_unlock_irqrestore(&priv->lock, flags);
 		} else {
-			ieee80211_stop_queue(priv->hw, swq_id);
+			ieee80211_stop_queue(priv->hw, txq->swq_id);
 		}
 	}
 
@@ -1011,7 +1051,7 @@
 {
 	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
 	struct iwl_queue *q = &txq->q;
-	struct iwl_tfd_frame *tfd;
+	struct iwl_tfd *tfd;
 	struct iwl_cmd *out_cmd;
 	dma_addr_t phys_addr;
 	unsigned long flags;
@@ -1040,7 +1080,7 @@
 
 	spin_lock_irqsave(&priv->hcmd_lock, flags);
 
-	tfd = &txq->bd[q->write_ptr];
+	tfd = &txq->tfds[q->write_ptr];
 	memset(tfd, 0, sizeof(*tfd));
 
 
@@ -1061,9 +1101,13 @@
 		out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
 	len = (idx == TFD_CMD_SLOTS) ?
 			IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
-	phys_addr = pci_map_single(priv->pci_dev, out_cmd, len,
-						PCI_DMA_TODEVICE);
+
+	phys_addr = pci_map_single(priv->pci_dev, out_cmd,
+				   len, PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
+	pci_unmap_len_set(&out_cmd->meta, len, len);
 	phys_addr += offsetof(struct iwl_cmd, hdr);
+
 	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -1113,8 +1157,9 @@
 		return 0;
 	}
 
-	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+	for (index = iwl_queue_inc_wrap(index, q->n_bd);
+	     q->read_ptr != index;
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
 		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
@@ -1138,44 +1183,34 @@
  * need to be reclaimed. As result, some free space forms.  If there is
  * enough free space (> low mark), wake the stack that feeds us.
  */
-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
+				   int idx, int cmd_idx)
 {
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
 	struct iwl_queue *q = &txq->q;
-	struct iwl_tfd_frame *bd = &txq->bd[index];
-	dma_addr_t dma_addr;
-	int is_odd, buf_len;
 	int nfreed = 0;
 
-	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
+	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
 		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
 			  "is out of range [0-%d] %d %d.\n", txq_id,
-			  index, q->n_bd, q->write_ptr, q->read_ptr);
+			  idx, q->n_bd, q->write_ptr, q->read_ptr);
 		return;
 	}
 
-	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+	pci_unmap_single(priv->pci_dev,
+		pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
+		pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
+		PCI_DMA_TODEVICE);
 
-		if (nfreed > 1) {
-			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
+	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		if (nfreed++ > 0) {
+			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", idx,
 					q->write_ptr, q->read_ptr);
 			queue_work(priv->workqueue, &priv->restart);
 		}
-		is_odd = (index/2) & 0x1;
-		if (is_odd) {
-			dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
-					(IWL_GET_BITS(bd->pa[index],
-							tb2_addr_hi20) << 16);
-			buf_len = IWL_GET_BITS(bd->pa[index], tb2_len);
-		} else {
-			dma_addr = le32_to_cpu(bd->pa[index].tb1_addr);
-			buf_len = IWL_GET_BITS(bd->pa[index], tb1_len);
-		}
 
-		pci_unmap_single(priv->pci_dev, dma_addr, buf_len,
-				 PCI_DMA_TODEVICE);
-		nfreed++;
 	}
 }
 
@@ -1215,7 +1250,7 @@
 		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
 		rxb->skb = NULL;
 
-	iwl_hcmd_queue_reclaim(priv, txq_id, index);
+	iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
 
 	if (!(cmd->meta.flags & CMD_ASYNC)) {
 		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
@@ -1248,15 +1283,14 @@
 	int ret;
 	unsigned long flags;
 	struct iwl_tid_data *tid_data;
-	DECLARE_MAC_BUF(mac);
 
 	if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
 		tx_fifo = default_tid_to_tx_fifo[tid];
 	else
 		return -EINVAL;
 
-	IWL_WARNING("%s on ra = %s tid = %d\n",
-			__func__, print_mac(mac, ra), tid);
+	IWL_WARNING("%s on ra = %pM tid = %d\n",
+			__func__, ra, tid);
 
 	sta_id = iwl_find_station(priv, ra);
 	if (sta_id == IWL_INVALID_STATION)
@@ -1301,7 +1335,6 @@
 	struct iwl_tid_data *tid_data;
 	int ret, write_ptr, read_ptr;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	if (!ra) {
 		IWL_ERROR("ra = NULL\n");
@@ -1362,8 +1395,8 @@
 	case IWL_EMPTYING_HW_QUEUE_DELBA:
 		/* We are reclaiming the last packet of the */
 		/* aggregated HW queue */
-		if (txq_id  == tid_data->agg.txq_id &&
-		    q->read_ptr == q->write_ptr) {
+		if ((txq_id  == tid_data->agg.txq_id) &&
+		    (q->read_ptr == q->write_ptr)) {
 			u16 ssn = SEQ_TO_SN(tid_data->seq_number);
 			int tx_fifo = default_tid_to_tx_fifo[tid];
 			IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n");
@@ -1414,7 +1447,7 @@
 	IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
 
 	/* Calculate shift to align block-ack bits with our Tx window bits */
-	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
+	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
 	if (sh < 0) /* tbw something is wrong with indices */
 		sh += 0x100;
 
@@ -1464,10 +1497,11 @@
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 	struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
-	int index;
 	struct iwl_tx_queue *txq = NULL;
 	struct iwl_ht_agg *agg;
-	DECLARE_MAC_BUF(mac);
+	int index;
+	int sta_id;
+	int tid;
 
 	/* "flow" corresponds to Tx queue */
 	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
@@ -1482,17 +1516,19 @@
 	}
 
 	txq = &priv->txq[scd_flow];
-	agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
+	sta_id = ba_resp->sta_id;
+	tid = ba_resp->tid;
+	agg = &priv->stations[sta_id].tid[tid].agg;
 
 	/* Find index just before block-ack window */
 	index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
 
 	/* TODO: Need to get this copy more safely - now good for debug */
 
-	IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
+	IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d] Received from %pM, "
 			   "sta_id = %d\n",
 			   agg->wait_for_ba,
-			   print_mac(mac, (u8 *) &ba_resp->sta_addr_lo32),
+			   (u8 *) &ba_resp->sta_addr_lo32,
 			   ba_resp->sta_id);
 	IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
 			   "%d, scd_ssn = %d\n",
@@ -1513,18 +1549,15 @@
 	 * transmitted ... if not, it's too late anyway). */
 	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
 		/* calculate mac80211 ampdu sw queue to wake */
-		int ampdu_q =
-		   scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
 		int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
-		priv->stations[ba_resp->sta_id].
-			tid[ba_resp->tid].tfds_in_queue -= freed;
-		if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-			priv->mac80211_registered &&
-			agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
-			ieee80211_wake_queue(priv->hw, ampdu_q);
+		priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
 
-		iwl_txq_check_empty(priv, ba_resp->sta_id,
-				    ba_resp->tid, scd_flow);
+		if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+		    priv->mac80211_registered &&
+		    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+			ieee80211_wake_queue(priv->hw, txq->swq_id);
+
+		iwl_txq_check_empty(priv, sta_id, tid, scd_flow);
 	}
 }
 EXPORT_SYMBOL(iwl_rx_reply_compressed_ba);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 285b53e..119185f 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -41,6 +41,7 @@
 #include <linux/if_arp.h>
 
 #include <net/ieee80211_radiotap.h>
+#include <net/lib80211.h>
 #include <net/mac80211.h>
 
 #include <asm/div64.h>
@@ -107,46 +108,6 @@
 	return priv->hw->wiphy->bands[band];
 }
 
-static int iwl3945_is_empty_essid(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
-static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
-{
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (iwl3945_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else
-			*d++ = *s++;
-	}
-	*d = '\0';
-	return escaped;
-}
-
 /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
  * DMA services
  *
@@ -446,7 +407,6 @@
 	int index = IWL_INVALID_STATION;
 	struct iwl3945_station_entry *station;
 	unsigned long flags_spin;
-	DECLARE_MAC_BUF(mac);
 	u8 rate;
 
 	spin_lock_irqsave(&priv->sta_lock, flags_spin);
@@ -480,7 +440,7 @@
 		return index;
 	}
 
-	IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
+	IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr);
 	station = &priv->stations[index];
 	station->used = 1;
 	priv->num_stations++;
@@ -1063,7 +1023,6 @@
 	/* cast away the const for active_rxon in this function */
 	struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
 	int rc = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (!iwl3945_is_alive(priv))
 		return -1;
@@ -1124,11 +1083,11 @@
 	IWL_DEBUG_INFO("Sending RXON\n"
 		       "* with%s RXON_FILTER_ASSOC_MSK\n"
 		       "* channel = %d\n"
-		       "* bssid = %s\n",
+		       "* bssid = %pM\n",
 		       ((priv->staging_rxon.filter_flags &
 			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
 		       le16_to_cpu(priv->staging_rxon.channel),
-		       print_mac(mac, priv->staging_rxon.bssid_addr));
+		       priv->staging_rxon.bssid_addr);
 
 	/* Apply the new configuration */
 	rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
@@ -1634,7 +1593,7 @@
  */
 static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
 			      struct ieee80211_mgmt *frame,
-			      int left, int is_direct)
+			      int left)
 {
 	int len = 0;
 	u8 *pos = NULL;
@@ -1664,20 +1623,6 @@
 	*pos++ = WLAN_EID_SSID;
 	*pos++ = 0;
 
-	/* fill in our direct SSID IE... */
-	if (is_direct) {
-		/* ...next IE... */
-		left -= 2 + priv->essid_len;
-		if (left < 0)
-			return 0;
-		/* ... fill it in... */
-		*pos++ = WLAN_EID_SSID;
-		*pos++ = priv->essid_len;
-		memcpy(pos, priv->essid, priv->essid_len);
-		pos += priv->essid_len;
-		len += 2 + priv->essid_len;
-	}
-
 	/* fill in supported rate */
 	/* ...next IE... */
 	left -= 2;
@@ -1846,7 +1791,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (force || iwl3945_is_associated(priv)) {
-		IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
+		IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n",
 			      priv->qos_data.qos_active);
 
 		iwl3945_send_qos_params_command(priv,
@@ -1870,7 +1815,7 @@
 
 
 /* default power management (not Tx power) table values */
-/* for tim  0-10 */
+/* for TIM  0-10 */
 static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
 	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -1880,7 +1825,7 @@
 	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
 };
 
-/* for tim > 10 */
+/* for TIM > 10 */
 static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = {
 	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
@@ -2230,13 +2175,14 @@
 /*
  * initialize rxon structure with default values from eeprom
  */
-static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
+					      int mode)
 {
 	const struct iwl3945_channel_info *ch_info;
 
 	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
 
-	switch (priv->iw_mode) {
+	switch (mode) {
 	case NL80211_IFTYPE_AP:
 		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
 		break;
@@ -2259,7 +2205,7 @@
 		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
 		break;
 	default:
-		IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+		IWL_ERROR("Unsupported interface type %d\n", mode);
 		break;
 	}
 
@@ -2282,8 +2228,7 @@
 	 * in some case A channels are all non IBSS
 	 * in this case force B/G channel
 	 */
-	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
-	    !(is_channel_ibss(ch_info)))
+	if ((mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info)))
 		ch_info = &priv->channel_info[0];
 
 	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
@@ -2316,14 +2261,12 @@
 		}
 	}
 
-	priv->iw_mode = mode;
-
-	iwl3945_connection_init_rx_config(priv);
+	iwl3945_connection_init_rx_config(priv, mode);
 	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 
 	iwl3945_clear_stations_table(priv);
 
-	/* dont commit rxon if rf-kill is on*/
+	/* don't commit rxon if rf-kill is on*/
 	if (!iwl3945_is_ready_rf(priv))
 		return -EAGAIN;
 
@@ -2352,7 +2295,7 @@
 	case ALG_CCMP:
 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
 		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
-		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+		IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
 		break;
 
 	case ALG_TKIP:
@@ -2397,6 +2340,7 @@
 {
 	__le16 fc = hdr->frame_control;
 	__le32 tx_flags = cmd->cmd.tx.tx_flags;
+	u8 rc_flags = info->control.rates[0].flags;
 
 	cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
@@ -2423,10 +2367,10 @@
 		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		tx_flags |= TX_CMD_FLG_RTS_MSK;
 		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-	} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+	} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
 		tx_flags |= TX_CMD_FLG_CTS_MSK;
 	}
@@ -2482,8 +2426,6 @@
 	/* If this frame is going out to an IBSS network, find the station,
 	 * or create a new station table entry */
 	case NL80211_IFTYPE_ADHOC: {
-		DECLARE_MAC_BUF(mac);
-
 		/* Create new station table entry */
 		sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
 		if (sta_id != IWL_INVALID_STATION)
@@ -2494,9 +2436,9 @@
 		if (sta_id != IWL_INVALID_STATION)
 			return sta_id;
 
-		IWL_DEBUG_DROP("Station %s not in station map. "
+		IWL_DEBUG_DROP("Station %pM not in station map. "
 			       "Defaulting to broadcast...\n",
-			       print_mac(mac, hdr->addr1));
+			       hdr->addr1);
 		iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
 		return priv->hw_setting.bcast_sta_id;
 	}
@@ -2579,10 +2521,8 @@
 	/* Find (or create) index into station table for destination station */
 	sta_id = iwl3945_get_sta_id(priv, hdr);
 	if (sta_id == IWL_INVALID_STATION) {
-		DECLARE_MAC_BUF(mac);
-
-		IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
-			       print_mac(mac, hdr->addr1));
+		IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+			       hdr->addr1);
 		goto drop;
 	}
 
@@ -4019,8 +3959,6 @@
 #ifdef CONFIG_IWL3945_DEBUG
 static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
 {
-	DECLARE_MAC_BUF(mac);
-
 	IWL_DEBUG_RADIO("RX CONFIG:\n");
 	iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
 	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
@@ -4031,10 +3969,8 @@
 	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
 			rxon->ofdm_basic_rates);
 	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
-	IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
-			print_mac(mac, rxon->node_addr));
-	IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
-			print_mac(mac, rxon->bssid_addr));
+	IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+	IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
 #endif
@@ -4050,7 +3986,7 @@
 /* call this function to flush any scheduled tasklet */
 static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
 {
-	/* wait to make sure we flush pedding tasklet*/
+	/* wait to make sure we flush pending tasklet*/
 	synchronize_irq(priv->pci_dev->irq);
 	tasklet_kill(&priv->irq_tasklet);
 }
@@ -5607,7 +5543,7 @@
 	iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
 				 priv->ucode_data.len);
 
-	/* Inst bytecount must be last to set up, bit 31 signals uCode
+	/* Inst byte count must be last to set up, bit 31 signals uCode
 	 *   that all new ptr/size info is in place */
 	iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
 				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -5699,7 +5635,7 @@
 
 	rc = iwl3945_grab_nic_access(priv);
 	if (rc) {
-		IWL_WARNING("Can not read rfkill status from adapter\n");
+		IWL_WARNING("Can not read RFKILL status from adapter\n");
 		return;
 	}
 
@@ -5709,7 +5645,7 @@
 
 	if (rfkill & 0x1) {
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-		/* if rfkill is not on, then wait for thermal
+		/* if RFKILL is not on, then wait for thermal
 		 * sensor in adapter to kick in */
 		while (iwl3945_hw_get_temperature(priv) == 0) {
 			thermal_spin++;
@@ -5747,7 +5683,7 @@
 		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	} else {
 		/* Initialize our rx_config data */
-		iwl3945_connection_init_rx_config(priv);
+		iwl3945_connection_init_rx_config(priv, priv->iw_mode);
 		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 	}
 
@@ -5902,7 +5838,7 @@
 	}
 
 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-		IWL_ERROR("ucode not available for device bringup\n");
+		IWL_ERROR("ucode not available for device bring up\n");
 		return -EIO;
 	}
 
@@ -6063,6 +5999,7 @@
 			IWL_ERROR("iwl3945_set_mode() failed\n");
 
 	mutex_unlock(&priv->mutex);
+	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
 }
 
 #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
@@ -6102,6 +6039,7 @@
 	struct ieee80211_conf *conf = NULL;
 	u8 n_probes = 2;
 	enum ieee80211_band band;
+	DECLARE_SSID_BUF(ssid);
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -6112,7 +6050,7 @@
 		goto done;
 	}
 
-	/* Make sure the scan wasn't cancelled before this queued work
+	/* Make sure the scan wasn't canceled before this queued work
 	 * was given the chance to run... */
 	if (!test_bit(STATUS_SCANNING, &priv->status))
 		goto done;
@@ -6202,21 +6140,13 @@
 	if (priv->one_direct_scan) {
 		IWL_DEBUG_SCAN
 		    ("Kicking off one direct scan for '%s'\n",
-		     iwl3945_escape_essid(priv->direct_ssid,
-				      priv->direct_ssid_len));
+		     print_ssid(ssid, priv->direct_ssid,
+				priv->direct_ssid_len));
 		scan->direct_scan[0].id = WLAN_EID_SSID;
 		scan->direct_scan[0].len = priv->direct_ssid_len;
 		memcpy(scan->direct_scan[0].ssid,
 		       priv->direct_ssid, priv->direct_ssid_len);
 		n_probes++;
-	} else if (!iwl3945_is_associated(priv) && priv->essid_len) {
-		IWL_DEBUG_SCAN
-		  ("Kicking off one direct scan for '%s' when not associated\n",
-		   iwl3945_escape_essid(priv->essid, priv->essid_len));
-		scan->direct_scan[0].id = WLAN_EID_SSID;
-		scan->direct_scan[0].len = priv->essid_len;
-		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
-		n_probes++;
 	} else
 		IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
 
@@ -6224,7 +6154,7 @@
 	 * that based on the direct_mask added to each channel entry */
 	scan->tx_cmd.len = cpu_to_le16(
 		iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+			IWL_MAX_SCAN_SIZE - sizeof(*scan)));
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
 	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -6334,7 +6264,6 @@
 {
 	int rc = 0;
 	struct ieee80211_conf *conf = NULL;
-	DECLARE_MAC_BUF(mac);
 
 	if (priv->iw_mode == NL80211_IFTYPE_AP) {
 		IWL_ERROR("%s Should not be called in AP mode\n", __func__);
@@ -6342,9 +6271,8 @@
 	}
 
 
-	IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
-			priv->assoc_id,
-			print_mac(mac, priv->active_rxon.bssid_addr));
+	IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+			priv->assoc_id, priv->active_rxon.bssid_addr);
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
@@ -6440,7 +6368,7 @@
 	mutex_unlock(&priv->mutex);
 }
 
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
 
 static void iwl3945_bg_scan_completed(struct work_struct *work)
 {
@@ -6453,7 +6381,7 @@
 		return;
 
 	if (test_bit(STATUS_CONF_PENDING, &priv->status))
-		iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+		iwl3945_mac_config(priv->hw, 0);
 
 	ieee80211_scan_completed(priv->hw);
 
@@ -6605,7 +6533,6 @@
 {
 	struct iwl3945_priv *priv = hw->priv;
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
 
@@ -6616,13 +6543,14 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->vif = conf->vif;
+	priv->iw_mode = conf->type;
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	mutex_lock(&priv->mutex);
 
 	if (conf->mac_addr) {
-		IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr));
+		IWL_DEBUG_MAC80211("Set: %pM\n", conf->mac_addr);
 		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
 	}
 
@@ -6642,10 +6570,11 @@
  * be set inappropriately and the driver currently sets the hardware up to
  * use it whenever needed.
  */
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct iwl3945_priv *priv = hw->priv;
 	const struct iwl3945_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
 	unsigned long flags;
 	int ret = 0;
 
@@ -6791,8 +6720,6 @@
 				    struct ieee80211_if_conf *conf)
 {
 	struct iwl3945_priv *priv = hw->priv;
-	DECLARE_MAC_BUF(mac);
-	unsigned long flags;
 	int rc;
 
 	if (conf == NULL)
@@ -6814,23 +6741,13 @@
 			return rc;
 	}
 
-	/* XXX: this MUST use conf->mac_addr */
-
-	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
-	    (!conf->ssid_len)) {
-		IWL_DEBUG_MAC80211
-		    ("Leaving in AP mode because HostAPD is not ready.\n");
-		return 0;
-	}
-
 	if (!iwl3945_is_alive(priv))
 		return -EAGAIN;
 
 	mutex_lock(&priv->mutex);
 
 	if (conf->bssid)
-		IWL_DEBUG_MAC80211("bssid: %s\n",
-				   print_mac(mac, conf->bssid));
+		IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
 
 /*
  * very dubious code was here; the probe filtering flag is never set:
@@ -6843,8 +6760,8 @@
 		if (!conf->bssid) {
 			conf->bssid = priv->mac_addr;
 			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-			IWL_DEBUG_MAC80211("bssid was set to: %s\n",
-					   print_mac(mac, conf->bssid));
+			IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+					   conf->bssid);
 		}
 		if (priv->ibss_beacon)
 			dev_kfree_skb(priv->ibss_beacon);
@@ -6890,15 +6807,6 @@
 	}
 
  done:
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!conf->ssid_len)
-		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-	else
-		memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
-	priv->essid_len = conf->ssid_len;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	IWL_DEBUG_MAC80211("leave\n");
 	mutex_unlock(&priv->mutex);
 
@@ -6941,8 +6849,6 @@
 	if (priv->vif == conf->vif) {
 		priv->vif = NULL;
 		memset(priv->bssid, 0, ETH_ALEN);
-		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-		priv->essid_len = 0;
 	}
 	mutex_unlock(&priv->mutex);
 
@@ -7011,6 +6917,7 @@
 	int rc = 0;
 	unsigned long flags;
 	struct iwl3945_priv *priv = hw->priv;
+	DECLARE_SSID_BUF(ssid_buf);
 
 	IWL_DEBUG_MAC80211("enter\n");
 
@@ -7044,7 +6951,7 @@
 	}
 	if (len) {
 		IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
-			       iwl3945_escape_essid(ssid, len), (int)len);
+			       print_ssid(ssid_buf, ssid, len), (int)len);
 
 		priv->one_direct_scan = 1;
 		priv->direct_ssid_len = (u8)
@@ -7085,10 +6992,8 @@
 
 	sta_id = iwl3945_hw_find_station(priv, addr);
 	if (sta_id == IWL_INVALID_STATION) {
-		DECLARE_MAC_BUF(mac);
-
-		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
-				   print_mac(mac, addr));
+		IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+				   addr);
 		return -EINVAL;
 	}
 
@@ -7220,14 +7125,6 @@
 	return 0;
 }
 
-static u64 iwl3945_mac_get_tsf(struct ieee80211_hw *hw)
-{
-	IWL_DEBUG_MAC80211("enter\n");
-	IWL_DEBUG_MAC80211("leave\n");
-
-	return 0;
-}
-
 static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
 {
 	struct iwl3945_priv *priv = hw->priv;
@@ -7793,7 +7690,7 @@
 
 /*****************************************************************************
  *
- * driver setup and teardown
+ * driver setup and tear down
  *
  *****************************************************************************/
 
@@ -7870,7 +7767,6 @@
 	.get_stats = iwl3945_mac_get_stats,
 	.get_tx_stats = iwl3945_mac_get_tx_stats,
 	.conf_tx = iwl3945_mac_conf_tx,
-	.get_tsf = iwl3945_mac_get_tsf,
 	.reset_tsf = iwl3945_mac_reset_tsf,
 	.bss_info_changed = iwl3945_bss_info_changed,
 	.hw_scan = iwl3945_mac_hw_scan
@@ -7883,7 +7779,6 @@
 	struct ieee80211_hw *hw;
 	struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
 
 	/* Disabling hardware scan means that mac80211 will perform scans
 	 * "the hard way", rather than using device's scan. */
@@ -8058,7 +7953,7 @@
 	}
 	/* MAC Address location in EEPROM same for 3945/4965 */
 	get_eeprom_mac(priv, priv->mac_addr);
-	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+	IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
 	err = iwl3945_init_channel_map(priv);
@@ -8223,7 +8118,7 @@
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return 0;
 
-	IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+	IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
 	mutex_lock(&priv->mutex);
 
 	switch (state) {
@@ -8238,7 +8133,7 @@
 		iwl3945_radio_kill_sw(priv, 1);
 		break;
 	default:
-		IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+		IWL_WARNING("we received unexpected RFKILL state %d\n", state);
 		break;
 	}
 out_unlock:
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 92be604..a0e440c 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -1,6 +1,10 @@
 /* Copyright (C) 2006, Red Hat, Inc. */
 
+#include <linux/types.h>
 #include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
+#include <net/lib80211.h>
 
 #include "assoc.h"
 #include "decl.h"
@@ -151,18 +155,18 @@
 	struct cmd_ds_802_11_ad_hoc_join cmd;
 	struct bss_descriptor *bss = &assoc_req->bss;
 	u8 preamble = RADIO_PREAMBLE_LONG;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 	u16 ratesize = 0;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	lbs_deb_join("current SSID '%s', ssid length %u\n",
-		escape_essid(priv->curbssparams.ssid,
+		print_ssid(ssid, priv->curbssparams.ssid,
 		priv->curbssparams.ssid_len),
 		priv->curbssparams.ssid_len);
 	lbs_deb_join("requested ssid '%s', ssid length %u\n",
-		escape_essid(bss->ssid, bss->ssid_len),
+		print_ssid(ssid, bss->ssid, bss->ssid_len),
 		bss->ssid_len);
 
 	/* check if the requested SSID is already joined */
@@ -226,8 +230,8 @@
 	       bss->capability, CAPINFO_MASK);
 
 	/* information on BSSID descriptor passed to FW */
-	lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
-			print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
+	lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
+			cmd.bss.bssid, cmd.bss.ssid);
 
 	/* Only v8 and below support setting these */
 	if (priv->fwrelease < 0x09000000) {
@@ -307,6 +311,7 @@
 	size_t ratesize = 0;
 	u16 tmpcap = 0;
 	int ret = 0;
+	DECLARE_SSID_BUF(ssid);
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
@@ -326,7 +331,7 @@
 	memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
 
 	lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
-		escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+		print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
 		assoc_req->ssid_len);
 
 	cmd.bsstype = CMD_BSS_TYPE_IBSS;
@@ -338,12 +343,12 @@
 	WARN_ON(!assoc_req->channel);
 
 	/* set Physical parameter set */
-	cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
+	cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS;
 	cmd.phyparamset.dsparamset.len = 1;
 	cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
 
 	/* set IBSS parameter set */
-	cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
+	cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS;
 	cmd.ssparamset.ibssparamset.len = 2;
 	cmd.ssparamset.ibssparamset.atimwindow = 0;
 
@@ -427,8 +432,8 @@
 {
 	if (!secinfo->wep_enabled  && !secinfo->WPAenabled
 	    && !secinfo->WPA2enabled
-	    && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
-	    && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
+	    && match_bss->wpa_ie[0] != WLAN_EID_GENERIC
+	    && match_bss->rsn_ie[0] != WLAN_EID_RSN
 	    && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
 		return 1;
 	else
@@ -450,7 +455,7 @@
 				struct bss_descriptor *match_bss)
 {
 	if (!secinfo->wep_enabled && secinfo->WPAenabled
-	    && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
+	    && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
 	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
 	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
 	   )
@@ -463,7 +468,7 @@
 				 struct bss_descriptor *match_bss)
 {
 	if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
-	    (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
+	    (match_bss->rsn_ie[0] == WLAN_EID_RSN)
 	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
 	    (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
 	   )
@@ -477,8 +482,8 @@
 {
 	if (!secinfo->wep_enabled && !secinfo->WPAenabled
 	    && !secinfo->WPA2enabled
-	    && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
-	    && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
+	    && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC)
+	    && (match_bss->rsn_ie[0] != WLAN_EID_RSN)
 	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
 		return 1;
 	else
@@ -694,6 +699,7 @@
 	int ret = 0;
 	struct bss_descriptor * bss;
 	int channel = -1;
+	DECLARE_SSID_BUF(ssid);
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
@@ -705,7 +711,7 @@
 		channel = assoc_req->channel;
 
 	lbs_deb_assoc("SSID '%s' requested\n",
-	              escape_essid(assoc_req->ssid, assoc_req->ssid_len));
+	              print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
 	if (assoc_req->mode == IW_MODE_INFRA) {
 		lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
 			assoc_req->ssid_len);
@@ -752,17 +758,15 @@
 {
 	int ret = 0;
 	struct bss_descriptor * bss;
-	DECLARE_MAC_BUF(mac);
 
-	lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %s",
-		print_mac(mac, assoc_req->bssid));
+	lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
 
 	/* Search for index position in list for requested MAC */
 	bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
 			    assoc_req->mode);
 	if (bss == NULL) {
-		lbs_deb_assoc("ASSOC: WAP: BSSID %s not found, "
-			"cannot associate.\n", print_mac(mac, assoc_req->bssid));
+		lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
+			"cannot associate.\n", assoc_req->bssid);
 		goto out;
 	}
 
@@ -1208,7 +1212,7 @@
 	struct assoc_request * assoc_req = NULL;
 	int ret = 0;
 	int find_any_ssid = 0;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
@@ -1228,13 +1232,13 @@
 		"    chann:     %d\n"
 		"    band:      %d\n"
 		"    mode:      %d\n"
-		"    BSSID:     %s\n"
+		"    BSSID:     %pM\n"
 		"    secinfo:  %s%s%s\n"
 		"    auth_mode: %d\n",
 		assoc_req->flags,
-		escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+		print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
 		assoc_req->channel, assoc_req->band, assoc_req->mode,
-		print_mac(mac, assoc_req->bssid),
+		assoc_req->bssid,
 		assoc_req->secinfo.WPAenabled ? " WPA" : "",
 		assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
 		assoc_req->secinfo.wep_enabled ? " WEP" : "",
@@ -1357,8 +1361,8 @@
 		}
 
 		if (success) {
-			lbs_deb_assoc("associated to %s\n",
-				print_mac(mac, priv->curbssparams.bssid));
+			lbs_deb_assoc("associated to %pM\n",
+				priv->curbssparams.bssid);
 			lbs_prepare_and_send_command(priv,
 				CMD_802_11_RSSI,
 				0, CMD_OPTION_WAITFORRSP, 0, NULL);
@@ -1478,7 +1482,6 @@
 	struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
 	int ret = -1;
 	u8 *bssid = pdata_buf;
-	DECLARE_MAC_BUF(mac);
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
@@ -1505,8 +1508,8 @@
 
 	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
 
-	lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
-		print_mac(mac, bssid), pauthenticate->authtype);
+	lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
+		bssid, pauthenticate->authtype);
 	ret = 0;
 
 out:
@@ -1770,7 +1773,7 @@
 	struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
 	union iwreq_data wrqu;
 	struct bss_descriptor *bss;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
@@ -1819,9 +1822,9 @@
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
-	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
-		     escape_essid(bss->ssid, bss->ssid_len),
-		     print_mac(mac, priv->curbssparams.bssid),
+	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
+		     print_ssid(ssid, bss->ssid, bss->ssid_len),
+		     priv->curbssparams.bssid,
 		     priv->curbssparams.channel);
 
 done:
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 8265c7d..957fd5a 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -4,7 +4,7 @@
   */
 
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
+#include <net/lib80211.h>
 #include <linux/kfifo.h>
 #include "host.h"
 #include "hostcmd.h"
@@ -87,7 +87,6 @@
 	struct cmd_ds_get_hw_spec cmd;
 	int ret = -1;
 	u32 i;
-	DECLARE_MAC_BUF(mac);
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
@@ -110,8 +109,8 @@
 	 * CF card    firmware 5.0.16p0:   cap 0x00000303
 	 * USB dongle firmware 5.110.17p2: cap 0x00000303
 	 */
-	lbs_pr_info("%s, fw %u.%u.%up%u, cap 0x%08x\n",
-		print_mac(mac, cmd.permanentaddr),
+	lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n",
+		cmd.permanentaddr,
 		priv->fwrelease >> 24 & 0xff,
 		priv->fwrelease >> 16 & 0xff,
 		priv->fwrelease >>  8 & 0xff,
@@ -1063,6 +1062,7 @@
 {
 	struct cmd_ds_mesh_config cmd;
 	struct mrvl_meshie *ie;
+	DECLARE_SSID_BUF(ssid);
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.channel = cpu_to_le16(chan);
@@ -1070,7 +1070,7 @@
 
 	switch (action) {
 	case CMD_ACT_MESH_CONFIG_START:
-		ie->hdr.id = MFIE_TYPE_GENERIC;
+		ie->id = WLAN_EID_GENERIC;
 		ie->val.oui[0] = 0x00;
 		ie->val.oui[1] = 0x50;
 		ie->val.oui[2] = 0x43;
@@ -1082,7 +1082,7 @@
 		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
 		ie->val.mesh_id_len = priv->mesh_ssid_len;
 		memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
-		ie->hdr.len = sizeof(struct mrvl_meshie_val) -
+		ie->len = sizeof(struct mrvl_meshie_val) -
 			IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
 		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
 		break;
@@ -1093,7 +1093,7 @@
 	}
 	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
 		    action, priv->mesh_tlv, chan,
-		    escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
+		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
 
 	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
 }
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 0aa0ce3..ec4efd7 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -5,6 +5,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <net/iw_handler.h>
+#include <net/lib80211.h>
 
 #include "dev.h"
 #include "decl.h"
@@ -65,7 +66,7 @@
 	int numscansdone = 0, res;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 	struct bss_descriptor * iter_bss;
 
 	pos += snprintf(buf+pos, len-pos,
@@ -77,17 +78,17 @@
 		u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
 		u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
 
-		pos += snprintf(buf+pos, len-pos,
-			"%02u| %03d | %04d | %s |",
+		pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
 			numscansdone, iter_bss->channel, iter_bss->rssi,
-			print_mac(mac, iter_bss->bssid));
+			iter_bss->bssid);
 		pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
 		pos += snprintf(buf+pos, len-pos, "%c%c%c |",
 				ibss ? 'A' : 'I', privacy ? 'P' : ' ',
 				spectrum_mgmt ? 'S' : ' ');
 		pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
 		pos += snprintf(buf+pos, len-pos, " %s\n",
-		                escape_essid(iter_bss->ssid, iter_bss->ssid_len));
+		                print_ssid(ssid, iter_bss->ssid,
+					   iter_bss->ssid_len));
 
 		numscansdone++;
 	}
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 1a8888c..0b84bdc 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -74,8 +74,4 @@
 
 int lbs_update_channel(struct lbs_private *priv);
 
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len);
-#endif
-
 #endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 076a636..2d4666f 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -79,7 +79,7 @@
 #define lbs_deb_tx(fmt, args...)        LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args)
 #define lbs_deb_fw(fmt, args...)        LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args)
 #define lbs_deb_usb(fmt, args...)       LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args)
-#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args)
+#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
 #define lbs_deb_cs(fmt, args...)        LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
 #define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
 #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f6f3753..dd682c4 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -10,7 +10,6 @@
 #include <linux/wireless.h>
 #include <linux/ethtool.h>
 #include <linux/debugfs.h>
-#include <net/ieee80211.h>
 
 #include "defs.h"
 #include "hostcmd.h"
@@ -278,6 +277,12 @@
 	struct enc_key wpa_mcast_key;
 	struct enc_key wpa_unicast_key;
 
+/*
+ * In theory, the IE is limited to the IE length, 255,
+ * but in practice 64 bytes are enough.
+ */
+#define MAX_WPA_IE_LEN 64
+
 	/** WPA Information Elements*/
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	u8 wpa_ie_len;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 73dc8c7..241af7f 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -12,9 +12,8 @@
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
 #include <linux/stddef.h>
-
+#include <linux/ieee80211.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 
 #include "host.h"
 #include "decl.h"
@@ -223,7 +222,7 @@
 static ssize_t lbs_anycast_get(struct device *dev,
 		struct device_attribute *attr, char * buf)
 {
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 	struct cmd_ds_mesh_access mesh_access;
 	int ret;
 
@@ -242,7 +241,7 @@
 static ssize_t lbs_anycast_set(struct device *dev,
 		struct device_attribute *attr, const char * buf, size_t count)
 {
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 	struct cmd_ds_mesh_access mesh_access;
 	uint32_t datum;
 	int ret;
@@ -270,7 +269,7 @@
 static ssize_t lbs_rtap_get(struct device *dev,
 		struct device_attribute *attr, char * buf)
 {
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 	return snprintf(buf, 5, "0x%X\n", priv->monitormode);
 }
 
@@ -281,7 +280,7 @@
 		struct device_attribute *attr, const char * buf, size_t count)
 {
 	int monitor_mode;
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 
 	sscanf(buf, "%x", &monitor_mode);
 	if (monitor_mode) {
@@ -332,7 +331,7 @@
 static ssize_t lbs_mesh_get(struct device *dev,
 		struct device_attribute *attr, char * buf)
 {
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
 }
 
@@ -342,7 +341,7 @@
 static ssize_t lbs_mesh_set(struct device *dev,
 		struct device_attribute *attr, const char * buf, size_t count)
 {
-	struct lbs_private *priv = to_net_dev(dev)->priv;
+	struct lbs_private *priv = netdev_priv(to_net_dev(dev));
 	int enable;
 	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
 
@@ -393,7 +392,7 @@
  */
 static int lbs_dev_open(struct net_device *dev)
 {
-	struct lbs_private *priv = (struct lbs_private *) dev->priv ;
+	struct lbs_private *priv = netdev_priv(dev) ;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_NET);
@@ -435,7 +434,7 @@
  */
 static int lbs_mesh_stop(struct net_device *dev)
 {
-	struct lbs_private *priv = (struct lbs_private *) (dev->priv);
+	struct lbs_private *priv = dev->ml_priv;
 
 	lbs_deb_enter(LBS_DEB_MESH);
 	spin_lock_irq(&priv->driver_lock);
@@ -462,7 +461,7 @@
  */
 static int lbs_eth_stop(struct net_device *dev)
 {
-	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 
 	lbs_deb_enter(LBS_DEB_NET);
 
@@ -479,7 +478,7 @@
 
 static void lbs_tx_timeout(struct net_device *dev)
 {
-	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 
 	lbs_deb_enter(LBS_DEB_TX);
 
@@ -531,7 +530,7 @@
  */
 static struct net_device_stats *lbs_get_stats(struct net_device *dev)
 {
-	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 
 	lbs_deb_enter(LBS_DEB_NET);
 	return &priv->stats;
@@ -540,7 +539,7 @@
 static int lbs_set_mac_address(struct net_device *dev, void *addr)
 {
 	int ret = 0;
-	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 	struct sockaddr *phwaddr = addr;
 	struct cmd_ds_802_11_mac_address cmd;
 
@@ -588,7 +587,6 @@
 {
 	int i = nr_addrs;
 	struct dev_mc_list *mc_list;
-	DECLARE_MAC_BUF(mac);
 
 	if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST))
 		return nr_addrs;
@@ -596,16 +594,16 @@
 	netif_addr_lock_bh(dev);
 	for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) {
 		if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) {
-			lbs_deb_net("mcast address %s:%s skipped\n", dev->name,
-				    print_mac(mac, mc_list->dmi_addr));
+			lbs_deb_net("mcast address %s:%pM skipped\n", dev->name,
+				    mc_list->dmi_addr);
 			continue;
 		}
 
 		if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE)
 			break;
 		memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN);
-		lbs_deb_net("mcast address %s:%s added to filter\n", dev->name,
-			    print_mac(mac, mc_list->dmi_addr));
+		lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name,
+			    mc_list->dmi_addr);
 		i++;
 	}
 	netif_addr_unlock_bh(dev);
@@ -674,7 +672,7 @@
 
 static void lbs_set_multicast_list(struct net_device *dev)
 {
-	struct lbs_private *priv = dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 
 	schedule_work(&priv->mcast_work);
 }
@@ -690,7 +688,7 @@
 static int lbs_thread(void *data)
 {
 	struct net_device *dev = data;
-	struct lbs_private *priv = dev->priv;
+	struct lbs_private *priv = netdev_priv(dev);
 	wait_queue_t wait;
 
 	lbs_deb_enter(LBS_DEB_THREAD);
@@ -1125,7 +1123,7 @@
 		lbs_pr_err("init ethX device failed\n");
 		goto done;
 	}
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 
 	if (lbs_init_adapter(priv)) {
 		lbs_pr_err("failed to initialize adapter structure.\n");
@@ -1378,7 +1376,7 @@
 		ret = -ENOMEM;
 		goto done;
 	}
-	mesh_dev->priv = priv;
+	mesh_dev->ml_priv = priv;
 	priv->mesh_dev = mesh_dev;
 
 	mesh_dev->open = lbs_dev_open;
@@ -1591,7 +1589,7 @@
 
 static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
 {
-	struct lbs_private *priv = dev->priv;
+	struct lbs_private *priv = dev->ml_priv;
 	lbs_deb_enter(LBS_DEB_NET);
 	return &priv->stats;
 }
@@ -1632,7 +1630,7 @@
 	rtap_dev->stop = lbs_rtap_stop;
 	rtap_dev->get_stats = lbs_rtap_get_stats;
 	rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
-	rtap_dev->priv = priv;
+	rtap_dev->ml_priv = priv;
 	SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
 
 	ret = register_netdev(rtap_dev);
@@ -1647,33 +1645,6 @@
 	return ret;
 }
 
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len)
-{
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (ieee80211_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else {
-			*d++ = *s++;
-		}
-	}
-	*d = '\0';
-	return escaped;
-}
-#endif
-
 module_init(lbs_init_module);
 module_exit(lbs_exit_module);
 
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c
index 3309a9c..56e2401 100644
--- a/drivers/net/wireless/libertas/persistcfg.c
+++ b/drivers/net/wireless/libertas/persistcfg.c
@@ -233,7 +233,7 @@
 	/* SSID len */
 	ie->val.mesh_id_len = len;
 	/* IE len */
-	ie->hdr.len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
+	ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
 
 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
 				   CMD_TYPE_MESH_SET_MESH_IE);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 22c4c61..93f7476 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,8 +4,11 @@
   * IOCTL handlers as well as command preperation and response routines
   *  for sending scan commands to the firmware.
   */
+#include <linux/types.h>
 #include <linux/etherdevice.h>
+#include <linux/if_arp.h>
 #include <asm/unaligned.h>
+#include <net/lib80211.h>
 
 #include "host.h"
 #include "decl.h"
@@ -52,6 +55,8 @@
 //! Scan time specified in the channel TLV for each channel for active scans
 #define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
 
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+
 static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
 			      struct cmd_header *resp);
 
@@ -359,7 +364,7 @@
 #ifdef CONFIG_LIBERTAS_DEBUG
 	struct bss_descriptor *iter;
 	int i = 0;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 #endif
 
 	lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
@@ -451,9 +456,9 @@
 	mutex_lock(&priv->lock);
 	lbs_deb_scan("scan table:\n");
 	list_for_each_entry(iter, &priv->network_list, list)
-		lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
-			     i++, print_mac(mac, iter->bssid), iter->rssi,
-			     escape_essid(iter->ssid, iter->ssid_len));
+		lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
+			     i++, iter->bssid, iter->rssi,
+			     print_ssid(ssid, iter->ssid, iter->ssid_len));
 	mutex_unlock(&priv->lock);
 #endif
 
@@ -512,7 +517,7 @@
 	struct ieeetypes_dsparamset *pDS;
 	struct ieeetypes_cfparamset *pCF;
 	struct ieeetypes_ibssparamset *pibss;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 	struct ieeetypes_countryinfoset *pcountryinfo;
 	uint8_t *pos, *end, *p;
 	uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
@@ -544,7 +549,7 @@
 	*bytesleft -= beaconsize;
 
 	memcpy(bss->bssid, pos, ETH_ALEN);
-	lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid));
+	lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
 	pos += ETH_ALEN;
 
 	if ((end - pos) < 12) {
@@ -588,38 +593,36 @@
 
 	/* process variable IE */
 	while (pos <= end - 2) {
-		struct ieee80211_info_element * elem = (void *)pos;
-
-		if (pos + elem->len > end) {
+		if (pos + pos[1] > end) {
 			lbs_deb_scan("process_bss: error in processing IE, "
 				     "bytes left < IE length\n");
 			break;
 		}
 
-		switch (elem->id) {
-		case MFIE_TYPE_SSID:
-			bss->ssid_len = min_t(int, 32, elem->len);
-			memcpy(bss->ssid, elem->data, bss->ssid_len);
+		switch (pos[0]) {
+		case WLAN_EID_SSID:
+			bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
+			memcpy(bss->ssid, pos + 2, bss->ssid_len);
 			lbs_deb_scan("got SSID IE: '%s', len %u\n",
-			             escape_essid(bss->ssid, bss->ssid_len),
+			             print_ssid(ssid, bss->ssid, bss->ssid_len),
 			             bss->ssid_len);
 			break;
 
-		case MFIE_TYPE_RATES:
-			n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
-			memcpy(bss->rates, elem->data, n_basic_rates);
+		case WLAN_EID_SUPP_RATES:
+			n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
+			memcpy(bss->rates, pos + 2, n_basic_rates);
 			got_basic_rates = 1;
 			lbs_deb_scan("got RATES IE\n");
 			break;
 
-		case MFIE_TYPE_FH_SET:
+		case WLAN_EID_FH_PARAMS:
 			pFH = (struct ieeetypes_fhparamset *) pos;
 			memmove(&bss->phyparamset.fhparamset, pFH,
 				sizeof(struct ieeetypes_fhparamset));
 			lbs_deb_scan("got FH IE\n");
 			break;
 
-		case MFIE_TYPE_DS_SET:
+		case WLAN_EID_DS_PARAMS:
 			pDS = (struct ieeetypes_dsparamset *) pos;
 			bss->channel = pDS->currentchan;
 			memcpy(&bss->phyparamset.dsparamset, pDS,
@@ -627,14 +630,14 @@
 			lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
 			break;
 
-		case MFIE_TYPE_CF_SET:
+		case WLAN_EID_CF_PARAMS:
 			pCF = (struct ieeetypes_cfparamset *) pos;
 			memcpy(&bss->ssparamset.cfparamset, pCF,
 			       sizeof(struct ieeetypes_cfparamset));
 			lbs_deb_scan("got CF IE\n");
 			break;
 
-		case MFIE_TYPE_IBSS_SET:
+		case WLAN_EID_IBSS_PARAMS:
 			pibss = (struct ieeetypes_ibssparamset *) pos;
 			bss->atimwindow = le16_to_cpu(pibss->atimwindow);
 			memmove(&bss->ssparamset.ibssparamset, pibss,
@@ -642,7 +645,7 @@
 			lbs_deb_scan("got IBSS IE\n");
 			break;
 
-		case MFIE_TYPE_COUNTRY:
+		case WLAN_EID_COUNTRY:
 			pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
 			lbs_deb_scan("got COUNTRY IE\n");
 			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
@@ -659,7 +662,7 @@
 				    (int) (pcountryinfo->len + 2));
 			break;
 
-		case MFIE_TYPE_RATES_EX:
+		case WLAN_EID_EXT_SUPP_RATES:
 			/* only process extended supported rate if data rate is
 			 * already found. Data rate IE should come before
 			 * extended supported rate IE
@@ -670,50 +673,51 @@
 				break;
 			}
 
-			n_ex_rates = elem->len;
+			n_ex_rates = pos[1];
 			if (n_basic_rates + n_ex_rates > MAX_RATES)
 				n_ex_rates = MAX_RATES - n_basic_rates;
 
 			p = bss->rates + n_basic_rates;
-			memcpy(p, elem->data, n_ex_rates);
+			memcpy(p, pos + 2, n_ex_rates);
 			break;
 
-		case MFIE_TYPE_GENERIC:
-			if (elem->len >= 4 &&
-			    elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
-			    elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
-				bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
-				memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
+		case WLAN_EID_GENERIC:
+			if (pos[1] >= 4 &&
+			    pos[2] == 0x00 && pos[3] == 0x50 &&
+			    pos[4] == 0xf2 && pos[5] == 0x01) {
+				bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+				memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
 				lbs_deb_scan("got WPA IE\n");
-				lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
-			} else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
-				   elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
-				   elem->data[2] == 0x43 && elem->data[3] == 0x04) {
+				lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
+					    bss->wpa_ie_len);
+			} else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
+				   pos[2] == 0x00 && pos[3] == 0x50 &&
+				   pos[4] == 0x43 && pos[4] == 0x04) {
 				lbs_deb_scan("got mesh IE\n");
 				bss->mesh = 1;
 			} else {
 				lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
-					elem->data[0], elem->data[1],
-					elem->data[2], elem->data[3],
-					elem->len);
+					pos[2], pos[3],
+					pos[4], pos[5],
+					pos[1]);
 			}
 			break;
 
-		case MFIE_TYPE_RSN:
+		case WLAN_EID_RSN:
 			lbs_deb_scan("got RSN IE\n");
-			bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
-			memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
+			bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+			memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
 			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
-				    bss->rsn_ie, elem->len);
+				    bss->rsn_ie, bss->rsn_ie_len);
 			break;
 
 		default:
 			lbs_deb_scan("got IE 0x%04x, len %d\n",
-				     elem->id, elem->len);
+				     pos[0], pos[1]);
 			break;
 		}
 
-		pos += elem->len + 2;
+		pos += pos[1] + 2;
 	}
 
 	/* Timestamp */
@@ -741,10 +745,11 @@
 int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
 				uint8_t ssid_len)
 {
+	DECLARE_SSID_BUF(ssid_buf);
 	int ret = 0;
 
 	lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
-			   escape_essid(ssid, ssid_len));
+			   print_ssid(ssid_buf, ssid, ssid_len));
 
 	if (!ssid_len)
 		goto out;
@@ -939,6 +944,7 @@
 int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
 		 union iwreq_data *wrqu, char *extra)
 {
+	DECLARE_SSID_BUF(ssid);
 	struct lbs_private *priv = dev->priv;
 	int ret = 0;
 
@@ -968,7 +974,7 @@
 		priv->scan_ssid_len = req->essid_len;
 		memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
 		lbs_deb_wext("set_scan, essid '%s'\n",
-			escape_essid(priv->scan_ssid, priv->scan_ssid_len));
+			print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
 	} else {
 		priv->scan_ssid_len = 0;
 	}
@@ -1151,7 +1157,6 @@
 		struct bss_descriptor new;
 		struct bss_descriptor *found = NULL;
 		struct bss_descriptor *oldest = NULL;
-		DECLARE_MAC_BUF(mac);
 
 		/* Process the data fields and IEs returned for this BSS */
 		memset(&new, 0, sizeof (struct bss_descriptor));
@@ -1190,7 +1195,7 @@
 			continue;
 		}
 
-		lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
+		lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
 
 		/* Copy the locally created newbssentry to the scan table */
 		memcpy(found, &new, offsetof(struct bss_descriptor, list));
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 9e07b04..fab7d5d 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -7,6 +7,10 @@
 #ifndef _LBS_SCAN_H
 #define _LBS_SCAN_H
 
+#include <net/iw_handler.h>
+
+#define MAX_NETWORK_COUNT 128
+
 /**
  *  @brief Maximum number of channels that can be sent in a setuserscan ioctl
  */
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index e0c2599..fb7a2d1 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -7,7 +7,6 @@
 #include <linux/if_ether.h>
 #include <asm/byteorder.h>
 #include <linux/wireless.h>
-#include <net/ieee80211.h>
 
 struct ieeetypes_cfparamset {
 	u8 elementid;
@@ -258,7 +257,7 @@
  * Note that the len member of the ieee80211_info_element varies depending on
  * the mesh_id_len */
 struct mrvl_meshie_val {
-	uint8_t oui[P80211_OUI_LEN];
+	uint8_t oui[3];
 	uint8_t type;
 	uint8_t subtype;
 	uint8_t version;
@@ -270,7 +269,7 @@
 } __attribute__ ((packed));
 
 struct mrvl_meshie {
-	struct ieee80211_info_element hdr;
+	u8 id, len;
 	struct mrvl_meshie_val val;
 } __attribute__ ((packed));
 
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 82c3e5a5..fe7498f 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -8,7 +8,7 @@
 #include <linux/wireless.h>
 #include <linux/bitops.h>
 
-#include <net/ieee80211.h>
+#include <net/lib80211.h>
 #include <net/iw_handler.h>
 
 #include "host.h"
@@ -1977,6 +1977,7 @@
 	u8 ssid_len = 0;
 	struct assoc_request * assoc_req;
 	int in_ssid_len = dwrq->length;
+	DECLARE_SSID_BUF(ssid_buf);
 
 	lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -2005,7 +2006,7 @@
 		lbs_deb_wext("requested any SSID\n");
 	} else {
 		lbs_deb_wext("requested SSID '%s'\n",
-		             escape_essid(ssid, ssid_len));
+		             print_ssid(ssid_buf, ssid, ssid_len));
 	}
 
 out:
@@ -2104,7 +2105,6 @@
 	struct lbs_private *priv = dev->priv;
 	struct assoc_request * assoc_req;
 	int ret = 0;
-	DECLARE_MAC_BUF(mac);
 
 	lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -2114,7 +2114,7 @@
 	if (awrq->sa_family != ARPHRD_ETHER)
 		return -EINVAL;
 
-	lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
+	lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
 
 	mutex_lock(&priv->lock);
 
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index fdbcf8b..3d3914c 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -79,7 +79,6 @@
 	struct cmd_ds_get_hw_spec cmd;
 	int ret = -1;
 	u32 i;
-	DECLARE_MAC_BUF(mac);
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
@@ -96,8 +95,8 @@
 	priv->fwrelease = (priv->fwrelease << 8) |
 		(priv->fwrelease >> 24 & 0xff);
 
-	printk(KERN_INFO "libertastf: %s, fw %u.%u.%up%u, cap 0x%08x\n",
-		print_mac(mac, cmd.permanentaddr),
+	printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
+		cmd.permanentaddr,
 		priv->fwrelease >> 24 & 0xff,
 		priv->fwrelease >> 16 & 0xff,
 		priv->fwrelease >>  8 & 0xff,
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index 1cc03a8..59634c3 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -331,7 +331,7 @@
 	/* Fill the receive configuration URB and initialise the Rx call back */
 	usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
 			  usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
-			  (void *) (skb->tail),
+			  skb_tail_pointer(skb),
 			  MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
 
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index feff945..d1fc305 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -354,9 +354,11 @@
 	priv->vif = NULL;
 }
 
-static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct lbtf_private *priv = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
+
 	if (conf->channel->center_freq != priv->cur_freq) {
 		priv->cur_freq = conf->channel->center_freq;
 		lbtf_set_channel(priv, conf->channel->hw_value);
@@ -590,14 +592,14 @@
 void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
-	memset(&info->status, 0, sizeof(info->status));
+
+	ieee80211_tx_info_clear_status(info);
 	/*
 	 * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
 	 * default pid rc algorithm.
 	 *
 	 * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
 	 */
-	info->status.excessive_retries = fail ? 1 : 0;
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
 		info->flags |= IEEE80211_TX_STAT_ACK;
 	skb_pull(priv->tx_skb, sizeof(struct txpd));
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 1a019e9..b9230da 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
+#include <linux/debugfs.h>
 
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
@@ -32,6 +33,9 @@
 
 struct hwsim_vif_priv {
 	u32 magic;
+	u8 bssid[ETH_ALEN];
+	bool assoc;
+	u16 aid;
 };
 
 #define HWSIM_VIF_MAGIC	0x69537748
@@ -63,13 +67,13 @@
 static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
 {
 	struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
-	WARN_ON(sp->magic != HWSIM_VIF_MAGIC);
+	WARN_ON(sp->magic != HWSIM_STA_MAGIC);
 }
 
 static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta)
 {
 	struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
-	sp->magic = HWSIM_VIF_MAGIC;
+	sp->magic = HWSIM_STA_MAGIC;
 }
 
 static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
@@ -132,6 +136,12 @@
 	unsigned int rx_filter;
 	int started;
 	struct timer_list beacon_timer;
+	enum ps_mode {
+		PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
+	} ps;
+	bool ps_poll_pending;
+	struct dentry *debugfs;
+	struct dentry *debugfs_ps;
 };
 
 
@@ -196,6 +206,34 @@
 }
 
 
+static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
+			   struct sk_buff *skb)
+{
+	switch (data->ps) {
+	case PS_DISABLED:
+		return true;
+	case PS_ENABLED:
+		return false;
+	case PS_AUTO_POLL:
+		/* TODO: accept (some) Beacons by default and other frames only
+		 * if pending PS-Poll has been sent */
+		return true;
+	case PS_MANUAL_POLL:
+		/* Allow unicast frames to own address if there is a pending
+		 * PS-Poll */
+		if (data->ps_poll_pending &&
+		    memcmp(data->hw->wiphy->perm_addr, skb->data + 4,
+			   ETH_ALEN) == 0) {
+			data->ps_poll_pending = false;
+			return true;
+		}
+		return false;
+	}
+
+	return true;
+}
+
+
 static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 				    struct sk_buff *skb)
 {
@@ -209,9 +247,12 @@
 	/* TODO: set mactime */
 	rx_status.freq = data->channel->center_freq;
 	rx_status.band = data->channel->band;
-	rx_status.rate_idx = info->tx_rate_idx;
+	rx_status.rate_idx = info->control.rates[0].idx;
 	/* TODO: simulate signal strength (and optional packet drop) */
 
+	if (data->ps != PS_DISABLED)
+		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+
 	/* Copy skb to all enabled radios that are on the current frequency */
 	spin_lock(&hwsim_radio_lock);
 	list_for_each_entry(data2, &hwsim_radios, list) {
@@ -221,6 +262,7 @@
 			continue;
 
 		if (!data2->started || !data2->radio_enabled ||
+		    !hwsim_ps_rx_ok(data2, skb) ||
 		    data->channel->center_freq != data2->channel->center_freq)
 			continue;
 
@@ -269,13 +311,9 @@
 	if (txi->control.sta)
 		hwsim_check_sta_magic(txi->control.sta);
 
-	memset(&txi->status, 0, sizeof(txi->status));
-	if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
-		if (ack)
-			txi->flags |= IEEE80211_TX_STAT_ACK;
-		else
-			txi->status.excessive_retries = 1;
-	}
+	ieee80211_tx_info_clear_status(txi);
+	if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
+		txi->flags |= IEEE80211_TX_STAT_ACK;
 	ieee80211_tx_status_irqsafe(hw, skb);
 	return NETDEV_TX_OK;
 }
@@ -294,6 +332,7 @@
 {
 	struct mac80211_hwsim_data *data = hw->priv;
 	data->started = 0;
+	del_timer(&data->beacon_timer);
 	printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
 }
 
@@ -301,10 +340,9 @@
 static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
 					struct ieee80211_if_init_conf *conf)
 {
-	DECLARE_MAC_BUF(mac);
-	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
+	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
 	       wiphy_name(hw->wiphy), __func__, conf->type,
-	       print_mac(mac, conf->mac_addr));
+	       conf->mac_addr);
 	hwsim_set_magic(conf->vif);
 	return 0;
 }
@@ -313,10 +351,9 @@
 static void mac80211_hwsim_remove_interface(
 	struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)
 {
-	DECLARE_MAC_BUF(mac);
-	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
+	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
 	       wiphy_name(hw->wiphy), __func__, conf->type,
-	       print_mac(mac, conf->mac_addr));
+	       conf->mac_addr);
 	hwsim_check_magic(conf->vif);
 	hwsim_clear_magic(conf->vif);
 }
@@ -361,10 +398,10 @@
 }
 
 
-static int mac80211_hwsim_config(struct ieee80211_hw *hw,
-				 struct ieee80211_conf *conf)
+static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct mac80211_hwsim_data *data = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
 
 	printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n",
 	       wiphy_name(hw->wiphy), __func__,
@@ -409,7 +446,16 @@
 					   struct ieee80211_vif *vif,
 					   struct ieee80211_if_conf *conf)
 {
+	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+
 	hwsim_check_magic(vif);
+	if (conf->changed & IEEE80211_IFCC_BSSID) {
+		DECLARE_MAC_BUF(mac);
+		printk(KERN_DEBUG "%s:%s: BSSID changed: %s\n",
+		       wiphy_name(hw->wiphy), __func__,
+		       print_mac(mac, conf->bssid));
+		memcpy(vp->bssid, conf->bssid, ETH_ALEN);
+	}
 	return 0;
 }
 
@@ -418,7 +464,48 @@
 					    struct ieee80211_bss_conf *info,
 					    u32 changed)
 {
+	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+
 	hwsim_check_magic(vif);
+
+	printk(KERN_DEBUG "%s:%s(changed=0x%x)\n",
+	       wiphy_name(hw->wiphy), __func__, changed);
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		printk(KERN_DEBUG "  %s: ASSOC: assoc=%d aid=%d\n",
+		       wiphy_name(hw->wiphy), info->assoc, info->aid);
+		vp->assoc = info->assoc;
+		vp->aid = info->aid;
+	}
+
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		printk(KERN_DEBUG "  %s: ERP_CTS_PROT: %d\n",
+		       wiphy_name(hw->wiphy), info->use_cts_prot);
+	}
+
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		printk(KERN_DEBUG "  %s: ERP_PREAMBLE: %d\n",
+		       wiphy_name(hw->wiphy), info->use_short_preamble);
+	}
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		printk(KERN_DEBUG "  %s: ERP_SLOT: %d\n",
+		       wiphy_name(hw->wiphy), info->use_short_slot);
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		printk(KERN_DEBUG "  %s: HT: sec_ch_offs=%d width_40_ok=%d "
+		       "op_mode=%d\n",
+		       wiphy_name(hw->wiphy),
+		       info->ht.secondary_channel_offset,
+		       info->ht.width_40_ok, info->ht.operation_mode);
+	}
+
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		printk(KERN_DEBUG "  %s: BASIC_RATES: 0x%llx\n",
+		       wiphy_name(hw->wiphy),
+		       (unsigned long long) info->basic_rates);
+	}
 }
 
 static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
@@ -445,6 +532,17 @@
 	return 0;
 }
 
+static int mac80211_hwsim_conf_tx(
+	struct ieee80211_hw *hw, u16 queue,
+	const struct ieee80211_tx_queue_params *params)
+{
+	printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d "
+	       "aifs=%d)\n",
+	       wiphy_name(hw->wiphy), __func__, queue,
+	       params->txop, params->cw_min, params->cw_max, params->aifs);
+	return 0;
+}
+
 static const struct ieee80211_ops mac80211_hwsim_ops =
 {
 	.tx = mac80211_hwsim_tx,
@@ -458,6 +556,7 @@
 	.bss_info_changed = mac80211_hwsim_bss_info_changed,
 	.sta_notify = mac80211_hwsim_sta_notify,
 	.set_tim = mac80211_hwsim_set_tim,
+	.conf_tx = mac80211_hwsim_conf_tx,
 };
 
 
@@ -474,6 +573,8 @@
 	spin_unlock_bh(&hwsim_radio_lock);
 
 	list_for_each_entry(data, &tmplist, list) {
+		debugfs_remove(data->debugfs_ps);
+		debugfs_remove(data->debugfs);
 		ieee80211_unregister_hw(data->hw);
 		device_unregister(data->dev);
 		ieee80211_free_hw(data->hw);
@@ -499,13 +600,133 @@
 }
 
 
+static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_data *data = dat;
+	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+	DECLARE_MAC_BUF(buf);
+	struct sk_buff *skb;
+	struct ieee80211_pspoll *pspoll;
+
+	if (!vp->assoc)
+		return;
+
+	printk(KERN_DEBUG "%s:%s: send PS-Poll to %s for aid %d\n",
+	       wiphy_name(data->hw->wiphy), __func__,
+	       print_mac(buf, vp->bssid), vp->aid);
+
+	skb = dev_alloc_skb(sizeof(*pspoll));
+	if (!skb)
+		return;
+	pspoll = (void *) skb_put(skb, sizeof(*pspoll));
+	pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+					    IEEE80211_STYPE_PSPOLL |
+					    IEEE80211_FCTL_PM);
+	pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
+	memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
+	memcpy(pspoll->ta, mac, ETH_ALEN);
+	if (data->radio_enabled &&
+	    !mac80211_hwsim_tx_frame(data->hw, skb))
+		printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
+	dev_kfree_skb(skb);
+}
+
+
+static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
+				struct ieee80211_vif *vif, int ps)
+{
+	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+	DECLARE_MAC_BUF(buf);
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+
+	if (!vp->assoc)
+		return;
+
+	printk(KERN_DEBUG "%s:%s: send data::nullfunc to %s ps=%d\n",
+	       wiphy_name(data->hw->wiphy), __func__,
+	       print_mac(buf, vp->bssid), ps);
+
+	skb = dev_alloc_skb(sizeof(*hdr));
+	if (!skb)
+		return;
+	hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN);
+	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					 IEEE80211_STYPE_NULLFUNC |
+					 (ps ? IEEE80211_FCTL_PM : 0));
+	hdr->duration_id = cpu_to_le16(0);
+	memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
+	memcpy(hdr->addr2, mac, ETH_ALEN);
+	memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
+	if (data->radio_enabled &&
+	    !mac80211_hwsim_tx_frame(data->hw, skb))
+		printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
+	dev_kfree_skb(skb);
+}
+
+
+static void hwsim_send_nullfunc_ps(void *dat, u8 *mac,
+				   struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_data *data = dat;
+	hwsim_send_nullfunc(data, mac, vif, 1);
+}
+
+
+static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac,
+				      struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_data *data = dat;
+	hwsim_send_nullfunc(data, mac, vif, 0);
+}
+
+
+static int hwsim_fops_ps_read(void *dat, u64 *val)
+{
+	struct mac80211_hwsim_data *data = dat;
+	*val = data->ps;
+	return 0;
+}
+
+static int hwsim_fops_ps_write(void *dat, u64 val)
+{
+	struct mac80211_hwsim_data *data = dat;
+	enum ps_mode old_ps;
+
+	if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL &&
+	    val != PS_MANUAL_POLL)
+		return -EINVAL;
+
+	old_ps = data->ps;
+	data->ps = val;
+
+	if (val == PS_MANUAL_POLL) {
+		ieee80211_iterate_active_interfaces(data->hw,
+						    hwsim_send_ps_poll, data);
+		data->ps_poll_pending = true;
+	} else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
+		ieee80211_iterate_active_interfaces(data->hw,
+						    hwsim_send_nullfunc_ps,
+						    data);
+	} else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
+		ieee80211_iterate_active_interfaces(data->hw,
+						    hwsim_send_nullfunc_no_ps,
+						    data);
+	}
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
+			"%llu\n");
+
+
 static int __init init_mac80211_hwsim(void)
 {
 	int i, err = 0;
 	u8 addr[ETH_ALEN];
 	struct mac80211_hwsim_data *data;
 	struct ieee80211_hw *hw;
-	DECLARE_MAC_BUF(mac);
 
 	if (radios < 1 || radios > 100)
 		return -EINVAL;
@@ -566,19 +787,18 @@
 		data->band.n_channels = ARRAY_SIZE(hwsim_channels);
 		data->band.bitrates = data->rates;
 		data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
-		data->band.ht_info.ht_supported = 1;
-		data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
+		data->band.ht_cap.ht_supported = true;
+		data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
 			IEEE80211_HT_CAP_GRN_FLD |
 			IEEE80211_HT_CAP_SGI_40 |
 			IEEE80211_HT_CAP_DSSSCCK40;
-		data->band.ht_info.ampdu_factor = 0x3;
-		data->band.ht_info.ampdu_density = 0x6;
-		memset(data->band.ht_info.supp_mcs_set, 0,
-		       sizeof(data->band.ht_info.supp_mcs_set));
-		data->band.ht_info.supp_mcs_set[0] = 0xff;
-		data->band.ht_info.supp_mcs_set[1] = 0xff;
-		data->band.ht_info.supp_mcs_set[12] =
-			IEEE80211_HT_CAP_MCS_TX_DEFINED;
+		data->band.ht_cap.ampdu_factor = 0x3;
+		data->band.ht_cap.ampdu_density = 0x6;
+		memset(&data->band.ht_cap.mcs, 0,
+		       sizeof(data->band.ht_cap.mcs));
+		data->band.ht_cap.mcs.rx_mask[0] = 0xff;
+		data->band.ht_cap.mcs.rx_mask[1] = 0xff;
+		data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
 
 		err = ieee80211_register_hw(hw);
@@ -588,9 +808,15 @@
 			goto failed_hw;
 		}
 
-		printk(KERN_DEBUG "%s: hwaddr %s registered\n",
+		printk(KERN_DEBUG "%s: hwaddr %pM registered\n",
 		       wiphy_name(hw->wiphy),
-		       print_mac(mac, hw->wiphy->perm_addr));
+		       hw->wiphy->perm_addr);
+
+		data->debugfs = debugfs_create_dir("hwsim",
+						   hw->wiphy->debugfsdir);
+		data->debugfs_ps = debugfs_create_file("ps", 0666,
+						       data->debugfs, data,
+						       &hwsim_fops_ps);
 
 		setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
 			    (unsigned long) hw);
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index a670f36b..24caec6 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -737,7 +737,6 @@
     win_req_t req;
     memreq_t mem;
     u_char __iomem *ramBase = NULL;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link);
 
@@ -808,12 +807,12 @@
 	dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i);
 
     printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, "
-	   "id %c%c, hw_addr %s\n",
+	   "id %c%c, hw_addr %pM\n",
 	   dev->name, dev->base_addr, dev->irq,
 	   (u_long) ramBase,
 	   (int) readb(ramBase+NETWAVE_EREG_NI),
 	   (int) readb(ramBase+NETWAVE_EREG_NI+1),
-	   print_mac(mac, dev->dev_addr));
+	   dev->dev_addr);
 
     /* get revision words */
     printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", 
@@ -1308,7 +1307,6 @@
 	/* Queue packet for network layer */
 	netif_rx(skb);
 
-	dev->last_rx = jiffies;
 	priv->stats.rx_packets++;
 	priv->stats.rx_bytes += rcvLen;
 
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile
new file mode 100644
index 0000000..791366e
--- /dev/null
+++ b/drivers/net/wireless/orinoco/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the orinoco wireless device drivers.
+#
+
+obj-$(CONFIG_HERMES)		+= orinoco.o hermes.o hermes_dld.o
+obj-$(CONFIG_PCMCIA_HERMES)	+= orinoco_cs.o
+obj-$(CONFIG_APPLE_AIRPORT)	+= airport.o
+obj-$(CONFIG_PLX_HERMES)	+= orinoco_plx.o
+obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.o
+obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/orinoco/airport.c
similarity index 100%
rename from drivers/net/wireless/airport.c
rename to drivers/net/wireless/orinoco/airport.c
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/orinoco/hermes.c
similarity index 100%
rename from drivers/net/wireless/hermes.c
rename to drivers/net/wireless/orinoco/hermes.c
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/orinoco/hermes.h
similarity index 100%
rename from drivers/net/wireless/hermes.h
rename to drivers/net/wireless/orinoco/hermes.h
diff --git a/drivers/net/wireless/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
similarity index 100%
rename from drivers/net/wireless/hermes_dld.c
rename to drivers/net/wireless/orinoco/hermes_dld.c
diff --git a/drivers/net/wireless/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
similarity index 100%
rename from drivers/net/wireless/hermes_dld.h
rename to drivers/net/wireless/orinoco/hermes_dld.h
diff --git a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/orinoco/hermes_rid.h
similarity index 100%
rename from drivers/net/wireless/hermes_rid.h
rename to drivers/net/wireless/orinoco/hermes_rid.h
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
similarity index 98%
rename from drivers/net/wireless/orinoco.c
rename to drivers/net/wireless/orinoco/orinoco.c
index e0512e4..072be44 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -86,8 +86,8 @@
 #include <linux/firmware.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 
 #include <linux/scatterlist.h>
 #include <linux/crypto.h>
@@ -143,7 +143,7 @@
 #define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)
 
 #define ORINOCO_MIN_MTU		256
-#define ORINOCO_MAX_MTU		(IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
+#define ORINOCO_MAX_MTU		(IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
 
 #define SYMBOL_MAX_VER_LEN	(14)
 #define USER_BAP		0
@@ -392,7 +392,7 @@
 }
 
 static inline u8 *orinoco_get_ie(u8 *data, size_t len,
-				 enum ieee80211_mfie eid)
+				 enum ieee80211_eid eid)
 {
 	u8 *p = data;
 	while ((p + 2) < (data + len)) {
@@ -409,7 +409,7 @@
 {
 	u8 *p = data;
 	while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
-		if ((p[0] == MFIE_TYPE_GENERIC) &&
+		if ((p[0] == WLAN_EID_GENERIC) &&
 		    (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
 			return p;
 		p += p[1] + 2;
@@ -487,12 +487,17 @@
 	if (err)
 		goto free;
 
-	err = request_firmware(&fw_entry, firmware, priv->dev);
-	if (err) {
-		printk(KERN_ERR "%s: Cannot find firmware %s\n",
-		       dev->name, firmware);
-		err = -ENOENT;
-		goto free;
+	if (priv->cached_fw)
+		fw_entry = priv->cached_fw;
+	else {
+		err = request_firmware(&fw_entry, firmware, priv->dev);
+		if (err) {
+			printk(KERN_ERR "%s: Cannot find firmware %s\n",
+			       dev->name, firmware);
+			err = -ENOENT;
+			goto free;
+		}
+		priv->cached_fw = fw_entry;
 	}
 
 	hdr = (const struct orinoco_fw_header *) fw_entry->data;
@@ -535,7 +540,11 @@
 	       dev->name, hermes_present(hw));
 
 abort:
-	release_firmware(fw_entry);
+	/* In case of error, assume firmware was bogus and release it */
+	if (err) {
+		priv->cached_fw = NULL;
+		release_firmware(fw_entry);
+	}
 
 free:
 	kfree(pda);
@@ -830,7 +839,8 @@
 	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
 		return -EINVAL;
 
-	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
+	/* MTU + encapsulation + header length */
+	if ( (new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
 	     (priv->nicbuf_size - ETH_HLEN) )
 		return -EINVAL;
 
@@ -1245,7 +1255,7 @@
 	}
 
 	/* sanity check the length */
-	if (datalen > IEEE80211_DATA_LEN + 12) {
+	if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
 		printk(KERN_DEBUG "%s: oversized monitor frame, "
 		       "data length = %d\n", dev->name, datalen);
 		stats->rx_length_errors++;
@@ -1280,7 +1290,6 @@
 	skb->pkt_type = PACKET_OTHERHOST;
 	skb->protocol = __constant_htons(ETH_P_802_2);
 	
-	dev->last_rx = jiffies;
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
 
@@ -1374,7 +1383,7 @@
                    data. */
 		goto out;
 	}
-	if (length > IEEE80211_DATA_LEN) {
+	if (length > IEEE80211_MAX_DATA_LEN) {
 		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
 		       dev->name, length);
 		stats->rx_length_errors++;
@@ -1477,12 +1486,11 @@
 			   MICHAEL_MIC_LEN)) {
 			union iwreq_data wrqu;
 			struct iw_michaelmicfailure wxmic;
-			DECLARE_MAC_BUF(mac);
 
 			printk(KERN_WARNING "%s: "
-			       "Invalid Michael MIC in data frame from %s, "
+			       "Invalid Michael MIC in data frame from %pM, "
 			       "using key %i\n",
-			       dev->name, print_mac(mac, src), key_id);
+			       dev->name, src, key_id);
 
 			/* TODO: update stats */
 
@@ -1530,7 +1538,6 @@
 	else
 		memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
 
-	dev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, dev);
 	skb->ip_summed = CHECKSUM_NONE;
 	if (fc & IEEE80211_FCTL_TODS)
@@ -2301,6 +2308,11 @@
 	int err;
 
 	err = hermes_init(hw);
+	if (priv->do_fw_download && !err) {
+		err = orinoco_download(priv);
+		if (err)
+			priv->do_fw_download = 0;
+	}
 	if (!err)
 		err = orinoco_allocate_fid(dev);
 
@@ -2926,12 +2938,6 @@
 		}
 	}
 
-	if (priv->do_fw_download) {
-		err = orinoco_download(priv);
-		if (err)
-			priv->do_fw_download = 0;
-	}
-
 	err = orinoco_reinit_firmware(dev);
 	if (err) {
 		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
@@ -3277,11 +3283,10 @@
 	struct hermes_idstring nickbuf;
 	u16 reclen;
 	int len;
-	DECLARE_MAC_BUF(mac);
 
 	/* No need to lock, the hw_unavailable flag is already set in
 	 * alloc_orinocodev() */
-	priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
+	priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
 
 	/* Initialize the firmware */
 	err = hermes_init(hw);
@@ -3348,8 +3353,8 @@
 		goto out;
 	}
 
-	printk(KERN_DEBUG "%s: MAC address %s\n",
-	       dev->name, print_mac(mac, dev->dev_addr));
+	printk(KERN_DEBUG "%s: MAC address %pM\n",
+	       dev->name, dev->dev_addr);
 
 	/* Get the station name */
 	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
@@ -3535,6 +3540,8 @@
 	netif_carrier_off(dev);
 	priv->last_linkstatus = 0xffff;
 
+	priv->cached_fw = NULL;
+
 	return dev;
 }
 
@@ -3546,6 +3553,9 @@
 	 * when we call tasklet_kill it will run one final time,
 	 * emptying the list */
 	tasklet_kill(&priv->rx_tasklet);
+	if (priv->cached_fw)
+		release_firmware(priv->cached_fw);
+	priv->cached_fw = NULL;
 	priv->wpa_ie_len = 0;
 	kfree(priv->wpa_ie);
 	orinoco_mic_free(priv);
@@ -4672,7 +4682,7 @@
 	/* Determine and validate the key index */
 	idx = encoding->flags & IW_ENCODE_INDEX;
 	if (idx) {
-		if ((idx < 1) || (idx > WEP_KEYS))
+		if ((idx < 1) || (idx > 4))
 			goto out;
 		idx--;
 	} else
@@ -4777,7 +4787,7 @@
 
 	idx = encoding->flags & IW_ENCODE_INDEX;
 	if (idx) {
-		if ((idx < 1) || (idx > WEP_KEYS))
+		if ((idx < 1) || (idx > 4))
 			goto out;
 		idx--;
 	} else
@@ -4940,7 +4950,8 @@
 	unsigned long flags;
 	int err = 0;
 
-	if ((wrqu->data.length > MAX_WPA_IE_LEN) ||
+	/* cut off at IEEE80211_MAX_DATA_LEN */
+	if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
 	    (wrqu->data.length && (extra == NULL)))
 		return -EINVAL;
 
@@ -5623,7 +5634,7 @@
 						  &iwe, IW_EV_UINT_LEN);
 	}
 
-	ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_DS_SET);
+	ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
 	channel = ie ? ie[2] : 0;
 	if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
 		/* Add channel and frequency */
@@ -5673,7 +5684,7 @@
 	}
 
 	/* RSN IE */
-	ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RSN);
+	ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
 	if (ie) {
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = ie[1] + 2;
@@ -5681,7 +5692,7 @@
 						  &iwe, ie);
 	}
 
-	ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RATES);
+	ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
 	if (ie) {
 		char *p = current_ev + iwe_stream_lcp_len(info);
 		int i;
@@ -5976,7 +5987,7 @@
 	strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
 	strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
 	if (dev->dev.parent)
-		strncpy(info->bus_info, dev->dev.parent->bus_id,
+		strncpy(info->bus_info, dev_name(dev->dev.parent),
 			sizeof(info->bus_info) - 1);
 	else
 		snprintf(info->bus_info, sizeof(info->bus_info) - 1,
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
similarity index 97%
rename from drivers/net/wireless/orinoco.h
rename to drivers/net/wireless/orinoco/orinoco.h
index 981570b..8c29538 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -66,6 +66,8 @@
 	struct list_head list;
 };
 
+struct firmware;
+
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	struct device *dev;
@@ -164,6 +166,9 @@
 	unsigned int wpa_enabled:1;
 	unsigned int tkip_cm_active:1;
 	unsigned int key_mgmt:3;
+
+	/* Cached in memory firmware to use in ->resume */
+	const struct firmware *cached_fw;
 };
 
 #ifdef ORINOCO_DEBUG
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
similarity index 99%
rename from drivers/net/wireless/orinoco_cs.c
rename to drivers/net/wireless/orinoco/orinoco_cs.c
index 6fcf2bd..bf6a51d 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -308,7 +308,7 @@
 
 	/* Finally, report what we've done */
 	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
-	       "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
+	       "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
 	       link->irq.AssignedIRQ, link->io.BasePort1,
 	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 	return 0;
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
similarity index 100%
rename from drivers/net/wireless/orinoco_nortel.c
rename to drivers/net/wireless/orinoco/orinoco_nortel.c
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
similarity index 100%
rename from drivers/net/wireless/orinoco_pci.c
rename to drivers/net/wireless/orinoco/orinoco_pci.c
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h
similarity index 100%
rename from drivers/net/wireless/orinoco_pci.h
rename to drivers/net/wireless/orinoco/orinoco_pci.h
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
similarity index 100%
rename from drivers/net/wireless/orinoco_plx.c
rename to drivers/net/wireless/orinoco/orinoco_plx.c
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
similarity index 100%
rename from drivers/net/wireless/orinoco_tmd.c
rename to drivers/net/wireless/orinoco/orinoco_tmd.c
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
similarity index 99%
rename from drivers/net/wireless/spectrum_cs.c
rename to drivers/net/wireless/orinoco/spectrum_cs.c
index 852789a..0bae3dc 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -383,7 +383,7 @@
 
 	/* Finally, report what we've done */
 	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
-	       "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
+	       "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
 	       link->irq.AssignedIRQ, link->io.BasePort1,
 	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 1d0704f..b585ff6 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -14,17 +14,17 @@
  * published by the Free Software Foundation.
  */
 
-enum control_frame_types {
-	P54_CONTROL_TYPE_FILTER_SET = 0,
-	P54_CONTROL_TYPE_CHANNEL_CHANGE,
-	P54_CONTROL_TYPE_FREQDONE,
+enum p54_control_frame_types {
+	P54_CONTROL_TYPE_SETUP = 0,
+	P54_CONTROL_TYPE_SCAN,
+	P54_CONTROL_TYPE_TRAP,
 	P54_CONTROL_TYPE_DCFINIT,
-	P54_CONTROL_TYPE_ENCRYPTION,
+	P54_CONTROL_TYPE_RX_KEYCACHE,
 	P54_CONTROL_TYPE_TIM,
-	P54_CONTROL_TYPE_POWERMGT,
-	P54_CONTROL_TYPE_FREEQUEUE,
+	P54_CONTROL_TYPE_PSM,
+	P54_CONTROL_TYPE_TXCANCEL,
 	P54_CONTROL_TYPE_TXDONE,
-	P54_CONTROL_TYPE_PING,
+	P54_CONTROL_TYPE_BURST,
 	P54_CONTROL_TYPE_STAT_READBACK,
 	P54_CONTROL_TYPE_BBP,
 	P54_CONTROL_TYPE_EEPROM_READBACK,
@@ -37,18 +37,30 @@
 	P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
 	P54_CONTROL_TYPE_CCE_QUIET,
 	P54_CONTROL_TYPE_PSM_STA_UNLOCK,
+	P54_CONTROL_TYPE_PCS,
+	P54_CONTROL_TYPE_BT_BALANCER = 28,
+	P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE = 30,
+	P54_CONTROL_TYPE_ARPTABLE = 31,
+	P54_CONTROL_TYPE_BT_OPTIONS = 35
 };
 
-struct p54_control_hdr {
-	__le16 magic1;
+struct p54_hdr {
+	__le16 flags;
 	__le16 len;
 	__le32 req_id;
-	__le16 type;	/* enum control_frame_types */
-	u8 retry1;
-	u8 retry2;
+	__le16 type;	/* enum p54_control_frame_types */
+	u8 rts_tries;
+	u8 tries;
 	u8 data[0];
 } __attribute__ ((packed));
 
+struct p54_edcf_queue_param {
+	__le16 aifs;
+	__le16 cwmin;
+	__le16 cwmax;
+	__le16 txop;
+} __attribute__ ((packed));
+
 #define EEPROM_READBACK_LEN 0x3fc
 
 #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
@@ -62,46 +74,48 @@
 	u32 rx_start;
 	u32 rx_end;
 	struct sk_buff_head tx_queue;
-	void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-		   size_t len, int free_on_tx);
+	void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb,
+		   int free_on_tx);
 	int (*open)(struct ieee80211_hw *dev);
 	void (*stop)(struct ieee80211_hw *dev);
 	int mode;
-	u16 seqno;
 	u16 rx_mtu;
 	u8 headroom;
 	u8 tailroom;
 	struct mutex conf_mutex;
 	u8 mac_addr[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
-	__le16 filter_type;
+	u16 mac_mode;
 	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;
 	unsigned int filter_flags;
+	bool use_short_slot;
 	u16 rxhw;
 	u8 version;
 	u8 rx_antenna;
 	unsigned int tx_hdr_len;
-	void *cached_vdcf;
 	unsigned int fw_var;
 	unsigned int fw_interface;
 	unsigned int output_power;
 	u32 tsf_low32;
 	u32 tsf_high32;
 	struct ieee80211_tx_queue_stats tx_stats[8];
+	struct p54_edcf_queue_param qos_params[8];
 	struct ieee80211_low_level_stats stats;
 	struct timer_list stats_timer;
 	struct completion stats_comp;
-	void *cached_stats;
+	struct sk_buff *cached_stats;
+	struct sk_buff *cached_beacon;
 	int noise;
 	void *eeprom;
 	struct completion eeprom_comp;
 };
 
 int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb);
 int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
 int p54_read_eeprom(struct ieee80211_hw *dev);
 struct ieee80211_hw *p54_init_common(size_t priv_data_len);
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 827ca03..1796b8c 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -1,12 +1,15 @@
-
 /*
  * Common code for mac80211 Prism54 drivers
  *
  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
  * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  *
- * Based on the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -183,7 +186,7 @@
 			priv->headroom = desc->headroom;
 			priv->tailroom = desc->tailroom;
 			if (le32_to_cpu(bootrec->len) == 11)
-				priv->rx_mtu = le16_to_cpu(bootrec->rx_mtu);
+				priv->rx_mtu = le16_to_cpu(desc->rx_mtu);
 			else
 				priv->rx_mtu = (size_t)
 					0x620 - priv->tx_hdr_len;
@@ -211,12 +214,17 @@
 		printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
 			fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
 
+	if (priv->fw_var < 0x500)
+		printk(KERN_INFO "p54: you are using an obsolete firmware. "
+		       "visit http://wireless.kernel.org/en/users/Drivers/p54 "
+		       "and grab one for \"kernel >= 2.6.28\"!\n");
+
 	if (priv->fw_var >= 0x300) {
 		/* Firmware supports QoS, use it! */
-		priv->tx_stats[4].limit = 3;
-		priv->tx_stats[5].limit = 4;
-		priv->tx_stats[6].limit = 3;
-		priv->tx_stats[7].limit = 1;
+		priv->tx_stats[4].limit = 3;		/* AC_VO */
+		priv->tx_stats[5].limit = 4;		/* AC_VI */
+		priv->tx_stats[6].limit = 3;		/* AC_BE */
+		priv->tx_stats[7].limit = 2;		/* AC_BK */
 		dev->queues = 4;
 	}
 
@@ -320,7 +328,6 @@
 	int err;
 	u8 *end = (u8 *)eeprom + len;
 	u16 synth = 0;
-	DECLARE_MAC_BUF(mac);
 
 	wrap = (struct eeprom_pda_wrap *) eeprom;
 	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
@@ -413,6 +420,30 @@
 			/* make it overrun */
 			entry_len = len;
 			break;
+		case PDR_MANUFACTURING_PART_NUMBER:
+		case PDR_PDA_VERSION:
+		case PDR_NIC_SERIAL_NUMBER:
+		case PDR_REGULATORY_DOMAIN_LIST:
+		case PDR_TEMPERATURE_TYPE:
+		case PDR_PRISM_PCI_IDENTIFIER:
+		case PDR_COUNTRY_INFORMATION:
+		case PDR_OEM_NAME:
+		case PDR_PRODUCT_NAME:
+		case PDR_UTF8_OEM_NAME:
+		case PDR_UTF8_PRODUCT_NAME:
+		case PDR_COUNTRY_LIST:
+		case PDR_DEFAULT_COUNTRY:
+		case PDR_ANTENNA_GAIN:
+		case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA:
+		case PDR_RSSI_LINEAR_APPROXIMATION:
+		case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
+		case PDR_REGULATORY_POWER_LIMITS:
+		case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
+		case PDR_RADIATED_TRANSMISSION_CORRECTION:
+		case PDR_PRISM_TX_IQ_CALIBRATION:
+		case PDR_BASEBAND_REGISTERS:
+		case PDR_PER_CHANNEL_BASEBAND_REGISTERS:
+			break;
 		default:
 			printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
 				le16_to_cpu(entry->code));
@@ -429,12 +460,12 @@
 		goto err;
 	}
 
-	priv->rxhw = synth & 0x07;
+	priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
 	if (priv->rxhw == 4)
 		p54_init_xbow_synth(dev);
-	if (!(synth & 0x40))
+	if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
 		dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
-	if (!(synth & 0x80))
+	if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
 		dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
 
 	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
@@ -446,9 +477,9 @@
 		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 	}
 
-	printk(KERN_INFO "%s: hwaddr %s, MAC:isl38%02x RF:%s\n",
+	printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
 		wiphy_name(dev->wiphy),
-		print_mac(mac, dev->wiphy->perm_addr),
+		dev->wiphy->perm_addr,
 		priv->version, p54_rf_chips[priv->rxhw]);
 
 	return 0;
@@ -482,13 +513,13 @@
 static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
+	struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
 	struct ieee80211_rx_status rx_status = {0};
 	u16 freq = le16_to_cpu(hdr->freq);
 	size_t header_len = sizeof(*hdr);
 	u32 tsf32;
 
-	if (!(hdr->magic & cpu_to_le16(0x0001))) {
+	if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
 		if (priv->filter_flags & FIF_FCSFAIL)
 			rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 		else
@@ -513,7 +544,7 @@
 
 	rx_status.flag |= RX_FLAG_TSFT;
 
-	if (hdr->magic & cpu_to_le16(0x4000))
+	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
 		header_len += hdr->align[0];
 
 	skb_pull(skb, header_len);
@@ -529,81 +560,155 @@
 	struct p54_common *priv = dev->priv;
 	int i;
 
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
 	for (i = 0; i < dev->queues; i++)
 		if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
 			ieee80211_wake_queue(dev, i);
 }
 
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+	struct p54_common *priv = dev->priv;
+	struct ieee80211_tx_info *info;
+	struct memrecord *range;
+	unsigned long flags;
+	u32 freed = 0, last_addr = priv->rx_start;
+
+	if (!skb || !dev)
+		return;
+
+	spin_lock_irqsave(&priv->tx_queue.lock, flags);
+	info = IEEE80211_SKB_CB(skb);
+	range = (void *)info->rate_driver_data;
+	if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
+		struct ieee80211_tx_info *ni;
+		struct memrecord *mr;
+
+		ni = IEEE80211_SKB_CB(skb->prev);
+		mr = (struct memrecord *)ni->rate_driver_data;
+		last_addr = mr->end_addr;
+	}
+	if (skb->next != (struct sk_buff *)&priv->tx_queue) {
+		struct ieee80211_tx_info *ni;
+		struct memrecord *mr;
+
+		ni = IEEE80211_SKB_CB(skb->next);
+		mr = (struct memrecord *)ni->rate_driver_data;
+		freed = mr->start_addr - last_addr;
+	} else
+		freed = priv->rx_end - last_addr;
+	__skb_unlink(skb, &priv->tx_queue);
+	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+	kfree_skb(skb);
+
+	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
+		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+		p54_wake_free_queues(dev);
+}
+EXPORT_SYMBOL_GPL(p54_free_skb);
+
 static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
-	struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
+	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+	struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
 	struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
 	u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
 	struct memrecord *range = NULL;
 	u32 freed = 0;
 	u32 last_addr = priv->rx_start;
 	unsigned long flags;
+	int count, idx;
 
 	spin_lock_irqsave(&priv->tx_queue.lock, flags);
 	while (entry != (struct sk_buff *)&priv->tx_queue) {
 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
-		range = (void *)info->driver_data;
-		if (range->start_addr == addr) {
-			struct p54_control_hdr *entry_hdr;
-			struct p54_tx_control_allocdata *entry_data;
-			int pad = 0;
+		struct p54_hdr *entry_hdr;
+		struct p54_tx_data *entry_data;
+		int pad = 0;
 
-			if (entry->next != (struct sk_buff *)&priv->tx_queue) {
-				struct ieee80211_tx_info *ni;
-				struct memrecord *mr;
-
-				ni = IEEE80211_SKB_CB(entry->next);
-				mr = (struct memrecord *)ni->driver_data;
-				freed = mr->start_addr - last_addr;
-			} else
-				freed = priv->rx_end - last_addr;
-
+		range = (void *)info->rate_driver_data;
+		if (range->start_addr != addr) {
 			last_addr = range->end_addr;
-			__skb_unlink(entry, &priv->tx_queue);
-			spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+			entry = entry->next;
+			continue;
+		}
 
-			memset(&info->status, 0, sizeof(info->status));
-			entry_hdr = (struct p54_control_hdr *) entry->data;
-			entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
-			if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
-				pad = entry_data->align[0];
+		if (entry->next != (struct sk_buff *)&priv->tx_queue) {
+			struct ieee80211_tx_info *ni;
+			struct memrecord *mr;
 
-			priv->tx_stats[entry_data->hw_queue].len--;
-			if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-				if (!(payload->status & 0x01))
-					info->flags |= IEEE80211_TX_STAT_ACK;
-				else
-					info->status.excessive_retries = 1;
-			}
-			info->status.retry_count = payload->retries - 1;
-			info->status.ack_signal = p54_rssi_to_dbm(dev,
-					le16_to_cpu(payload->ack_rssi));
-			skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
-			ieee80211_tx_status_irqsafe(dev, entry);
-			goto out;
+			ni = IEEE80211_SKB_CB(entry->next);
+			mr = (struct memrecord *)ni->rate_driver_data;
+			freed = mr->start_addr - last_addr;
 		} else
-			last_addr = range->end_addr;
-		entry = entry->next;
+			freed = priv->rx_end - last_addr;
+
+		last_addr = range->end_addr;
+		__skb_unlink(entry, &priv->tx_queue);
+		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+
+		if (unlikely(entry == priv->cached_beacon)) {
+			kfree_skb(entry);
+			priv->cached_beacon = NULL;
+			goto out;
+		}
+
+		/*
+		 * Clear manually, ieee80211_tx_info_clear_status would
+		 * clear the counts too and we need them.
+		 */
+		memset(&info->status.ampdu_ack_len, 0,
+		       sizeof(struct ieee80211_tx_info) -
+		       offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+		BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
+				      status.ampdu_ack_len) != 23);
+
+		entry_hdr = (struct p54_hdr *) entry->data;
+		entry_data = (struct p54_tx_data *) entry_hdr->data;
+		if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
+			pad = entry_data->align[0];
+
+		/* walk through the rates array and adjust the counts */
+		count = payload->tries;
+		for (idx = 0; idx < 4; idx++) {
+			if (count >= info->status.rates[idx].count) {
+				count -= info->status.rates[idx].count;
+			} else if (count > 0) {
+				info->status.rates[idx].count = count;
+				count = 0;
+			} else {
+				info->status.rates[idx].idx = -1;
+				info->status.rates[idx].count = 0;
+			}
+		}
+
+		priv->tx_stats[entry_data->hw_queue].len--;
+		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+		     (!payload->status))
+			info->flags |= IEEE80211_TX_STAT_ACK;
+		if (payload->status & P54_TX_PSM_CANCELLED)
+			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+		info->status.ack_signal = p54_rssi_to_dbm(dev,
+				(int)payload->ack_rssi);
+		skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
+		ieee80211_tx_status_irqsafe(dev, entry);
+		goto out;
 	}
 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
 out:
-	if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
-	    sizeof(struct p54_control_hdr))
+	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
+		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
 		p54_wake_free_queues(dev);
 }
 
 static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
 				   struct sk_buff *skb)
 {
-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
 	struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
 	struct p54_common *priv = dev->priv;
 
@@ -618,7 +723,7 @@
 static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
 	struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
 	u32 tsf32 = le32_to_cpu(stats->tsf32);
 
@@ -636,14 +741,46 @@
 	mod_timer(&priv->stats_timer, jiffies + 5 * HZ);
 }
 
+static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+	struct p54_trap *trap = (struct p54_trap *) hdr->data;
+	u16 event = le16_to_cpu(trap->event);
+	u16 freq = le16_to_cpu(trap->frequency);
+
+	switch (event) {
+	case P54_TRAP_BEACON_TX:
+		break;
+	case P54_TRAP_RADAR:
+		printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
+			wiphy_name(dev->wiphy), freq);
+		break;
+	case P54_TRAP_NO_BEACON:
+		break;
+	case P54_TRAP_SCAN:
+		break;
+	case P54_TRAP_TBTT:
+		break;
+	case P54_TRAP_TIMER:
+		break;
+	default:
+		printk(KERN_INFO "%s: received event:%x freq:%d\n",
+		       wiphy_name(dev->wiphy), event, freq);
+		break;
+	}
+}
+
 static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
 
 	switch (le16_to_cpu(hdr->type)) {
 	case P54_CONTROL_TYPE_TXDONE:
 		p54_rx_frame_sent(dev, skb);
 		break;
+	case P54_CONTROL_TYPE_TRAP:
+		p54_rx_trap(dev, skb);
+		break;
 	case P54_CONTROL_TYPE_BBP:
 		break;
 	case P54_CONTROL_TYPE_STAT_READBACK:
@@ -664,9 +801,9 @@
 /* returns zero if skb can be reused */
 int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
-	u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
+	u16 type = le16_to_cpu(*((__le16 *)skb->data));
 
-	if (type == 0x80)
+	if (type & P54_HDR_FLAG_CONTROL)
 		return p54_rx_control(dev, skb);
 	else
 		return p54_rx_data(dev, skb);
@@ -682,12 +819,14 @@
  * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
  * allocated areas.
  */
-static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
-			       struct p54_control_hdr *data, u32 len)
+static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
+			       struct p54_hdr *data, u32 len)
 {
 	struct p54_common *priv = dev->priv;
 	struct sk_buff *entry = priv->tx_queue.next;
 	struct sk_buff *target_skb = NULL;
+	struct ieee80211_tx_info *info;
+	struct memrecord *range;
 	u32 last_addr = priv->rx_start;
 	u32 largest_hole = 0;
 	u32 target_addr = priv->rx_start;
@@ -695,12 +834,15 @@
 	unsigned int left;
 	len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
 
+	if (!skb)
+		return -EINVAL;
+
 	spin_lock_irqsave(&priv->tx_queue.lock, flags);
 	left = skb_queue_len(&priv->tx_queue);
 	while (left--) {
 		u32 hole_size;
-		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
-		struct memrecord *range = (void *)info->driver_data;
+		info = IEEE80211_SKB_CB(entry);
+		range = (void *)info->rate_driver_data;
 		hole_size = range->start_addr - last_addr;
 		if (!target_skb && hole_size >= len) {
 			target_skb = entry->prev;
@@ -715,64 +857,89 @@
 		target_skb = priv->tx_queue.prev;
 		largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
 		if (!skb_queue_empty(&priv->tx_queue)) {
-			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb);
-			struct memrecord *range = (void *)info->driver_data;
+			info = IEEE80211_SKB_CB(target_skb);
+			range = (void *)info->rate_driver_data;
 			target_addr = range->end_addr;
 		}
 	} else
 		largest_hole = max(largest_hole, priv->rx_end - last_addr);
 
-	if (skb) {
-		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-		struct memrecord *range = (void *)info->driver_data;
-		range->start_addr = target_addr;
-		range->end_addr = target_addr + len;
-		__skb_queue_after(&priv->tx_queue, target_skb, skb);
-		if (largest_hole < priv->rx_mtu + priv->headroom +
-				   priv->tailroom +
-				   sizeof(struct p54_control_hdr))
-			ieee80211_stop_queues(dev);
+	if (!target_skb) {
+		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+		ieee80211_stop_queues(dev);
+		return -ENOMEM;
 	}
+
+	info = IEEE80211_SKB_CB(skb);
+	range = (void *)info->rate_driver_data;
+	range->start_addr = target_addr;
+	range->end_addr = target_addr + len;
+	__skb_queue_after(&priv->tx_queue, target_skb, skb);
 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
+	if (largest_hole < priv->headroom + sizeof(struct p54_hdr) +
+			   48 + IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+		ieee80211_stop_queues(dev);
+
 	data->req_id = cpu_to_le32(target_addr + priv->headroom);
+	return 0;
+}
+
+static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev,
+		u16 hdr_flags, u16 len, u16 type, gfp_t memflags)
+{
+	struct p54_common *priv = dev->priv;
+	struct p54_hdr *hdr;
+	struct sk_buff *skb;
+
+	skb = __dev_alloc_skb(len + priv->tx_hdr_len, memflags);
+	if (!skb)
+		return NULL;
+	skb_reserve(skb, priv->tx_hdr_len);
+
+	hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
+	hdr->flags = cpu_to_le16(hdr_flags);
+	hdr->len = cpu_to_le16(len - sizeof(*hdr));
+	hdr->type = cpu_to_le16(type);
+	hdr->tries = hdr->rts_tries = 0;
+
+	if (unlikely(p54_assign_address(dev, skb, hdr, len))) {
+		kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
 }
 
 int p54_read_eeprom(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr = NULL;
+	struct p54_hdr *hdr = NULL;
 	struct p54_eeprom_lm86 *eeprom_hdr;
+	struct sk_buff *skb;
 	size_t eeprom_size = 0x2020, offset = 0, blocksize;
 	int ret = -ENOMEM;
 	void *eeprom = NULL;
 
-	hdr = (struct p54_control_hdr *)kzalloc(sizeof(*hdr) +
-		sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN, GFP_KERNEL);
-	if (!hdr)
+	skb = p54_alloc_skb(dev, 0x8000, sizeof(*hdr) + sizeof(*eeprom_hdr) +
+			    EEPROM_READBACK_LEN,
+			    P54_CONTROL_TYPE_EEPROM_READBACK, GFP_KERNEL);
+	if (!skb)
 		goto free;
-
 	priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
 	if (!priv->eeprom)
 		goto free;
-
 	eeprom = kzalloc(eeprom_size, GFP_KERNEL);
 	if (!eeprom)
 		goto free;
 
-	hdr->magic1 = cpu_to_le16(0x8000);
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
-	hdr->retry1 = hdr->retry2 = 0;
-	eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+	eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
+		     sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN);
 
 	while (eeprom_size) {
 		blocksize = min(eeprom_size, (size_t)EEPROM_READBACK_LEN);
-		hdr->len = cpu_to_le16(blocksize + sizeof(*eeprom_hdr));
 		eeprom_hdr->offset = cpu_to_le16(offset);
 		eeprom_hdr->len = cpu_to_le16(blocksize);
-		p54_assign_address(dev, NULL, hdr, le16_to_cpu(hdr->len) +
-				   sizeof(*hdr));
-		priv->tx(dev, hdr, le16_to_cpu(hdr->len) + sizeof(*hdr), 0);
+		priv->tx(dev, skb, 0);
 
 		if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
 			printk(KERN_ERR "%s: device does not respond!\n",
@@ -790,165 +957,336 @@
 free:
 	kfree(priv->eeprom);
 	priv->eeprom = NULL;
-	kfree(hdr);
+	p54_free_skb(dev, skb);
 	kfree(eeprom);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(p54_read_eeprom);
 
+static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
+		bool set)
+{
+	struct p54_common *priv = dev->priv;
+	struct sk_buff *skb;
+	struct p54_tim *tim;
+
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+		      sizeof(struct p54_hdr) + sizeof(*tim),
+		      P54_CONTROL_TYPE_TIM, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
+	tim->count = 1;
+	tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid);
+	priv->tx(dev, skb, 1);
+	return 0;
+}
+
+static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
+{
+	struct p54_common *priv = dev->priv;
+	struct sk_buff *skb;
+	struct p54_sta_unlock *sta;
+
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+		sizeof(struct p54_hdr) + sizeof(*sta),
+		P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
+	memcpy(sta->addr, addr, ETH_ALEN);
+	priv->tx(dev, skb, 1);
+	return 0;
+}
+
+static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry)
+{
+	struct p54_common *priv = dev->priv;
+	struct sk_buff *skb;
+	struct p54_hdr *hdr;
+	struct p54_txcancel *cancel;
+
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+		sizeof(struct p54_hdr) + sizeof(*cancel),
+		P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	hdr = (void *)entry->data;
+	cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
+	cancel->req_id = hdr->req_id;
+	priv->tx(dev, skb, 1);
+	return 0;
+}
+
+static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
+		struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len,
+		u16 *flags, u16 *aid)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct p54_common *priv = dev->priv;
+	int ret = 0;
+
+	if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
+		if (ieee80211_is_beacon(hdr->frame_control)) {
+			*aid = 0;
+			*queue = 0;
+			*extra_len = IEEE80211_MAX_TIM_LEN;
+			*flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
+			return 0;
+		} else if (ieee80211_is_probe_resp(hdr->frame_control)) {
+			*aid = 0;
+			*queue = 2;
+			*flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
+				 P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+			return 0;
+		} else {
+			*queue = 2;
+			ret = 0;
+		}
+	} else {
+		*queue += 4;
+		ret = 1;
+	}
+
+	switch (priv->mode) {
+	case NL80211_IFTYPE_STATION:
+		*aid = 1;
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+		if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+			*aid = 0;
+			*queue = 3;
+			return 0;
+		}
+		if (info->control.sta)
+			*aid = info->control.sta->aid;
+		else
+			*flags = P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+	}
+	return ret;
+}
+
 static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_queue_stats *current_queue;
+	struct ieee80211_tx_queue_stats *current_queue = NULL;
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
-	struct p54_tx_control_allocdata *txhdr;
-	size_t padding, len;
-	u8 rate;
+	struct p54_hdr *hdr;
+	struct p54_tx_data *txhdr;
+	size_t padding, len, tim_len = 0;
+	int i, j, ridx;
+	u16 hdr_flags = 0, aid = 0;
+	u8 rate, queue;
 	u8 cts_rate = 0x20;
+	u8 rc_flags;
+	u8 calculated_tries[4];
+	u8 nrates = 0, nremaining = 8;
 
-	current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4];
-	if (unlikely(current_queue->len > current_queue->limit))
-		return NETDEV_TX_BUSY;
-	current_queue->len++;
-	current_queue->count++;
-	if (current_queue->len == current_queue->limit)
-		ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
+	queue = skb_get_queue_mapping(skb);
+
+	if (p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid)) {
+		current_queue = &priv->tx_stats[queue];
+		if (unlikely(current_queue->len > current_queue->limit))
+			return NETDEV_TX_BUSY;
+		current_queue->len++;
+		current_queue->count++;
+		if (current_queue->len == current_queue->limit)
+			ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
+	}
 
 	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
 	len = skb->len;
 
-	txhdr = (struct p54_tx_control_allocdata *)
-			skb_push(skb, sizeof(*txhdr) + padding);
-	hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
+	if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) {
+		if (info->control.sta)
+			if (p54_sta_unlock(dev, info->control.sta->addr)) {
+				if (current_queue) {
+					current_queue->len--;
+					current_queue->count--;
+				}
+				return NETDEV_TX_BUSY;
+			}
+	}
+
+	txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
+	hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
 
 	if (padding)
-		hdr->magic1 = cpu_to_le16(0x4010);
-	else
-		hdr->magic1 = cpu_to_le16(0x0010);
+		hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
 	hdr->len = cpu_to_le16(len);
-	hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1);
-	hdr->retry1 = hdr->retry2 = info->control.retry_limit;
+	hdr->type = cpu_to_le16(aid);
+	hdr->rts_tries = info->control.rates[0].count;
 
-	/* TODO: add support for alternate retry TX rates */
-	rate = ieee80211_get_tx_rate(dev, info)->hw_value;
-	if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) {
-		rate |= 0x10;
-		cts_rate |= 0x10;
+	/*
+	 * we register the rates in perfect order, and
+	 * RTS/CTS won't happen on 5 GHz
+	 */
+	cts_rate = info->control.rts_cts_rate_idx;
+
+	memset(&txhdr->rateset, 0, sizeof(txhdr->rateset));
+
+	/* see how many rates got used */
+	for (i = 0; i < 4; i++) {
+		if (info->control.rates[i].idx < 0)
+			break;
+		nrates++;
 	}
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
-		rate |= 0x40;
-		cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
-	} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
-		rate |= 0x20;
-		cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
+
+	/* limit tries to 8/nrates per rate */
+	for (i = 0; i < nrates; i++) {
+		/*
+		 * The magic expression here is equivalent to 8/nrates for
+		 * all values that matter, but avoids division and jumps.
+		 * Note that nrates can only take the values 1 through 4.
+		 */
+		calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1,
+						 info->control.rates[i].count);
+		nremaining -= calculated_tries[i];
 	}
-	memset(txhdr->rateset, rate, 8);
+
+	/* if there are tries left, distribute from back to front */
+	for (i = nrates - 1; nremaining > 0 && i >= 0; i--) {
+		int tmp = info->control.rates[i].count - calculated_tries[i];
+
+		if (tmp <= 0)
+			continue;
+		/* RC requested more tries at this rate */
+
+		tmp = min_t(int, tmp, nremaining);
+		calculated_tries[i] += tmp;
+		nremaining -= tmp;
+	}
+
+	ridx = 0;
+	for (i = 0; i < nrates && ridx < 8; i++) {
+		/* we register the rates in perfect order */
+		rate = info->control.rates[i].idx;
+		if (info->band == IEEE80211_BAND_5GHZ)
+			rate += 4;
+
+		/* store the count we actually calculated for TX status */
+		info->control.rates[i].count = calculated_tries[i];
+
+		rc_flags = info->control.rates[i].flags;
+		if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) {
+			rate |= 0x10;
+			cts_rate |= 0x10;
+		}
+		if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
+			rate |= 0x40;
+		else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+			rate |= 0x20;
+		for (j = 0; j < calculated_tries[i] && ridx < 8; j++) {
+			txhdr->rateset[ridx] = rate;
+			ridx++;
+		}
+	}
+
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+		hdr_flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
+
+	/* TODO: enable bursting */
+	hdr->flags = cpu_to_le16(hdr_flags);
+	hdr->tries = ridx;
+	txhdr->crypt_offset = 0;
+	txhdr->rts_rate_idx = 0;
 	txhdr->key_type = 0;
 	txhdr->key_len = 0;
-	txhdr->hw_queue = skb_get_queue_mapping(skb) + 4;
+	txhdr->hw_queue = queue;
+	txhdr->backlog = 32;
+	memset(txhdr->durations, 0, sizeof(txhdr->durations));
 	txhdr->tx_antenna = (info->antenna_sel_tx == 0) ?
 		2 : info->antenna_sel_tx - 1;
 	txhdr->output_power = priv->output_power;
-	txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
-			  0 : cts_rate;
+	txhdr->cts_rate = cts_rate;
 	if (padding)
 		txhdr->align[0] = padding;
 
-	/* FIXME: The sequence that follows is needed for this driver to
-	 * work with mac80211 since "mac80211: fix TX sequence numbers".
-	 * As with the temporary code in rt2x00, changes will be needed
-	 * to get proper sequence numbers on beacons. In addition, this
-	 * patch places the sequence number in the hardware state, which
-	 * limits us to a single virtual state.
-	 */
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-			priv->seqno += 0x10;
-		ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
-	}
 	/* modifies skb->cb and with it info, so must be last! */
-	p54_assign_address(dev, skb, hdr, skb->len);
-
-	priv->tx(dev, hdr, skb->len, 0);
-	return 0;
-}
-
-static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
-			  const u8 *bssid)
-{
-	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_filter *filter;
-	size_t data_len;
-
-	hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
-		      priv->tx_hdr_len, GFP_ATOMIC);
-	if (!hdr)
-		return -ENOMEM;
-
-	hdr = (void *)hdr + priv->tx_hdr_len;
-
-	filter = (struct p54_tx_control_filter *) hdr->data;
-	hdr->magic1 = cpu_to_le16(0x8001);
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
-
-	priv->filter_type = filter->filter_type = cpu_to_le16(filter_type);
-	memcpy(filter->mac_addr, priv->mac_addr, ETH_ALEN);
-	if (!bssid)
-		memset(filter->bssid, ~0, ETH_ALEN);
-	else
-		memcpy(filter->bssid, bssid, ETH_ALEN);
-
-	filter->rx_antenna = priv->rx_antenna;
-
-	if (priv->fw_var < 0x500) {
-		data_len = P54_TX_CONTROL_FILTER_V1_LEN;
-		filter->v1.basic_rate_mask = cpu_to_le32(0x15F);
-		filter->v1.rx_addr = cpu_to_le32(priv->rx_end);
-		filter->v1.max_rx = cpu_to_le16(priv->rx_mtu);
-		filter->v1.rxhw = cpu_to_le16(priv->rxhw);
-		filter->v1.wakeup_timer = cpu_to_le16(500);
-	} else {
-		data_len = P54_TX_CONTROL_FILTER_V2_LEN;
-		filter->v2.rx_addr = cpu_to_le32(priv->rx_end);
-		filter->v2.max_rx = cpu_to_le16(priv->rx_mtu);
-		filter->v2.rxhw = cpu_to_le16(priv->rxhw);
-		filter->v2.timer = cpu_to_le16(1000);
+	if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) {
+		skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
+		if (current_queue) {
+			current_queue->len--;
+			current_queue->count--;
+		}
+		return NETDEV_TX_BUSY;
 	}
-
-	hdr->len = cpu_to_le16(data_len);
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
-	priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+	priv->tx(dev, skb, 0);
 	return 0;
 }
 
-static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
+static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_channel *chan;
-	unsigned int i;
-	size_t data_len;
-	void *entry;
+	struct sk_buff *skb;
+	struct p54_setup_mac *setup;
 
-	hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
-		      priv->tx_hdr_len, GFP_KERNEL);
-	if (!hdr)
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup) +
+			    sizeof(struct p54_hdr), P54_CONTROL_TYPE_SETUP,
+			    GFP_ATOMIC);
+	if (!skb)
 		return -ENOMEM;
 
-	hdr = (void *)hdr + priv->tx_hdr_len;
+	setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
+	priv->mac_mode = mode;
+	setup->mac_mode = cpu_to_le16(mode);
+	memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
+	if (!bssid)
+		memset(setup->bssid, ~0, ETH_ALEN);
+	else
+		memcpy(setup->bssid, bssid, ETH_ALEN);
+	setup->rx_antenna = priv->rx_antenna;
+	setup->rx_align = 0;
+	if (priv->fw_var < 0x500) {
+		setup->v1.basic_rate_mask = cpu_to_le32(0x15f);
+		memset(setup->v1.rts_rates, 0, 8);
+		setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
+		setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
+		setup->v1.rxhw = cpu_to_le16(priv->rxhw);
+		setup->v1.wakeup_timer = cpu_to_le16(500);
+		setup->v1.unalloc0 = cpu_to_le16(0);
+	} else {
+		setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
+		setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
+		setup->v2.rxhw = cpu_to_le16(priv->rxhw);
+		setup->v2.timer = cpu_to_le16(1000);
+		setup->v2.truncate = cpu_to_le16(48896);
+		setup->v2.basic_rate_mask = cpu_to_le32(0x15f);
+		setup->v2.sbss_offset = 0;
+		setup->v2.mcast_window = 0;
+		setup->v2.rx_rssi_threshold = 0;
+		setup->v2.rx_ed_threshold = 0;
+		setup->v2.ref_clock = cpu_to_le32(644245094);
+		setup->v2.lpf_bandwidth = cpu_to_le16(65535);
+		setup->v2.osc_start_delay = cpu_to_le16(65535);
+	}
+	priv->tx(dev, skb, 1);
+	return 0;
+}
 
-	chan = (struct p54_tx_control_channel *) hdr->data;
+static int p54_set_freq(struct ieee80211_hw *dev, u16 frequency)
+{
+	struct p54_common *priv = dev->priv;
+	struct sk_buff *skb;
+	struct p54_scan *chan;
+	unsigned int i;
+	void *entry;
+	__le16 freq = cpu_to_le16(frequency);
 
-	hdr->magic1 = cpu_to_le16(0x8001);
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) +
+			    sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN,
+			    GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
 
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
-
-	chan->flags = cpu_to_le16(0x1);
+	chan = (struct p54_scan *) skb_put(skb, sizeof(*chan));
+	memset(chan->padding1, 0, sizeof(chan->padding1));
+	chan->mode = cpu_to_le16(P54_SCAN_EXIT);
 	chan->dwell = cpu_to_le16(0x0);
 
 	for (i = 0; i < priv->iq_autocal_len; i++) {
@@ -990,61 +1328,50 @@
 		}
 
 		entry += sizeof(__le16);
-		chan->pa_points_per_curve =
-			min(priv->curve_data->points_per_channel, (u8) 8);
-
-		memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
-		       chan->pa_points_per_curve);
+		chan->pa_points_per_curve = 8;
+		memset(chan->curve_data, 0, sizeof(*chan->curve_data));
+		memcpy(chan->curve_data, entry,
+		       sizeof(struct p54_pa_curve_data_sample) *
+		       min((u8)8, priv->curve_data->points_per_channel));
 		break;
 	}
 
 	if (priv->fw_var < 0x500) {
-		data_len = P54_TX_CONTROL_CHANNEL_V1_LEN;
 		chan->v1.rssical_mul = cpu_to_le16(130);
 		chan->v1.rssical_add = cpu_to_le16(0xfe70);
 	} else {
-		data_len = P54_TX_CONTROL_CHANNEL_V2_LEN;
 		chan->v2.rssical_mul = cpu_to_le16(130);
 		chan->v2.rssical_add = cpu_to_le16(0xfe70);
 		chan->v2.basic_rate_mask = cpu_to_le32(0x15f);
+		memset(chan->v2.rts_rates, 0, 8);
 	}
-
-	hdr->len = cpu_to_le16(data_len);
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
-	priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+	priv->tx(dev, skb, 1);
 	return 0;
 
  err:
 	printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
-	kfree(hdr);
+	kfree_skb(skb);
 	return -EINVAL;
 }
 
 static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_led *led;
+	struct sk_buff *skb;
+	struct p54_led *led;
 
-	hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
-		      priv->tx_hdr_len, GFP_KERNEL);
-	if (!hdr)
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led) +
+			sizeof(struct p54_hdr),	P54_CONTROL_TYPE_LED,
+			GFP_ATOMIC);
+	if (!skb)
 		return -ENOMEM;
 
-	hdr = (void *)hdr + priv->tx_hdr_len;
-	hdr->magic1 = cpu_to_le16(0x8001);
-	hdr->len = cpu_to_le16(sizeof(*led));
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led));
-
-	led = (struct p54_tx_control_led *) hdr->data;
+	led = (struct p54_led *)skb_put(skb, sizeof(*led));
 	led->mode = cpu_to_le16(mode);
 	led->led_permanent = cpu_to_le16(link);
 	led->led_temporary = cpu_to_le16(act);
 	led->duration = cpu_to_le16(1000);
-
-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
-
+	priv->tx(dev, skb, 1);
 	return 0;
 }
 
@@ -1056,53 +1383,132 @@
 	queue.txop = cpu_to_le16(_txop);			\
 } while(0)
 
-static void p54_init_vdcf(struct ieee80211_hw *dev)
+static int p54_set_edcf(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_vdcf *vdcf;
+	struct sk_buff *skb;
+	struct p54_edcf *edcf;
 
-	/* all USB V1 adapters need a extra headroom */
-	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
-	hdr->magic1 = cpu_to_le16(0x8001);
-	hdr->len = cpu_to_le16(sizeof(*vdcf));
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
-	hdr->req_id = cpu_to_le32(priv->rx_start);
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf) +
+			sizeof(struct p54_hdr), P54_CONTROL_TYPE_DCFINIT,
+			GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
 
-	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
-
-	P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
-	P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
-	P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
-	P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
+	edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
+	if (priv->use_short_slot) {
+		edcf->slottime = 9;
+		edcf->sifs = 0x10;
+		edcf->eofpad = 0x00;
+	} else {
+		edcf->slottime = 20;
+		edcf->sifs = 0x0a;
+		edcf->eofpad = 0x06;
+	}
+	/* (see prism54/isl_oid.h for further details) */
+	edcf->frameburst = cpu_to_le16(0);
+	edcf->round_trip_delay = cpu_to_le16(0);
+	edcf->flags = 0;
+	memset(edcf->mapping, 0, sizeof(edcf->mapping));
+	memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
+	priv->tx(dev, skb, 1);
+	return 0;
 }
 
-static void p54_set_vdcf(struct ieee80211_hw *dev)
+static int p54_init_stats(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_vdcf *vdcf;
 
-	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+	priv->cached_stats = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL,
+			sizeof(struct p54_hdr) + sizeof(struct p54_statistics),
+			P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
+	if (!priv->cached_stats)
+			return -ENOMEM;
 
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf));
+	mod_timer(&priv->stats_timer, jiffies + HZ);
+	return 0;
+}
 
-	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+static int p54_beacon_tim(struct sk_buff *skb)
+{
+	/*
+	 * the good excuse for this mess is ... the firmware.
+	 * The dummy TIM MUST be at the end of the beacon frame,
+	 * because it'll be overwritten!
+	 */
 
-	if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-		vdcf->slottime = 9;
-		vdcf->magic1 = 0x10;
-		vdcf->magic2 = 0x00;
-	} else {
-		vdcf->slottime = 20;
-		vdcf->magic1 = 0x0a;
-		vdcf->magic2 = 0x06;
+	struct ieee80211_mgmt *mgmt = (void *)skb->data;
+	u8 *pos, *end;
+
+	if (skb->len <= sizeof(mgmt)) {
+		printk(KERN_ERR "p54: beacon is too short!\n");
+		return -EINVAL;
 	}
 
-	/* (see prism54/isl_oid.h for further details) */
-	vdcf->frameburst = cpu_to_le16(0);
+	pos = (u8 *)mgmt->u.beacon.variable;
+	end = skb->data + skb->len;
+	while (pos < end) {
+		if (pos + 2 + pos[1] > end) {
+			printk(KERN_ERR "p54: parsing beacon failed\n");
+			return -EINVAL;
+		}
 
-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
+		if (pos[0] == WLAN_EID_TIM) {
+			u8 dtim_len = pos[1];
+			u8 dtim_period = pos[3];
+			u8 *next = pos + 2 + dtim_len;
+
+			if (dtim_len < 3) {
+				printk(KERN_ERR "p54: invalid dtim len!\n");
+				return -EINVAL;
+			}
+			memmove(pos, next, end - next);
+
+			if (dtim_len > 3)
+				skb_trim(skb, skb->len - (dtim_len - 3));
+
+			pos = end - (dtim_len + 2);
+
+			/* add the dummy at the end */
+			pos[0] = WLAN_EID_TIM;
+			pos[1] = 3;
+			pos[2] = 0;
+			pos[3] = dtim_period;
+			pos[4] = 0;
+			return 0;
+		}
+		pos += 2 + pos[1];
+	}
+	return 0;
+}
+
+static int p54_beacon_update(struct ieee80211_hw *dev,
+			struct ieee80211_vif *vif)
+{
+	struct p54_common *priv = dev->priv;
+	struct sk_buff *beacon;
+	int ret;
+
+	if (priv->cached_beacon) {
+		p54_tx_cancel(dev, priv->cached_beacon);
+		/* wait for the last beacon the be freed */
+		msleep(10);
+	}
+
+	beacon = ieee80211_beacon_get(dev, vif);
+	if (!beacon)
+		return -ENOMEM;
+	ret = p54_beacon_tim(beacon);
+	if (ret)
+		return ret;
+	ret = p54_tx(dev, beacon);
+	if (ret)
+		return ret;
+	priv->cached_beacon = beacon;
+	priv->tsf_high32 = 0;
+	priv->tsf_low32 = 0;
+
+	return 0;
 }
 
 static int p54_start(struct ieee80211_hw *dev)
@@ -1110,34 +1516,19 @@
 	struct p54_common *priv = dev->priv;
 	int err;
 
-	if (!priv->cached_vdcf) {
-		priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf)+
-			priv->tx_hdr_len + sizeof(struct p54_control_hdr),
-			GFP_KERNEL);
-
-		if (!priv->cached_vdcf)
-			return -ENOMEM;
-	}
-
-	if (!priv->cached_stats) {
-		priv->cached_stats = kzalloc(sizeof(struct p54_statistics) +
-			priv->tx_hdr_len + sizeof(struct p54_control_hdr),
-			GFP_KERNEL);
-
-		if (!priv->cached_stats) {
-			kfree(priv->cached_vdcf);
-			priv->cached_vdcf = NULL;
-			return -ENOMEM;
-		}
-	}
-
+	mutex_lock(&priv->conf_mutex);
 	err = priv->open(dev);
 	if (!err)
 		priv->mode = NL80211_IFTYPE_MONITOR;
+	P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
+	P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
+	P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
+	P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
+	err = p54_set_edcf(dev);
+	if (!err)
+		err = p54_init_stats(dev);
 
-	p54_init_vdcf(dev);
-
-	mod_timer(&priv->stats_timer, jiffies + HZ);
+	mutex_unlock(&priv->conf_mutex);
 	return err;
 }
 
@@ -1146,12 +1537,22 @@
 	struct p54_common *priv = dev->priv;
 	struct sk_buff *skb;
 
+	mutex_lock(&priv->conf_mutex);
 	del_timer(&priv->stats_timer);
+	p54_free_skb(dev, priv->cached_stats);
+	priv->cached_stats = NULL;
+	if (priv->cached_beacon)
+		p54_tx_cancel(dev, priv->cached_beacon);
+
 	while ((skb = skb_dequeue(&priv->tx_queue)))
 		kfree_skb(skb);
+
+	kfree(priv->cached_beacon);
+	priv->cached_beacon = NULL;
 	priv->stop(dev);
 	priv->tsf_high32 = priv->tsf_low32 = 0;
 	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+	mutex_unlock(&priv->conf_mutex);
 }
 
 static int p54_add_interface(struct ieee80211_hw *dev,
@@ -1159,24 +1560,36 @@
 {
 	struct p54_common *priv = dev->priv;
 
-	if (priv->mode != NL80211_IFTYPE_MONITOR)
+	mutex_lock(&priv->conf_mutex);
+	if (priv->mode != NL80211_IFTYPE_MONITOR) {
+		mutex_unlock(&priv->conf_mutex);
 		return -EOPNOTSUPP;
+	}
 
 	switch (conf->type) {
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
 		priv->mode = conf->type;
 		break;
 	default:
+		mutex_unlock(&priv->conf_mutex);
 		return -EOPNOTSUPP;
 	}
 
 	memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
 
-	p54_set_filter(dev, 0, NULL);
+	p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL);
 
 	switch (conf->type) {
 	case NL80211_IFTYPE_STATION:
-		p54_set_filter(dev, 1, NULL);
+		p54_setup_mac(dev, P54_FILTER_TYPE_STATION, NULL);
+		break;
+	case NL80211_IFTYPE_AP:
+		p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL);
 		break;
 	default:
 		BUG();	/* impossible */
@@ -1185,6 +1598,7 @@
 
 	p54_set_leds(dev, 1, 0, 0);
 
+	mutex_unlock(&priv->conf_mutex);
 	return 0;
 }
 
@@ -1192,22 +1606,28 @@
 				 struct ieee80211_if_init_conf *conf)
 {
 	struct p54_common *priv = dev->priv;
+
+	mutex_lock(&priv->conf_mutex);
+	if (priv->cached_beacon)
+		p54_tx_cancel(dev, priv->cached_beacon);
+	p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL);
 	priv->mode = NL80211_IFTYPE_MONITOR;
 	memset(priv->mac_addr, 0, ETH_ALEN);
-	p54_set_filter(dev, 0, NULL);
+	mutex_unlock(&priv->conf_mutex);
 }
 
-static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int p54_config(struct ieee80211_hw *dev, u32 changed)
 {
 	int ret;
 	struct p54_common *priv = dev->priv;
+	struct ieee80211_conf *conf = &dev->conf;
 
 	mutex_lock(&priv->conf_mutex);
-	priv->rx_antenna = (conf->antenna_sel_rx == 0) ?
-		2 : conf->antenna_sel_tx - 1;
+	priv->rx_antenna = 2; /* automatic */
 	priv->output_power = conf->power_level << 2;
-	ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
-	p54_set_vdcf(dev);
+	ret = p54_set_freq(dev, conf->channel->center_freq);
+	if (!ret)
+		ret = p54_set_edcf(dev);
 	mutex_unlock(&priv->conf_mutex);
 	return ret;
 }
@@ -1217,13 +1637,41 @@
 				struct ieee80211_if_conf *conf)
 {
 	struct p54_common *priv = dev->priv;
+	int ret = 0;
 
 	mutex_lock(&priv->conf_mutex);
-	p54_set_filter(dev, 0, conf->bssid);
-	p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
-	memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+	switch (priv->mode) {
+	case NL80211_IFTYPE_STATION:
+		ret = p54_setup_mac(dev, P54_FILTER_TYPE_STATION, conf->bssid);
+		if (ret)
+			goto out;
+		ret = p54_set_leds(dev, 1,
+				   !is_multicast_ether_addr(conf->bssid), 0);
+		if (ret)
+			goto out;
+		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+		ret = p54_set_freq(dev, dev->conf.channel->center_freq);
+		if (ret)
+			goto out;
+		ret = p54_setup_mac(dev, priv->mac_mode, priv->bssid);
+		if (ret)
+			goto out;
+		if (conf->changed & IEEE80211_IFCC_BEACON) {
+			ret = p54_beacon_update(dev, vif);
+			if (ret)
+				goto out;
+			ret = p54_set_edcf(dev);
+			if (ret)
+				goto out;
+		}
+	}
+out:
 	mutex_unlock(&priv->conf_mutex);
-	return 0;
+	return ret;
 }
 
 static void p54_configure_filter(struct ieee80211_hw *dev,
@@ -1241,20 +1689,16 @@
 
 	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
-			p54_set_filter(dev, le16_to_cpu(priv->filter_type),
-				 NULL);
+			p54_setup_mac(dev, priv->mac_mode, NULL);
 		else
-			p54_set_filter(dev, le16_to_cpu(priv->filter_type),
-				 priv->bssid);
+			p54_setup_mac(dev, priv->mac_mode, priv->bssid);
 	}
 
 	if (changed_flags & FIF_PROMISC_IN_BSS) {
 		if (*total_flags & FIF_PROMISC_IN_BSS)
-			p54_set_filter(dev, le16_to_cpu(priv->filter_type) |
-				0x8, NULL);
+			p54_setup_mac(dev, priv->mac_mode | 0x8, NULL);
 		else
-			p54_set_filter(dev, le16_to_cpu(priv->filter_type) &
-				~0x8, priv->bssid);
+			p54_setup_mac(dev, priv->mac_mode & ~0x8, priv->bssid);
 	}
 }
 
@@ -1262,46 +1706,39 @@
 		       const struct ieee80211_tx_queue_params *params)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_tx_control_vdcf *vdcf;
+	int ret;
 
-	vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
-		((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
-
+	mutex_lock(&priv->conf_mutex);
 	if ((params) && !(queue > 4)) {
-		P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
+		P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
 			params->cw_min, params->cw_max, params->txop);
 	} else
-		return -EINVAL;
-
-	p54_set_vdcf(dev);
-
-	return 0;
+		ret = -EINVAL;
+	if (!ret)
+		ret = p54_set_edcf(dev);
+	mutex_unlock(&priv->conf_mutex);
+	return ret;
 }
 
 static int p54_init_xbow_synth(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_tx_control_xbow_synth *xbow;
+	struct sk_buff *skb;
+	struct p54_xbow_synth *xbow;
 
-	hdr = kzalloc(sizeof(*hdr) + sizeof(*xbow) +
-		      priv->tx_hdr_len, GFP_KERNEL);
-	if (!hdr)
+	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow) +
+			    sizeof(struct p54_hdr),
+			    P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
+			    GFP_KERNEL);
+	if (!skb)
 		return -ENOMEM;
 
-	hdr = (void *)hdr + priv->tx_hdr_len;
-	hdr->magic1 = cpu_to_le16(0x8001);
-	hdr->len = cpu_to_le16(sizeof(*xbow));
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_XBOW_SYNTH_CFG);
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*xbow));
-
-	xbow = (struct p54_tx_control_xbow_synth *) hdr->data;
+	xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
 	xbow->magic1 = cpu_to_le16(0x1);
 	xbow->magic2 = cpu_to_le16(0x2);
 	xbow->freq = cpu_to_le16(5390);
-
-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*xbow), 1);
-
+	memset(xbow->padding, 0, sizeof(xbow->padding));
+	priv->tx(dev, skb, 1);
 	return 0;
 }
 
@@ -1309,18 +1746,10 @@
 {
 	struct ieee80211_hw *dev = (struct ieee80211_hw *) data;
 	struct p54_common *priv = dev->priv;
-	struct p54_control_hdr *hdr;
-	struct p54_statistics *stats;
 
 	BUG_ON(!priv->cached_stats);
 
-	hdr = (void *)priv->cached_stats + priv->tx_hdr_len;
-	hdr->magic1 = cpu_to_le16(0x8000);
-	hdr->len = cpu_to_le16(sizeof(*stats));
-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_STAT_READBACK);
-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*stats));
-
-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*stats), 0);
+	priv->tx(dev, priv->cached_stats, 0);
 }
 
 static int p54_get_stats(struct ieee80211_hw *dev,
@@ -1352,14 +1781,29 @@
 	return 0;
 }
 
+static void p54_bss_info_changed(struct ieee80211_hw *dev,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_bss_conf *info,
+				 u32 changed)
+{
+	struct p54_common *priv = dev->priv;
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		priv->use_short_slot = info->use_short_slot;
+		p54_set_edcf(dev);
+	}
+}
+
 static const struct ieee80211_ops p54_ops = {
 	.tx			= p54_tx,
 	.start			= p54_start,
 	.stop			= p54_stop,
 	.add_interface		= p54_add_interface,
 	.remove_interface	= p54_remove_interface,
+	.set_tim		= p54_set_tim,
 	.config			= p54_config,
 	.config_interface	= p54_config_interface,
+	.bss_info_changed	= p54_bss_info_changed,
 	.configure_filter	= p54_configure_filter,
 	.conf_tx		= p54_conf_tx,
 	.get_stats		= p54_get_stats,
@@ -1378,24 +1822,34 @@
 	priv = dev->priv;
 	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
 	skb_queue_head_init(&priv->tx_queue);
-	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
-		     IEEE80211_HW_RX_INCLUDES_FCS |
+	dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 		     IEEE80211_HW_SIGNAL_DBM |
 		     IEEE80211_HW_NOISE_DBM;
 
-	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION |
+					  NL80211_IFTYPE_ADHOC |
+					  NL80211_IFTYPE_AP);
 
 	dev->channel_change_time = 1000;	/* TODO: find actual value */
-
-	priv->tx_stats[0].limit = 1;
-	priv->tx_stats[1].limit = 1;
-	priv->tx_stats[2].limit = 1;
-	priv->tx_stats[3].limit = 1;
-	priv->tx_stats[4].limit = 5;
+	priv->tx_stats[0].limit = 1;		/* Beacon queue */
+	priv->tx_stats[1].limit = 1;		/* Probe queue for HW scan */
+	priv->tx_stats[2].limit = 3;		/* queue for MLMEs */
+	priv->tx_stats[3].limit = 3;		/* Broadcast / MC queue */
+	priv->tx_stats[4].limit = 5;		/* Data */
 	dev->queues = 1;
 	priv->noise = -94;
-	dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
-				 sizeof(struct p54_tx_control_allocdata);
+	/*
+	 * We support at most 8 tries no matter which rate they're at,
+	 * we cannot support max_rates * max_rate_tries as we set it
+	 * here, but setting it correctly to 4/2 or so would limit us
+	 * artificially if the RC algorithm wants just two rates, so
+	 * let's say 4/7, we'll redistribute it at TX time, see the
+	 * comments there.
+	 */
+	dev->max_rates = 4;
+	dev->max_rate_tries = 7;
+	dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
+				 sizeof(struct p54_tx_data);
 
 	mutex_init(&priv->conf_mutex);
 	init_completion(&priv->eeprom_comp);
@@ -1410,11 +1864,11 @@
 void p54_free_common(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
-	kfree(priv->cached_stats);
+	del_timer(&priv->stats_timer);
+	kfree_skb(priv->cached_stats);
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
-	kfree(priv->cached_vdcf);
 }
 EXPORT_SYMBOL_GPL(p54_free_common);
 
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index 2fa994c..8c8793c 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -7,8 +7,12 @@
  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
  * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
  *
- * Based on the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ *
+ * - LMAC API interface header file for STLC4560 (lmac_longbow.h)
+ *   Copyright (C) 2007 Conexant Systems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,9 +23,24 @@
 	__le32 code;
 	__le32 len;
 	u32 data[10];
-	__le16 rx_mtu;
 } __attribute__((packed));
 
+#define PDR_SYNTH_FRONTEND_MASK		0x0007
+#define PDR_SYNTH_IQ_CAL_MASK		0x0018
+#define PDR_SYNTH_IQ_CAL_PA_DETECTOR	0x0000
+#define PDR_SYNTH_IQ_CAL_DISABLED	0x0008
+#define PDR_SYNTH_IQ_CAL_ZIF		0x0010
+#define PDR_SYNTH_FAA_SWITCH_MASK	0x0020
+#define PDR_SYNTH_FAA_SWITCH_ENABLED	0x0001
+#define PDR_SYNTH_24_GHZ_MASK		0x0040
+#define PDR_SYNTH_24_GHZ_DISABLED	0x0040
+#define PDR_SYNTH_5_GHZ_MASK		0x0080
+#define PDR_SYNTH_5_GHZ_DISABLED	0x0080
+#define PDR_SYNTH_RX_DIV_MASK		0x0100
+#define PDR_SYNTH_RX_DIV_SUPPORTED	0x0100
+#define PDR_SYNTH_TX_DIV_MASK		0x0200
+#define PDR_SYNTH_TX_DIV_SUPPORTED	0x0200
+
 struct bootrec_exp_if {
 	__le16 role;
 	__le16 if_id;
@@ -30,6 +49,13 @@
 	__le16 top_compat;
 } __attribute__((packed));
 
+#define BR_DESC_PRIV_CAP_WEP		BIT(0)
+#define BR_DESC_PRIV_CAP_TKIP		BIT(1)
+#define BR_DESC_PRIV_CAP_MICHAEL	BIT(2)
+#define BR_DESC_PRIV_CAP_CCX_CP		BIT(3)
+#define BR_DESC_PRIV_CAP_CCX_MIC	BIT(4)
+#define BR_DESC_PRIV_CAP_AESCCMP	BIT(5)
+
 struct bootrec_desc {
 	__le16 modes;
 	__le16 flags;
@@ -37,8 +63,15 @@
 	__le32 rx_end;
 	u8 headroom;
 	u8 tailroom;
-	u8 unimportant[6];
+	u8 tx_queues;
+	u8 tx_depth;
+	u8 privacy_caps;
+	u8 rx_keycache_size;
+	u8 time_size;
+	u8 padding;
 	u8 rates[16];
+	u8 padding2[4];
+	__le16 rx_mtu;
 } __attribute__((packed));
 
 #define BR_CODE_MIN			0x80000000
@@ -51,6 +84,34 @@
 #define BR_CODE_END_OF_BRA		0xFF0000FF
 #define LEGACY_BR_CODE_END_OF_BRA	0xFFFFFFFF
 
+#define P54_HDR_FLAG_CONTROL		BIT(15)
+#define P54_HDR_FLAG_CONTROL_OPSET	(BIT(15) + BIT(0))
+
+#define P54_HDR_FLAG_DATA_ALIGN		BIT(14)
+#define P54_HDR_FLAG_DATA_OUT_PROMISC	BIT(0)
+#define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1)
+#define P54_HDR_FLAG_DATA_OUT_SEQNR	BIT(2)
+#define P54_HDR_FLAG_DATA_OUT_BIT3	BIT(3)
+#define P54_HDR_FLAG_DATA_OUT_BURST	BIT(4)
+#define P54_HDR_FLAG_DATA_OUT_NOCANCEL	BIT(5)
+#define P54_HDR_FLAG_DATA_OUT_CLEARTIM	BIT(6)
+#define P54_HDR_FLAG_DATA_OUT_HITCHHIKE	BIT(7)
+#define P54_HDR_FLAG_DATA_OUT_COMPRESS	BIT(8)
+#define P54_HDR_FLAG_DATA_OUT_CONCAT	BIT(9)
+#define P54_HDR_FLAG_DATA_OUT_PCS_ACCEPT BIT(10)
+#define P54_HDR_FLAG_DATA_OUT_WAITEOSP	BIT(11)
+
+#define P54_HDR_FLAG_DATA_IN_FCS_GOOD	BIT(0)
+#define P54_HDR_FLAG_DATA_IN_MATCH_MAC	BIT(1)
+#define P54_HDR_FLAG_DATA_IN_MCBC	BIT(2)
+#define P54_HDR_FLAG_DATA_IN_BEACON	BIT(3)
+#define P54_HDR_FLAG_DATA_IN_MATCH_BSS	BIT(4)
+#define P54_HDR_FLAG_DATA_IN_BCAST_BSS	BIT(5)
+#define P54_HDR_FLAG_DATA_IN_DATA	BIT(6)
+#define P54_HDR_FLAG_DATA_IN_TRUNCATED	BIT(7)
+#define P54_HDR_FLAG_DATA_IN_BIT8	BIT(8)
+#define P54_HDR_FLAG_DATA_IN_TRANSPARENT BIT(9)
+
 /* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
 
 struct pda_entry {
@@ -165,6 +226,19 @@
 #define PDR_BASEBAND_REGISTERS			0x8000
 #define PDR_PER_CHANNEL_BASEBAND_REGISTERS	0x8001
 
+/* PDR definitions for default country & country list */
+#define PDR_COUNTRY_CERT_CODE		0x80
+#define PDR_COUNTRY_CERT_CODE_REAL	0x00
+#define PDR_COUNTRY_CERT_CODE_PSEUDO	0x80
+#define PDR_COUNTRY_CERT_BAND		0x40
+#define PDR_COUNTRY_CERT_BAND_2GHZ	0x00
+#define PDR_COUNTRY_CERT_BAND_5GHZ	0x40
+#define PDR_COUNTRY_CERT_IODOOR		0x30
+#define PDR_COUNTRY_CERT_IODOOR_BOTH	0x00
+#define PDR_COUNTRY_CERT_IODOOR_INDOOR	0x20
+#define PDR_COUNTRY_CERT_IODOOR_OUTDOOR	0x30
+#define PDR_COUNTRY_CERT_INDEX		0x0F
+
 /* stored in skb->cb */
 struct memrecord {
 	u32 start_addr;
@@ -177,36 +251,91 @@
 	u8 data[0];
 } __attribute__ ((packed));
 
-struct p54_rx_hdr {
-	__le16 magic;
+enum p54_rx_decrypt_status {
+	P54_DECRYPT_NONE = 0,
+	P54_DECRYPT_OK,
+	P54_DECRYPT_NOKEY,
+	P54_DECRYPT_NOMICHAEL,
+	P54_DECRYPT_NOCKIPMIC,
+	P54_DECRYPT_FAIL_WEP,
+	P54_DECRYPT_FAIL_TKIP,
+	P54_DECRYPT_FAIL_MICAHEL,
+	P54_DECRYPT_FAIL_CKIPKP,
+	P54_DECRYPT_FAIL_CKIPMIC,
+	P54_DECRYPT_FAIL_AESCCMP
+};
+
+struct p54_rx_data {
+	__le16 flags;
 	__le16 len;
 	__le16 freq;
 	u8 antenna;
 	u8 rate;
 	u8 rssi;
 	u8 quality;
-	u16 unknown2;
+	u8 decrypt_status;
+	u8 rssi_raw;
 	__le32 tsf32;
 	__le32 unalloc0;
 	u8 align[0];
 } __attribute__ ((packed));
 
-struct p54_frame_sent_hdr {
-	u8 status;
-	u8 retries;
-	__le16 ack_rssi;
-	__le16 seq;
-	u16 rate;
+enum p54_trap_type {
+	P54_TRAP_SCAN = 0,
+	P54_TRAP_TIMER,
+	P54_TRAP_BEACON_TX,
+	P54_TRAP_FAA_RADIO_ON,
+	P54_TRAP_FAA_RADIO_OFF,
+	P54_TRAP_RADAR,
+	P54_TRAP_NO_BEACON,
+	P54_TRAP_TBTT,
+	P54_TRAP_SCO_ENTER,
+	P54_TRAP_SCO_EXIT
+};
+
+struct p54_trap {
+	__le16 event;
+	__le16 frequency;
 } __attribute__ ((packed));
 
-struct p54_tx_control_allocdata {
+enum p54_frame_sent_status {
+	P54_TX_OK = 0,
+	P54_TX_FAILED,
+	P54_TX_PSM,
+	P54_TX_PSM_CANCELLED
+};
+
+struct p54_frame_sent {
+	u8 status;
+	u8 tries;
+	u8 ack_rssi;
+	u8 quality;
+	__le16 seq;
+	u8 antenna;
+	u8 padding;
+} __attribute__ ((packed));
+
+enum  p54_tx_data_crypt {
+	P54_CRYPTO_NONE = 0,
+	P54_CRYPTO_WEP,
+	P54_CRYPTO_TKIP,
+	P54_CRYPTO_TKIPMICHAEL,
+	P54_CRYPTO_CCX_WEPMIC,
+	P54_CRYPTO_CCX_KPMIC,
+	P54_CRYPTO_CCX_KP,
+	P54_CRYPTO_AESCCMP
+};
+
+struct p54_tx_data {
 	u8 rateset[8];
-	u8 unalloc0[2];
+	u8 rts_rate_idx;
+	u8 crypt_offset;
 	u8 key_type;
 	u8 key_len;
 	u8 key[16];
 	u8 hw_queue;
-	u8 unalloc1[9];
+	u8 backlog;
+	__le16 durations[4];
 	u8 tx_antenna;
 	u8 output_power;
 	u8 cts_rate;
@@ -214,8 +343,18 @@
 	u8 align[0];
 } __attribute__ ((packed));
 
-struct p54_tx_control_filter {
-	__le16 filter_type;
+#define P54_FILTER_TYPE_NONE		0
+#define P54_FILTER_TYPE_STATION		BIT(0)
+#define P54_FILTER_TYPE_IBSS		BIT(1)
+#define P54_FILTER_TYPE_AP		BIT(2)
+#define P54_FILTER_TYPE_TRANSPARENT	BIT(3)
+#define P54_FILTER_TYPE_PROMISCUOUS	BIT(4)
+#define P54_FILTER_TYPE_HIBERNATE	BIT(5)
+#define P54_FILTER_TYPE_NOACK		BIT(6)
+#define P54_FILTER_TYPE_RX_DISABLED	BIT(7)
+
+struct p54_setup_mac {
+	__le16 mac_mode;
 	u8 mac_addr[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
 	u8 rx_antenna;
@@ -235,17 +374,29 @@
 			__le16 max_rx;
 			__le16 rxhw;
 			__le16 timer;
-			__le16 unalloc0;
-			__le32 unalloc1;
+			__le16 truncate;
+			__le32 basic_rate_mask;
+			u8 sbss_offset;
+			u8 mcast_window;
+			u8 rx_rssi_threshold;
+			u8 rx_ed_threshold;
+			__le32 ref_clock;
+			__le16 lpf_bandwidth;
+			__le16 osc_start_delay;
 		} v2 __attribute__ ((packed));
 	} __attribute__ ((packed));
 } __attribute__ ((packed));
 
-#define P54_TX_CONTROL_FILTER_V1_LEN (sizeof(struct p54_tx_control_filter))
-#define P54_TX_CONTROL_FILTER_V2_LEN (sizeof(struct p54_tx_control_filter)-8)
+#define P54_SETUP_V1_LEN 40
+#define P54_SETUP_V2_LEN (sizeof(struct p54_setup_mac))
 
-struct p54_tx_control_channel {
-	__le16 flags;
+#define P54_SCAN_EXIT	BIT(0)
+#define P54_SCAN_TRAP	BIT(1)
+#define P54_SCAN_ACTIVE BIT(2)
+#define P54_SCAN_FILTER BIT(3)
+
+struct p54_scan {
+	__le16 mode;
 	__le16 dwell;
 	u8 padding1[20];
 	struct pda_iq_autocal_entry iq_autocal;
@@ -268,38 +419,32 @@
 
 		struct {
 			__le32 basic_rate_mask;
-			 u8 rts_rates[8];
+			u8 rts_rates[8];
 			__le16 rssical_mul;
 			__le16 rssical_add;
 		} v2 __attribute__ ((packed));
 	} __attribute__ ((packed));
 } __attribute__ ((packed));
 
-#define P54_TX_CONTROL_CHANNEL_V1_LEN (sizeof(struct p54_tx_control_channel)-12)
-#define P54_TX_CONTROL_CHANNEL_V2_LEN (sizeof(struct p54_tx_control_channel))
+#define P54_SCAN_V1_LEN (sizeof(struct p54_scan)-12)
+#define P54_SCAN_V2_LEN (sizeof(struct p54_scan))
 
-struct p54_tx_control_led {
+struct p54_led {
 	__le16 mode;
 	__le16 led_temporary;
 	__le16 led_permanent;
 	__le16 duration;
 } __attribute__ ((packed));
 
-struct p54_tx_vdcf_queues {
-	__le16 aifs;
-	__le16 cwmin;
-	__le16 cwmax;
-	__le16 txop;
-} __attribute__ ((packed));
-
-struct p54_tx_control_vdcf {
-	u8 padding;
+struct p54_edcf {
+	u8 flags;
 	u8 slottime;
-	u8 magic1;
-	u8 magic2;
-	struct p54_tx_vdcf_queues queue[8];
-	u8 pad2[4];
+	u8 sifs;
+	u8 eofpad;
+	struct p54_edcf_queue_param queue[8];
+	u8 mapping[4];
 	__le16 frameburst;
+	__le16 round_trip_delay;
 } __attribute__ ((packed));
 
 struct p54_statistics {
@@ -312,14 +457,103 @@
 	__le32 tsf32;
 	__le32 airtime;
 	__le32 noise;
-	__le32 unkn[10]; /* CCE / CCA / RADAR */
+	__le32 sample_noise[8];
+	__le32 sample_cca;
+	__le32 sample_tx;
 } __attribute__ ((packed));
 
-struct p54_tx_control_xbow_synth {
+struct p54_xbow_synth {
 	__le16 magic1;
 	__le16 magic2;
 	__le16 freq;
 	u32 padding[5];
 } __attribute__ ((packed));
 
+struct p54_timer {
+	__le32 interval;
+} __attribute__ ((packed));
+
+struct p54_keycache {
+	u8 entry;
+	u8 key_id;
+	u8 mac[ETH_ALEN];
+	u8 padding[2];
+	u8 key_type;
+	u8 key_len;
+	u8 key[24];
+} __attribute__ ((packed));
+
+struct p54_burst {
+	u8 flags;
+	u8 queue;
+	u8 backlog;
+	u8 pad;
+	__le16 durations[32];
+} __attribute__ ((packed));
+
+struct p54_psm_interval {
+	__le16 interval;
+	__le16 periods;
+} __attribute__ ((packed));
+
+#define P54_PSM				BIT(0)
+#define P54_PSM_DTIM			BIT(1)
+#define P54_PSM_MCBC			BIT(2)
+#define P54_PSM_CHECKSUM		BIT(3)
+#define P54_PSM_SKIP_MORE_DATA		BIT(4)
+#define P54_PSM_BEACON_TIMEOUT		BIT(5)
+#define P54_PSM_HFOSLEEP		BIT(6)
+#define P54_PSM_AUTOSWITCH_SLEEP	BIT(7)
+#define P54_PSM_LPIT			BIT(8)
+#define P54_PSM_BF_UCAST_SKIP		BIT(9)
+#define P54_PSM_BF_MCAST_SKIP		BIT(10)
+
+struct p54_psm {
+	__le16 mode;
+	__le16 aid;
+	struct p54_psm_interval intervals[4];
+	u8 beacon_rssi_skip_max;
+	u8 rssi_delta_threshold;
+	u8 nr;
+	u8 exclude[1];
+} __attribute__ ((packed));
+
+#define MC_FILTER_ADDRESS_NUM 4
+
+struct p54_group_address_table {
+	__le16 filter_enable;
+	__le16 num_address;
+	u8 mac_list[MC_FILTER_ADDRESS_NUM][ETH_ALEN];
+} __attribute__ ((packed));
+
+struct p54_txcancel {
+	__le32 req_id;
+} __attribute__ ((packed));
+
+struct p54_sta_unlock {
+	u8 addr[ETH_ALEN];
+	u16 padding;
+} __attribute__ ((packed));
+
+#define P54_TIM_CLEAR BIT(15)
+struct p54_tim {
+	u8 count;
+	u8 padding[3];
+	__le16 entry[8];
+} __attribute__ ((packed));
+
+struct p54_cce_quiet {
+	__le32 period;
+} __attribute__ ((packed));
+
+struct p54_bt_balancer {
+	__le16 prio_thresh;
+	__le16 acl_thresh;
+} __attribute__ ((packed));
+
+struct p54_arp_table {
+	__le16 filter_enable;
+	u8 ipv4_addr[4];
+} __attribute__ ((packed));
+
 #endif /* P54COMMON_H */
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 88b3cad..c4a868a 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -28,6 +28,7 @@
 MODULE_DESCRIPTION("Prism54 PCI wireless driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("prism54pci");
+MODULE_FIRMWARE("isl3886pci");
 
 static struct pci_device_id p54p_table[] __devinitdata = {
 	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
@@ -72,11 +73,13 @@
 	P54P_WRITE(ctrl_stat, reg);
 	wmb();
 
-	err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
+	err = request_firmware(&fw_entry, "isl3886pci", &priv->pdev->dev);
 	if (err) {
 		printk(KERN_ERR "%s (p54pci): cannot find firmware "
-		       "(isl3886)\n", pci_name(priv->pdev));
-		return err;
+		       "(isl3886pci)\n", pci_name(priv->pdev));
+		err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
+		if (err)
+			return err;
 	}
 
 	err = p54_parse_firmware(dev, fw_entry);
@@ -235,7 +238,7 @@
 
 	while (i != idx) {
 		desc = &ring[i];
-		kfree(tx_buf[i]);
+		p54_free_skb(dev, tx_buf[i]);
 		tx_buf[i] = NULL;
 
 		pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -306,8 +309,8 @@
 	return reg ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-		    size_t len, int free_on_tx)
+static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+		    int free_on_tx)
 {
 	struct p54p_priv *priv = dev->priv;
 	struct p54p_ring_control *ring_control = priv->ring_control;
@@ -322,18 +325,19 @@
 	idx = le32_to_cpu(ring_control->host_idx[1]);
 	i = idx % ARRAY_SIZE(ring_control->tx_data);
 
-	mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+	mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+				 PCI_DMA_TODEVICE);
 	desc = &ring_control->tx_data[i];
 	desc->host_addr = cpu_to_le32(mapping);
-	desc->device_addr = data->req_id;
-	desc->len = cpu_to_le16(len);
+	desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
+	desc->len = cpu_to_le16(skb->len);
 	desc->flags = 0;
 
 	wmb();
 	ring_control->host_idx[1] = cpu_to_le32(idx + 1);
 
 	if (free_on_tx)
-		priv->tx_buf_data[i] = data;
+		priv->tx_buf_data[i] = skb;
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -342,8 +346,10 @@
 
 	/* FIXME: unlikely to happen because the device usually runs out of
 	   memory before we fill the ring up, but we can make it impossible */
-	if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
+	if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) {
+		p54_free_skb(dev, skb);
 		printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
+	}
 }
 
 static void p54p_stop(struct ieee80211_hw *dev)
@@ -393,7 +399,7 @@
 					 le16_to_cpu(desc->len),
 					 PCI_DMA_TODEVICE);
 
-		kfree(priv->tx_buf_data[i]);
+		p54_free_skb(dev, priv->tx_buf_data[i]);
 		priv->tx_buf_data[i] = NULL;
 	}
 
@@ -405,7 +411,7 @@
 					 le16_to_cpu(desc->len),
 					 PCI_DMA_TODEVICE);
 
-		kfree(priv->tx_buf_mgmt[i]);
+		p54_free_skb(dev, priv->tx_buf_mgmt[i]);
 		priv->tx_buf_mgmt[i] = NULL;
 	}
 
@@ -481,7 +487,6 @@
 	struct ieee80211_hw *dev;
 	unsigned long mem_addr, mem_len;
 	int err;
-	DECLARE_MAC_BUF(mac);
 
 	err = pci_enable_device(pdev);
 	if (err) {
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 75d749b..21ba526 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -28,6 +28,8 @@
 MODULE_DESCRIPTION("Prism54 USB wireless driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("prism54usb");
+MODULE_FIRMWARE("isl3886usb");
+MODULE_FIRMWARE("isl3887usb");
 
 static struct usb_device_id p54u_table[] __devinitdata = {
 	/* Version 1 devices (pci chip + net2280) */
@@ -135,6 +137,16 @@
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
+static void p54u_tx_reuse_skb_cb(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *)
+		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
+
+	skb_pull(skb, priv->common.tx_hdr_len);
+	usb_free_urb(urb);
+}
+
 static void p54u_tx_cb(struct urb *urb)
 {
 	usb_free_urb(urb);
@@ -146,6 +158,16 @@
 	usb_free_urb(urb);
 }
 
+static void p54u_tx_free_skb_cb(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct ieee80211_hw *dev = (struct ieee80211_hw *)
+		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+
+	p54_free_skb(dev, skb);
+	usb_free_urb(urb);
+}
+
 static int p54u_init_urbs(struct ieee80211_hw *dev)
 {
 	struct p54u_priv *priv = dev->priv;
@@ -192,8 +214,8 @@
 	}
 }
 
-static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-			 size_t len, int free_on_tx)
+static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
+			 int free_on_tx)
 {
 	struct p54u_priv *priv = dev->priv;
 	struct urb *addr_urb, *data_urb;
@@ -209,11 +231,14 @@
 	}
 
 	usb_fill_bulk_urb(addr_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
-		sizeof(data->req_id), p54u_tx_cb, dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  &((struct p54_hdr *)skb->data)->req_id, 4,
+			  p54u_tx_cb, dev);
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  skb->data, skb->len,
+			  free_on_tx ? p54u_tx_free_skb_cb :
+				       p54u_tx_reuse_skb_cb, skb);
 
 	usb_submit_urb(addr_urb, GFP_ATOMIC);
 	usb_submit_urb(data_urb, GFP_ATOMIC);
@@ -232,31 +257,35 @@
 	return cpu_to_le32(chk);
 }
 
-static void p54u_tx_lm87(struct ieee80211_hw *dev,
-			 struct p54_control_hdr *data,
-			 size_t len, int free_on_tx)
+static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
+			 int free_on_tx)
 {
 	struct p54u_priv *priv = dev->priv;
 	struct urb *data_urb;
-	struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
+	struct lm87_tx_hdr *hdr;
+	__le32 checksum;
+	__le32 addr = ((struct p54_hdr *)skb->data)->req_id;
 
 	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!data_urb)
 		return;
 
-	hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
-	hdr->device_addr = data->req_id;
+	checksum = p54u_lm87_chksum((u32 *)skb->data, skb->len);
+	hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
+	hdr->chksum = checksum;
+	hdr->device_addr = addr;
 
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
-		len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
-		dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  skb->data, skb->len,
+			  free_on_tx ? p54u_tx_free_skb_cb :
+				       p54u_tx_reuse_skb_cb, skb);
 
 	usb_submit_urb(data_urb, GFP_ATOMIC);
 }
 
-static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-			    size_t len, int free_on_tx)
+static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
+			    int free_on_tx)
 {
 	struct p54u_priv *priv = dev->priv;
 	struct urb *int_urb, *data_urb;
@@ -284,11 +313,10 @@
 	reg->addr = cpu_to_le32(P54U_DEV_BASE);
 	reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
 
-	len += sizeof(*data);
-	hdr = (void *)data - sizeof(*hdr);
+	hdr = (void *)skb_push(skb, sizeof(*hdr));
 	memset(hdr, 0, sizeof(*hdr));
-	hdr->device_addr = data->req_id;
-	hdr->len = cpu_to_le16(len);
+	hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
+	hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_hdr));
 
 	usb_fill_bulk_urb(int_urb, priv->udev,
 		usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
@@ -296,8 +324,10 @@
 	usb_submit_urb(int_urb, GFP_ATOMIC);
 
 	usb_fill_bulk_urb(data_urb, priv->udev,
-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+			  skb->data, skb->len,
+			  free_on_tx ? p54u_tx_free_skb_cb :
+				       p54u_tx_reuse_skb_cb, skb);
 	usb_submit_urb(data_urb, GFP_ATOMIC);
 }
 
@@ -387,10 +417,13 @@
 		goto err_reset;
 	}
 
-	err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
+	err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
 	if (err) {
-		printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
-		goto err_req_fw_failed;
+		printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb)\n");
+		err = request_firmware(&fw_entry, "isl3887usb_bare",
+			&priv->udev->dev);
+		if (err)
+			goto err_req_fw_failed;
 	}
 
 	err = p54_parse_firmware(dev, fw_entry);
@@ -525,11 +558,15 @@
 		return -ENOMEM;
 	}
 
-	err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
+	err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
 	if (err) {
-		printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
-		kfree(buf);
-		return err;
+		printk(KERN_ERR "p54usb: cannot find firmware (isl3886usb)\n");
+		err = request_firmware(&fw_entry, "isl3890usb",
+			&priv->udev->dev);
+		if (err) {
+			kfree(buf);
+			return err;
+			}
 	}
 
 	err = p54_parse_firmware(dev, fw_entry);
@@ -786,7 +823,6 @@
 	struct p54u_priv *priv;
 	int err;
 	unsigned int i, recognized_pipes;
-	DECLARE_MAC_BUF(mac);
 
 	dev = p54_init_common(sizeof(*priv));
 	if (!dev) {
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 16e68f4..57a150a 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -2028,12 +2028,11 @@
 format_event(islpci_private *priv, char *dest, const char *str,
 	     const struct obj_mlme *mlme, u16 *length, int error)
 {
-	DECLARE_MAC_BUF(mac);
 	int n = snprintf(dest, IW_CUSTOM_MAX,
-			 "%s %s %s %s (%2.2X)",
+			 "%s %s %pM %s (%2.2X)",
 			 str,
 			 ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"),
-			 print_mac(mac, mlme->address),
+			 mlme->address,
 			 (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ")
 			  : ""), mlme->code);
 	BUG_ON(n > IW_CUSTOM_MAX);
@@ -2113,7 +2112,6 @@
 {
 	struct list_head *ptr;
 	struct islpci_bss_wpa_ie *bss = NULL;
-	DECLARE_MAC_BUF(mac);
 
 	if (wpa_ie_len > MAX_WPA_IE_LEN)
 		wpa_ie_len = MAX_WPA_IE_LEN;
@@ -2154,7 +2152,7 @@
 		bss->last_update = jiffies;
 	} else {
 		printk(KERN_DEBUG "Failed to add BSS WPA entry for "
-		       "%s\n", print_mac(mac, bssid));
+		       "%pM\n", bssid);
 	}
 
 	/* expire old entries from WPA list */
@@ -2219,7 +2217,6 @@
 {
 	struct ieee80211_beacon_phdr *hdr;
 	u8 *pos, *end;
-	DECLARE_MAC_BUF(mac);
 
 	if (!priv->wpa)
 		return;
@@ -2230,7 +2227,7 @@
 	while (pos < end) {
 		if (pos + 2 + pos[1] > end) {
 			printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed "
-			       "for %s\n", print_mac(mac, addr));
+			       "for %pM\n", addr);
 			return;
 		}
 		if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
@@ -2269,7 +2266,6 @@
 	size_t len = 0; /* u16, better? */
 	u8 *payload = NULL, *pos = NULL;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	/* I think all trapable objects are listed here.
 	 * Some oids have a EX version. The difference is that they are emitted
@@ -2358,8 +2354,8 @@
 			break;
 
 		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
-		printk(KERN_DEBUG "Authenticate from: address:\t%s\n",
-		       print_mac(mac, mlmeex->address));
+		printk(KERN_DEBUG "Authenticate from: address:\t%pM\n",
+		       mlmeex->address);
 		confirm->id = -1; /* or mlmeex->id ? */
 		confirm->state = 0; /* not used */
 		confirm->code = 0;
@@ -2404,8 +2400,8 @@
 		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
 		if (!wpa_ie_len) {
-			printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",
-			       print_mac(mac, mlmeex->address));
+			printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n",
+			       mlmeex->address);
 			kfree(confirm);
 			break;
 		}
@@ -2441,8 +2437,8 @@
 		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
 		if (!wpa_ie_len) {
-			printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",
-			       print_mac(mac, mlmeex->address));
+			printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n",
+			       mlmeex->address);
 			kfree(confirm);
 			break;
 		}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 1404a57..81b71f0 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -414,7 +414,6 @@
     memreq_t mem;
     struct net_device *dev = (struct net_device *)link->priv;
     ray_dev_t *local = netdev_priv(dev);
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(1, "ray_config(0x%p)\n", link);
 
@@ -485,8 +484,8 @@
     strcpy(local->node.dev_name, dev->name);
     link->dev_node = &local->node;
 
-    printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %s\n",
-       dev->name, dev->irq, print_mac(mac, dev->dev_addr));
+    printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n",
+       dev->name, dev->irq, dev->dev_addr);
 
     return 0;
 
@@ -2285,7 +2284,6 @@
 
     skb->protocol = eth_type_trans(skb,dev);
     netif_rx(skb);
-    dev->last_rx = jiffies;
     local->stats.rx_packets++;
     local->stats.rx_bytes += total_len;
 
@@ -2595,7 +2593,6 @@
     UCHAR *p;
     struct freq_hop_element *pfh;
     UCHAR c[33];
-    DECLARE_MAC_BUF(mac);
 
     link = this_device;
     if (!link)
@@ -2623,8 +2620,7 @@
                    nettype[local->sparm.b5.a_network_type], c);
 
     p = local->bss_id;
-    seq_printf(m, "BSSID                = %s\n",
-                   print_mac(mac, p));
+    seq_printf(m, "BSSID                = %pM\n", p);
 
     seq_printf(m, "Country code         = %d\n",
                    local->sparm.b5.a_curr_country_code);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2b41489..a1eeb48 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -37,11 +37,11 @@
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 #include <linux/if_arp.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/rndis_host.h>
 
@@ -1276,12 +1276,11 @@
 	struct usbnet *usbdev = dev->priv;
 	unsigned char bssid[ETH_ALEN];
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	ret = get_bssid(usbdev, bssid);
 
 	if (ret == 0)
-		devdbg(usbdev, "SIOCGIWAP: %s", print_mac(mac, bssid));
+		devdbg(usbdev, "SIOCGIWAP: %pM", bssid);
 	else
 		devdbg(usbdev, "SIOCGIWAP: <not associated>");
 
@@ -1297,10 +1296,9 @@
 {
 	struct usbnet *usbdev = dev->priv;
 	u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
-	DECLARE_MAC_BUF(mac);
 	int ret;
 
-	devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid));
+	devdbg(usbdev, "SIOCSIWAP: %pM", bssid);
 
 	ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
 
@@ -1654,17 +1652,16 @@
 #ifdef DEBUG
 	struct usbnet *usbdev = dev->priv;
 #endif
-	struct ieee80211_info_element *ie;
+	u8 *ie;
 	char *current_val;
 	int bssid_len, ie_len, i;
 	u32 beacon, atim;
 	struct iw_event iwe;
 	unsigned char sbuf[32];
-	DECLARE_MAC_BUF(mac);
 
 	bssid_len = le32_to_cpu(bssid->length);
 
-	devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
+	devdbg(usbdev, "BSSID %pM", bssid->mac);
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
@@ -1753,20 +1750,20 @@
 	ie_len = min(bssid_len - (int)sizeof(*bssid),
 					(int)le32_to_cpu(bssid->ie_length));
 	ie_len -= sizeof(struct ndis_80211_fixed_ies);
-	while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
-		if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
-				memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
-				ie->id == MFIE_TYPE_RSN) {
+	while (ie_len >= 2 && 2 + ie[1] <= ie_len) {
+		if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 &&
+		     memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) ||
+		    ie[0] == WLAN_EID_RSN) {
 			devdbg(usbdev, "IE: WPA%d",
-					(ie->id == MFIE_TYPE_RSN) ? 2 : 1);
+					(ie[0] == WLAN_EID_RSN) ? 2 : 1);
 			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN);
-			cev = iwe_stream_add_point(info, cev, end_buf, &iwe,
-								(u8 *)ie);
+			/* arbitrary cut-off at 64 */
+			iwe.u.data.length = min(ie[1] + 2, 64);
+			cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie);
 		}
 
-		ie_len -= sizeof(*ie) + ie->len;
-		ie = (struct ieee80211_info_element *)&ie->data[ie->len];
+		ie_len -= 2 + ie[1];
+		ie += 2 + ie[1];
 	}
 
 	return cev;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 08cb9ee..42bd38a 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -188,43 +188,34 @@
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)	( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt2400pci_read_csr(struct rt2x00_dev *rt2x00dev,
-			       const unsigned int word, u32 *data)
-{
-	rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt2400pci_write_csr(struct rt2x00_dev *rt2x00dev,
-				const unsigned int word, u32 data)
-{
-	rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
 static const struct rt2x00debug rt2400pci_rt2x00debug = {
 	.owner	= THIS_MODULE,
 	.csr	= {
-		.read		= rt2400pci_read_csr,
-		.write		= rt2400pci_write_csr,
+		.read		= rt2x00pci_register_read,
+		.write		= rt2x00pci_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= CSR_REG_SIZE / sizeof(u32),
 	},
 	.eeprom	= {
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= EEPROM_SIZE / sizeof(u16),
 	},
 	.bbp	= {
 		.read		= rt2400pci_bbp_read,
 		.write		= rt2400pci_bbp_write,
+		.word_base	= BBP_BASE,
 		.word_size	= sizeof(u8),
 		.word_count	= BBP_SIZE / sizeof(u8),
 	},
 	.rf	= {
 		.read		= rt2x00_rf_read,
 		.write		= rt2400pci_rf_write,
+		.word_base	= RF_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= RF_SIZE / sizeof(u32),
 	},
@@ -396,12 +387,74 @@
 	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
 	rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
 	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+
+	rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+
+	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+	rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+	rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
 }
 
-static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev,
-				     const int basic_rate_mask)
+static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
+				 struct antenna_setup *ant)
 {
-	rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
+	u8 r1;
+	u8 r4;
+
+	/*
+	 * We should never come here because rt2x00lib is supposed
+	 * to catch this and send us the correct antenna explicitely.
+	 */
+	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+	       ant->tx == ANTENNA_SW_DIVERSITY);
+
+	rt2400pci_bbp_read(rt2x00dev, 4, &r4);
+	rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+
+	/*
+	 * Configure the TX antenna.
+	 */
+	switch (ant->tx) {
+	case ANTENNA_HW_DIVERSITY:
+		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
+		break;
+	case ANTENNA_A:
+		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
+		break;
+	case ANTENNA_B:
+	default:
+		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
+		break;
+	}
+
+	/*
+	 * Configure the RX antenna.
+	 */
+	switch (ant->rx) {
+	case ANTENNA_HW_DIVERSITY:
+		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+		break;
+	case ANTENNA_A:
+		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
+		break;
+	case ANTENNA_B:
+	default:
+		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+		break;
+	}
+
+	rt2400pci_bbp_write(rt2x00dev, 4, r4);
+	rt2400pci_bbp_write(rt2x00dev, 1, r1);
 }
 
 static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -460,56 +513,17 @@
 	rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
 }
 
-static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
-				     struct antenna_setup *ant)
+static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00lib_conf *libconf)
 {
-	u8 r1;
-	u8 r4;
+	u32 reg;
 
-	/*
-	 * We should never come here because rt2x00lib is supposed
-	 * to catch this and send us the correct antenna explicitely.
-	 */
-	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-	       ant->tx == ANTENNA_SW_DIVERSITY);
-
-	rt2400pci_bbp_read(rt2x00dev, 4, &r4);
-	rt2400pci_bbp_read(rt2x00dev, 1, &r1);
-
-	/*
-	 * Configure the TX antenna.
-	 */
-	switch (ant->tx) {
-	case ANTENNA_HW_DIVERSITY:
-		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
-		break;
-	case ANTENNA_A:
-		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
-		break;
-	case ANTENNA_B:
-	default:
-		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
-		break;
-	}
-
-	/*
-	 * Configure the RX antenna.
-	 */
-	switch (ant->rx) {
-	case ANTENNA_HW_DIVERSITY:
-		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-		break;
-	case ANTENNA_A:
-		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
-		break;
-	case ANTENNA_B:
-	default:
-		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
-		break;
-	}
-
-	rt2400pci_bbp_write(rt2x00dev, 4, r4);
-	rt2400pci_bbp_write(rt2x00dev, 1, r1);
+	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+	rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+			   libconf->conf->long_frame_max_tx_count);
+	rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+			   libconf->conf->short_frame_max_tx_count);
+	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 }
 
 static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
@@ -517,20 +531,6 @@
 {
 	u32 reg;
 
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
-	rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
-	rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
-	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
-	rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
-	rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
-	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
-
 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
 	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
@@ -548,16 +548,14 @@
 			     struct rt2x00lib_conf *libconf,
 			     const unsigned int flags)
 {
-	if (flags & CONFIG_UPDATE_PHYMODE)
-		rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
-	if (flags & CONFIG_UPDATE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt2400pci_config_channel(rt2x00dev, &libconf->rf);
-	if (flags & CONFIG_UPDATE_TXPOWER)
+	if (flags & IEEE80211_CONF_CHANGE_POWER)
 		rt2400pci_config_txpower(rt2x00dev,
 					 libconf->conf->power_level);
-	if (flags & CONFIG_UPDATE_ANTENNA)
-		rt2400pci_config_antenna(rt2x00dev, &libconf->ant);
-	if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		rt2400pci_config_retry_limit(rt2x00dev, libconf);
+	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
 		rt2400pci_config_duration(rt2x00dev, libconf);
 }
 
@@ -1313,10 +1311,8 @@
 	 */
 	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
-		DECLARE_MAC_BUF(macbuf);
-
 		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1504,20 +1500,6 @@
 /*
  * IEEE80211 stack callback functions.
  */
-static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
-				     u32 short_retry, u32 long_retry)
-{
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_LONG_RETRY, long_retry);
-	rt2x00_set_field32(&reg, CSR11_SHORT_RETRY, short_retry);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
-	return 0;
-}
-
 static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
 			     const struct ieee80211_tx_queue_params *params)
 {
@@ -1576,7 +1558,6 @@
 	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.get_stats		= rt2x00mac_get_stats,
-	.set_retry_limit	= rt2400pci_set_retry_limit,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt2400pci_conf_tx,
 	.get_tx_stats		= rt2x00mac_get_tx_stats,
@@ -1604,6 +1585,7 @@
 	.config_filter		= rt2400pci_config_filter,
 	.config_intf		= rt2400pci_config_intf,
 	.config_erp		= rt2400pci_config_erp,
+	.config_ant		= rt2400pci_config_ant,
 	.config			= rt2400pci_config,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index bbff381..9aefda4 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -46,7 +46,9 @@
 #define CSR_REG_SIZE			0x014c
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
+#define BBP_BASE			0x0000
 #define BBP_SIZE			0x0020
+#define RF_BASE				0x0000
 #define RF_SIZE				0x0010
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ef42cc0..928452f 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -188,43 +188,34 @@
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)	( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt2500pci_read_csr(struct rt2x00_dev *rt2x00dev,
-			       const unsigned int word, u32 *data)
-{
-	rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt2500pci_write_csr(struct rt2x00_dev *rt2x00dev,
-				const unsigned int word, u32 data)
-{
-	rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
 static const struct rt2x00debug rt2500pci_rt2x00debug = {
 	.owner	= THIS_MODULE,
 	.csr	= {
-		.read		= rt2500pci_read_csr,
-		.write		= rt2500pci_write_csr,
+		.read		= rt2x00pci_register_read,
+		.write		= rt2x00pci_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= CSR_REG_SIZE / sizeof(u32),
 	},
 	.eeprom	= {
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= EEPROM_SIZE / sizeof(u16),
 	},
 	.bbp	= {
 		.read		= rt2500pci_bbp_read,
 		.write		= rt2500pci_bbp_write,
+		.word_base	= BBP_BASE,
 		.word_size	= sizeof(u8),
 		.word_count	= BBP_SIZE / sizeof(u8),
 	},
 	.rf	= {
 		.read		= rt2x00_rf_read,
 		.write		= rt2500pci_rf_write,
+		.word_base	= RF_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= RF_SIZE / sizeof(u32),
 	},
@@ -402,12 +393,94 @@
 	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
 	rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
 	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+
+	rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+
+	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+	rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+	rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
 }
 
-static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev,
-				     const int basic_rate_mask)
+static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
+				 struct antenna_setup *ant)
 {
-	rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
+	u32 reg;
+	u8 r14;
+	u8 r2;
+
+	/*
+	 * We should never come here because rt2x00lib is supposed
+	 * to catch this and send us the correct antenna explicitely.
+	 */
+	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+	       ant->tx == ANTENNA_SW_DIVERSITY);
+
+	rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
+	rt2500pci_bbp_read(rt2x00dev, 14, &r14);
+	rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+
+	/*
+	 * Configure the TX antenna.
+	 */
+	switch (ant->tx) {
+	case ANTENNA_A:
+		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
+		rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
+		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
+		break;
+	case ANTENNA_B:
+	default:
+		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+		rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
+		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
+		break;
+	}
+
+	/*
+	 * Configure the RX antenna.
+	 */
+	switch (ant->rx) {
+	case ANTENNA_A:
+		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+		break;
+	case ANTENNA_B:
+	default:
+		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+		break;
+	}
+
+	/*
+	 * RT2525E and RT5222 need to flip TX I/Q
+	 */
+	if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
+	    rt2x00_rf(&rt2x00dev->chip, RF5222)) {
+		rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
+		rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
+		rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
+
+		/*
+		 * RT2525E does not need RX I/Q Flip.
+		 */
+		if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
+			rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
+	} else {
+		rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
+		rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
+	}
+
+	rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
+	rt2500pci_bbp_write(rt2x00dev, 14, r14);
+	rt2500pci_bbp_write(rt2x00dev, 2, r2);
 }
 
 static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -489,76 +562,17 @@
 	rt2500pci_rf_write(rt2x00dev, 3, rf3);
 }
 
-static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
-				     struct antenna_setup *ant)
+static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00lib_conf *libconf)
 {
 	u32 reg;
-	u8 r14;
-	u8 r2;
 
-	/*
-	 * We should never come here because rt2x00lib is supposed
-	 * to catch this and send us the correct antenna explicitely.
-	 */
-	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-	       ant->tx == ANTENNA_SW_DIVERSITY);
-
-	rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
-	rt2500pci_bbp_read(rt2x00dev, 14, &r14);
-	rt2500pci_bbp_read(rt2x00dev, 2, &r2);
-
-	/*
-	 * Configure the TX antenna.
-	 */
-	switch (ant->tx) {
-	case ANTENNA_A:
-		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
-		rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
-		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
-		break;
-	case ANTENNA_B:
-	default:
-		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
-		rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
-		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
-		break;
-	}
-
-	/*
-	 * Configure the RX antenna.
-	 */
-	switch (ant->rx) {
-	case ANTENNA_A:
-		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
-		break;
-	case ANTENNA_B:
-	default:
-		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
-		break;
-	}
-
-	/*
-	 * RT2525E and RT5222 need to flip TX I/Q
-	 */
-	if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF5222)) {
-		rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
-		rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
-		rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
-
-		/*
-		 * RT2525E does not need RX I/Q Flip.
-		 */
-		if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
-			rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
-	} else {
-		rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
-		rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
-	}
-
-	rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
-	rt2500pci_bbp_write(rt2x00dev, 14, r14);
-	rt2500pci_bbp_write(rt2x00dev, 2, r2);
+	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+	rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+			   libconf->conf->long_frame_max_tx_count);
+	rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+			   libconf->conf->short_frame_max_tx_count);
+	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 }
 
 static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
@@ -566,20 +580,6 @@
 {
 	u32 reg;
 
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
-	rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
-	rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
-	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
-	rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
-	rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
-	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
-
 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
 	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
@@ -597,17 +597,16 @@
 			     struct rt2x00lib_conf *libconf,
 			     const unsigned int flags)
 {
-	if (flags & CONFIG_UPDATE_PHYMODE)
-		rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
-	if (flags & CONFIG_UPDATE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt2500pci_config_channel(rt2x00dev, &libconf->rf,
 					 libconf->conf->power_level);
-	if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
 		rt2500pci_config_txpower(rt2x00dev,
 					 libconf->conf->power_level);
-	if (flags & CONFIG_UPDATE_ANTENNA)
-		rt2500pci_config_antenna(rt2x00dev, &libconf->ant);
-	if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		rt2500pci_config_retry_limit(rt2x00dev, libconf);
+	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
 		rt2500pci_config_duration(rt2x00dev, libconf);
 }
 
@@ -1451,11 +1450,8 @@
 	 */
 	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
-		DECLARE_MAC_BUF(macbuf);
-
 		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %s\n",
-		       print_mac(macbuf, mac));
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1830,20 +1826,6 @@
 /*
  * IEEE80211 stack callback functions.
  */
-static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
-				     u32 short_retry, u32 long_retry)
-{
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_LONG_RETRY, long_retry);
-	rt2x00_set_field32(&reg, CSR11_SHORT_RETRY, short_retry);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
-	return 0;
-}
-
 static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1877,7 +1859,6 @@
 	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.get_stats		= rt2x00mac_get_stats,
-	.set_retry_limit	= rt2500pci_set_retry_limit,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt2x00mac_conf_tx,
 	.get_tx_stats		= rt2x00mac_get_tx_stats,
@@ -1905,6 +1886,7 @@
 	.config_filter		= rt2500pci_config_filter,
 	.config_intf		= rt2500pci_config_intf,
 	.config_erp		= rt2500pci_config_erp,
+	.config_ant		= rt2500pci_config_ant,
 	.config			= rt2500pci_config,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
index 8c26bef..e135247 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -57,7 +57,9 @@
 #define CSR_REG_SIZE			0x0174
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0200
+#define BBP_BASE			0x0000
 #define BBP_SIZE			0x0040
+#define RF_BASE				0x0000
 #define RF_SIZE				0x0014
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index d3bf7bb..639d5a2 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -245,43 +245,48 @@
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)	( CSR_REG_BASE + ((__word) * sizeof(u16)) )
-
-static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev,
-			       const unsigned int word, u32 *data)
+static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+				     const unsigned int offset,
+				     u32 *value)
 {
-	rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data);
+	rt2500usb_register_read(rt2x00dev, offset, (u16 *)value);
 }
 
-static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev,
-				const unsigned int word, u32 data)
+static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
+				      const unsigned int offset,
+				      u32 value)
 {
-	rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
+	rt2500usb_register_write(rt2x00dev, offset, value);
 }
 
 static const struct rt2x00debug rt2500usb_rt2x00debug = {
 	.owner	= THIS_MODULE,
 	.csr	= {
-		.read		= rt2500usb_read_csr,
-		.write		= rt2500usb_write_csr,
+		.read		= _rt2500usb_register_read,
+		.write		= _rt2500usb_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= CSR_REG_SIZE / sizeof(u16),
 	},
 	.eeprom	= {
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= EEPROM_SIZE / sizeof(u16),
 	},
 	.bbp	= {
 		.read		= rt2500usb_bbp_read,
 		.write		= rt2500usb_bbp_write,
+		.word_base	= BBP_BASE,
 		.word_size	= sizeof(u8),
 		.word_count	= BBP_SIZE / sizeof(u8),
 	},
 	.rf	= {
 		.read		= rt2x00_rf_read,
 		.write		= rt2500usb_rf_write,
+		.word_base	= RF_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= RF_SIZE / sizeof(u32),
 	},
@@ -423,57 +428,16 @@
 	rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
 			   !!erp->short_preamble);
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+
+	rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
+
+	rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
+	rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
+	rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
 }
 
-static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
-				     const int basic_rate_mask)
-{
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
-}
-
-static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
-				     struct rf_channel *rf, const int txpower)
-{
-	/*
-	 * Set TXpower.
-	 */
-	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-
-	/*
-	 * For RT2525E we should first set the channel to half band higher.
-	 */
-	if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
-		static const u32 vals[] = {
-			0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
-			0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
-			0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
-			0x00000902, 0x00000906
-		};
-
-		rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
-		if (rf->rf4)
-			rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
-	}
-
-	rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
-	rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
-	rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
-	if (rf->rf4)
-		rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
-}
-
-static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-				     const int txpower)
-{
-	u32 rf3;
-
-	rt2x00_rf_read(rt2x00dev, 3, &rf3);
-	rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-	rt2500usb_rf_write(rt2x00dev, 3, rf3);
-}
-
-static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
-				     struct antenna_setup *ant)
+static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
+				 struct antenna_setup *ant)
 {
 	u8 r2;
 	u8 r14;
@@ -555,15 +519,52 @@
 	rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6);
 }
 
+static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
+				     struct rf_channel *rf, const int txpower)
+{
+	/*
+	 * Set TXpower.
+	 */
+	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+
+	/*
+	 * For RT2525E we should first set the channel to half band higher.
+	 */
+	if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
+		static const u32 vals[] = {
+			0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
+			0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
+			0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
+			0x00000902, 0x00000906
+		};
+
+		rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+		if (rf->rf4)
+			rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+	}
+
+	rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
+	if (rf->rf4)
+		rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+				     const int txpower)
+{
+	u32 rf3;
+
+	rt2x00_rf_read(rt2x00dev, 3, &rf3);
+	rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+	rt2500usb_rf_write(rt2x00dev, 3, rf3);
+}
+
 static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
 				      struct rt2x00lib_conf *libconf)
 {
 	u16 reg;
 
-	rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
-	rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
-	rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
-
 	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
 	rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
 			   libconf->conf->beacon_int * 4);
@@ -574,17 +575,14 @@
 			     struct rt2x00lib_conf *libconf,
 			     const unsigned int flags)
 {
-	if (flags & CONFIG_UPDATE_PHYMODE)
-		rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
-	if (flags & CONFIG_UPDATE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt2500usb_config_channel(rt2x00dev, &libconf->rf,
 					 libconf->conf->power_level);
-	if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
 		rt2500usb_config_txpower(rt2x00dev,
 					 libconf->conf->power_level);
-	if (flags & CONFIG_UPDATE_ANTENNA)
-		rt2500usb_config_antenna(rt2x00dev, &libconf->ant);
-	if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
 		rt2500usb_config_duration(rt2x00dev, libconf);
 }
 
@@ -1319,10 +1317,8 @@
 	 */
 	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
-		DECLARE_MAC_BUF(macbuf);
-
 		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1796,6 +1792,7 @@
 	.config_filter		= rt2500usb_config_filter,
 	.config_intf		= rt2500usb_config_intf,
 	.config_erp		= rt2500usb_config_erp,
+	.config_ant		= rt2500usb_config_ant,
 	.config			= rt2500usb_config,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index 89e5ed2..dbb5d689 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -57,7 +57,9 @@
 #define CSR_REG_SIZE			0x0100
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x006a
+#define BBP_BASE			0x0000
 #define BBP_SIZE			0x0060
+#define RF_BASE				0x0000
 #define RF_SIZE				0x0014
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 1359a37..f85eedb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -44,7 +44,7 @@
 /*
  * Module information.
  */
-#define DRV_VERSION	"2.2.1"
+#define DRV_VERSION	"2.2.2"
 #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
 
 /*
@@ -348,13 +348,6 @@
 	spinlock_t lock;
 
 	/*
-	 * BSS configuration. Copied from the structure
-	 * passed to us through the bss_info_changed()
-	 * callback funtion.
-	 */
-	struct ieee80211_bss_conf conf;
-
-	/*
 	 * MAC of the device.
 	 */
 	u8 mac[ETH_ALEN];
@@ -433,18 +426,6 @@
 
 	struct rf_channel rf;
 	struct channel_info channel;
-
-	struct antenna_setup ant;
-
-	enum ieee80211_band band;
-
-	u32 basic_rates;
-	u32 slot_time;
-
-	short sifs;
-	short pifs;
-	short difs;
-	short eifs;
 };
 
 /*
@@ -456,6 +437,15 @@
 
 	int ack_timeout;
 	int ack_consume_time;
+
+	u64 basic_rates;
+
+	int slot_time;
+
+	short sifs;
+	short pifs;
+	short difs;
+	short eifs;
 };
 
 /*
@@ -589,16 +579,11 @@
 
 	void (*config_erp) (struct rt2x00_dev *rt2x00dev,
 			    struct rt2x00lib_erp *erp);
+	void (*config_ant) (struct rt2x00_dev *rt2x00dev,
+			    struct antenna_setup *ant);
 	void (*config) (struct rt2x00_dev *rt2x00dev,
 			struct rt2x00lib_conf *libconf,
-			const unsigned int flags);
-#define CONFIG_UPDATE_PHYMODE		( 1 << 1 )
-#define CONFIG_UPDATE_CHANNEL		( 1 << 2 )
-#define CONFIG_UPDATE_TXPOWER		( 1 << 3 )
-#define CONFIG_UPDATE_ANTENNA		( 1 << 4 )
-#define CONFIG_UPDATE_SLOT_TIME 	( 1 << 5 )
-#define CONFIG_UPDATE_BEACON_INT	( 1 << 6 )
-#define CONFIG_UPDATE_ALL		0xffff
+			const unsigned int changed_flags);
 };
 
 /*
@@ -997,7 +982,7 @@
 			    struct ieee80211_if_init_conf *conf);
 void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
 				struct ieee80211_if_init_conf *conf);
-int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
 int rt2x00mac_config_interface(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_if_conf *conf);
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 4d5e87b..3e4eee3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -86,13 +86,14 @@
 	erp.short_preamble = bss_conf->use_short_preamble;
 	erp.cts_protection = bss_conf->use_cts_prot;
 
-	erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
-	erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
+	erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
+	erp.sifs = SIFS;
+	erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
+	erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
+	erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
 
-	if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
-		erp.ack_timeout += SHORT_DIFS;
-	else
-		erp.ack_timeout += DIFS;
+	erp.ack_timeout = PLCP + erp.difs + get_duration(ACK_SIZE, 10);
+	erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
 
 	if (bss_conf->use_short_preamble) {
 		erp.ack_timeout += SHORT_PREAMBLE;
@@ -102,16 +103,18 @@
 		erp.ack_consume_time += PREAMBLE;
 	}
 
+	erp.basic_rates = bss_conf->basic_rates;
+
 	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
 }
 
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      enum antenna rx, enum antenna tx)
 {
-	struct rt2x00lib_conf libconf;
+	struct antenna_setup ant;
 
-	libconf.ant.rx = rx;
-	libconf.ant.tx = tx;
+	ant.rx = rx;
+	ant.tx = tx;
 
 	if (rx == rt2x00dev->link.ant.active.rx &&
 	    tx == rt2x00dev->link.ant.active.tx)
@@ -129,119 +132,28 @@
 	 * The latter is required since we need to recalibrate the
 	 * noise-sensitivity ratio for the new setup.
 	 */
-	rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
+	rt2x00dev->ops->lib->config_ant(rt2x00dev, &ant);
+
 	rt2x00lib_reset_link_tuner(rt2x00dev);
 	rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
 
-	rt2x00dev->link.ant.active.rx = libconf.ant.rx;
-	rt2x00dev->link.ant.active.tx = libconf.ant.tx;
+	memcpy(&rt2x00dev->link.ant.active, &ant, sizeof(ant));
 
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
 }
 
-static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band)
-{
-	const struct rt2x00_rate *rate;
-	unsigned int i;
-	u32 mask = 0;
-
-	for (i = 0; i < band->n_bitrates; i++) {
-		rate = rt2x00_get_rate(band->bitrates[i].hw_value);
-		if (rate->flags & DEV_RATE_BASIC)
-			mask |= rate->ratemask;
-	}
-
-	return mask;
-}
-
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
-		      struct ieee80211_conf *conf, const int force_config)
+		      struct ieee80211_conf *conf,
+		      unsigned int ieee80211_flags)
 {
 	struct rt2x00lib_conf libconf;
-	struct ieee80211_supported_band *band;
-	struct antenna_setup *default_ant = &rt2x00dev->default_ant;
-	struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
-	int flags = 0;
-	int short_slot_time;
 
-	/*
-	 * In some situations we want to force all configurations
-	 * to be reloaded (When resuming for instance).
-	 */
-	if (force_config) {
-		flags = CONFIG_UPDATE_ALL;
-		goto config;
-	}
-
-	/*
-	 * Check which configuration options have been
-	 * updated and should be send to the device.
-	 */
-	if (rt2x00dev->rx_status.band != conf->channel->band)
-		flags |= CONFIG_UPDATE_PHYMODE;
-	if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
-		flags |= CONFIG_UPDATE_CHANNEL;
-	if (rt2x00dev->tx_power != conf->power_level)
-		flags |= CONFIG_UPDATE_TXPOWER;
-
-	/*
-	 * Determining changes in the antenna setups request several checks:
-	 * antenna_sel_{r,t}x = 0
-	 *    -> Does active_{r,t}x match default_{r,t}x
-	 *    -> Is default_{r,t}x SW_DIVERSITY
-	 * antenna_sel_{r,t}x = 1/2
-	 *    -> Does active_{r,t}x match antenna_sel_{r,t}x
-	 * The reason for not updating the antenna while SW diversity
-	 * should be used is simple: Software diversity means that
-	 * we should switch between the antenna's based on the
-	 * quality. This means that the current antenna is good enough
-	 * to work with untill the link tuner decides that an antenna
-	 * switch should be performed.
-	 */
-	if (!conf->antenna_sel_rx &&
-	    default_ant->rx != ANTENNA_SW_DIVERSITY &&
-	    default_ant->rx != active_ant->rx)
-		flags |= CONFIG_UPDATE_ANTENNA;
-	else if (conf->antenna_sel_rx &&
-		 conf->antenna_sel_rx != active_ant->rx)
-		flags |= CONFIG_UPDATE_ANTENNA;
-	else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
-		flags |= CONFIG_UPDATE_ANTENNA;
-
-	if (!conf->antenna_sel_tx &&
-	    default_ant->tx != ANTENNA_SW_DIVERSITY &&
-	    default_ant->tx != active_ant->tx)
-		flags |= CONFIG_UPDATE_ANTENNA;
-	else if (conf->antenna_sel_tx &&
-		 conf->antenna_sel_tx != active_ant->tx)
-		flags |= CONFIG_UPDATE_ANTENNA;
-	else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
-		flags |= CONFIG_UPDATE_ANTENNA;
-
-	/*
-	 * The following configuration options are never
-	 * stored anywhere and will always be updated.
-	 */
-	flags |= CONFIG_UPDATE_SLOT_TIME;
-	flags |= CONFIG_UPDATE_BEACON_INT;
-
-	/*
-	 * We have determined what options should be updated,
-	 * now precalculate device configuration values depending
-	 * on what configuration options need to be updated.
-	 */
-config:
 	memset(&libconf, 0, sizeof(libconf));
 
-	if (flags & CONFIG_UPDATE_PHYMODE) {
-		band = &rt2x00dev->bands[conf->channel->band];
+	libconf.conf = conf;
 
-		libconf.band = conf->channel->band;
-		libconf.basic_rates = rt2x00lib_get_basic_rates(band);
-	}
-
-	if (flags & CONFIG_UPDATE_CHANNEL) {
+	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		memcpy(&libconf.rf,
 		       &rt2x00dev->spec.channels[conf->channel->hw_value],
 		       sizeof(libconf.rf));
@@ -251,61 +163,21 @@
 		       sizeof(libconf.channel));
 	}
 
-	if (flags & CONFIG_UPDATE_ANTENNA) {
-		if (conf->antenna_sel_rx)
-			libconf.ant.rx = conf->antenna_sel_rx;
-		else if (default_ant->rx != ANTENNA_SW_DIVERSITY)
-			libconf.ant.rx = default_ant->rx;
-		else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
-			libconf.ant.rx = ANTENNA_B;
-		else
-			libconf.ant.rx = active_ant->rx;
-
-		if (conf->antenna_sel_tx)
-			libconf.ant.tx = conf->antenna_sel_tx;
-		else if (default_ant->tx != ANTENNA_SW_DIVERSITY)
-			libconf.ant.tx = default_ant->tx;
-		else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
-			libconf.ant.tx = ANTENNA_B;
-		else
-			libconf.ant.tx = active_ant->tx;
-	}
-
-	if (flags & CONFIG_UPDATE_SLOT_TIME) {
-		short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
-		libconf.slot_time =
-		    short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
-		libconf.sifs = SIFS;
-		libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
-		libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
-		libconf.eifs = short_slot_time ? SHORT_EIFS : EIFS;
-	}
-
-	libconf.conf = conf;
-
 	/*
 	 * Start configuration.
 	 */
-	rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
+	rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
 
 	/*
 	 * Some configuration changes affect the link quality
 	 * which means we need to reset the link tuner.
 	 */
-	if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
+	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt2x00lib_reset_link_tuner(rt2x00dev);
 
-	if (flags & CONFIG_UPDATE_PHYMODE) {
-		rt2x00dev->curr_band = conf->channel->band;
-		rt2x00dev->rx_status.band = conf->channel->band;
-	}
-
-	rt2x00dev->rx_status.freq = conf->channel->center_freq;
+	rt2x00dev->curr_band = conf->channel->band;
 	rt2x00dev->tx_power = conf->power_level;
 
-	if (flags & CONFIG_UPDATE_ANTENNA) {
-		rt2x00dev->link.ant.active.rx = libconf.ant.rx;
-		rt2x00dev->link.ant.active.tx = libconf.ant.tx;
-	}
+	rt2x00dev->rx_status.band = conf->channel->band;
+	rt2x00dev->rx_status.freq = conf->channel->center_freq;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 5cf4c85..54dd100 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -285,7 +285,7 @@
 }
 
 static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
-					        poll_table *wait)
+						poll_table *wait)
 {
 	struct rt2x00debug_intf *intf = file->private_data;
 
@@ -377,7 +377,7 @@
 	if (*offset)
 		return 0;
 
-	data = kzalloc((1 + CIPHER_MAX)* MAX_LINE_LENGTH, GFP_KERNEL);
+	data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -424,16 +424,21 @@
 	const struct rt2x00debug *debug = intf->debug;		\
 	char line[16];						\
 	size_t size;						\
+	unsigned int index = intf->offset_##__name;		\
 	__type value;						\
 								\
 	if (*offset)						\
 		return 0;					\
 								\
-	if (intf->offset_##__name >= debug->__name.word_count)	\
+	if (index >= debug->__name.word_count)			\
 		return -EINVAL;					\
 								\
-	debug->__name.read(intf->rt2x00dev,			\
-			   intf->offset_##__name, &value);	\
+	if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)		\
+		index *= debug->__name.word_size;		\
+								\
+	index += debug->__name.word_base;			\
+								\
+	debug->__name.read(intf->rt2x00dev, index, &value);	\
 								\
 	size = sprintf(line, __format, value);			\
 								\
@@ -454,12 +459,13 @@
 	const struct rt2x00debug *debug = intf->debug;		\
 	char line[16];						\
 	size_t size;						\
+	unsigned int index = intf->offset_##__name;		\
 	__type value;						\
 								\
 	if (*offset)						\
 		return 0;					\
 								\
-	if (intf->offset_##__name >= debug->__name.word_count)	\
+	if (index >= debug->__name.word_count)			\
 		return -EINVAL;					\
 								\
 	if (copy_from_user(line, buf, length))			\
@@ -468,8 +474,12 @@
 	size = strlen(line);					\
 	value = simple_strtoul(line, NULL, 0);			\
 								\
-	debug->__name.write(intf->rt2x00dev,			\
-			    intf->offset_##__name, value);	\
+	if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)		\
+		index *= debug->__name.word_size;		\
+								\
+	index += debug->__name.word_base;			\
+								\
+	debug->__name.write(intf->rt2x00dev, index, value);	\
 								\
 	*offset += size;					\
 	return size;						\
@@ -587,29 +597,29 @@
 	intf->driver_folder =
 	    debugfs_create_dir(intf->rt2x00dev->ops->name,
 			       rt2x00dev->hw->wiphy->debugfsdir);
-	if (IS_ERR(intf->driver_folder))
+	if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
 		goto exit;
 
 	intf->driver_entry =
 	    rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
-	if (IS_ERR(intf->driver_entry))
+	if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
 		goto exit;
 
 	intf->chipset_entry =
 	    rt2x00debug_create_file_chipset("chipset",
 					    intf, &intf->chipset_blob);
-	if (IS_ERR(intf->chipset_entry))
+	if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
 		goto exit;
 
 	intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
 					      intf->driver_folder, intf,
 					      &rt2x00debug_fop_dev_flags);
-	if (IS_ERR(intf->dev_flags))
+	if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
 		goto exit;
 
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
-	if (IS_ERR(intf->register_folder))
+	if (IS_ERR(intf->register_folder) || !intf->register_folder)
 		goto exit;
 
 #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)	\
@@ -619,7 +629,8 @@
 			       S_IRUSR | S_IWUSR,		\
 			       (__intf)->register_folder,	\
 			       &(__intf)->offset_##__name);	\
-	if (IS_ERR((__intf)->__name##_off_entry))		\
+	if (IS_ERR((__intf)->__name##_off_entry)		\
+			|| !(__intf)->__name##_off_entry)	\
 		goto exit;					\
 								\
 	(__intf)->__name##_val_entry =				\
@@ -627,7 +638,8 @@
 				S_IRUSR | S_IWUSR,		\
 				(__intf)->register_folder,	\
 				(__intf), &rt2x00debug_fop_##__name);\
-	if (IS_ERR((__intf)->__name##_val_entry))		\
+	if (IS_ERR((__intf)->__name##_val_entry)		\
+			|| !(__intf)->__name##_val_entry)	\
 		goto exit;					\
 })
 
@@ -640,13 +652,14 @@
 
 	intf->queue_folder =
 	    debugfs_create_dir("queue", intf->driver_folder);
-	if (IS_ERR(intf->queue_folder))
+	if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
 		goto exit;
 
 	intf->queue_frame_dump_entry =
 	    debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
 				intf, &rt2x00debug_fop_queue_dump);
-	if (IS_ERR(intf->queue_frame_dump_entry))
+	if (IS_ERR(intf->queue_frame_dump_entry)
+		|| !intf->queue_frame_dump_entry)
 		goto exit;
 
 	skb_queue_head_init(&intf->frame_dump_skbqueue);
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
index c4ce895..a92104d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
@@ -28,6 +28,16 @@
 
 struct rt2x00_dev;
 
+/**
+ * enum rt2x00debugfs_entry_flags: Flags for debugfs registry entry
+ *
+ * @RT2X00DEBUGFS_OFFSET: rt2x00lib should pass the register offset
+ *	as argument when using the callback function read()/write()
+ */
+enum rt2x00debugfs_entry_flags {
+	RT2X00DEBUGFS_OFFSET	= (1 << 0),
+};
+
 #define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type)		\
 struct reg##__name {						\
 	void (*read)(struct rt2x00_dev *rt2x00dev,		\
@@ -35,6 +45,9 @@
 	void (*write)(struct rt2x00_dev *rt2x00dev,		\
 		      const unsigned int word, __type data);	\
 								\
+	unsigned int flags;					\
+								\
+	unsigned int word_base;					\
 	unsigned int word_size;					\
 	unsigned int word_count;				\
 } __name
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 86840e3..477a944 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -249,11 +249,9 @@
 	rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY;
 	rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY;
 
-	if (rt2x00dev->hw->conf.antenna_sel_rx == 0 &&
-	    rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
 		rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY;
-	if (rt2x00dev->hw->conf.antenna_sel_tx == 0 &&
-	    rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
 		rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY;
 
 	if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) &&
@@ -419,7 +417,7 @@
 	 */
 	spin_lock(&intf->lock);
 
-	memcpy(&conf, &intf->conf, sizeof(conf));
+	memcpy(&conf, &vif->bss_conf, sizeof(conf));
 	delayed_flags = intf->delayed_flags;
 	intf->delayed_flags = 0;
 
@@ -500,7 +498,9 @@
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 	enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
+	u8 rate_idx, rate_flags;
 
 	/*
 	 * Unmap the skb.
@@ -530,14 +530,18 @@
 	rt2x00dev->link.qual.tx_failed +=
 	    test_bit(TXDONE_FAILURE, &txdesc->flags);
 
+	rate_idx = skbdesc->tx_rate_idx;
+	rate_flags = skbdesc->tx_rate_flags;
+
 	/*
 	 * Initialize TX status
 	 */
 	memset(&tx_info->status, 0, sizeof(tx_info->status));
 	tx_info->status.ack_signal = 0;
-	tx_info->status.excessive_retries =
-	    test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags);
-	tx_info->status.retry_count = txdesc->retry;
+	tx_info->status.rates[0].idx = rate_idx;
+	tx_info->status.rates[0].flags = rate_flags;
+	tx_info->status.rates[0].count = txdesc->retry + 1;
+	tx_info->status.rates[1].idx = -1; /* terminate */
 
 	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 		if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
@@ -546,7 +550,7 @@
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
 	}
 
-	if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+	if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
 			rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
 		else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
@@ -1052,10 +1056,16 @@
 	 */
 	rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
 
-	rt2x00dev->hw->wiphy->interface_modes =
-	    BIT(NL80211_IFTYPE_AP) |
-	    BIT(NL80211_IFTYPE_STATION) |
-	    BIT(NL80211_IFTYPE_ADHOC);
+	/*
+	 * Determine which operating modes are supported, all modes
+	 * which require beaconing, depend on the availability of
+	 * beacon entries.
+	 */
+	rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	if (rt2x00dev->ops->bcn->entry_num > 0)
+		rt2x00dev->hw->wiphy->interface_modes |=
+		    BIT(NL80211_IFTYPE_ADHOC) |
+		    BIT(NL80211_IFTYPE_AP);
 
 	/*
 	 * Let the driver probe the device to detect the capabilities.
@@ -1247,7 +1257,7 @@
 	/*
 	 * Reconfigure device.
 	 */
-	retval = rt2x00mac_config(rt2x00dev->hw, &rt2x00dev->hw->conf);
+	retval = rt2x00mac_config(rt2x00dev->hw, ~0);
 	if (retval)
 		goto exit;
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 797eb61..9f214f8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -96,7 +96,8 @@
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      enum antenna rx, enum antenna tx);
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
-		      struct ieee80211_conf *conf, const int force_config);
+		      struct ieee80211_conf *conf,
+		      const unsigned int changed_flags);
 
 /**
  * DOC: Queue handlers
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 2c6cc5c..8fc2315 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -39,7 +39,7 @@
 	unsigned int data_length;
 	int retval = 0;
 
-	if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		data_length = sizeof(struct ieee80211_cts);
 	else
 		data_length = sizeof(struct ieee80211_rts);
@@ -64,11 +64,11 @@
 	 */
 	memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
 	rts_info = IEEE80211_SKB_CB(skb);
-	rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
-	rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
+	rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
+	rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
 	rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
 
-	if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
 	else
 		rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
@@ -84,7 +84,7 @@
 		data_length += rt2x00crypto_tx_overhead(tx_info);
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
-	if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
 					frag_skb->data, data_length, tx_info,
 					(struct ieee80211_cts *)(skb->data));
@@ -146,8 +146,8 @@
 	 * inside the hardware.
 	 */
 	frame_control = le16_to_cpu(ieee80211hdr->frame_control);
-	if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
-			       IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
+	if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+						IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
 	    !rt2x00dev->ops->hw->set_rts_threshold) {
 		if (rt2x00queue_available(queue) <= 1)
 			goto exit_fail;
@@ -335,9 +335,10 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
 
-int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
 	int radio_on;
 	int status;
 
@@ -369,7 +370,7 @@
 		 * When we've just turned on the radio, we want to reprogram
 		 * everything to ensure a consistent state
 		 */
-		rt2x00lib_config(rt2x00dev, conf, !radio_on);
+		rt2x00lib_config(rt2x00dev, conf, changed);
 
 		/* Turn RX back on */
 		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
@@ -633,7 +634,6 @@
 	}
 
 	spin_lock(&intf->lock);
-	memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
 	if (delayed) {
 		intf->delayed_flags |= delayed;
 		schedule_work(&rt2x00dev->intf_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index adf2876..62449da 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -222,8 +222,7 @@
 {
 	struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev);
 
-	rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
-				      pci_resource_len(pci_dev, 0));
+	rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0);
 	if (!rt2x00dev->csr.base)
 		goto exit;
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 80bf97c..a83f45f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -58,7 +58,7 @@
  * Register access.
  */
 static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
-					   const unsigned long offset,
+					   const unsigned int offset,
 					   u32 *value)
 {
 	*value = readl(rt2x00dev->csr.base + offset);
@@ -66,14 +66,14 @@
 
 static inline void
 rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
-			     const unsigned long offset,
+			     const unsigned int offset,
 			     void *value, const u16 length)
 {
 	memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
 }
 
 static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
-					    const unsigned long offset,
+					    const unsigned int offset,
 					    u32 value)
 {
 	writel(value, rt2x00dev->csr.base + offset);
@@ -81,7 +81,7 @@
 
 static inline void
 rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-			      const unsigned long offset,
+			      const unsigned int offset,
 			      const void *value, const u16 length)
 {
 	memcpy_toio(rt2x00dev->csr.base + offset, value, length);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 451d410..e9f4261 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -230,8 +230,15 @@
 	/*
 	 * Determine retry information.
 	 */
-	txdesc->retry_limit = tx_info->control.retry_limit;
-	if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+	txdesc->retry_limit = tx_info->control.rates[0].count - 1;
+	/*
+	 * XXX: If at this point we knew whether the HW is going to use
+	 *	the RETRY_MODE bit or the retry_limit (currently all
+	 *	use the RETRY_MODE bit) we could do something like b43
+	 *	does, set the RETRY_MODE bit when the RC algorithm is
+	 *	requesting more than the long retry limit.
+	 */
+	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		__set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
 
 	/*
@@ -371,10 +378,12 @@
 
 int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 {
+	struct ieee80211_tx_info *tx_info;
 	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
 	struct txentry_desc txdesc;
 	struct skb_frame_desc *skbdesc;
 	unsigned int iv_len = 0;
+	u8 rate_idx, rate_flags;
 
 	if (unlikely(rt2x00queue_full(queue)))
 		return -EINVAL;
@@ -399,13 +408,18 @@
 		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
 
 	/*
-	 * All information is retreived from the skb->cb array,
+	 * All information is retrieved from the skb->cb array,
 	 * now we should claim ownership of the driver part of that
-	 * array.
+	 * array, preserving the bitrate index and flags.
 	 */
+	tx_info = IEEE80211_SKB_CB(skb);
+	rate_idx = tx_info->control.rates[0].idx;
+	rate_flags = tx_info->control.rates[0].flags;
 	skbdesc = get_skb_frame_desc(entry->skb);
 	memset(skbdesc, 0, sizeof(*skbdesc));
 	skbdesc->entry = entry;
+	skbdesc->tx_rate_idx = rate_idx;
+	skbdesc->tx_rate_flags = rate_flags;
 
 	/*
 	 * When hardware encryption is supported, and this frame
@@ -556,7 +570,7 @@
 		queue->length++;
 	} else if (index == Q_INDEX_DONE) {
 		queue->length--;
-		queue->count ++;
+		queue->count++;
 	}
 
 	spin_unlock_irqrestore(&queue->lock, irqflags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 9dbf04f..4d3c724 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -104,6 +104,8 @@
  *
  * @flags: Frame flags, see &enum skb_frame_desc_flags.
  * @desc_len: Length of the frame descriptor.
+ * @tx_rate_idx: the index of the TX rate, used for TX status reporting
+ * @tx_rate_flags: the TX rate flags, used for TX status reporting
  * @desc: Pointer to descriptor part of the frame.
  *	Note that this pointer could point to something outside
  *	of the scope of the skb->data pointer.
@@ -113,9 +115,12 @@
  * @entry: The entry to which this sk buffer belongs.
  */
 struct skb_frame_desc {
-	unsigned int flags;
+	u8 flags;
 
-	unsigned int desc_len;
+	u8 desc_len;
+	u8 tx_rate_idx;
+	u8 tx_rate_flags;
+
 	void *desc;
 
 	__le32 iv;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index a461620..3f27279 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -228,43 +228,34 @@
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)	( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt61pci_read_csr(struct rt2x00_dev *rt2x00dev,
-			     const unsigned int word, u32 *data)
-{
-	rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt61pci_write_csr(struct rt2x00_dev *rt2x00dev,
-			      const unsigned int word, u32 data)
-{
-	rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
 static const struct rt2x00debug rt61pci_rt2x00debug = {
 	.owner	= THIS_MODULE,
 	.csr	= {
-		.read		= rt61pci_read_csr,
-		.write		= rt61pci_write_csr,
+		.read		= rt2x00pci_register_read,
+		.write		= rt2x00pci_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= CSR_REG_SIZE / sizeof(u32),
 	},
 	.eeprom	= {
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= EEPROM_SIZE / sizeof(u16),
 	},
 	.bbp	= {
 		.read		= rt61pci_bbp_read,
 		.write		= rt61pci_bbp_write,
+		.word_base	= BBP_BASE,
 		.word_size	= sizeof(u8),
 		.word_count	= BBP_SIZE / sizeof(u8),
 	},
 	.rf	= {
 		.read		= rt2x00_rf_read,
 		.write		= rt61pci_rf_write,
+		.word_base	= RF_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= RF_SIZE / sizeof(u32),
 	},
@@ -643,95 +634,18 @@
 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 			   !!erp->short_preamble);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
 
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
-static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
-				    struct rt2x00lib_conf *libconf)
-{
-	u16 eeprom;
-	short lna_gain = 0;
+	rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+	rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
 
-	if (libconf->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-			lna_gain += 14;
-
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
-		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
-	} else {
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
-			lna_gain += 14;
-
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
-		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
-	}
-
-	rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
-				   const int basic_rate_mask)
-{
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
-}
-
-static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
-				   struct rf_channel *rf, const int txpower)
-{
-	u8 r3;
-	u8 r94;
-	u8 smart;
-
-	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
-	smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-		  rt2x00_rf(&rt2x00dev->chip, RF2527));
-
-	rt61pci_bbp_read(rt2x00dev, 3, &r3);
-	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
-	rt61pci_bbp_write(rt2x00dev, 3, r3);
-
-	r94 = 6;
-	if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
-		r94 += txpower - MAX_TXPOWER;
-	else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
-		r94 += txpower;
-	rt61pci_bbp_write(rt2x00dev, 94, r94);
-
-	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-	udelay(200);
-
-	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
-	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-	udelay(200);
-
-	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-	msleep(1);
-}
-
-static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
-				   const int txpower)
-{
-	struct rf_channel rf;
-
-	rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-	rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-	rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-	rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
-
-	rt61pci_config_channel(rt2x00dev, &rf, txpower);
+	rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+	rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
 }
 
 static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -906,8 +820,8 @@
 	{ 98,  { 0x48, 0x48 } },
 };
 
-static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
-				   struct antenna_setup *ant)
+static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
+			       struct antenna_setup *ant)
 {
 	const struct antenna_sel *sel;
 	unsigned int lna;
@@ -954,20 +868,105 @@
 	}
 }
 
-static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+				    struct rt2x00lib_conf *libconf)
+{
+	u16 eeprom;
+	short lna_gain = 0;
+
+	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+			lna_gain += 14;
+
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+	} else {
+		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+			lna_gain += 14;
+
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+	}
+
+	rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
+				   struct rf_channel *rf, const int txpower)
+{
+	u8 r3;
+	u8 r94;
+	u8 smart;
+
+	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+	smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+		  rt2x00_rf(&rt2x00dev->chip, RF2527));
+
+	rt61pci_bbp_read(rt2x00dev, 3, &r3);
+	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+	rt61pci_bbp_write(rt2x00dev, 3, r3);
+
+	r94 = 6;
+	if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+		r94 += txpower - MAX_TXPOWER;
+	else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+		r94 += txpower;
+	rt61pci_bbp_write(rt2x00dev, 94, r94);
+
+	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+	udelay(200);
+
+	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+	udelay(200);
+
+	rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+	rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+	rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+	msleep(1);
+}
+
+static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
+				   const int txpower)
+{
+	struct rf_channel rf;
+
+	rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+	rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+	rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+	rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+	rt61pci_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 				    struct rt2x00lib_conf *libconf)
 {
 	u32 reg;
 
-	rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
-	rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+			   libconf->conf->long_frame_max_tx_count);
+	rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+			   libconf->conf->short_frame_max_tx_count);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
 
-	rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
-	rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+				    struct rt2x00lib_conf *libconf)
+{
+	u32 reg;
 
 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
@@ -990,16 +989,15 @@
 	/* Always recalculate LNA gain before changing configuration */
 	rt61pci_config_lna_gain(rt2x00dev, libconf);
 
-	if (flags & CONFIG_UPDATE_PHYMODE)
-		rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
-	if (flags & CONFIG_UPDATE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt61pci_config_channel(rt2x00dev, &libconf->rf,
 				       libconf->conf->power_level);
-	if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
 		rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
-	if (flags & CONFIG_UPDATE_ANTENNA)
-		rt61pci_config_antenna(rt2x00dev, &libconf->ant);
-	if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		rt61pci_config_retry_limit(rt2x00dev, libconf);
+	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
 		rt61pci_config_duration(rt2x00dev, libconf);
 }
 
@@ -1934,7 +1932,7 @@
 }
 
 static void rt61pci_fill_rxdone(struct queue_entry *entry,
-			        struct rxdone_entry_desc *rxdesc)
+				struct rxdone_entry_desc *rxdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
@@ -2175,10 +2173,8 @@
 	 */
 	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
-		DECLARE_MAC_BUF(macbuf);
-
 		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2630,20 +2626,6 @@
 /*
  * IEEE80211 stack callback functions.
  */
-static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
-				   u32 short_retry, u32 long_retry)
-{
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT, long_retry);
-	rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT, short_retry);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
-
-	return 0;
-}
-
 static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 			   const struct ieee80211_tx_queue_params *params)
 {
@@ -2726,7 +2708,6 @@
 	.configure_filter	= rt2x00mac_configure_filter,
 	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
-	.set_retry_limit	= rt61pci_set_retry_limit,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt61pci_conf_tx,
 	.get_tx_stats		= rt2x00mac_get_tx_stats,
@@ -2758,6 +2739,7 @@
 	.config_filter		= rt61pci_config_filter,
 	.config_intf		= rt61pci_config_intf,
 	.config_erp		= rt61pci_config_erp,
+	.config_ant		= rt61pci_config_ant,
 	.config			= rt61pci_config,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 8ec1451..65fe333 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -48,7 +48,9 @@
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
+#define BBP_BASE			0x0000
 #define BBP_SIZE			0x0080
+#define RF_BASE				0x0000
 #define RF_SIZE				0x0014
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 934f8e03..767e3c9 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -249,43 +249,34 @@
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)	( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev,
-			     const unsigned int word, u32 *data)
-{
-	rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev,
-			      const unsigned int word, u32 data)
-{
-	rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
 static const struct rt2x00debug rt73usb_rt2x00debug = {
 	.owner	= THIS_MODULE,
 	.csr	= {
-		.read		= rt73usb_read_csr,
-		.write		= rt73usb_write_csr,
+		.read		= rt73usb_register_read,
+		.write		= rt73usb_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= CSR_REG_SIZE / sizeof(u32),
 	},
 	.eeprom	= {
 		.read		= rt2x00_eeprom_read,
 		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
 		.word_size	= sizeof(u16),
 		.word_count	= EEPROM_SIZE / sizeof(u16),
 	},
 	.bbp	= {
 		.read		= rt73usb_bbp_read,
 		.write		= rt73usb_bbp_write,
+		.word_base	= BBP_BASE,
 		.word_size	= sizeof(u8),
 		.word_count	= BBP_SIZE / sizeof(u8),
 	},
 	.rf	= {
 		.read		= rt2x00_rf_read,
 		.write		= rt73usb_rf_write,
+		.word_base	= RF_BASE,
 		.word_size	= sizeof(u32),
 		.word_count	= RF_SIZE / sizeof(u32),
 	},
@@ -669,87 +660,18 @@
 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 			   !!erp->short_preamble);
 	rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
 
-static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
-				    struct rt2x00lib_conf *libconf)
-{
-	u16 eeprom;
-	short lna_gain = 0;
+	rt73usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
-	if (libconf->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-			lna_gain += 14;
+	rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+	rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
-		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
-	} else {
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
-		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
-	}
-
-	rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
-				   const int basic_rate_mask)
-{
-	rt73usb_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
-}
-
-static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
-				   struct rf_channel *rf, const int txpower)
-{
-	u8 r3;
-	u8 r94;
-	u8 smart;
-
-	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
-	smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-		  rt2x00_rf(&rt2x00dev->chip, RF2527));
-
-	rt73usb_bbp_read(rt2x00dev, 3, &r3);
-	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
-	rt73usb_bbp_write(rt2x00dev, 3, r3);
-
-	r94 = 6;
-	if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
-		r94 += txpower - MAX_TXPOWER;
-	else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
-		r94 += txpower;
-	rt73usb_bbp_write(rt2x00dev, 94, r94);
-
-	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
-	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-	udelay(10);
-}
-
-static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-				   const int txpower)
-{
-	struct rf_channel rf;
-
-	rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-	rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-	rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-	rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
-
-	rt73usb_config_channel(rt2x00dev, &rf, txpower);
+	rt73usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+	rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
 }
 
 static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -869,8 +791,8 @@
 	{ 98,  { 0x48, 0x48 } },
 };
 
-static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
-				   struct antenna_setup *ant)
+static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
+			       struct antenna_setup *ant)
 {
 	const struct antenna_sel *sel;
 	unsigned int lna;
@@ -912,21 +834,99 @@
 		rt73usb_config_antenna_2x(rt2x00dev, ant);
 }
 
+static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+				    struct rt2x00lib_conf *libconf)
+{
+	u16 eeprom;
+	short lna_gain = 0;
+
+	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+			lna_gain += 14;
+
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+	} else {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+	}
+
+	rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
+				   struct rf_channel *rf, const int txpower)
+{
+	u8 r3;
+	u8 r94;
+	u8 smart;
+
+	rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+	smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+		  rt2x00_rf(&rt2x00dev->chip, RF2527));
+
+	rt73usb_bbp_read(rt2x00dev, 3, &r3);
+	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+	rt73usb_bbp_write(rt2x00dev, 3, r3);
+
+	r94 = 6;
+	if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+		r94 += txpower - MAX_TXPOWER;
+	else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+		r94 += txpower;
+	rt73usb_bbp_write(rt2x00dev, 94, r94);
+
+	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+	rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+	udelay(10);
+}
+
+static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+				   const int txpower)
+{
+	struct rf_channel rf;
+
+	rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+	rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+	rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+	rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+	rt73usb_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00lib_conf *libconf)
+{
+	u32 reg;
+
+	rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+			   libconf->conf->long_frame_max_tx_count);
+	rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+			   libconf->conf->short_frame_max_tx_count);
+	rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
+
 static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
 				    struct rt2x00lib_conf *libconf)
 {
 	u32 reg;
 
-	rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
-	rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
-
-	rt73usb_register_read(rt2x00dev, MAC_CSR8, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
-	rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
-
 	rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
 	rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
@@ -948,16 +948,15 @@
 	/* Always recalculate LNA gain before changing configuration */
 	rt73usb_config_lna_gain(rt2x00dev, libconf);
 
-	if (flags & CONFIG_UPDATE_PHYMODE)
-		rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
-	if (flags & CONFIG_UPDATE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
 		rt73usb_config_channel(rt2x00dev, &libconf->rf,
 				       libconf->conf->power_level);
-	if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+	if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
 		rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
-	if (flags & CONFIG_UPDATE_ANTENNA)
-		rt73usb_config_antenna(rt2x00dev, &libconf->ant);
-	if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		rt73usb_config_retry_limit(rt2x00dev, libconf);
+	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
 		rt73usb_config_duration(rt2x00dev, libconf);
 }
 
@@ -1685,7 +1684,7 @@
 }
 
 static void rt73usb_fill_rxdone(struct queue_entry *entry,
-			        struct rxdone_entry_desc *rxdesc)
+				struct rxdone_entry_desc *rxdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -1781,10 +1780,8 @@
 	 */
 	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
 	if (!is_valid_ether_addr(mac)) {
-		DECLARE_MAC_BUF(macbuf);
-
 		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
 	}
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2211,20 +2208,6 @@
 /*
  * IEEE80211 stack callback functions.
  */
-static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
-				   u32 short_retry, u32 long_retry)
-{
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	u32 reg;
-
-	rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT, long_retry);
-	rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT, short_retry);
-	rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-
-	return 0;
-}
-
 static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 			   const struct ieee80211_tx_queue_params *params)
 {
@@ -2317,7 +2300,6 @@
 	.configure_filter	= rt2x00mac_configure_filter,
 	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
-	.set_retry_limit	= rt73usb_set_retry_limit,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt73usb_conf_tx,
 	.get_tx_stats		= rt2x00mac_get_tx_stats,
@@ -2348,6 +2330,7 @@
 	.config_filter		= rt73usb_config_filter,
 	.config_intf		= rt73usb_config_intf,
 	.config_erp		= rt73usb_config_erp,
+	.config_ant		= rt73usb_config_ant,
 	.config			= rt73usb_config,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index 868386c..46e1405 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -48,7 +48,9 @@
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
+#define BBP_BASE			0x0000
 #define BBP_SIZE			0x0080
+#define RF_BASE				0x0000
 #define RF_SIZE				0x0014
 
 /*
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index df7e78e..6c226c0 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -182,15 +182,13 @@
 				 skb->len, PCI_DMA_TODEVICE);
 
 		info = IEEE80211_SKB_CB(skb);
-		memset(&info->status, 0, sizeof(info->status));
+		ieee80211_tx_info_clear_status(info);
 
-		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-			if (flags & RTL818X_TX_DESC_FLAG_TX_OK)
-				info->flags |= IEEE80211_TX_STAT_ACK;
-			else
-				info->status.excessive_retries = 1;
-		}
-		info->status.retry_count = flags & 0xFF;
+		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+		    (flags & RTL818X_TX_DESC_FLAG_TX_OK))
+			info->flags |= IEEE80211_TX_STAT_ACK;
+
+		info->status.rates[0].count = (flags & 0xFF) + 1;
 
 		ieee80211_tx_status_irqsafe(dev, skb);
 		if (ring->entries - skb_queue_len(&ring->queue) == 2)
@@ -243,6 +241,7 @@
 	unsigned int idx, prio;
 	dma_addr_t mapping;
 	u32 tx_flags;
+	u8 rc_flags;
 	u16 plcp_len = 0;
 	__le16 rts_duration = 0;
 
@@ -261,15 +260,16 @@
 		tx_flags |= RTL818X_TX_DESC_FLAG_DMA |
 			    RTL818X_TX_DESC_FLAG_NO_ENC;
 
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+	rc_flags = info->control.rates[0].flags;
+	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		tx_flags |= RTL818X_TX_DESC_FLAG_RTS;
 		tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
-	} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+	} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
 		tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
 						      info);
 
@@ -292,9 +292,9 @@
 	entry->plcp_len = cpu_to_le16(plcp_len);
 	entry->tx_buf = cpu_to_le32(mapping);
 	entry->frame_len = cpu_to_le32(skb->len);
-	entry->flags2 = info->control.retries[0].rate_idx >= 0 ?
+	entry->flags2 = info->control.rates[1].idx >= 0 ?
 		ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
-	entry->retry_limit = info->control.retry_limit;
+	entry->retry_limit = info->control.rates[0].count;
 	entry->flags = cpu_to_le32(tx_flags);
 	__skb_queue_tail(&ring->queue, skb);
 	if (ring->entries - skb_queue_len(&ring->queue) < 2)
@@ -692,9 +692,10 @@
 	priv->vif = NULL;
 }
 
-static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
 {
 	struct rtl8180_priv *priv = dev->priv;
+	struct ieee80211_conf *conf = &dev->conf;
 
 	priv->rf->set_chan(dev, conf);
 
@@ -806,7 +807,6 @@
 	const char *chip_name, *rf_name = NULL;
 	u32 reg;
 	u16 eeprom_val;
-	DECLARE_MAC_BUF(mac);
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -855,7 +855,7 @@
 	priv = dev->priv;
 	priv->pdev = pdev;
 
-	dev->max_altrates = 1;
+	dev->max_rates = 2;
 	SET_IEEE80211_DEV(dev, &pdev->dev);
 	pci_set_drvdata(pdev, dev);
 
@@ -1002,8 +1002,8 @@
 		goto err_iounmap;
 	}
 
-	printk(KERN_INFO "%s: hwaddr %s, %s + %s\n",
-	       wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+	printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n",
+	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
 	       chip_name, priv->rf->name);
 
 	return 0;
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index e82bb4d..33725d0 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -100,7 +100,6 @@
 	struct usb_device *udev;
 	u32 rx_conf;
 	u16 txpwr_base;
-	u16 seqno;
 	u8 asic_rev;
 	u8 is_rtl8187b;
 	enum {
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 431e3c7..66add5e 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -152,21 +152,19 @@
 	rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
 	rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
 	rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
-
-	msleep(1);
 }
 
 static void rtl8187_tx_cb(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *)urb->context;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hw *hw = info->driver_data[0];
+	struct ieee80211_hw *hw = info->rate_driver_data[0];
 	struct rtl8187_priv *priv = hw->priv;
 
-	usb_free_urb(info->driver_data[1]);
+	usb_free_urb(info->rate_driver_data[1]);
 	skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
 					  sizeof(struct rtl8187_tx_hdr));
-	memset(&info->status, 0, sizeof(info->status));
+	ieee80211_tx_info_clear_status(info);
 	info->flags |= IEEE80211_TX_STAT_ACK;
 	ieee80211_tx_status_irqsafe(hw, skb);
 }
@@ -175,7 +173,6 @@
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
 	unsigned int ep;
 	void *buf;
 	struct urb *urb;
@@ -195,12 +192,12 @@
 	flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
 	if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
 		flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		flags |= RTL818X_TX_DESC_FLAG_RTS;
 		flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
 		rts_dur = ieee80211_rts_duration(dev, priv->vif,
 						 skb->len, info);
-	} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+	} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		flags |= RTL818X_TX_DESC_FLAG_CTS;
 		flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
 	}
@@ -211,7 +208,7 @@
 		hdr->flags = cpu_to_le32(flags);
 		hdr->len = 0;
 		hdr->rts_duration = rts_dur;
-		hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+		hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
 		buf = hdr;
 
 		ep = 2;
@@ -229,7 +226,7 @@
 		memset(hdr, 0, sizeof(*hdr));
 		hdr->flags = cpu_to_le32(flags);
 		hdr->rts_duration = rts_dur;
-		hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+		hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
 		hdr->tx_duration =
 			ieee80211_generic_frame_duration(dev, priv->vif,
 							 skb->len, txrate);
@@ -241,22 +238,8 @@
 			ep = epmap[skb_get_queue_mapping(skb)];
 	}
 
-	/* FIXME: The sequence that follows is needed for this driver to
-	 * work with mac80211 since "mac80211: fix TX sequence numbers".
-	 * As with the temporary code in rt2x00, changes will be needed
-	 * to get proper sequence numbers on beacons. In addition, this
-	 * patch places the sequence number in the hardware state, which
-	 * limits us to a single virtual state.
-	 */
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-			priv->seqno += 0x10;
-		ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
-	}
-
-	info->driver_data[0] = dev;
-	info->driver_data[1] = urb;
+	info->rate_driver_data[0] = dev;
+	info->rate_driver_data[1] = urb;
 
 	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
 			  buf, skb->len, rtl8187_tx_cb, skb);
@@ -684,7 +667,7 @@
 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
-	msleep(1100);
+	msleep(100);
 
 	priv->rf->init(dev);
 
@@ -873,9 +856,10 @@
 	mutex_unlock(&priv->conf_mutex);
 }
 
-static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int rtl8187_config(struct ieee80211_hw *dev, u32 changed)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	struct ieee80211_conf *conf = &dev->conf;
 	u32 reg;
 
 	mutex_lock(&priv->conf_mutex);
@@ -886,27 +870,10 @@
 	 */
 	rtl818x_iowrite32(priv, &priv->map->TX_CONF,
 			  reg | RTL818X_TX_CONF_LOOPBACK_MAC);
-	msleep(10);
 	priv->rf->set_chan(dev, conf);
 	msleep(10);
 	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
 
-	if (!priv->is_rtl8187b) {
-		rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
-
-		if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
-			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
-			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
-			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
-		} else {
-			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
-			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
-			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
-			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
-		}
-	}
-
 	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
 	rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
 	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
@@ -941,6 +908,72 @@
 	return 0;
 }
 
+static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
+			     bool use_short_preamble)
+{
+	if (priv->is_rtl8187b) {
+		u8 difs, eifs, slot_time;
+		u16 ack_timeout;
+
+		if (use_short_slot) {
+			slot_time = 0x9;
+			difs = 0x1c;
+			eifs = 0x53;
+		} else {
+			slot_time = 0x14;
+			difs = 0x32;
+			eifs = 0x5b;
+		}
+		rtl818x_iowrite8(priv, &priv->map->SIFS, 0xa);
+		rtl818x_iowrite8(priv, &priv->map->SLOT, slot_time);
+		rtl818x_iowrite8(priv, &priv->map->DIFS, difs);
+
+		/*
+		 * BRSR+1 on 8187B is in fact EIFS register
+		 * Value in units of 4 us
+		 */
+		rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs);
+
+		/*
+		 * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout
+		 * register. In units of 4 us like eifs register
+		 * ack_timeout = ack duration + plcp + difs + preamble
+		 */
+		ack_timeout = 112 + 48 + difs;
+		if (use_short_preamble)
+			ack_timeout += 72;
+		else
+			ack_timeout += 144;
+		rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER,
+				 DIV_ROUND_UP(ack_timeout, 4));
+	} else {
+		rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+		if (use_short_slot) {
+			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+		} else {
+			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+		}
+	}
+}
+
+static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *info,
+				     u32 changed)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
+		rtl8187_conf_erp(priv, info->use_short_slot,
+				 info->use_short_preamble);
+}
+
 static void rtl8187_configure_filter(struct ieee80211_hw *dev,
 				     unsigned int changed_flags,
 				     unsigned int *total_flags,
@@ -981,6 +1014,7 @@
 	.remove_interface	= rtl8187_remove_interface,
 	.config			= rtl8187_config,
 	.config_interface	= rtl8187_config_interface,
+	.bss_info_changed	= rtl8187_bss_info_changed,
 	.configure_filter	= rtl8187_configure_filter,
 };
 
@@ -1026,7 +1060,6 @@
 	const char *chip_name;
 	u16 txpwr, reg;
 	int err, i;
-	DECLARE_MAC_BUF(mac);
 
 	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
 	if (!dev) {
@@ -1187,6 +1220,10 @@
 		dev->max_signal = 65;
 	}
 
+	/*
+	 * XXX: Once this driver supports anything that requires
+	 *	beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
+	 */
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
 	if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
@@ -1209,8 +1246,8 @@
 	}
 	mutex_init(&priv->conf_mutex);
 
-	printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
-	       wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+	printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
+	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
 	       chip_name, priv->asic_rev, priv->rf->name);
 
 	return 0;
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index 1bae899..69030be 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -64,7 +64,6 @@
 
 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
-	msleep(2);
 }
 
 static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
@@ -98,7 +97,6 @@
 
 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
 	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
-	msleep(2);
 }
 
 static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
@@ -333,21 +331,21 @@
 	struct rtl8187_priv *priv = dev->priv;
 	int i;
 
-	rtl8225_write(dev, 0x0, 0x067); msleep(1);
-	rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
-	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
-	rtl8225_write(dev, 0x3, 0x441); msleep(1);
-	rtl8225_write(dev, 0x4, 0x486); msleep(1);
-	rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
-	rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
-	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
-	rtl8225_write(dev, 0x8, 0x01F); msleep(1);
-	rtl8225_write(dev, 0x9, 0x334); msleep(1);
-	rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
-	rtl8225_write(dev, 0xB, 0x391); msleep(1);
-	rtl8225_write(dev, 0xC, 0x050); msleep(1);
-	rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
-	rtl8225_write(dev, 0xE, 0x029); msleep(1);
+	rtl8225_write(dev, 0x0, 0x067);
+	rtl8225_write(dev, 0x1, 0xFE0);
+	rtl8225_write(dev, 0x2, 0x44D);
+	rtl8225_write(dev, 0x3, 0x441);
+	rtl8225_write(dev, 0x4, 0x486);
+	rtl8225_write(dev, 0x5, 0xBC0);
+	rtl8225_write(dev, 0x6, 0xAE6);
+	rtl8225_write(dev, 0x7, 0x82A);
+	rtl8225_write(dev, 0x8, 0x01F);
+	rtl8225_write(dev, 0x9, 0x334);
+	rtl8225_write(dev, 0xA, 0xFD4);
+	rtl8225_write(dev, 0xB, 0x391);
+	rtl8225_write(dev, 0xC, 0x050);
+	rtl8225_write(dev, 0xD, 0x6DB);
+	rtl8225_write(dev, 0xE, 0x029);
 	rtl8225_write(dev, 0xF, 0x914); msleep(100);
 
 	rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
@@ -375,91 +373,89 @@
 
 	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
-		msleep(1);
 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
-		msleep(1);
 	}
 
 	msleep(1);
 
-	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
 
 	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
 	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
 	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
 	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
 
-	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x00, 0x98);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47);
 	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 	rtl8225_write_phy_cck(dev, 0x19, 0x00);
 	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 	rtl8225_write_phy_cck(dev, 0x40, 0x86);
-	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18);
+	rtl8225_write_phy_cck(dev, 0x44, 0x1f);
+	rtl8225_write_phy_cck(dev, 0x45, 0x1e);
+	rtl8225_write_phy_cck(dev, 0x46, 0x1a);
+	rtl8225_write_phy_cck(dev, 0x47, 0x15);
+	rtl8225_write_phy_cck(dev, 0x48, 0x10);
+	rtl8225_write_phy_cck(dev, 0x49, 0x0a);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x05);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x02);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05);
 
 	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
 
 	rtl8225_rf_set_tx_power(dev, 1);
 
 	/* RX antenna default to A */
-	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
-	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b);			/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);		/* B: 0x10 */
 
 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
 	msleep(1);
@@ -629,7 +625,7 @@
 		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 
 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
-			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+			 rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
 	msleep(1);
 
 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
@@ -687,22 +683,23 @@
 	struct rtl8187_priv *priv = dev->priv;
 	int i;
 
-	rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
-	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
-	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
-	rtl8225_write(dev, 0x3, 0x441); msleep(1);
-	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
-	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
-	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
-	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
-	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
-	rtl8225_write(dev, 0x9, 0x335); msleep(1);
-	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
-	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
-	rtl8225_write(dev, 0xc, 0x850); msleep(1);
-	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
-	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
-	rtl8225_write(dev, 0xf, 0x114); msleep(100);
+	rtl8225_write(dev, 0x0, 0x2BF);
+	rtl8225_write(dev, 0x1, 0xEE0);
+	rtl8225_write(dev, 0x2, 0x44D);
+	rtl8225_write(dev, 0x3, 0x441);
+	rtl8225_write(dev, 0x4, 0x8C3);
+	rtl8225_write(dev, 0x5, 0xC72);
+	rtl8225_write(dev, 0x6, 0x0E6);
+	rtl8225_write(dev, 0x7, 0x82A);
+	rtl8225_write(dev, 0x8, 0x03F);
+	rtl8225_write(dev, 0x9, 0x335);
+	rtl8225_write(dev, 0xa, 0x9D4);
+	rtl8225_write(dev, 0xb, 0x7BB);
+	rtl8225_write(dev, 0xc, 0x850);
+	rtl8225_write(dev, 0xd, 0xCDF);
+	rtl8225_write(dev, 0xe, 0x02B);
+	rtl8225_write(dev, 0xf, 0x114);
+	msleep(100);
 
 	rtl8225_write(dev, 0x0, 0x1B7);
 
@@ -736,94 +733,92 @@
 
 	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
 		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
-		msleep(1);
 		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
-		msleep(1);
 	}
 
 	msleep(1);
 
-	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
 	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
-	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
-	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
+	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
+	rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
 
 	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
 	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
 	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
 	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
 
-	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x00, 0x98);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47);
 	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
 	rtl8225_write_phy_cck(dev, 0x19, 0x00);
 	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
 	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
 	rtl8225_write_phy_cck(dev, 0x40, 0x86);
-	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
-	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18);
+	rtl8225_write_phy_cck(dev, 0x44, 0x36);
+	rtl8225_write_phy_cck(dev, 0x45, 0x35);
+	rtl8225_write_phy_cck(dev, 0x46, 0x2e);
+	rtl8225_write_phy_cck(dev, 0x47, 0x25);
+	rtl8225_write_phy_cck(dev, 0x48, 0x1c);
+	rtl8225_write_phy_cck(dev, 0x49, 0x12);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x09);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x04);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05);
 
 	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
 
 	rtl8225z2_rf_set_tx_power(dev, 1);
 
 	/* RX antenna default to A */
-	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
-	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b);			/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90);		/* B: 0x10 */
 
 	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
 	msleep(1);
@@ -835,40 +830,38 @@
 	struct rtl8187_priv *priv = dev->priv;
 	int i;
 
-	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
-	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
-	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
-	rtl8225_write(dev, 0x3, 0x441); msleep(1);
-	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
-	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
-	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
-	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
-	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
-	rtl8225_write(dev, 0x9, 0x335); msleep(1);
-	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
-	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
-	rtl8225_write(dev, 0xc, 0x850); msleep(1);
-	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
-	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
-	rtl8225_write(dev, 0xf, 0x114); msleep(1);
+	rtl8225_write(dev, 0x0, 0x0B7);
+	rtl8225_write(dev, 0x1, 0xEE0);
+	rtl8225_write(dev, 0x2, 0x44D);
+	rtl8225_write(dev, 0x3, 0x441);
+	rtl8225_write(dev, 0x4, 0x8C3);
+	rtl8225_write(dev, 0x5, 0xC72);
+	rtl8225_write(dev, 0x6, 0x0E6);
+	rtl8225_write(dev, 0x7, 0x82A);
+	rtl8225_write(dev, 0x8, 0x03F);
+	rtl8225_write(dev, 0x9, 0x335);
+	rtl8225_write(dev, 0xa, 0x9D4);
+	rtl8225_write(dev, 0xb, 0x7BB);
+	rtl8225_write(dev, 0xc, 0x850);
+	rtl8225_write(dev, 0xd, 0xCDF);
+	rtl8225_write(dev, 0xe, 0x02B);
+	rtl8225_write(dev, 0xf, 0x114);
 
-	rtl8225_write(dev, 0x0, 0x1B7); msleep(1);
+	rtl8225_write(dev, 0x0, 0x1B7);
 
 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
-		rtl8225_write(dev, 0x1, i + 1); msleep(1);
-		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
 	}
 
-	rtl8225_write(dev, 0x3, 0x080); msleep(1);
-	rtl8225_write(dev, 0x5, 0x004); msleep(1);
-	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
-	msleep(3000);
+	rtl8225_write(dev, 0x3, 0x080);
+	rtl8225_write(dev, 0x5, 0x004);
+	rtl8225_write(dev, 0x0, 0x0B7);
 
-	rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
-	msleep(2000);
+	rtl8225_write(dev, 0x2, 0xC4D);
 
-	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
-	rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+	rtl8225_write(dev, 0x2, 0x44D);
+	rtl8225_write(dev, 0x0, 0x2BF);
 
 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
 	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
@@ -885,24 +878,16 @@
 	for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
 		rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
 
-	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
-	rtl818x_iowrite8(priv, &priv->map->SLOT, 9);
-	rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28);
-	rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28);
-	rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28);
-	rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28);
-	rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B);
-	rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B);
 	rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
 	rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
 	rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
 	rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
 	rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
 
-	rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1);
-	rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1);
-	rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
+	rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
+	rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
+	rtl8225_write_phy_cck(dev, 0xc1, 0x88);
 }
 
 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
@@ -910,7 +895,7 @@
 	u8 reg;
 	struct rtl8187_priv *priv = dev->priv;
 
-	rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+	rtl8225_write(dev, 0x4, 0x1f);
 
 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 417e9e6..cf0d070 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1997,7 +1997,6 @@
 #ifdef EXT_COUNTERS
 		strip_info->rx_bytes += packetlen;
 #endif
-		skb->dev->last_rx = jiffies;
 		netif_rx(skb);
 	}
 }
@@ -2490,7 +2489,6 @@
 	 */
 
 	dev->trans_start = 0;
-	dev->last_rx = 0;
 	dev->tx_queue_len = 30;	/* Drop after 30 frames queued */
 
 	dev->flags = 0;
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index e939a73..1ac37e8 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -859,8 +859,6 @@
  */
 static void wv_psa_show(psa_t * p)
 {
-	DECLARE_MAC_BUF(mac);
-
 	printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
 	printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
 	       p->psa_io_base_addr_1,
@@ -872,13 +870,10 @@
 	printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
 	printk("psa_int_req_no: %d\n", p->psa_int_req_no);
 #ifdef DEBUG_SHOW_UNUSED
-	printk(KERN_DEBUG "psa_unused0[]: %s\n",
-	       print_mac(mac, p->psa_unused0));
+	printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0);
 #endif				/* DEBUG_SHOW_UNUSED */
-	printk(KERN_DEBUG "psa_univ_mac_addr[]: %s\n",
-	       print_mac(mac, p->psa_univ_mac_addr));
-	printk(KERN_DEBUG "psa_local_mac_addr[]: %s\n",
-	       print_mac(mac, p->psa_local_mac_addr));
+	printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr);
+	printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr);
 	printk(KERN_DEBUG "psa_univ_local_sel: %d, ",
 	       p->psa_univ_local_sel);
 	printk("psa_comp_number: %d, ", p->psa_comp_number);
@@ -1220,14 +1215,13 @@
 {				/* Name of the function */
 	int i;
 	int maxi;
-	DECLARE_MAC_BUF(mac);
 
 	printk(KERN_DEBUG
-	       "%s: %s(): dest %s, length %d\n",
-	       msg1, msg2, print_mac(mac, p), length);
+	       "%s: %s(): dest %pM, length %d\n",
+	       msg1, msg2, p, length);
 	printk(KERN_DEBUG
-	       "%s: %s(): src %s, type 0x%02X%02X\n",
-	       msg1, msg2, print_mac(mac, &p[6]), p[12], p[13]);
+	       "%s: %s(): src %pM, type 0x%02X%02X\n",
+	       msg1, msg2, &p[6], p[12], p[13]);
 
 #ifdef DEBUG_PACKET_DUMP
 
@@ -1258,9 +1252,6 @@
 	short ioaddr = dev->base_addr;
 	net_local *lp = (net_local *) dev->priv;
 	psa_t psa;
-#ifdef DEBUG_BASIC_SHOW
-	DECLARE_MAC_BUF(mac);
-#endif
 
 	/* Read the parameter storage area */
 	psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
@@ -1277,8 +1268,8 @@
 
 #ifdef DEBUG_BASIC_SHOW
 	/* Now, let's go for the basic stuff. */
-	printk(KERN_NOTICE "%s: WaveLAN at %#x, %s, IRQ %d",
-	       dev->name, ioaddr, print_mac(mac, dev->dev_addr), dev->irq);
+	printk(KERN_NOTICE "%s: WaveLAN at %#x, %pM, IRQ %d",
+	       dev->name, ioaddr, dev->dev_addr, dev->irq);
 
 	/* Print current network ID. */
 	if (psa.psa_nwid_select)
@@ -2537,7 +2528,6 @@
 	netif_rx(skb);
 
 	/* Keep statistics up to date */
-	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += sksize;
 
@@ -3565,15 +3555,11 @@
 			      WAVELAN_ADDR_SIZE >> 1);
 
 #ifdef DEBUG_CONFIG_INFO
- {
-		DECLARE_MAC_BUF(mac);
 		printk(KERN_DEBUG
 		       "%s: wv_82586_config(): set %d multicast addresses:\n",
 		       dev->name, lp->mc_count);
 		for (dmi = dev->mc_list; dmi; dmi = dmi->next)
-			printk(KERN_DEBUG " %s\n",
-			       print_mac(mac, dmi->dmi_addr));
- }
+			printk(KERN_DEBUG " %pM\n", dmi->dmi_addr);
 #endif
 	}
 
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index e124b1d..de717f8 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1020,7 +1020,6 @@
 static void
 wv_psa_show(psa_t *	p)
 {
-  DECLARE_MAC_BUF(mac);
   printk(KERN_DEBUG "##### wavelan psa contents: #####\n");
   printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
 	 p->psa_io_base_addr_1,
@@ -1034,13 +1033,10 @@
   printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
   printk("psa_int_req_no: %d\n", p->psa_int_req_no);
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "psa_unused0[]: %s\n",
-	 print_mac(mac, p->psa_unused0));
+  printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0);
 #endif	/* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "psa_univ_mac_addr[]: %s\n",
-	 print_mac(mac, p->psa_univ_mac_addr));
-  printk(KERN_DEBUG "psa_local_mac_addr[]: %s\n",
-	 print_mac(mac, p->psa_local_mac_addr));
+  printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr);
+  printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr);
   printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel);
   printk("psa_comp_number: %d, ", p->psa_comp_number);
   printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
@@ -1238,12 +1234,11 @@
 {
   int		i;
   int		maxi;
-  DECLARE_MAC_BUF(mac);
 
-  printk(KERN_DEBUG "%s: %s(): dest %s, length %d\n",
-	 msg1, msg2, print_mac(mac, p), length);
-  printk(KERN_DEBUG "%s: %s(): src %s, type 0x%02X%02X\n",
-	 msg1, msg2, print_mac(mac, &p[6]), p[12], p[13]);
+  printk(KERN_DEBUG "%s: %s(): dest %pM, length %d\n",
+	 msg1, msg2, p, length);
+  printk(KERN_DEBUG "%s: %s(): src %pM, type 0x%02X%02X\n",
+	 msg1, msg2, &p[6], p[12], p[13]);
 
 #ifdef DEBUG_PACKET_DUMP
 
@@ -1274,7 +1269,6 @@
 {
   unsigned int	base = dev->base_addr;
   psa_t		psa;
-  DECLARE_MAC_BUF(mac);
 
   /* Read the parameter storage area */
   psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
@@ -1291,10 +1285,8 @@
 
 #ifdef DEBUG_BASIC_SHOW
   /* Now, let's go for the basic stuff */
-  printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, "
-	 "hw_addr %s",
-	 dev->name, base, dev->irq,
-	 print_mac(mac, dev->dev_addr));
+  printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, hw_addr %pM",
+	 dev->name, base, dev->irq, dev->dev_addr);
 
   /* Print current network id */
   if(psa.psa_nwid_select)
@@ -2243,13 +2235,7 @@
 			   char *extra)
 {
 #ifdef DEBUG_IOCTL_INFO
-	printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
-	       wrqu->ap_addr.sa_data[0],
-	       wrqu->ap_addr.sa_data[1],
-	       wrqu->ap_addr.sa_data[2],
-	       wrqu->ap_addr.sa_data[3],
-	       wrqu->ap_addr.sa_data[4],
-	       wrqu->ap_addr.sa_data[5]);
+	printk(KERN_DEBUG "Set AP to : %pM\n", wrqu->ap_addr.sa_data);
 #endif	/* DEBUG_IOCTL_INFO */
 
 	return -EOPNOTSUPP;
@@ -2892,7 +2878,6 @@
   netif_rx(skb);
 
   /* Keep stats up to date */
-  dev->last_rx = jiffies;
   lp->stats.rx_packets++;
   lp->stats.rx_bytes += sksize;
 
@@ -3647,12 +3632,10 @@
       int			addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count;
 
 #ifdef DEBUG_CONFIG_INFO
-      DECLARE_MAC_BUF(mac);
       printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n",
 	     dev->name, lp->mc_count);
       for(dmi=dev->mc_list; dmi; dmi=dmi->next)
-	printk(KERN_DEBUG " %s\n",
-	       print_mac(mac, dmi->dmi_addr));
+	printk(KERN_DEBUG " %pM\n", dmi->dmi_addr);
 #endif
 
       /* Initialize adapter's ethernet multicast addresses */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 65ceb08..59bb3a5 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -2,7 +2,7 @@
 #define __WL3501_H__
 
 #include <linux/spinlock.h>
-#include <net/ieee80211.h>
+#include <linux/ieee80211.h>
 
 /* define for WLA 2.0 */
 #define WL3501_BLKSZ 256
@@ -548,7 +548,7 @@
 
 struct wl3501_80211_tx_hdr {
 	struct wl3501_80211_tx_plcp_hdr	pclp_hdr;
-	struct ieee80211_hdr_4addr		mac_hdr;
+	struct ieee80211_hdr		mac_hdr;
 } __attribute__ ((packed));
 
 /*
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 68789c6..c99a1b6 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -860,10 +860,9 @@
 static void wl3501_online(struct net_device *dev)
 {
 	struct wl3501_card *this = netdev_priv(dev);
-	DECLARE_MAC_BUF(mac);
 
-	printk(KERN_INFO "%s: Wireless LAN online. BSSID: %s\n",
-	       dev->name, print_mac(mac, this->bssid));
+	printk(KERN_INFO "%s: Wireless LAN online. BSSID: %pM\n",
+	       dev->name, this->bssid);
 	netif_wake_queue(dev);
 }
 
@@ -1014,7 +1013,6 @@
 		wl3501_receive(this, skb->data, pkt_len);
 		skb_put(skb, pkt_len);
 		skb->protocol	= eth_type_trans(skb, dev);
-		dev->last_rx	= jiffies;
 		this->stats.rx_packets++;
 		this->stats.rx_bytes += skb->len;
 		netif_rx(skb);
@@ -1965,7 +1963,6 @@
 	struct net_device *dev = link->priv;
 	int i = 0, j, last_fn, last_ret;
 	struct wl3501_card *this;
-	DECLARE_MAC_BUF(mac);
 
 	/* Try allocating IO ports.  This tries a few fixed addresses.  If you
 	 * want, you can also read the card's config table to pick addresses --
@@ -2024,9 +2021,9 @@
 
 	/* print probe information */
 	printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, "
-	       "MAC addr in flash ROM:%s\n",
+	       "MAC addr in flash ROM:%pM\n",
 	       dev->name, this->base_addr, (int)dev->irq,
-	       print_mac(mac, dev->dev_addr));
+	       dev->dev_addr);
 	/*
 	 * Initialize card parameters - added by jss
 	 */
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index b16ec6e..1134e2f 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -17,11 +17,11 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 #include <net/iw_handler.h>
 #include <linux/string.h>
 #include <linux/if_arp.h>
 #include <linux/firmware.h>
-#include <net/ieee80211.h>
 #include "zd1201.h"
 
 static struct usb_device_id zd1201_table[] = {
@@ -328,7 +328,6 @@
 			memcpy(skb_put(skb, 2), &data[datalen-24], 2);
 			memcpy(skb_put(skb, len), data, len);
 			skb->protocol = eth_type_trans(skb, zd->dev);
-			skb->dev->last_rx = jiffies;
 			zd->stats.rx_packets++;
 			zd->stats.rx_bytes += skb->len;
 			netif_rx(skb);
@@ -346,7 +345,7 @@
 				frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
 				if (!frag)
 					goto resubmit;
-				skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
+				skb = dev_alloc_skb(IEEE80211_MAX_DATA_LEN +14+2);
 				if (!skb) {
 					kfree(frag);
 					goto resubmit;
@@ -385,7 +384,6 @@
 			memcpy(skb_put(skb, len), data+8, len);
 		}
 		skb->protocol = eth_type_trans(skb, zd->dev);
-		skb->dev->last_rx = jiffies;
 		zd->stats.rx_packets++;
 		zd->stats.rx_bytes += skb->len;
 		netif_rx(skb);
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index e0ac58b..f151914 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -378,7 +378,6 @@
 		[0] = { .addr = CR_MAC_ADDR_P1 },
 		[1] = { .addr = CR_MAC_ADDR_P2 },
 	};
-	DECLARE_MAC_BUF(mac);
 
 	if (mac_addr) {
 		reqs[0].value = (mac_addr[3] << 24)
@@ -387,8 +386,7 @@
 			      |  mac_addr[0];
 		reqs[1].value = (mac_addr[5] <<  8)
 			      |  mac_addr[4];
-		dev_dbg_f(zd_chip_dev(chip),
-			"mac addr %s\n", print_mac(mac, mac_addr));
+		dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
 	} else {
 		dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
 	}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index fe1867b..07513e4 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -171,7 +171,7 @@
 
 	r = zd_reg2alpha2(mac->regdomain, alpha2);
 	if (!r)
-		regulatory_hint(hw->wiphy, alpha2, NULL);
+		regulatory_hint(hw->wiphy, alpha2);
 
 	r = 0;
 disable_int:
@@ -296,15 +296,14 @@
  * If no status information has been requested, the skb is freed.
  */
 static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-		      u32 flags, int ackssi, bool success)
+		      int ackssi, bool success)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-	memset(&info->status, 0, sizeof(info->status));
+	ieee80211_tx_info_clear_status(info);
 
-	if (!success)
-		info->status.excessive_retries = 1;
-	info->flags |= flags;
+	if (success)
+		info->flags |= IEEE80211_TX_STAT_ACK;
 	info->status.ack_signal = ackssi;
 	ieee80211_tx_status_irqsafe(hw, skb);
 }
@@ -326,7 +325,7 @@
 	if (skb == NULL)
 		return;
 
-	tx_status(hw, skb, 0, 0, 0);
+	tx_status(hw, skb, 0, 0);
 }
 
 /**
@@ -342,12 +341,12 @@
 void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hw *hw = info->driver_data[0];
+	struct ieee80211_hw *hw = info->rate_driver_data[0];
 
 	skb_pull(skb, sizeof(struct zd_ctrlset));
 	if (unlikely(error ||
 	    (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
-		tx_status(hw, skb, 0, 0, !error);
+		tx_status(hw, skb, 0, !error);
 	} else {
 		struct sk_buff_head *q =
 			&zd_hw_mac(hw)->ack_wait_queue;
@@ -406,7 +405,8 @@
 }
 
 static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
-	                   struct ieee80211_hdr *header, u32 flags)
+	                   struct ieee80211_hdr *header,
+	                   struct ieee80211_tx_info *info)
 {
 	/*
 	 * CONTROL TODO:
@@ -417,7 +417,7 @@
 	cs->control = 0;
 
 	/* First fragment */
-	if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
 		cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
 
 	/* Multicast */
@@ -428,10 +428,10 @@
 	if (ieee80211_is_pspoll(header->frame_control))
 		cs->control |= ZD_CS_PS_POLL_FRAME;
 
-	if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		cs->control |= ZD_CS_RTS;
 
-	if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		cs->control |= ZD_CS_SELF_CTS;
 
 	/* FIXME: Management frame? */
@@ -517,12 +517,12 @@
 	txrate = ieee80211_get_tx_rate(mac->hw, info);
 
 	cs->modulation = txrate->hw_value;
-	if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 		cs->modulation = txrate->hw_value_short;
 
 	cs->tx_length = cpu_to_le16(frag_len);
 
-	cs_set_control(mac, cs, hdr, info->flags);
+	cs_set_control(mac, cs, hdr, info);
 
 	packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
 	ZD_ASSERT(packet_length <= 0xffff);
@@ -577,7 +577,7 @@
 	if (r)
 		return r;
 
-	info->driver_data[0] = hw;
+	info->rate_driver_data[0] = hw;
 
 	r = zd_usb_tx(&mac->chip.usb, skb);
 	if (r)
@@ -618,7 +618,7 @@
 		if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
 		{
 			__skb_unlink(skb, q);
-			tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
+			tx_status(hw, skb, stats->signal, 1);
 			goto out;
 		}
 	}
@@ -743,9 +743,11 @@
 	zd_write_mac_addr(&mac->chip, NULL);
 }
 
-static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
+	struct ieee80211_conf *conf = &hw->conf;
+
 	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
@@ -852,14 +854,12 @@
 	if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
 		zd_mc_add_all(&hash);
 	} else {
-		DECLARE_MAC_BUF(macbuf);
-
 		zd_mc_clear(&hash);
 		for (i = 0; i < mc_count; i++) {
 			if (!mclist)
 				break;
-			dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
-				  print_mac(macbuf, mclist->dmi_addr));
+			dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n",
+				  mclist->dmi_addr);
 			zd_mc_add_addr(&hash, mclist->dmi_addr);
 			mclist = mclist->next;
 		}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index a3ccd8c..04c1396 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -909,7 +909,7 @@
 	 * it might be freed by zd_mac_tx_to_dev or mac80211)
 	 */
 	info = IEEE80211_SKB_CB(skb);
-	usb = &zd_hw_mac(info->driver_data[0])->chip.usb;
+	usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
 	zd_mac_tx_to_dev(skb, urb->status);
 	free_tx_urb(usb, urb);
 	tx_dec_submitted_urbs(usb);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index c6948d8..4b21bcf 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -841,7 +841,6 @@
 
 		/* Pass it up. */
 		netif_receive_skb(skb);
-		dev->last_rx = jiffies;
 	}
 
 	return packets_dropped;
diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c
index da42aa0..03a3f34 100644
--- a/drivers/net/xtsonic.c
+++ b/drivers/net/xtsonic.c
@@ -239,8 +239,6 @@
 	struct resource *resmem, *resirq;
 	int err = 0;
 
-	DECLARE_MAC_BUF(mac);
-
 	if ((resmem = platform_get_resource(pdev, IORESOURCE_MEM, 0)) == NULL)
 		return -ENODEV;
 
@@ -263,8 +261,8 @@
 	if ((err = register_netdev(dev)))
 		goto out1;
 
-	printk("%s: SONIC ethernet @%08lx, MAC %s, IRQ %d\n", dev->name,
-	       dev->base_addr, print_mac(mac, dev->dev_addr), dev->irq);
+	printk("%s: SONIC ethernet @%08lx, MAC %pM, IRQ %d\n", dev->name,
+	       dev->base_addr, dev->dev_addr, dev->irq);
 
 	return 0;
 
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 57e1f49..d8dbc57 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -374,7 +374,6 @@
 #else
 	int bar = 1;
 #endif
-	DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -481,10 +480,10 @@
 	if (i)
 		goto err_out_unmap_status;
 
-	printk(KERN_INFO "%s: %s type %8x at %p, %s, IRQ %d.\n",
+	printk(KERN_INFO "%s: %s type %8x at %p, %pM, IRQ %d.\n",
 		   dev->name, pci_id_tbl[chip_idx].name,
 		   ioread32(ioaddr + ChipRev), ioaddr,
-		   print_mac(mac, dev->dev_addr), irq);
+		   dev->dev_addr, irq);
 
 	if (np->drv_flags & HasMII) {
 		int phy, phy_idx = 0;
@@ -1100,11 +1099,9 @@
 			memcmp(le32_to_cpu(yp->rx_ring_dma +
 				entry*sizeof(struct yellowfin_desc)),
 				"\377\377\377\377\377\377", 6) != 0) {
-			if (bogus_rx++ == 0) {
-				DECLARE_MAC_BUF(mac);
-				printk(KERN_WARNING "%s: Bad frame to %s\n",
-					   dev->name, print_mac(mac, buf_addr));
-			}
+			if (bogus_rx++ == 0)
+				printk(KERN_WARNING "%s: Bad frame to %pM\n",
+					   dev->name, buf_addr);
 #endif
 		} else {
 			struct sk_buff *skb;
@@ -1141,7 +1138,6 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			dev->last_rx = jiffies;
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index a86c022..d7588bf 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -370,7 +370,6 @@
 	struct net_device *dev;
 	char *p;
 	int err = -ENOMEM;
-	DECLARE_MAC_BUF(mac);
 
 	/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
 	for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
@@ -397,9 +396,9 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = netinfo->netid[i];
 
-	printk(KERN_INFO "%s: ZNET at %#3lx, %s"
+	printk(KERN_INFO "%s: ZNET at %#3lx, %pM"
 	       ", using IRQ %d DMA %d and %d.\n",
-	       dev->name, dev->base_addr, print_mac(mac, dev->dev_addr),
+	       dev->name, dev->base_addr, dev->dev_addr,
 	       dev->irq, netinfo->dma1, netinfo->dma2);
 
 	if (znet_debug > 1) {
@@ -786,7 +785,6 @@
 		  }
 		  skb->protocol=eth_type_trans(skb,dev);
 		  netif_rx(skb);
-		  dev->last_rx = jiffies;
 		  dev->stats.rx_packets++;
 		  dev->stats.rx_bytes += pkt_len;
 		}
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 3926b2a..9c73df4 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -151,7 +151,6 @@
 	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
-    DECLARE_MAC_BUF(mac);
 
     /* Reset card. Who knows what dain-bramaged state it was left in. */
     {
@@ -216,7 +215,7 @@
 	dev->dev_addr[i] = SA_prom[i];
 
 #ifdef DEBUG
-    printk("%s", print_mac(mac, dev->dev_addr));
+    printk("%pM", dev->dev_addr);
 #endif
 
     ei_status.name = name;
@@ -244,8 +243,8 @@
 	return err;
     }
 
-    printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %s\n",
-	   dev->name, name, board, print_mac(mac, dev->dev_addr));
+    printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %pM\n",
+	   dev->name, name, board, dev->dev_addr);
 
     return 0;
 }
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 1b1e803..8a8fad7 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -131,17 +131,13 @@
 	mac = &cmd->data.setdelmac.mac[0];
 	/* MAC already registered, needed in couple/uncouple case */
 	if (cmd->hdr.return_code == 0x2005) {
-		QETH_DBF_MESSAGE(2, "Group MAC %02x:%02x:%02x:%02x:%02x:%02x "
-			  "already existing on %s \n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card));
+		QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s \n",
+			  mac, QETH_CARD_IFNAME(card));
 		cmd->hdr.return_code = 0;
 	}
 	if (cmd->hdr.return_code)
-		QETH_DBF_MESSAGE(2, "Could not set group MAC "
-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+		QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %x\n",
+			  mac, QETH_CARD_IFNAME(card), cmd->hdr.return_code);
 	return 0;
 }
 
@@ -163,10 +159,8 @@
 	cmd = (struct qeth_ipa_cmd *) data;
 	mac = &cmd->data.setdelmac.mac[0];
 	if (cmd->hdr.return_code)
-		QETH_DBF_MESSAGE(2, "Could not delete group MAC "
-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+		QETH_DBF_MESSAGE(2, "Could not delete group MAC %pM on %s: %x\n",
+			  mac, QETH_CARD_IFNAME(card), cmd->hdr.return_code);
 	return 0;
 }
 
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index ed6c54c..e11bce6 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1601,14 +1601,14 @@
 	case AF_INET:
 		sin = (struct sockaddr_in *)addr;
 		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
+		sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
 		*port = be16_to_cpu(sin->sin_port);
 		spin_unlock_bh(&conn->session->lock);
 		break;
 	case AF_INET6:
 		sin6 = (struct sockaddr_in6 *)addr;
 		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
+		sprintf(buf, "%pI6", &sin6->sin6_addr);
 		*port = be16_to_cpu(sin6->sin6_port);
 		spin_unlock_bh(&conn->session->lock);
 		break;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index db7ea3b..eb3a414 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -206,8 +206,7 @@
 		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
 		/* TODO: what are the ipv6 bits */
-		len = sprintf(buf, "%u.%u.%u.%u\n",
-			      NIPQUAD(ddb_entry->ip_addr));
+		len = sprintf(buf, "%pI4\n", &ddb_entry->ip_addr);
 		break;
 	default:
 		return -ENOSYS;
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 9aea43a..5ed4ae0 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -286,9 +286,7 @@
 	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
 	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
 
-	return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n",
-			atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2],
-			atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
+	return snprintf(buf, PAGE_SIZE, "%pM\n", atm_dev->esi);
 }
 
 static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 06dd114..fbea856 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -770,10 +770,7 @@
 		return sprintf(page, "%s\n", instance->description);
 
 	if (!left--)
-		return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
-			       atm_dev->esi[0], atm_dev->esi[1],
-			       atm_dev->esi[2], atm_dev->esi[3],
-			       atm_dev->esi[4], atm_dev->esi[5]);
+		return sprintf(page, "MAC: %pM\n", atm_dev->esi);
 
 	if (!left--)
 		return sprintf(page,
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 66948b7..00fa523 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -787,10 +787,8 @@
 		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 		free_netdev(net);
 	} else {
-		DECLARE_MAC_BUF(tmp);
-
-		INFO(dev, "MAC %s\n", print_mac(tmp, net->dev_addr));
-		INFO(dev, "HOST MAC %s\n", print_mac(tmp, dev->host_mac));
+		INFO(dev, "MAC %pM\n", net->dev_addr);
+		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 
 		the_dev = dev;
 	}
diff --git a/drivers/uwb/wlp/eda.c b/drivers/uwb/wlp/eda.c
index cdfe8df..10985fa 100644
--- a/drivers/uwb/wlp/eda.c
+++ b/drivers/uwb/wlp/eda.c
@@ -313,12 +313,9 @@
 	list_for_each_entry(itr, &eda->cache, list_node) {
 		if (!memcmp(itr->virt_addr, virt_addr,
 			   sizeof(itr->virt_addr))) {
-			d_printf(6, dev, "EDA: looking for "
-			       "%02x:%02x:%02x:%02x:%02x:%02x hit %02x:%02x "
+			d_printf(6, dev, "EDA: looking for %pM hit %02x:%02x "
 			       "wss %p tag 0x%02x state %u\n",
-			       virt_addr[0], virt_addr[1],
-			       virt_addr[2], virt_addr[3],
-			       virt_addr[4], virt_addr[5],
+			       virt_addr,
 			       itr->dev_addr.data[1],
 			       itr->dev_addr.data[0], itr->wss,
 			       itr->tag, itr->state);
@@ -327,24 +324,13 @@
 			found = 1;
 			break;
 		} else
-			d_printf(6, dev, "EDA: looking for "
-			       "%02x:%02x:%02x:%02x:%02x:%02x "
-			       "against "
-			       "%02x:%02x:%02x:%02x:%02x:%02x miss\n",
-			       virt_addr[0], virt_addr[1],
-			       virt_addr[2], virt_addr[3],
-			       virt_addr[4], virt_addr[5],
-			       itr->virt_addr[0], itr->virt_addr[1],
-			       itr->virt_addr[2], itr->virt_addr[3],
-			       itr->virt_addr[4], itr->virt_addr[5]);
+			d_printf(6, dev, "EDA: looking for %pM against %pM miss\n",
+			         virt_addr, itr->virt_addr);
 	}
 	if (!found) {
 		if (printk_ratelimit())
-			dev_err(dev, "EDA: Eth addr %02x:%02x:%02x"
-				":%02x:%02x:%02x not found.\n",
-				virt_addr[0], virt_addr[1],
-				virt_addr[2], virt_addr[3],
-				virt_addr[4], virt_addr[5]);
+			dev_err(dev, "EDA: Eth addr %pM not found.\n",
+				virt_addr);
 		result = -ENODEV;
 	}
 	spin_unlock_irqrestore(&eda->lock, flags);
@@ -380,19 +366,13 @@
 			   "tag state virt_addr\n");
 	list_for_each_entry(entry, &eda->cache, list_node) {
 		result += scnprintf(buf + result, PAGE_SIZE - result,
-				    "%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x "
-				    "%p 0x%02x %s "
-				    "%02x:%02x:%02x:%02x:%02x:%02x\n",
-				    entry->eth_addr[0], entry->eth_addr[1],
-				    entry->eth_addr[2], entry->eth_addr[3],
-				    entry->eth_addr[4], entry->eth_addr[5],
+				    "%pM %02x:%02x %p 0x%02x %s %pM\n",
+				    entry->eth_addr,
 				    entry->dev_addr.data[1],
 				    entry->dev_addr.data[0], entry->wss,
 				    entry->tag,
 				    wlp_wss_connect_state_str(entry->state),
-				    entry->virt_addr[0], entry->virt_addr[1],
-				    entry->virt_addr[2], entry->virt_addr[3],
-				    entry->virt_addr[4], entry->virt_addr[5]);
+				    entry->virt_addr);
 		if (result >= PAGE_SIZE)
 			break;
 	}
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 9f7d1ae..7578c1a 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -646,7 +646,7 @@
 	}
 
 	/* display one cell per line on subsequent lines */
-	seq_printf(m, "%u.%u.%u.%u\n", NIPQUAD(addr->s_addr));
+	seq_printf(m, "%pI4\n", &addr->s_addr);
 	return 0;
 }
 
@@ -737,7 +737,7 @@
 	}
 
 	/* display one cell per line on subsequent lines */
-	sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(server->addr));
+	sprintf(ipaddr, "%pI4", &server->addr);
 	seq_printf(m, "%3d %-15.15s %5d\n",
 		   atomic_read(&server->usage), ipaddr, server->fs_state);
 
diff --git a/fs/afs/server.c b/fs/afs/server.c
index 28f2451..f490995 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -105,7 +105,7 @@
 {
 	struct afs_server *server, *candidate;
 
-	_enter("%p,"NIPQUAD_FMT, cell, NIPQUAD(addr->s_addr));
+	_enter("%p,%pI4", cell, &addr->s_addr);
 
 	/* quick scan of the list to see if we already have the server */
 	read_lock(&cell->servers_lock);
@@ -168,9 +168,8 @@
 server_in_two_cells:
 	write_unlock(&cell->servers_lock);
 	kfree(candidate);
-	printk(KERN_NOTICE "kAFS:"
-	       " Server "NIPQUAD_FMT" appears to be in two cells\n",
-	       NIPQUAD(*addr));
+	printk(KERN_NOTICE "kAFS: Server %pI4 appears to be in two cells\n",
+	       addr);
 	_leave(" = -EEXIST");
 	return ERR_PTR(-EEXIST);
 }
@@ -184,7 +183,7 @@
 	struct rb_node *p;
 	struct in_addr addr = *_addr;
 
-	_enter(NIPQUAD_FMT, NIPQUAD(addr.s_addr));
+	_enter("%pI4", &addr.s_addr);
 
 	read_lock(&afs_servers_lock);
 
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index fcee929..359144c 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -121,11 +121,9 @@
 
 	/* add the server address */
 	if (server->addr.sockAddr.sin_family == AF_INET)
-		sprintf(dp, "ip4=" NIPQUAD_FMT,
-			NIPQUAD(server->addr.sockAddr.sin_addr));
+		sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr);
 	else if (server->addr.sockAddr.sin_family == AF_INET6)
-		sprintf(dp, "ip6=" NIP6_SEQFMT,
-			NIP6(server->addr.sockAddr6.sin6_addr));
+		sprintf(dp, "ip6=%pi6", &server->addr.sockAddr6.sin6_addr);
 	else
 		goto out;
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e9f9248..2df8e6d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2082,8 +2082,8 @@
 			rc = -ENOMEM;
 		else {
 			pSesInfo->server = srvTcp;
-			sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
-				NIPQUAD(sin_server.sin_addr.s_addr));
+			sprintf(pSesInfo->serverName, "%pI4",
+				&sin_server.sin_addr.s_addr);
 		}
 
 		if (!rc) {
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 9fd8889..c48c263 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -115,14 +115,14 @@
 		snprintf(buf, len, "unspecified");
 		break;
 	case AF_INET:
-		snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
+		snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
 		break;
 	case AF_INET6:
 		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
-			snprintf(buf, len, NIPQUAD_FMT,
-				 NIPQUAD(sin6->sin6_addr.s6_addr32[3]));
+			snprintf(buf, len, "%pI4",
+				 &sin6->sin6_addr.s6_addr32[3]);
 		else
-			snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr));
+			snprintf(buf, len, "%pI6", &sin6->sin6_addr);
 		break;
 	default:
 		snprintf(buf, len, "unsupported address family");
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 4e7e958..ffd3461 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -179,7 +179,7 @@
 
 	if (!nsm_use_hostnames) {
 		snprintf(buffer, XDR_ADDRBUF_LEN,
-			 NIPQUAD_FMT, NIPQUAD(argp->addr));
+			 "%pI4", &argp->addr);
 		name = buffer;
 	}
 
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 8478fc2..d74d16c 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -329,7 +329,7 @@
 	}
 
 	snprintf(nfs_data.hostname, sizeof(nfs_data.hostname),
-		 "%u.%u.%u.%u", NIPQUAD(servaddr));
+		 "%pI4", &servaddr);
 	return 0;
 }
 
@@ -421,8 +421,8 @@
 {
 	struct sockaddr_in sin;
 
-	printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
-		program, version, NIPQUAD(servaddr));
+	printk(KERN_NOTICE "Looking up port of RPC %d/%d on %pI4\n",
+		program, version, &servaddr);
 	set_sockaddr(&sin, servaddr, 0);
 	return rpcb_getport_sync(&sin, program, version, proto);
 }
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f48db67..bb0313ac 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -462,14 +462,12 @@
 	switch (sap->sa_family) {
 	case AF_INET: {
 		struct sockaddr_in *sin = (struct sockaddr_in *)sap;
-		seq_printf(m, ",mountaddr=" NIPQUAD_FMT,
-				NIPQUAD(sin->sin_addr.s_addr));
+		seq_printf(m, ",mountaddr=%pI4", &sin->sin_addr.s_addr);
 		break;
 	}
 	case AF_INET6: {
 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
-		seq_printf(m, ",mountaddr=" NIP6_FMT,
-				NIP6(sin6->sin6_addr));
+		seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr);
 		break;
 	}
 	default:
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b0bebc5..16efb8f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -719,8 +719,8 @@
 		status = nfserr_clid_inuse;
 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)
 				|| conf->cl_addr != sin->sin_addr.s_addr) {
-			dprintk("NFSD: setclientid: string in use by client"
-				"at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr));
+			dprintk("NFSD: setclientid: string in use by clientat %pI4\n",
+				&conf->cl_addr);
 			goto out;
 		}
 	}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index e3f9783..77d7b8c 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -330,7 +330,7 @@
 		return -EINVAL;
 
 	/* get ipv4 address */
-	if (sscanf(fo_path, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) != 4)
+	if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
 		return -EINVAL;
 	if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255)
 		return -EINVAL;
diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c
index 52276c0..f842487 100644
--- a/fs/ocfs2/cluster/netdebug.c
+++ b/fs/ocfs2/cluster/netdebug.c
@@ -304,8 +304,8 @@
 		 * use of it here generates a warning with -Wbitwise */
 		seq_printf(seq, "%p:\n"
 			   "  krefs:           %d\n"
-			   "  sock:            %u.%u.%u.%u:%u -> "
-					      "%u.%u.%u.%u:%u\n"
+			   "  sock:            %pI4:%u -> "
+					      "%pI4:%u\n"
 			   "  remote node:     %s\n"
 			   "  page off:        %zu\n"
 			   "  handshake ok:    %u\n"
@@ -319,8 +319,8 @@
 			   "  func type:       %u\n",
 			   sc,
 			   atomic_read(&sc->sc_kref.refcount),
-			   NIPQUAD(saddr), inet ? ntohs(sport) : 0,
-			   NIPQUAD(daddr), inet ? ntohs(dport) : 0,
+			   &saddr, inet ? ntohs(sport) : 0,
+			   &daddr, inet ? ntohs(dport) : 0,
 			   sc->sc_node->nd_name,
 			   sc->sc_page_off,
 			   sc->sc_handshake_ok,
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 816a3f6..70e8fa9 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -250,7 +250,7 @@
 
 static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page)
 {
-	return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address));
+	return sprintf(page, "%pI4\n", &node->nd_ipv4_address);
 }
 
 static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 2bcf706..9fbe849 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1597,8 +1597,8 @@
 	ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr,
 			      sizeof(myaddr));
 	if (ret) {
-		mlog(ML_ERROR, "bind failed with %d at address %u.%u.%u.%u\n",
-		     ret, NIPQUAD(mynode->nd_ipv4_address));
+		mlog(ML_ERROR, "bind failed with %d at address %pI4\n",
+		     ret, &mynode->nd_ipv4_address);
 		goto out;
 	}
 
@@ -1790,17 +1790,16 @@
 
 	node = o2nm_get_node_by_ip(sin.sin_addr.s_addr);
 	if (node == NULL) {
-		mlog(ML_NOTICE, "attempt to connect from unknown node at "
-		     "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr),
-		     ntohs(sin.sin_port));
+		mlog(ML_NOTICE, "attempt to connect from unknown node at %pI4:%d\n",
+		     &sin.sin_addr.s_addr, ntohs(sin.sin_port));
 		ret = -EINVAL;
 		goto out;
 	}
 
 	if (o2nm_this_node() > node->nd_num) {
 		mlog(ML_NOTICE, "unexpected connect attempted from a lower "
-		     "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n",
-		     node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+		     "numbered node '%s' at " "%pI4:%d with num %u\n",
+		     node->nd_name, &sin.sin_addr.s_addr,
 		     ntohs(sin.sin_port), node->nd_num);
 		ret = -EINVAL;
 		goto out;
@@ -1810,8 +1809,8 @@
 	 * and tries to connect before we see their heartbeat */
 	if (!o2hb_check_node_heartbeating_from_callback(node->nd_num)) {
 		mlog(ML_CONN, "attempt to connect from node '%s' at "
-		     "%u.%u.%u.%u:%d but it isn't heartbeating\n",
-		     node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+		     "%pI4:%d but it isn't heartbeating\n",
+		     node->nd_name, &sin.sin_addr.s_addr,
 		     ntohs(sin.sin_port));
 		ret = -EINVAL;
 		goto out;
@@ -1827,8 +1826,8 @@
 	spin_unlock(&nn->nn_lock);
 	if (ret) {
 		mlog(ML_NOTICE, "attempt to connect from node '%s' at "
-		     "%u.%u.%u.%u:%d but it already has an open connection\n",
-		     node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+		     "%pI4:%d but it already has an open connection\n",
+		     node->nd_name, &sin.sin_addr.s_addr,
 		     ntohs(sin.sin_port));
 		goto out;
 	}
@@ -1924,15 +1923,15 @@
 	sock->sk->sk_reuse = 1;
 	ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
 	if (ret < 0) {
-		mlog(ML_ERROR, "unable to bind socket at %u.%u.%u.%u:%u, "
-		     "ret=%d\n", NIPQUAD(addr), ntohs(port), ret);
+		mlog(ML_ERROR, "unable to bind socket at %pI4:%u, "
+		     "ret=%d\n", &addr, ntohs(port), ret);
 		goto out;
 	}
 
 	ret = sock->ops->listen(sock, 64);
 	if (ret < 0) {
-		mlog(ML_ERROR, "unable to listen on %u.%u.%u.%u:%u, ret=%d\n",
-		     NIPQUAD(addr), ntohs(port), ret);
+		mlog(ML_ERROR, "unable to listen on %pI4:%u, ret=%d\n",
+		     &addr, ntohs(port), ret);
 	}
 
 out:
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 9c22396..9c8d31b 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -54,3 +54,9 @@
 #endif
 
 /* */
+
+#ifdef CONFIG_NET_CLS_CGROUP
+SUBSYS(net_cls)
+#endif
+
+/* */
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 6080449..484b8a1 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -176,19 +176,20 @@
 };
 
 /* DCCP features (RFC 4340 section 6.4) */
-enum {
+enum dccp_feature_numbers {
 	DCCPF_RESERVED = 0,
 	DCCPF_CCID = 1,
-	DCCPF_SHORT_SEQNOS = 2,		/* XXX: not yet implemented */
+	DCCPF_SHORT_SEQNOS = 2,
 	DCCPF_SEQUENCE_WINDOW = 3,
-	DCCPF_ECN_INCAPABLE = 4,	/* XXX: not yet implemented */
+	DCCPF_ECN_INCAPABLE = 4,
 	DCCPF_ACK_RATIO = 5,
 	DCCPF_SEND_ACK_VECTOR = 6,
 	DCCPF_SEND_NDP_COUNT = 7,
 	DCCPF_MIN_CSUM_COVER = 8,
-	DCCPF_DATA_CHECKSUM = 9,	/* XXX: not yet implemented */
+	DCCPF_DATA_CHECKSUM = 9,
 	/* 10-127 reserved */
 	DCCPF_MIN_CCID_SPECIFIC = 128,
+	DCCPF_SEND_LEV_RATE = 192,	/* RFC 4342, sec. 8.4 */
 	DCCPF_MAX_CCID_SPECIFIC = 255,
 };
 
@@ -411,6 +412,7 @@
  * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1)
  * @dreq_isr: initial sequence number received on the Request
  * @dreq_service: service code present on the Request (there is just one)
+ * @dreq_featneg: feature negotiation options for this connection
  * The following two fields are analogous to the ones in dccp_sock:
  * @dreq_timestamp_echo: last received timestamp to echo (13.1)
  * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo
@@ -420,6 +422,7 @@
 	__u64			 dreq_iss;
 	__u64			 dreq_isr;
 	__be32			 dreq_service;
+	struct list_head	 dreq_featneg;
 	__u32			 dreq_timestamp_echo;
 	__u32			 dreq_timestamp_time;
 };
@@ -497,6 +500,7 @@
  * @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)
  * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection)
@@ -534,6 +538,7 @@
 	__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;
 	struct ccid			*dccps_hc_tx_ccid;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 14126bc..56b0eb2 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -12,8 +12,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef IEEE80211_H
-#define IEEE80211_H
+#ifndef LINUX_IEEE80211_H
+#define LINUX_IEEE80211_H
 
 #include <linux/types.h>
 #include <asm/byteorder.h>
@@ -97,7 +97,10 @@
 #define IEEE80211_MAX_FRAME_LEN		2352
 
 #define IEEE80211_MAX_SSID_LEN		32
+
 #define IEEE80211_MAX_MESH_ID_LEN	32
+#define IEEE80211_MESH_CONFIG_LEN	19
+
 #define IEEE80211_QOS_CTL_LEN		2
 #define IEEE80211_QOS_CTL_TID_MASK	0x000F
 #define IEEE80211_QOS_CTL_TAG1D_MASK	0x0007
@@ -666,6 +669,13 @@
 	u8 ra[6];
 } __attribute__ ((packed));
 
+struct ieee80211_pspoll {
+	__le16 frame_control;
+	__le16 aid;
+	u8 bssid[6];
+	u8 ta[6];
+} __attribute__ ((packed));
+
 /**
  * struct ieee80211_bar - HT Block Ack Request
  *
@@ -685,28 +695,88 @@
 #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL     0x0000
 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA  0x0004
 
+
+#define IEEE80211_HT_MCS_MASK_LEN		10
+
+/**
+ * struct ieee80211_mcs_info - MCS information
+ * @rx_mask: RX mask
+ * @rx_highest: highest supported RX rate
+ * @tx_params: TX parameters
+ */
+struct ieee80211_mcs_info {
+	u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
+	__le16 rx_highest;
+	u8 tx_params;
+	u8 reserved[3];
+} __attribute__((packed));
+
+/* 802.11n HT capability MSC set */
+#define IEEE80211_HT_MCS_RX_HIGHEST_MASK	0x3ff
+#define IEEE80211_HT_MCS_TX_DEFINED		0x01
+#define IEEE80211_HT_MCS_TX_RX_DIFF		0x02
+/* value 0 == 1 stream etc */
+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK	0x0C
+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT	2
+#define		IEEE80211_HT_MCS_TX_MAX_STREAMS	4
+#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION	0x10
+
+/*
+ * 802.11n D5.0 20.3.5 / 20.6 says:
+ * - indices 0 to 7 and 32 are single spatial stream
+ * - 8 to 31 are multiple spatial streams using equal modulation
+ *   [8..15 for two streams, 16..23 for three and 24..31 for four]
+ * - remainder are multiple spatial streams using unequal modulation
+ */
+#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33
+#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \
+	(IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
+
 /**
  * struct ieee80211_ht_cap - HT capabilities
  *
- * This structure refers to "HT capabilities element" as
- * described in 802.11n draft section 7.3.2.52
+ * This structure is the "HT capabilities element" as
+ * described in 802.11n D5.0 7.3.2.57
  */
 struct ieee80211_ht_cap {
 	__le16 cap_info;
 	u8 ampdu_params_info;
-	u8 supp_mcs_set[16];
+
+	/* 16 bytes MCS information */
+	struct ieee80211_mcs_info mcs;
+
 	__le16 extended_ht_cap_info;
 	__le32 tx_BF_cap_info;
 	u8 antenna_selection_info;
 } __attribute__ ((packed));
 
+/* 802.11n HT capabilities masks (for cap_info) */
+#define IEEE80211_HT_CAP_LDPC_CODING		0x0001
+#define IEEE80211_HT_CAP_SUP_WIDTH_20_40	0x0002
+#define IEEE80211_HT_CAP_SM_PS			0x000C
+#define IEEE80211_HT_CAP_GRN_FLD		0x0010
+#define IEEE80211_HT_CAP_SGI_20			0x0020
+#define IEEE80211_HT_CAP_SGI_40			0x0040
+#define IEEE80211_HT_CAP_TX_STBC		0x0080
+#define IEEE80211_HT_CAP_RX_STBC		0x0300
+#define IEEE80211_HT_CAP_DELAY_BA		0x0400
+#define IEEE80211_HT_CAP_MAX_AMSDU		0x0800
+#define IEEE80211_HT_CAP_DSSSCCK40		0x1000
+#define IEEE80211_HT_CAP_PSMP_SUPPORT		0x2000
+#define IEEE80211_HT_CAP_40MHZ_INTOLERANT	0x4000
+#define IEEE80211_HT_CAP_LSIG_TXOP_PROT		0x8000
+
+/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
+#define IEEE80211_HT_AMPDU_PARM_FACTOR		0x03
+#define IEEE80211_HT_AMPDU_PARM_DENSITY		0x1C
+
 /**
- * struct ieee80211_ht_cap - HT additional information
+ * struct ieee80211_ht_info - HT information
  *
- * This structure refers to "HT information element" as
- * described in 802.11n draft section 7.3.2.53
+ * This structure is the "HT information element" as
+ * described in 802.11n D5.0 7.3.2.58
  */
-struct ieee80211_ht_addt_info {
+struct ieee80211_ht_info {
 	u8 control_chan;
 	u8 ht_param;
 	__le16 operation_mode;
@@ -714,36 +784,33 @@
 	u8 basic_set[16];
 } __attribute__ ((packed));
 
-/* 802.11n HT capabilities masks */
-#define IEEE80211_HT_CAP_SUP_WIDTH		0x0002
-#define IEEE80211_HT_CAP_SM_PS			0x000C
-#define IEEE80211_HT_CAP_GRN_FLD		0x0010
-#define IEEE80211_HT_CAP_SGI_20			0x0020
-#define IEEE80211_HT_CAP_SGI_40			0x0040
-#define IEEE80211_HT_CAP_DELAY_BA		0x0400
-#define IEEE80211_HT_CAP_MAX_AMSDU		0x0800
-#define IEEE80211_HT_CAP_DSSSCCK40		0x1000
-/* 802.11n HT capability AMPDU settings */
-#define IEEE80211_HT_CAP_AMPDU_FACTOR		0x03
-#define IEEE80211_HT_CAP_AMPDU_DENSITY		0x1C
-/* 802.11n HT capability MSC set */
-#define IEEE80211_SUPP_MCS_SET_UEQM		4
-#define IEEE80211_HT_CAP_MAX_STREAMS		4
-#define IEEE80211_SUPP_MCS_SET_LEN		10
-/* maximum streams the spec allows */
-#define IEEE80211_HT_CAP_MCS_TX_DEFINED		0x01
-#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF		0x02
-#define IEEE80211_HT_CAP_MCS_TX_STREAMS		0x0C
-#define IEEE80211_HT_CAP_MCS_TX_UEQM		0x10
-/* 802.11n HT IE masks */
-#define IEEE80211_HT_IE_CHA_SEC_OFFSET		0x03
-#define IEEE80211_HT_IE_CHA_SEC_NONE	 	0x00
-#define IEEE80211_HT_IE_CHA_SEC_ABOVE 		0x01
-#define IEEE80211_HT_IE_CHA_SEC_BELOW 		0x03
-#define IEEE80211_HT_IE_CHA_WIDTH		0x04
-#define IEEE80211_HT_IE_HT_PROTECTION		0x0003
-#define IEEE80211_HT_IE_NON_GF_STA_PRSNT	0x0004
-#define IEEE80211_HT_IE_NON_HT_STA_PRSNT	0x0010
+/* for ht_param */
+#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET		0x03
+#define		IEEE80211_HT_PARAM_CHA_SEC_NONE		0x00
+#define		IEEE80211_HT_PARAM_CHA_SEC_ABOVE	0x01
+#define		IEEE80211_HT_PARAM_CHA_SEC_BELOW	0x03
+#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY		0x04
+#define IEEE80211_HT_PARAM_RIFS_MODE			0x08
+#define IEEE80211_HT_PARAM_SPSMP_SUPPORT		0x10
+#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN		0xE0
+
+/* for operation_mode */
+#define IEEE80211_HT_OP_MODE_PROTECTION			0x0003
+#define		IEEE80211_HT_OP_MODE_PROTECTION_NONE		0
+#define		IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER	1
+#define		IEEE80211_HT_OP_MODE_PROTECTION_20MHZ		2
+#define		IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED	3
+#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT		0x0004
+#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT		0x0010
+
+/* for stbc_param */
+#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON		0x0040
+#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT		0x0080
+#define IEEE80211_HT_STBC_PARAM_STBC_BEACON		0x0100
+#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT	0x0200
+#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE		0x0400
+#define IEEE80211_HT_STBC_PARAM_PCO_PHASE		0x0800
+
 
 /* block-ack parameters */
 #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
@@ -769,8 +836,7 @@
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN 0
 #define WLAN_AUTH_SHARED_KEY 1
-#define WLAN_AUTH_FAST_BSS_TRANSITION 2
-#define WLAN_AUTH_LEAP 128
+#define WLAN_AUTH_LEAP 2
 
 #define WLAN_AUTH_CHALLENGE_LEN 128
 
@@ -949,7 +1015,7 @@
 	WLAN_EID_EXT_SUPP_RATES = 50,
 	/* 802.11n */
 	WLAN_EID_HT_CAPABILITY = 45,
-	WLAN_EID_HT_EXTRA_INFO = 61,
+	WLAN_EID_HT_INFORMATION = 61,
 	/* 802.11i */
 	WLAN_EID_RSN = 48,
 	WLAN_EID_WPA = 221,
@@ -1057,4 +1123,4 @@
 		return hdr->addr1;
 }
 
-#endif /* IEEE80211_H */
+#endif /* LINUX_IEEE80211_H */
diff --git a/include/linux/if.h b/include/linux/if.h
index 6524684..2a6e296 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -65,6 +65,7 @@
 #define IFF_BONDING	0x20		/* bonding master or slave	*/
 #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 IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index fba141d..ed60f87 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -357,18 +357,6 @@
 	((unsigned char *)&addr)[3]
 #define NIPQUAD_FMT "%u.%u.%u.%u"
 
-#define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]), \
-	ntohs((addr).s6_addr16[1]), \
-	ntohs((addr).s6_addr16[2]), \
-	ntohs((addr).s6_addr16[3]), \
-	ntohs((addr).s6_addr16[4]), \
-	ntohs((addr).s6_addr16[5]), \
-	ntohs((addr).s6_addr16[6]), \
-	ntohs((addr).s6_addr16[7])
-#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
-#define NIP6_SEQFMT "%04x%04x%04x%04x%04x%04x%04x%04x"
-
 #if defined(__LITTLE_ENDIAN)
 #define HIPQUAD(addr) \
 	((unsigned char *)&addr)[3], \
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9d77b1d..12d7f44 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1742,26 +1742,31 @@
 	struct net_device *dev = skb->dev;
 	struct net_device *master = dev->master;
 
-	if (master &&
-	    (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
-		if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
-		    skb->protocol == __constant_htons(ETH_P_ARP))
-			return 0;
+	if (master) {
+		if (master->priv_flags & IFF_MASTER_ARPMON)
+			dev->last_rx = jiffies;
 
-		if (master->priv_flags & IFF_MASTER_ALB) {
-			if (skb->pkt_type != PACKET_BROADCAST &&
-			    skb->pkt_type != PACKET_MULTICAST)
+		if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
+			if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+			    skb->protocol == __constant_htons(ETH_P_ARP))
 				return 0;
-		}
-		if (master->priv_flags & IFF_MASTER_8023AD &&
-		    skb->protocol == __constant_htons(ETH_P_SLOW))
-			return 0;
 
-		return 1;
+			if (master->priv_flags & IFF_MASTER_ALB) {
+				if (skb->pkt_type != PACKET_BROADCAST &&
+				    skb->pkt_type != PACKET_MULTICAST)
+					return 0;
+			}
+			if (master->priv_flags & IFF_MASTER_8023AD &&
+			    skb->protocol == __constant_htons(ETH_P_SLOW))
+				return 0;
+
+			return 1;
+		}
 	}
 	return 0;
 }
 
+extern struct pernet_operations __net_initdata loopback_net_ops;
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_DEV_H */
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 9bad6540..7982734 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -25,8 +25,9 @@
  *
  * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
  *	to get a list of all present wiphys.
- * @NL80211_CMD_SET_WIPHY: set wiphy name, needs %NL80211_ATTR_WIPHY and
- *	%NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
+ *	%NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME
+ *	and/or %NL80211_ATTR_WIPHY_TXQ_PARAMS.
  * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
  *	or rename notification. Has attributes %NL80211_ATTR_WIPHY and
  *	%NL80211_ATTR_WIPHY_NAME.
@@ -106,6 +107,12 @@
  * 	to the the specified ISO/IEC 3166-1 alpha2 country code. The core will
  * 	store this as a valid request and then query userspace for it.
  *
+ * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the
+ *	interface identified by %NL80211_ATTR_IFINDEX
+ *
+ * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
+ *      interface identified by %NL80211_ATTR_IFINDEX
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -148,6 +155,9 @@
 	NL80211_CMD_SET_REG,
 	NL80211_CMD_REQ_SET_REG,
 
+	NL80211_CMD_GET_MESH_PARAMS,
+	NL80211_CMD_SET_MESH_PARAMS,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -169,6 +179,7 @@
  * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
  *	/sys/class/ieee80211/<phyname>/index
  * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
+ * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
  *
  * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
  * @NL80211_ATTR_IFNAME: network interface name
@@ -234,6 +245,9 @@
  *	(u8, 0 or 1)
  * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
  *	(u8, 0 or 1)
+ * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic
+ *	rates in format defined by IEEE 802.11 7.3.2.2 but without the length
+ *	restriction (at most %NL80211_MAX_SUPP_RATES).
  *
  * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
  *	association request when used with NL80211_CMD_NEW_STATION)
@@ -296,6 +310,12 @@
 	NL80211_ATTR_REG_ALPHA2,
 	NL80211_ATTR_REG_RULES,
 
+	NL80211_ATTR_MESH_PARAMS,
+
+	NL80211_ATTR_BSS_BASIC_RATES,
+
+	NL80211_ATTR_WIPHY_TXQ_PARAMS,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -307,6 +327,8 @@
  * here
  */
 #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
+#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
+#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
 
 #define NL80211_MAX_SUPP_RATES			32
 #define NL80211_MAX_SUPP_REG_RULES		32
@@ -452,17 +474,29 @@
  *	an array of nested frequency attributes
  * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
  *	an array of nested bitrate attributes
+ * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as
+ *	defined in 802.11n
+ * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
+ * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
+ * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
  */
 enum nl80211_band_attr {
 	__NL80211_BAND_ATTR_INVALID,
 	NL80211_BAND_ATTR_FREQS,
 	NL80211_BAND_ATTR_RATES,
 
+	NL80211_BAND_ATTR_HT_MCS_SET,
+	NL80211_BAND_ATTR_HT_CAPA,
+	NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
+	NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+
 	/* keep last */
 	__NL80211_BAND_ATTR_AFTER_LAST,
 	NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
 };
 
+#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+
 /**
  * enum nl80211_frequency_attr - frequency attributes
  * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
@@ -594,4 +628,113 @@
 	NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
 };
 
+/**
+ * enum nl80211_meshconf_params - mesh configuration parameters
+ *
+ * Mesh configuration parameters
+ *
+ * @__NL80211_MESHCONF_INVALID: internal use
+ *
+ * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
+ * millisecond units, used by the Peer Link Open message
+ *
+ * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in
+ * millisecond units, used by the peer link management to close a peer link
+ *
+ * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
+ * millisecond units
+ *
+ * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed
+ * on this mesh interface
+ *
+ * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link
+ * open retries that can be sent to establish a new peer link instance in a
+ * mesh
+ *
+ * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
+ * point.
+ *
+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
+ * open peer links when we detect compatible mesh peers.
+ *
+ * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
+ * containing a PREQ that an MP can send to a particular destination (path
+ * target)
+ *
+ * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths
+ * (in milliseconds)
+ *
+ * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait
+ * until giving up on a path discovery (in milliseconds)
+ *
+ * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh
+ * points receiving a PREQ shall consider the forwarding information from the
+ * root to be valid. (TU = time unit)
+ *
+ * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in
+ * TUs) during which an MP can send only one action frame containing a PREQ
+ * reference element
+ *
+ * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
+ * that it takes for an HWMP information element to propagate across the mesh
+ *
+ * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
+ *
+ * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_meshconf_params {
+	__NL80211_MESHCONF_INVALID,
+	NL80211_MESHCONF_RETRY_TIMEOUT,
+	NL80211_MESHCONF_CONFIRM_TIMEOUT,
+	NL80211_MESHCONF_HOLDING_TIMEOUT,
+	NL80211_MESHCONF_MAX_PEER_LINKS,
+	NL80211_MESHCONF_MAX_RETRIES,
+	NL80211_MESHCONF_TTL,
+	NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+	NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+	NL80211_MESHCONF_PATH_REFRESH_TIME,
+	NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+	NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+	NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+	NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+
+	/* keep last */
+	__NL80211_MESHCONF_ATTR_AFTER_LAST,
+	NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_txq_attr - TX queue parameter attributes
+ * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
+ * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
+ * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning
+ *	disabled
+ * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form
+ *	2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form
+ *	2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255]
+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
+ * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number
+ */
+enum nl80211_txq_attr {
+	__NL80211_TXQ_ATTR_INVALID,
+	NL80211_TXQ_ATTR_QUEUE,
+	NL80211_TXQ_ATTR_TXOP,
+	NL80211_TXQ_ATTR_CWMIN,
+	NL80211_TXQ_ATTR_CWMAX,
+	NL80211_TXQ_ATTR_AIFS,
+
+	/* keep last */
+	__NL80211_TXQ_ATTR_AFTER_LAST,
+	NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1
+};
+
+enum nl80211_txq_q {
+	NL80211_TXQ_Q_VO,
+	NL80211_TXQ_Q_VI,
+	NL80211_TXQ_Q_BE,
+	NL80211_TXQ_Q_BK
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index 7cf7824d..e6aa848 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -394,6 +394,20 @@
 
 #define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
 
+
+/* Cgroup classifier */
+
+enum
+{
+	TCA_CGROUP_UNSPEC,
+	TCA_CGROUP_ACT,
+	TCA_CGROUP_POLICE,
+	TCA_CGROUP_EMATCHES,
+	__TCA_CGROUP_MAX,
+};
+
+#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
+
 /* Extended Matches */
 
 struct tcf_ematch_tree_hdr
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index e649bd3..3ba2998 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -383,5 +383,22 @@
 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
 		pos = rcu_dereference(pos->next))
 
+/**
+ * hlist_for_each_entry_rcu_safenext - iterate over rcu list of given type
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ * @next:       the &struct hlist_node to use as a next cursor
+ *
+ * Special version of hlist_for_each_entry_rcu that make sure
+ * each next pointer is fetched before each iteration.
+ */
+#define hlist_for_each_entry_rcu_safenext(tpos, pos, head, member, next) \
+	for (pos = rcu_dereference((head)->first);			 \
+		pos && ({ next = pos->next; smp_rmb(); prefetch(next); 1; }) &&	\
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+		pos = rcu_dereference(next))
+
 #endif	/* __KERNEL__ */
 #endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2725f4e..a01b6f8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -250,6 +250,9 @@
  *	@tc_verd: traffic control verdict
  *	@ndisc_nodetype: router type (from link layer)
  *	@do_not_encrypt: set to prevent encryption of this frame
+ *	@requeue: set to indicate that the wireless core should attempt
+ *		a software retry on this frame if we failed to
+ *		receive an ACK for it
  *	@dma_cookie: a cookie to one of several possible DMA operations
  *		done by skb DMA functions
  *	@secmark: security marking
@@ -269,8 +272,9 @@
 		struct  dst_entry	*dst;
 		struct  rtable		*rtable;
 	};
+#ifdef CONFIG_XFRM
 	struct	sec_path	*sp;
-
+#endif
 	/*
 	 * This is the control buffer. It is free to use for every
 	 * layer. Please put your private variables there. If you
@@ -325,6 +329,7 @@
 #endif
 #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
 	__u8			do_not_encrypt:1;
+	__u8			requeue:1;
 #endif
 	/* 0/13/14 bit hole */
 
@@ -1864,6 +1869,18 @@
 	to->queue_mapping = from->queue_mapping;
 }
 
+#ifdef CONFIG_XFRM
+static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
+{
+	return skb->sp;
+}
+#else
+static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
+{
+	return NULL;
+}
+#endif
+
 static inline int skb_is_gso(const struct sk_buff *skb)
 {
 	return skb_shinfo(skb)->gso_size;
diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h
new file mode 100644
index 0000000..47c4ffd
--- /dev/null
+++ b/include/linux/smsc911x.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2004-2008 SMSC
+ * Copyright (C) 2005-2008 ARM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ ***************************************************************************/
+#ifndef __LINUX_SMSC911X_H__
+#define __LINUX_SMSC911X_H__
+
+#include <linux/phy.h>
+
+/* platform_device configuration data, should be assigned to
+ * the platform_device's dev.platform_data */
+struct smsc911x_platform_config {
+	unsigned int irq_polarity;
+	unsigned int irq_type;
+	phy_interface_t phy_interface;
+};
+
+/* Constants for platform_device irq polarity configuration */
+#define SMSC911X_IRQ_POLARITY_ACTIVE_LOW	0
+#define SMSC911X_IRQ_POLARITY_ACTIVE_HIGH	1
+
+/* Constants for platform_device irq type configuration */
+#define SMSC911X_IRQ_TYPE_OPEN_DRAIN		0
+#define SMSC911X_IRQ_TYPE_PUSH_PULL		1
+
+#endif /* __LINUX_SMSC911X_H__ */
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 6fd7b01..0127dac 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -139,14 +139,14 @@
 {
 	switch (addr->sa_family) {
 	case AF_INET:
-		snprintf(buf, len, "%u.%u.%u.%u, port=%u",
-			NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
+		snprintf(buf, len, "%pI4, port=%u",
+			&((struct sockaddr_in *)addr)->sin_addr,
 			ntohs(((struct sockaddr_in *) addr)->sin_port));
 		break;
 
 	case AF_INET6:
-		snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
-			NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
+		snprintf(buf, len, "%pI6, port=%u",
+			 &((struct sockaddr_in6 *)addr)->sin6_addr,
 			ntohs(((struct sockaddr_in6 *) addr)->sin6_port));
 		break;
 
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 4bc1e6b..52f3abd 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -199,6 +199,9 @@
 #define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO
 	XFRM_MSG_GETSPDINFO,
 #define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO
+
+	XFRM_MSG_MAPPING,
+#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
 	__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -438,6 +441,15 @@
 	__u16				new_family;
 };
 
+struct xfrm_user_mapping {
+	struct xfrm_usersa_id		id;
+	__u32				reqid;
+	xfrm_address_t			old_saddr;
+	xfrm_address_t			new_saddr;
+	__be16				old_sport;
+	__be16				new_sport;
+};
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
@@ -464,6 +476,8 @@
 #define XFRMNLGRP_REPORT	XFRMNLGRP_REPORT
 	XFRMNLGRP_MIGRATE,
 #define XFRMNLGRP_MIGRATE	XFRMNLGRP_MIGRATE
+	XFRMNLGRP_MAPPING,
+#define XFRMNLGRP_MAPPING	XFRMNLGRP_MAPPING
 	__XFRMNLGRP_MAX
 };
 #define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0e85ec3..1d57835 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -280,11 +280,16 @@
  *	(0 = no, 1 = yes, -1 = do not change)
  * @use_short_slot_time: Whether the use of short slot time is allowed
  *	(0 = no, 1 = yes, -1 = do not change)
+ * @basic_rates: basic rates in IEEE 802.11 format
+ *	(or NULL for no change)
+ * @basic_rates_len: number of basic rates
  */
 struct bss_parameters {
 	int use_cts_prot;
 	int use_short_preamble;
 	int use_short_slot_time;
+	u8 *basic_rates;
+	u8 basic_rates_len;
 };
 
 /**
@@ -331,22 +336,59 @@
 	struct ieee80211_reg_rule reg_rules[];
 };
 
-#define MHZ_TO_KHZ(freq) (freq * 1000)
-#define KHZ_TO_MHZ(freq) (freq / 1000)
-#define DBI_TO_MBI(gain) (gain * 100)
-#define MBI_TO_DBI(gain) (gain / 100)
-#define DBM_TO_MBM(gain) (gain * 100)
-#define MBM_TO_DBM(gain) (gain / 100)
+#define MHZ_TO_KHZ(freq) ((freq) * 1000)
+#define KHZ_TO_MHZ(freq) ((freq) / 1000)
+#define DBI_TO_MBI(gain) ((gain) * 100)
+#define MBI_TO_DBI(gain) ((gain) / 100)
+#define DBM_TO_MBM(gain) ((gain) * 100)
+#define MBM_TO_DBM(gain) ((gain) / 100)
 
 #define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \
-	.freq_range.start_freq_khz = (start) * 1000, \
-	.freq_range.end_freq_khz = (end) * 1000, \
-	.freq_range.max_bandwidth_khz = (bw) * 1000, \
-	.power_rule.max_antenna_gain = (gain) * 100, \
-	.power_rule.max_eirp = (eirp) * 100, \
+	.freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
+	.freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
+	.freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
+	.power_rule.max_antenna_gain = DBI_TO_MBI(gain), \
+	.power_rule.max_eirp = DBM_TO_MBM(eirp), \
 	.flags = reg_flags, \
 	}
 
+struct mesh_config {
+	/* Timeouts in ms */
+	/* Mesh plink management parameters */
+	u16 dot11MeshRetryTimeout;
+	u16 dot11MeshConfirmTimeout;
+	u16 dot11MeshHoldingTimeout;
+	u16 dot11MeshMaxPeerLinks;
+	u8  dot11MeshMaxRetries;
+	u8  dot11MeshTTL;
+	bool auto_open_plinks;
+	/* HWMP parameters */
+	u8  dot11MeshHWMPmaxPREQretries;
+	u32 path_refresh_time;
+	u16 min_discovery_timeout;
+	u32 dot11MeshHWMPactivePathTimeout;
+	u16 dot11MeshHWMPpreqMinInterval;
+	u16 dot11MeshHWMPnetDiameterTraversalTime;
+};
+
+/**
+ * struct ieee80211_txq_params - TX queue parameters
+ * @queue: TX queue identifier (NL80211_TXQ_Q_*)
+ * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range
+ *	1..32767]
+ * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range
+ *	1..32767]
+ * @aifs: Arbitration interframe space [0..255]
+ */
+struct ieee80211_txq_params {
+	enum nl80211_txq_q queue;
+	u16 txop;
+	u16 cwmin;
+	u16 cwmax;
+	u8 aifs;
+};
+
 /* from net/wireless.h */
 struct wiphy;
 
@@ -397,9 +439,17 @@
  *
  * @change_station: Modify a given station.
  *
+ * @get_mesh_params: Put the current mesh parameters into *params
+ *
+ * @set_mesh_params: Set mesh parameters.
+ *	The mask is a bitfield which tells us which parameters to
+ *	set, and which to leave alone.
+ *
  * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
  *
  * @change_bss: Modify parameters for a given BSS.
+ *
+ * @set_txq_params: Set TX queue parameters
  */
 struct cfg80211_ops {
 	int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
@@ -452,9 +502,17 @@
 	int	(*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
 			       int idx, u8 *dst, u8 *next_hop,
 			       struct mpath_info *pinfo);
-
+	int	(*get_mesh_params)(struct wiphy *wiphy,
+				struct net_device *dev,
+				struct mesh_config *conf);
+	int	(*set_mesh_params)(struct wiphy *wiphy,
+				struct net_device *dev,
+				const struct mesh_config *nconf, u32 mask);
 	int	(*change_bss)(struct wiphy *wiphy, struct net_device *dev,
 			      struct bss_parameters *params);
+
+	int	(*set_txq_params)(struct wiphy *wiphy,
+				  struct ieee80211_txq_params *params);
 };
 
 #endif /* __NET_CFG80211_H */
diff --git a/include/net/dst.h b/include/net/dst.h
index 8a8b71e..f96c4ba 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -59,8 +59,9 @@
 
 	struct neighbour	*neighbour;
 	struct hh_cache		*hh;
+#ifdef CONFIG_XFRM
 	struct xfrm_state	*xfrm;
-
+#endif
 	int			(*input)(struct sk_buff*);
 	int			(*output)(struct sk_buff*);
 
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 93a56de..738734a 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -28,6 +28,7 @@
 #include <linux/if_ether.h>	/* ETH_ALEN */
 #include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
 
 #define IEEE80211_VERSION "git-1.1.13"
 
@@ -127,10 +128,6 @@
 }
 #endif				/* CONFIG_IEEE80211_DEBUG */
 
-/* escape_essid() is intended to be used in debug (and possibly error)
- * messages. It should never be used for passing essid to user space. */
-const char *escape_essid(const char *essid, u8 essid_len);
-
 /*
  * To use the debug system:
  *
@@ -218,94 +215,6 @@
 #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
 #define WLAN_GET_SEQ_SEQ(seq)  (((seq) & IEEE80211_SCTL_SEQ) >> 4)
 
-/* Authentication algorithms */
-#define WLAN_AUTH_OPEN 0
-#define WLAN_AUTH_SHARED_KEY 1
-#define WLAN_AUTH_LEAP 2
-
-#define WLAN_AUTH_CHALLENGE_LEN 128
-
-#define WLAN_CAPABILITY_ESS (1<<0)
-#define WLAN_CAPABILITY_IBSS (1<<1)
-#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
-#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
-#define WLAN_CAPABILITY_PRIVACY (1<<4)
-#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
-#define WLAN_CAPABILITY_PBCC (1<<6)
-#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
-#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
-#define WLAN_CAPABILITY_QOS (1<<9)
-#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
-#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
-
-/* 802.11g ERP information element */
-#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
-#define WLAN_ERP_USE_PROTECTION (1<<1)
-#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
-
-/* Status codes */
-enum ieee80211_statuscode {
-	WLAN_STATUS_SUCCESS = 0,
-	WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
-	WLAN_STATUS_CAPS_UNSUPPORTED = 10,
-	WLAN_STATUS_REASSOC_NO_ASSOC = 11,
-	WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
-	WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
-	WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
-	WLAN_STATUS_CHALLENGE_FAIL = 15,
-	WLAN_STATUS_AUTH_TIMEOUT = 16,
-	WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
-	WLAN_STATUS_ASSOC_DENIED_RATES = 18,
-	/* 802.11b */
-	WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
-	WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
-	WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
-	/* 802.11h */
-	WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
-	WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
-	WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
-	/* 802.11g */
-	WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
-	WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
-	/* 802.11i */
-	WLAN_STATUS_INVALID_IE = 40,
-	WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
-	WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
-	WLAN_STATUS_INVALID_AKMP = 43,
-	WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
-	WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
-	WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
-};
-
-/* Reason codes */
-enum ieee80211_reasoncode {
-	WLAN_REASON_UNSPECIFIED = 1,
-	WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
-	WLAN_REASON_DEAUTH_LEAVING = 3,
-	WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
-	WLAN_REASON_DISASSOC_AP_BUSY = 5,
-	WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
-	WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
-	WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
-	WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
-	/* 802.11h */
-	WLAN_REASON_DISASSOC_BAD_POWER = 10,
-	WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
-	/* 802.11i */
-	WLAN_REASON_INVALID_IE = 13,
-	WLAN_REASON_MIC_FAILURE = 14,
-	WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
-	WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
-	WLAN_REASON_IE_DIFFERENT = 17,
-	WLAN_REASON_INVALID_GROUP_CIPHER = 18,
-	WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
-	WLAN_REASON_INVALID_AKMP = 20,
-	WLAN_REASON_UNSUPP_RSN_VERSION = 21,
-	WLAN_REASON_INVALID_RSN_IE_CAP = 22,
-	WLAN_REASON_IEEE8021X_FAILED = 23,
-	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
-};
-
 /* Action categories - 802.11h */
 enum ieee80211_actioncategories {
 	WLAN_ACTION_SPECTRUM_MGMT = 0,
@@ -534,15 +443,6 @@
 	MFIE_TYPE_QOS_PARAMETER = 222,
 };
 
-/* Minimal header; can be used for passing 802.11 frames with sufficient
- * information to determine what type of underlying data type is actually
- * stored in the data. */
-struct ieee80211_hdr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 payload[0];
-} __attribute__ ((packed));
-
 struct ieee80211_hdr_1addr {
 	__le16 frame_ctl;
 	__le16 duration_id;
@@ -590,18 +490,6 @@
 	__le16 qos_ctl;
 } __attribute__ ((packed));
 
-struct ieee80211_hdr_4addrqos {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-	u8 payload[0];
-	__le16 qos_ctl;
-} __attribute__ ((packed));
-
 struct ieee80211_info_element {
 	u8 id;
 	u8 len;
@@ -733,7 +621,6 @@
 
 #define MAX_WPA_IE_LEN 64
 
-#define NETWORK_EMPTY_ESSID    (1<<0)
 #define NETWORK_HAS_OFDM       (1<<1)
 #define NETWORK_HAS_CCK        (1<<2)
 
@@ -1135,22 +1022,6 @@
 	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
 static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
 					  int mode)
 {
@@ -1208,7 +1079,7 @@
 
 static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
 {
-	switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+	switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control))) {
 	case IEEE80211_1ADDR_LEN:
 		return ((struct ieee80211_hdr_1addr *)hdr)->payload;
 	case IEEE80211_2ADDR_LEN:
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index fe9fcf7..8f6abf4 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -87,12 +87,12 @@
 	int len;
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
-		len = snprintf(&buf[*idx], buf_len - *idx, "[" NIP6_FMT "]",
-			       NIP6(addr->in6)) + 1;
+		len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+			       &addr->in6) + 1;
 	else
 #endif
-		len = snprintf(&buf[*idx], buf_len - *idx, NIPQUAD_FMT,
-			       NIPQUAD(addr->ip)) + 1;
+		len = snprintf(&buf[*idx], buf_len - *idx, "%pI4",
+			       &addr->ip) + 1;
 
 	*idx += len;
 	BUG_ON(*idx > buf_len + 1);
@@ -503,9 +503,6 @@
 	char			*name;		/* scheduler name */
 	atomic_t		refcnt;		/* reference counter */
 	struct module		*module;	/* THIS_MODULE/NULL */
-#ifdef CONFIG_IP_VS_IPV6
-	int			supports_ipv6;	/* scheduler has IPv6 support */
-#endif
 
 	/* scheduler initializing service */
 	int (*init_service)(struct ip_vs_service *svc);
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
new file mode 100644
index 0000000..e1558a1
--- /dev/null
+++ b/include/net/lib80211.h
@@ -0,0 +1,18 @@
+/*
+ * lib80211.h -- common bits for IEEE802.11 wireless drivers
+ *
+ * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
+ *
+ */
+
+#ifndef LIB80211_H
+#define LIB80211_H
+
+#include <linux/ieee80211.h>
+
+/* print_ssid() is intended to be used in debug (and possibly error)
+ * messages. It should never be used for passing ssid to user space. */
+const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
+#define DECLARE_SSID_BUF(var) char var[IEEE80211_MAX_SSID_LEN * 4 + 1] __maybe_unused
+
+#endif /* LIB80211_H */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8856e2d..5385600 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3,7 +3,7 @@
  *
  * Copyright 2002-2005, Devicescape Software, Inc.
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
- * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2007-2008	Johannes Berg <johannes@sipsolutions.net>
  *
  * 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
@@ -82,22 +82,6 @@
 };
 
 /**
- * struct ieee80211_ht_bss_info - describing BSS's HT characteristics
- *
- * This structure describes most essential parameters needed
- * to describe 802.11n HT characteristics in a BSS.
- *
- * @primary_channel: channel number of primery channel
- * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width)
- * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection)
- */
-struct ieee80211_ht_bss_info {
-	u8 primary_channel;
-	u8 bss_cap;  /* use IEEE80211_HT_IE_CHA_ */
-	u8 bss_op_mode; /* use IEEE80211_HT_IE_ */
-};
-
-/**
  * enum ieee80211_max_queues - maximum number of queues
  *
  * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
@@ -115,7 +99,7 @@
  * The information provided in this structure is required for QoS
  * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
  *
- * @aifs: arbitration interface space [0..255]
+ * @aifs: arbitration interframe space [0..255]
  * @cw_min: minimum contention window [a value of the form
  *	2^n-1 in the range 1..32767]
  * @cw_max: maximum contention window [like @cw_min]
@@ -172,6 +156,19 @@
 };
 
 /**
+ * struct ieee80211_bss_ht_conf - BSS's changing HT configuration
+ * @secondary_channel_offset: secondary channel offset, uses
+ *	%IEEE80211_HT_PARAM_CHA_SEC_ values
+ * @width_40_ok: indicates that 40 MHz bandwidth may be used for TX
+ * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info)
+ */
+struct ieee80211_bss_ht_conf {
+	u8 secondary_channel_offset;
+	bool width_40_ok;
+	u16 operation_mode;
+};
+
+/**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
  * This structure keeps information about a BSS (and an association
@@ -180,15 +177,17 @@
  * @assoc: association status
  * @aid: association ID number, valid only when @assoc is true
  * @use_cts_prot: use CTS protection
- * @use_short_preamble: use 802.11b short preamble
- * @use_short_slot: use short slot time (only relevant for ERP)
+ * @use_short_preamble: use 802.11b short preamble;
+ *	if the hardware cannot handle this it must set the
+ *	IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag
+ * @use_short_slot: use short slot time (only relevant for ERP);
+ *	if the hardware cannot handle this it must set the
+ *	IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
  * @dtim_period: num of beacons before the next DTIM, for PSM
  * @timestamp: beacon timestamp
  * @beacon_int: beacon interval
  * @assoc_capability: capabilities taken from assoc resp
- * @assoc_ht: association in HT mode
- * @ht_conf: ht capabilities
- * @ht_bss_conf: ht extended capabilities
+ * @ht: BSS's HT configuration
  * @basic_rates: bitmap of basic rates, each bit stands for an
  *	index into the rate table configured by the driver in
  *	the current band.
@@ -206,10 +205,7 @@
 	u16 assoc_capability;
 	u64 timestamp;
 	u64 basic_rates;
-	/* ht related data */
-	bool assoc_ht;
-	struct ieee80211_ht_info *ht_conf;
-	struct ieee80211_ht_bss_info *ht_bss_conf;
+	struct ieee80211_bss_ht_conf ht;
 };
 
 /**
@@ -218,29 +214,24 @@
  * These flags are used with the @flags member of &ieee80211_tx_info.
  *
  * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame.
- * @IEEE80211_TX_CTL_USE_RTS_CTS: use RTS-CTS before sending frame
- * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
- *	for combined 802.11g / 802.11b networks)
+ * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence
+ *	number to this frame, taking care of not overwriting the fragment
+ *	number and increasing the sequence number only when the
+ *	IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly
+ *	assign sequence numbers to QoS-data frames but cannot do so correctly
+ *	for non-QoS-data and management frames because beacons need them from
+ *	that counter as well and mac80211 cannot guarantee proper sequencing.
+ *	If this flag is set, the driver should instruct the hardware to
+ *	assign a sequence number to the frame or assign one itself. Cf. IEEE
+ *	802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for
+ *	beacons and always be clear for frames without a sequence number field.
  * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack
- * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: TBD
  * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination
  *	station
- * @IEEE80211_TX_CTL_REQUEUE: TBD
  * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame
- * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD
- * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the
- *	through set_retry_limit configured long retry value
  * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
  * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
- * @IEEE80211_TX_CTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
- *	of streams when this flag is on can be extracted from antenna_sel_tx,
- *	so if 1 antenna is marked use SISO, 2 antennas marked use MIMO, n
- *	antennas marked use MIMO_n.
- * @IEEE80211_TX_CTL_GREEN_FIELD: use green field protection for this frame
- * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
- * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
- * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval
- * @IEEE80211_TX_CTL_INJECTED: TBD
+ * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.
  * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
  *	because the destination STA was in powersave mode.
  * @IEEE80211_TX_STAT_ACK: Frame was acknowledged
@@ -248,62 +239,66 @@
  * 	is for the whole aggregation.
  * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned,
  * 	so consider using block ack request (BAR).
- * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence
- *	number to this frame, taking care of not overwriting the fragment
- *	number and increasing the sequence number only when the
- *	IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly
- *	assign sequence numbers to QoS-data frames but cannot do so correctly
- *	for non-QoS-data and management frames because beacons need them from
- *	that counter as well and mac80211 cannot guarantee proper sequencing.
- *	If this flag is set, the driver should instruct the hardware to
- *	assign a sequence number to the frame or assign one itself. Cf. IEEE
- *	802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for
- *	beacons always be clear for frames without a sequence number field.
+ * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
+ *	set by rate control algorithms to indicate probe rate, will
+ *	be cleared for fragmented frames (except on the last fragment)
  */
 enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTL_REQ_TX_STATUS		= BIT(0),
-	IEEE80211_TX_CTL_USE_RTS_CTS		= BIT(2),
-	IEEE80211_TX_CTL_USE_CTS_PROTECT	= BIT(3),
-	IEEE80211_TX_CTL_NO_ACK			= BIT(4),
-	IEEE80211_TX_CTL_RATE_CTRL_PROBE	= BIT(5),
-	IEEE80211_TX_CTL_CLEAR_PS_FILT		= BIT(6),
-	IEEE80211_TX_CTL_REQUEUE		= BIT(7),
-	IEEE80211_TX_CTL_FIRST_FRAGMENT		= BIT(8),
-	IEEE80211_TX_CTL_SHORT_PREAMBLE		= BIT(9),
-	IEEE80211_TX_CTL_LONG_RETRY_LIMIT	= BIT(10),
-	IEEE80211_TX_CTL_SEND_AFTER_DTIM	= BIT(12),
-	IEEE80211_TX_CTL_AMPDU			= BIT(13),
-	IEEE80211_TX_CTL_OFDM_HT		= BIT(14),
-	IEEE80211_TX_CTL_GREEN_FIELD		= BIT(15),
-	IEEE80211_TX_CTL_40_MHZ_WIDTH		= BIT(16),
-	IEEE80211_TX_CTL_DUP_DATA		= BIT(17),
-	IEEE80211_TX_CTL_SHORT_GI		= BIT(18),
-	IEEE80211_TX_CTL_INJECTED		= BIT(19),
-	IEEE80211_TX_STAT_TX_FILTERED		= BIT(20),
-	IEEE80211_TX_STAT_ACK			= BIT(21),
-	IEEE80211_TX_STAT_AMPDU			= BIT(22),
-	IEEE80211_TX_STAT_AMPDU_NO_BACK		= BIT(23),
-	IEEE80211_TX_CTL_ASSIGN_SEQ		= BIT(24),
+	IEEE80211_TX_CTL_ASSIGN_SEQ		= BIT(1),
+	IEEE80211_TX_CTL_NO_ACK			= BIT(2),
+	IEEE80211_TX_CTL_CLEAR_PS_FILT		= BIT(3),
+	IEEE80211_TX_CTL_FIRST_FRAGMENT		= BIT(4),
+	IEEE80211_TX_CTL_SEND_AFTER_DTIM	= BIT(5),
+	IEEE80211_TX_CTL_AMPDU			= BIT(6),
+	IEEE80211_TX_CTL_INJECTED		= BIT(7),
+	IEEE80211_TX_STAT_TX_FILTERED		= BIT(8),
+	IEEE80211_TX_STAT_ACK			= BIT(9),
+	IEEE80211_TX_STAT_AMPDU			= BIT(10),
+	IEEE80211_TX_STAT_AMPDU_NO_BACK		= BIT(11),
+	IEEE80211_TX_CTL_RATE_CTRL_PROBE	= BIT(12),
+};
+
+enum mac80211_rate_control_flags {
+	IEEE80211_TX_RC_USE_RTS_CTS		= BIT(0),
+	IEEE80211_TX_RC_USE_CTS_PROTECT		= BIT(1),
+	IEEE80211_TX_RC_USE_SHORT_PREAMBLE	= BIT(2),
+
+	/* rate index is an MCS rate number instead of an index */
+	IEEE80211_TX_RC_MCS			= BIT(3),
+	IEEE80211_TX_RC_GREEN_FIELD		= BIT(4),
+	IEEE80211_TX_RC_40_MHZ_WIDTH		= BIT(5),
+	IEEE80211_TX_RC_DUP_DATA		= BIT(6),
+	IEEE80211_TX_RC_SHORT_GI		= BIT(7),
 };
 
 
-#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE \
-	(sizeof(((struct sk_buff *)0)->cb) - 8)
-#define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \
-	(IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *))
+/* there are 40 bytes if you don't need the rateset to be kept */
+#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
-/* maximum number of alternate rate retry stages */
-#define IEEE80211_TX_MAX_ALTRATE	3
+/* if you do need the rateset, then you have less space */
+#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24
+
+/* maximum number of rate stages */
+#define IEEE80211_TX_MAX_RATES	5
 
 /**
- * struct ieee80211_tx_altrate - alternate rate selection/status
+ * struct ieee80211_tx_rate - rate selection/status
  *
- * @rate_idx: rate index to attempt to send with
- * @limit: number of retries before fallback
+ * @idx: rate index to attempt to send with
+ * @flags: rate control flags (&enum mac80211_rate_control_flags)
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate along with the flags it used.
  */
-struct ieee80211_tx_altrate {
-	s8 rate_idx;
-	u8 limit;
+struct ieee80211_tx_rate {
+	s8 idx;
+	u8 count;
+	u8 flags;
 };
 
 /**
@@ -318,15 +313,12 @@
  * it may be NULL.
  *
  * @flags: transmit info flags, defined above
- * @band: TBD
- * @tx_rate_idx: TBD
- * @antenna_sel_tx: TBD
+ * @band: the band to transmit on (use for checking for races)
+ * @antenna_sel_tx: antenna to use, 0 for automatic diversity
  * @control: union for control data
  * @status: union for status data
  * @driver_data: array of driver_data pointers
  * @retry_count: number of retries
- * @excessive_retries: set to 1 if the frame was retried many times
- *	but not acknowledged
  * @ampdu_ack_len: number of aggregated frames.
  * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
  * @ampdu_ack_map: block ack bit map for the aggregation.
@@ -337,31 +329,43 @@
 	/* common information */
 	u32 flags;
 	u8 band;
-	s8 tx_rate_idx;
+
 	u8 antenna_sel_tx;
 
-	/* 1 byte hole */
+	/* 2 byte hole */
 
 	union {
 		struct {
+			union {
+				/* rate control */
+				struct {
+					struct ieee80211_tx_rate rates[
+						IEEE80211_TX_MAX_RATES];
+					s8 rts_cts_rate_idx;
+				};
+				/* only needed before rate control */
+				unsigned long jiffies;
+			};
 			/* NB: vif can be NULL for injected frames */
 			struct ieee80211_vif *vif;
 			struct ieee80211_key_conf *hw_key;
 			struct ieee80211_sta *sta;
-			unsigned long jiffies;
-			s8 rts_cts_rate_idx;
-			u8 retry_limit;
-			struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE];
 		} control;
 		struct {
+			struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
+			u8 ampdu_ack_len;
 			u64 ampdu_ack_map;
 			int ack_signal;
-			struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1];
-			u8 retry_count;
-			bool excessive_retries;
-			u8 ampdu_ack_len;
+			/* 8 bytes free */
 		} status;
-		void *driver_data[IEEE80211_TX_INFO_DRIVER_DATA_PTRS];
+		struct {
+			struct ieee80211_tx_rate driver_rates[
+				IEEE80211_TX_MAX_RATES];
+			void *rate_driver_data[
+				IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
+		};
+		void *driver_data[
+			IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)];
 	};
 };
 
@@ -370,6 +374,41 @@
 	return (struct ieee80211_tx_info *)skb->cb;
 }
 
+/**
+ * ieee80211_tx_info_clear_status - clear TX status
+ *
+ * @info: The &struct ieee80211_tx_info to be cleared.
+ *
+ * When the driver passes an skb back to mac80211, it must report
+ * a number of things in TX status. This function clears everything
+ * in the TX status but the rate control information (it does clear
+ * the count since you need to fill that in anyway).
+ *
+ * NOTE: You can only use this function if you do NOT use
+ *	 info->driver_data! Use info->rate_driver_data
+ *	 instead if you need only the less space that allows.
+ */
+static inline void
+ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+{
+	int i;
+
+	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) !=
+		     offsetof(struct ieee80211_tx_info, control.rates));
+	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) !=
+		     offsetof(struct ieee80211_tx_info, driver_rates));
+	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8);
+	/* clear the rate counts */
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++)
+		info->status.rates[i].count = 0;
+
+	BUILD_BUG_ON(
+	    offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+	memset(&info->status.ampdu_ack_len, 0,
+	       sizeof(struct ieee80211_tx_info) -
+	       offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+}
+
 
 /**
  * enum mac80211_rx_flags - receive flags
@@ -442,21 +481,48 @@
  *
  * Flags to define PHY configuration options
  *
- * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time
  * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported)
- * @IEEE80211_CONF_SUPPORT_HT_MODE: use 802.11n HT capabilities (if supported)
  * @IEEE80211_CONF_PS: Enable 802.11 power save mode
  */
 enum ieee80211_conf_flags {
-	/*
-	 * TODO: IEEE80211_CONF_SHORT_SLOT_TIME will be removed once drivers
-	 * have been converted to use bss_info_changed() for slot time
-	 * configuration
-	 */
-	IEEE80211_CONF_SHORT_SLOT_TIME	= (1<<0),
-	IEEE80211_CONF_RADIOTAP		= (1<<1),
-	IEEE80211_CONF_SUPPORT_HT_MODE	= (1<<2),
-	IEEE80211_CONF_PS		= (1<<3),
+	IEEE80211_CONF_RADIOTAP		= (1<<0),
+	IEEE80211_CONF_PS		= (1<<1),
+};
+
+/* XXX: remove all this once drivers stop trying to use it */
+static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void)
+{
+	return 0;
+}
+#define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME())
+
+struct ieee80211_ht_conf {
+	bool enabled;
+};
+
+/**
+ * enum ieee80211_conf_changed - denotes which configuration changed
+ *
+ * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
+ * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed
+ * @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_POWER: the TX power changed
+ * @IEEE80211_CONF_CHANGE_CHANNEL: the channel 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),
+	IEEE80211_CONF_CHANGE_BEACON_INTERVAL	= BIT(1),
+	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),
 };
 
 /**
@@ -465,34 +531,31 @@
  * This struct indicates how the driver shall configure the hardware.
  *
  * @radio_enabled: when zero, driver is required to switch off the radio.
- *	TODO make a flag
  * @beacon_int: beacon interval (TODO make interface config)
  * @listen_interval: listen interval in units of beacon interval
  * @flags: configuration flags defined above
  * @power_level: requested transmit power (in dBm)
- * @max_antenna_gain: maximum antenna gain (in dBi)
- * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
- *	1/2: antenna 0/1
- * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
- * @ht_conf: describes current self configuration of 802.11n HT capabilies
- * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters
  * @channel: the channel to tune to
+ * @ht: the HT configuration for the device
+ * @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
+ * @short_frame_max_tx_count: Maximum number of transmissions for a "short"
+ *    frame, called "dot11ShortRetryLimit" in 802.11, but actually means the
+ *    number of transmissions not the number of retries
  */
 struct ieee80211_conf {
-	int radio_enabled;
-
 	int beacon_int;
-	u16 listen_interval;
 	u32 flags;
 	int power_level;
-	int max_antenna_gain;
-	u8 antenna_sel_tx;
-	u8 antenna_sel_rx;
+
+	u16 listen_interval;
+	bool radio_enabled;
+
+	u8 long_frame_max_tx_count, short_frame_max_tx_count;
 
 	struct ieee80211_channel *channel;
-
-	struct ieee80211_ht_info ht_conf;
-	struct ieee80211_ht_bss_info ht_bss_conf;
+	struct ieee80211_ht_conf ht;
 };
 
 /**
@@ -502,11 +565,14 @@
  * use during the life of a virtual interface.
  *
  * @type: type of this virtual interface
+ * @bss_conf: BSS configuration for this interface, either our own
+ *	or the BSS we're associated to
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  */
 struct ieee80211_vif {
 	enum nl80211_iftype type;
+	struct ieee80211_bss_conf bss_conf;
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 };
@@ -550,14 +616,12 @@
  * enum ieee80211_if_conf_change - interface config change flags
  *
  * @IEEE80211_IFCC_BSSID: The BSSID changed.
- * @IEEE80211_IFCC_SSID: The SSID changed.
  * @IEEE80211_IFCC_BEACON: The beacon for this interface changed
  *	(currently AP and MESH only), use ieee80211_beacon_get().
  */
 enum ieee80211_if_conf_change {
 	IEEE80211_IFCC_BSSID	= BIT(0),
-	IEEE80211_IFCC_SSID	= BIT(1),
-	IEEE80211_IFCC_BEACON	= BIT(2),
+	IEEE80211_IFCC_BEACON	= BIT(1),
 };
 
 /**
@@ -565,11 +629,6 @@
  *
  * @changed: parameters that have changed, see &enum ieee80211_if_conf_change.
  * @bssid: BSSID of the network we are associated to/creating.
- * @ssid: used (together with @ssid_len) by drivers for hardware that
- *	generate beacons independently. The pointer is valid only during the
- *	config_interface() call, so copy the value somewhere if you need
- *	it.
- * @ssid_len: length of the @ssid field.
  *
  * This structure is passed to the config_interface() callback of
  * &struct ieee80211_hw.
@@ -577,8 +636,6 @@
 struct ieee80211_if_conf {
 	u32 changed;
 	u8 *bssid;
-	u8 *ssid;
-	size_t ssid_len;
 };
 
 /**
@@ -685,7 +742,7 @@
  * @addr: MAC address
  * @aid: AID we assigned to the station if we're an AP
  * @supp_rates: Bitmap of supported rates (per band)
- * @ht_info: HT capabilities of this STA
+ * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *), size is determined in hw information.
  */
@@ -693,7 +750,7 @@
 	u64 supp_rates[IEEE80211_NUM_BANDS];
 	u8 addr[ETH_ALEN];
 	u16 aid;
-	struct ieee80211_ht_info ht_info;
+	struct ieee80211_sta_ht_cap ht_cap;
 
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
@@ -777,6 +834,9 @@
  * @IEEE80211_HW_SPECTRUM_MGMT:
  * 	Hardware supports spectrum management defined in 802.11h
  * 	Measurement, Channel Switch, Quieting, TPC
+ *
+ * @IEEE80211_HW_AMPDU_AGGREGATION:
+ *	Hardware supports 11n A-MPDU aggregation.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_RX_INCLUDES_FCS			= 1<<1,
@@ -788,6 +848,7 @@
 	IEEE80211_HW_SIGNAL_DBM				= 1<<7,
 	IEEE80211_HW_NOISE_DBM				= 1<<8,
 	IEEE80211_HW_SPECTRUM_MGMT			= 1<<9,
+	IEEE80211_HW_AMPDU_AGGREGATION			= 1<<10,
 };
 
 /**
@@ -846,8 +907,8 @@
  * @sta_data_size: size (in bytes) of the drv_priv data area
  *	within &struct ieee80211_sta.
  *
- * @max_altrates: maximum number of alternate rate retry stages
- * @max_altrate_tries: maximum number of tries for each stage
+ * @max_rates: maximum number of alternate rate retry stages
+ * @max_rate_tries: maximum number of tries for each stage
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -864,12 +925,10 @@
 	u16 ampdu_queues;
 	u16 max_listen_interval;
 	s8 max_signal;
-	u8 max_altrates;
-	u8 max_altrate_tries;
+	u8 max_rates;
+	u8 max_rate_tries;
 };
 
-struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy);
-
 /**
  * SET_IEEE80211_DEV - set device for 802.11 hardware
  *
@@ -882,7 +941,7 @@
 }
 
 /**
- * SET_IEEE80211_PERM_ADDR - set the permanenet MAC address for 802.11 hardware
+ * SET_IEEE80211_PERM_ADDR - set the permanent MAC address for 802.11 hardware
  *
  * @hw: the &struct ieee80211_hw to set the MAC address for
  * @addr: the address to set
@@ -906,9 +965,9 @@
 ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
 		      const struct ieee80211_tx_info *c)
 {
-	if (WARN_ON(c->tx_rate_idx < 0))
+	if (WARN_ON(c->control.rates[0].idx < 0))
 		return NULL;
-	return &hw->wiphy->bands[c->band]->bitrates[c->tx_rate_idx];
+	return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx];
 }
 
 static inline struct ieee80211_rate *
@@ -924,9 +983,9 @@
 ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
 			     const struct ieee80211_tx_info *c, int idx)
 {
-	if (c->control.retries[idx].rate_idx < 0)
+	if (c->control.rates[idx + 1].idx < 0)
 		return NULL;
-	return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx];
+	return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx];
 }
 
 /**
@@ -975,7 +1034,7 @@
  * This happens everytime the iv16 wraps around (every 65536 packets). The
  * set_key() call will happen only once for each key (unless the AP did
  * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
- * provided by udpate_tkip_key only. The trigger that makes mac80211 call this
+ * provided by update_tkip_key only. The trigger that makes mac80211 call this
  * handler is software decryption with wrap around of iv16.
  */
 
@@ -1068,12 +1127,14 @@
  * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
  * @IEEE80211_AMPDU_TX_START: start Tx aggregation
  * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
+ * @IEEE80211_AMPDU_TX_RESUME: resume TX aggregation
  */
 enum ieee80211_ampdu_mlme_action {
 	IEEE80211_AMPDU_RX_START,
 	IEEE80211_AMPDU_RX_STOP,
 	IEEE80211_AMPDU_TX_START,
 	IEEE80211_AMPDU_TX_STOP,
+	IEEE80211_AMPDU_TX_RESUME,
 };
 
 /**
@@ -1109,7 +1170,7 @@
  *	Must be implemented.
  *
  * @add_interface: Called when a netdevice attached to the hardware is
- *	enabled. Because it is not called for monitor mode devices, @open
+ *	enabled. Because it is not called for monitor mode devices, @start
  *	and @stop must be implemented.
  *	The driver should perform any initialization it needs before
  *	the device can be enabled. The initial configuration for the
@@ -1175,10 +1236,8 @@
  *	the device does fragmentation by itself; if this method is assigned then
  *	the stack will not do fragmentation.
  *
- * @set_retry_limit: Configuration of retry limits (if device needs it)
- *
  * @sta_notify: Notifies low level driver about addition or removal
- *	of assocaited station or AP.
+ *	of associated station or AP.
  *
  * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
  *	bursting) for a hardware TX queue.
@@ -1219,7 +1278,7 @@
 			     struct ieee80211_if_init_conf *conf);
 	void (*remove_interface)(struct ieee80211_hw *hw,
 				 struct ieee80211_if_init_conf *conf);
-	int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+	int (*config)(struct ieee80211_hw *hw, u32 changed);
 	int (*config_interface)(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				struct ieee80211_if_conf *conf);
@@ -1246,8 +1305,6 @@
 			     u32 *iv32, u16 *iv16);
 	int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
 	int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
-	int (*set_retry_limit)(struct ieee80211_hw *hw,
-			       u32 short_retry, u32 long_retr);
 	void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum sta_notify_cmd, struct ieee80211_sta *sta);
 	int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
@@ -1480,7 +1537,7 @@
  * the next beacon frame from the 802.11 code. The low-level is responsible
  * for calling this function before beacon data is needed (e.g., based on
  * hardware interrupt). Returned skb is used only once and low-level driver
- * is responsible of freeing it.
+ * is responsible for freeing it.
  */
 struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif);
@@ -1823,24 +1880,38 @@
 
 
 /* Rate control API */
+
 /**
- * struct rate_selection - rate information for/from rate control algorithms
+ * struct ieee80211_tx_rate_control - rate control information for/from RC algo
  *
- * @rate_idx: selected transmission rate index
- * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used
- * @probe_idx: rate for probing (or -1)
- * @max_rate_idx: maximum rate index that can be used, this is
- *	input to the algorithm and will be enforced
+ * @hw: The hardware the algorithm is invoked for.
+ * @sband: The band this frame is being transmitted on.
+ * @bss_conf: the current BSS configuration
+ * @reported_rate: The rate control algorithm can fill this in to indicate
+ *	which rate should be reported to userspace as the current rate and
+ *	used for rate calculations in the mesh network.
+ * @rts: whether RTS will be used for this frame because it is longer than the
+ *	RTS threshold
+ * @short_preamble: whether mac80211 will request short-preamble transmission
+ *	if the selected rate supports it
+ * @max_rate_idx: user-requested maximum rate (not MCS for now)
+ * @skb: the skb that will be transmitted, the control information in it needs
+ *	to be filled in
  */
-struct rate_selection {
-	s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx;
+struct ieee80211_tx_rate_control {
+	struct ieee80211_hw *hw;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_bss_conf *bss_conf;
+	struct sk_buff *skb;
+	struct ieee80211_tx_rate reported_rate;
+	bool rts, short_preamble;
+	u8 max_rate_idx;
 };
 
 struct rate_control_ops {
 	struct module *module;
 	const char *name;
 	void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
-	void (*clear)(void *priv);
 	void (*free)(void *priv);
 
 	void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
@@ -1852,10 +1923,8 @@
 	void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
 			  struct ieee80211_sta *sta, void *priv_sta,
 			  struct sk_buff *skb);
-	void (*get_rate)(void *priv, struct ieee80211_supported_band *sband,
-			 struct ieee80211_sta *sta, void *priv_sta,
-			 struct sk_buff *skb,
-			 struct rate_selection *sel);
+	void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+			 struct ieee80211_tx_rate_control *txrc);
 
 	void (*add_sta_debugfs)(void *priv, void *priv_sta,
 				struct dentry *dir);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 11dd013..ce532f2 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -108,6 +108,20 @@
 
 extern int			ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir);
 
+extern struct sk_buff		*ndisc_build_skb(struct net_device *dev,
+						 const struct in6_addr *daddr,
+						 const struct in6_addr *saddr,
+						 struct icmp6hdr *icmp6h,
+						 const struct in6_addr *target,
+						 int llinfo);
+
+extern void			ndisc_send_skb(struct sk_buff *skb,
+					       struct net_device *dev,
+					       struct neighbour *neigh,
+					       const struct in6_addr *daddr,
+					       const struct in6_addr *saddr,
+					       struct icmp6hdr *icmp6h);
+
 
 
 /*
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index a6874ba2..f2f6aa7 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -112,20 +112,20 @@
 static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
 {
 #ifdef DEBUG
-	printk("tuple %p: %u " NIPQUAD_FMT ":%hu -> " NIPQUAD_FMT ":%hu\n",
+	printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n",
 	       t, t->dst.protonum,
-	       NIPQUAD(t->src.u3.ip), ntohs(t->src.u.all),
-	       NIPQUAD(t->dst.u3.ip), ntohs(t->dst.u.all));
+	       &t->src.u3.ip, ntohs(t->src.u.all),
+	       &t->dst.u3.ip, ntohs(t->dst.u.all));
 #endif
 }
 
 static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
 {
 #ifdef DEBUG
-	printk("tuple %p: %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",
+	printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n",
 	       t, t->dst.protonum,
-	       NIP6(*(struct in6_addr *)t->src.u3.all), ntohs(t->src.u.all),
-	       NIP6(*(struct in6_addr *)t->dst.u3.all), ntohs(t->dst.u.all));
+	       t->src.u3.all, ntohs(t->src.u.all),
+	       t->dst.u3.all, ntohs(t->dst.u.all));
 #endif
 }
 
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 3643bbb..46b7764 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -233,7 +233,7 @@
 extern struct nlattr *	nla_find(struct nlattr *head, int len, int attrtype);
 extern size_t		nla_strlcpy(char *dst, const struct nlattr *nla,
 				    size_t dstsize);
-extern int		nla_memcpy(void *dest, struct nlattr *src, int count);
+extern int		nla_memcpy(void *dest, const struct nlattr *src, int count);
 extern int		nla_memcmp(const struct nlattr *nla, const void *data,
 				   size_t size);
 extern int		nla_strcmp(const struct nlattr *nla, const char *str);
@@ -741,7 +741,7 @@
  * See nla_parse()
  */
 static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
-				   struct nlattr *nla,
+				   const struct nlattr *nla,
 				   const struct nla_policy *policy)
 {
 	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
@@ -875,7 +875,7 @@
  * nla_get_u32 - return payload of u32 attribute
  * @nla: u32 netlink attribute
  */
-static inline u32 nla_get_u32(struct nlattr *nla)
+static inline u32 nla_get_u32(const struct nlattr *nla)
 {
 	return *(u32 *) nla_data(nla);
 }
@@ -884,7 +884,7 @@
  * nla_get_be32 - return payload of __be32 attribute
  * @nla: __be32 netlink attribute
  */
-static inline __be32 nla_get_be32(struct nlattr *nla)
+static inline __be32 nla_get_be32(const struct nlattr *nla)
 {
 	return *(__be32 *) nla_data(nla);
 }
@@ -893,7 +893,7 @@
  * nla_get_u16 - return payload of u16 attribute
  * @nla: u16 netlink attribute
  */
-static inline u16 nla_get_u16(struct nlattr *nla)
+static inline u16 nla_get_u16(const struct nlattr *nla)
 {
 	return *(u16 *) nla_data(nla);
 }
@@ -902,7 +902,7 @@
  * nla_get_be16 - return payload of __be16 attribute
  * @nla: __be16 netlink attribute
  */
-static inline __be16 nla_get_be16(struct nlattr *nla)
+static inline __be16 nla_get_be16(const struct nlattr *nla)
 {
 	return *(__be16 *) nla_data(nla);
 }
@@ -911,7 +911,7 @@
  * nla_get_le16 - return payload of __le16 attribute
  * @nla: __le16 netlink attribute
  */
-static inline __le16 nla_get_le16(struct nlattr *nla)
+static inline __le16 nla_get_le16(const struct nlattr *nla)
 {
 	return *(__le16 *) nla_data(nla);
 }
@@ -920,7 +920,7 @@
  * nla_get_u8 - return payload of u8 attribute
  * @nla: u8 netlink attribute
  */
-static inline u8 nla_get_u8(struct nlattr *nla)
+static inline u8 nla_get_u8(const struct nlattr *nla)
 {
 	return *(u8 *) nla_data(nla);
 }
@@ -929,7 +929,7 @@
  * nla_get_u64 - return payload of u64 attribute
  * @nla: u64 netlink attribute
  */
-static inline u64 nla_get_u64(struct nlattr *nla)
+static inline u64 nla_get_u64(const struct nlattr *nla)
 {
 	u64 tmp;
 
@@ -942,7 +942,7 @@
  * nla_get_flag - return payload of flag attribute
  * @nla: flag netlink attribute
  */
-static inline int nla_get_flag(struct nlattr *nla)
+static inline int nla_get_flag(const struct nlattr *nla)
 {
 	return !!nla;
 }
@@ -953,7 +953,7 @@
  *
  * Returns the number of milliseconds in jiffies.
  */
-static inline unsigned long nla_get_msecs(struct nlattr *nla)
+static inline unsigned long nla_get_msecs(const struct nlattr *nla)
 {
 	u64 msecs = nla_get_u64(nla);
 
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index ece1c92..977f482 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -49,6 +49,8 @@
 	int sysctl_icmp_ratelimit;
 	int sysctl_icmp_ratemask;
 	int sysctl_icmp_errors_use_inbound_ifaddr;
+	int sysctl_rt_cache_rebuild_count;
+	int current_rt_cache_rebuild_count;
 
 	struct timer_list rt_secret_timer;
 	atomic_t rt_genid;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 3fe49d8..64ae1ba 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -111,6 +111,7 @@
 
 	int 			(*enqueue)(struct sk_buff *, struct Qdisc *);
 	struct sk_buff *	(*dequeue)(struct Qdisc *);
+	struct sk_buff *	(*peek)(struct Qdisc *);
 	int 			(*requeue)(struct sk_buff *, struct Qdisc *);
 	unsigned int		(*drop)(struct Qdisc *);
 
@@ -432,6 +433,40 @@
 	return __qdisc_dequeue_tail(sch, &sch->q);
 }
 
+static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch)
+{
+	return skb_peek(&sch->q);
+}
+
+/* generic pseudo peek method for non-work-conserving qdisc */
+static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
+{
+	/* we can reuse ->gso_skb because peek isn't called for root qdiscs */
+	if (!sch->gso_skb) {
+		sch->gso_skb = sch->dequeue(sch);
+		if (sch->gso_skb)
+			/* it's still part of the queue */
+			sch->q.qlen++;
+	}
+
+	return sch->gso_skb;
+}
+
+/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */
+static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
+{
+	struct sk_buff *skb = sch->gso_skb;
+
+	if (skb) {
+		sch->gso_skb = NULL;
+		sch->q.qlen--;
+	} else {
+		skb = sch->dequeue(sch);
+	}
+
+	return skb;
+}
+
 static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch,
 				  struct sk_buff_head *list)
 {
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ed71b11..2379750 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -285,15 +285,15 @@
 	if (sctp_debug_flag) { \
 		if (saddr->sa.sa_family == AF_INET6) { \
 			printk(KERN_DEBUG \
-			       lead NIP6_FMT trail, \
+			       lead "%pI6" trail, \
 			       leadparm, \
-			       NIP6(saddr->v6.sin6_addr), \
+			       &saddr->v6.sin6_addr, \
 			       otherparms); \
 		} else { \
 			printk(KERN_DEBUG \
-			       lead NIPQUAD_FMT trail, \
+			       lead "%pI4" trail, \
 			       leadparm, \
-			       NIPQUAD(saddr->v4.sin_addr.s_addr), \
+			       &saddr->v4.sin_addr.s_addr, \
 			       otherparms); \
 		} \
 	}
diff --git a/include/net/sock.h b/include/net/sock.h
index c04f9e1..08291c1 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -229,7 +229,9 @@
 	} sk_backlog;
 	wait_queue_head_t	*sk_sleep;
 	struct dst_entry	*sk_dst_cache;
+#ifdef CONFIG_XFRM
 	struct xfrm_policy	*sk_policy[2];
+#endif
 	rwlock_t		sk_dst_lock;
 	atomic_t		sk_rmem_alloc;
 	atomic_t		sk_wmem_alloc;
@@ -269,7 +271,9 @@
 	struct sk_buff		*sk_send_head;
 	__u32			sk_sndmsg_off;
 	int			sk_write_pending;
+#ifdef CONFIG_SECURITY
 	void			*sk_security;
+#endif
 	__u32			sk_mark;
 	/* XXX 4 bytes hole on 64 bit */
 	void			(*sk_state_change)(struct sock *sk);
@@ -361,6 +365,27 @@
 	return rc;
 }
 
+static __inline__ int __sk_del_node_init_rcu(struct sock *sk)
+{
+	if (sk_hashed(sk)) {
+		hlist_del_init_rcu(&sk->sk_node);
+		return 1;
+	}
+	return 0;
+}
+
+static __inline__ int sk_del_node_init_rcu(struct sock *sk)
+{
+	int rc = __sk_del_node_init_rcu(sk);
+
+	if (rc) {
+		/* paranoid for a while -acme */
+		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+		__sock_put(sk);
+	}
+	return rc;
+}
+
 static __inline__ void __sk_add_node(struct sock *sk, struct hlist_head *list)
 {
 	hlist_add_head(&sk->sk_node, list);
@@ -372,6 +397,17 @@
 	__sk_add_node(sk, list);
 }
 
+static __inline__ void __sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
+{
+	hlist_add_head_rcu(&sk->sk_node, list);
+}
+
+static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
+{
+	sock_hold(sk);
+	__sk_add_node_rcu(sk, list);
+}
+
 static __inline__ void __sk_del_bind_node(struct sock *sk)
 {
 	__hlist_del(&sk->sk_bind_node);
@@ -385,6 +421,8 @@
 
 #define sk_for_each(__sk, node, list) \
 	hlist_for_each_entry(__sk, node, list, sk_node)
+#define sk_for_each_rcu_safenext(__sk, node, list, next) \
+	hlist_for_each_entry_rcu_safenext(__sk, node, list, sk_node, next)
 #define sk_for_each_from(__sk, node) \
 	if (__sk && ({ node = &(__sk)->sk_node; 1; })) \
 		hlist_for_each_entry_from(__sk, node, sk_node)
@@ -587,8 +625,9 @@
 	int			*sysctl_rmem;
 	int			max_header;
 
-	struct kmem_cache		*slab;
+	struct kmem_cache	*slab;
 	unsigned int		obj_size;
+	int			slab_flags;
 
 	atomic_t		*orphan_count;
 
@@ -597,7 +636,7 @@
 
 	union {
 		struct inet_hashinfo	*hashinfo;
-		struct hlist_head	*udp_hash;
+		struct udp_table	*udp_table;
 		struct raw_hashinfo	*raw_hash;
 	} h;
 
diff --git a/include/net/udp.h b/include/net/udp.h
index 1e20509..df2bfe5 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -50,8 +50,15 @@
 };
 #define UDP_SKB_CB(__skb)	((struct udp_skb_cb *)((__skb)->cb))
 
-extern struct hlist_head udp_hash[UDP_HTABLE_SIZE];
-extern rwlock_t udp_hash_lock;
+struct udp_hslot {
+	struct hlist_head	head;
+	spinlock_t		lock;
+} __attribute__((aligned(2 * sizeof(long))));
+struct udp_table {
+	struct udp_hslot	hash[UDP_HTABLE_SIZE];
+};
+extern struct udp_table udp_table;
+extern void udp_table_init(struct udp_table *);
 
 
 /* Note: this must match 'valbool' in sock_setsockopt */
@@ -110,15 +117,7 @@
 	BUG();
 }
 
-static inline void udp_lib_unhash(struct sock *sk)
-{
-	write_lock_bh(&udp_hash_lock);
-	if (sk_del_node_init(sk)) {
-		inet_sk(sk)->num = 0;
-		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-	}
-	write_unlock_bh(&udp_hash_lock);
-}
+extern void udp_lib_unhash(struct sock *sk);
 
 static inline void udp_lib_close(struct sock *sk, long timeout)
 {
@@ -187,7 +186,7 @@
 struct udp_seq_afinfo {
 	char			*name;
 	sa_family_t		family;
-	struct hlist_head	*hashtable;
+	struct udp_table	*udp_table;
 	struct file_operations	seq_fops;
 	struct seq_operations	seq_ops;
 };
@@ -196,7 +195,7 @@
 	struct seq_net_private  p;
 	sa_family_t		family;
 	int			bucket;
-	struct hlist_head	*hashtable;
+	struct udp_table	*udp_table;
 };
 
 #ifdef CONFIG_PROC_FS
diff --git a/include/net/udplite.h b/include/net/udplite.h
index b76b2e3..afdffe6 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -11,7 +11,7 @@
 #define UDPLITE_RECV_CSCOV   11 /* receiver partial coverage (threshold ) */
 
 extern struct proto 		udplite_prot;
-extern struct hlist_head 	udplite_hash[UDP_HTABLE_SIZE];
+extern struct udp_table		udplite_table;
 
 /*
  *	Checksum computation is all in software, hence simpler getfrag.
diff --git a/include/net/wireless.h b/include/net/wireless.h
index 721efb3..4123515 100644
--- a/include/net/wireless.h
+++ b/include/net/wireless.h
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/debugfs.h>
 #include <linux/list.h>
+#include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 
 /**
@@ -133,23 +134,23 @@
 };
 
 /**
- * struct ieee80211_ht_info - describing STA's HT capabilities
+ * struct ieee80211_sta_ht_cap - STA's HT capabilities
  *
  * This structure describes most essential parameters needed
  * to describe 802.11n HT capabilities for an STA.
  *
- * @ht_supported: is HT supported by STA, 0: no, 1: yes
+ * @ht_supported: is HT supported by the STA
  * @cap: HT capabilities map as described in 802.11n spec
  * @ampdu_factor: Maximum A-MPDU length factor
  * @ampdu_density: Minimum A-MPDU spacing
- * @supp_mcs_set: Supported MCS set as described in 802.11n spec
+ * @mcs: Supported MCS rates
  */
-struct ieee80211_ht_info {
+struct ieee80211_sta_ht_cap {
 	u16 cap; /* use IEEE80211_HT_CAP_ */
-	u8 ht_supported;
+	bool ht_supported;
 	u8 ampdu_factor;
 	u8 ampdu_density;
-	u8 supp_mcs_set[16];
+	struct ieee80211_mcs_info mcs;
 };
 
 /**
@@ -173,7 +174,7 @@
 	enum ieee80211_band band;
 	int n_channels;
 	int n_bitrates;
-	struct ieee80211_ht_info ht_info;
+	struct ieee80211_sta_ht_cap ht_cap;
 };
 
 /**
@@ -262,9 +263,9 @@
 /**
  * wiphy_name - get wiphy name
  */
-static inline char *wiphy_name(struct wiphy *wiphy)
+static inline const char *wiphy_name(struct wiphy *wiphy)
 {
-	return wiphy->dev.bus_id;
+	return dev_name(&wiphy->dev);
 }
 
 /**
@@ -340,55 +341,36 @@
 }
 
 /**
- * __regulatory_hint - hint to the wireless core a regulatory domain
- * @wiphy: if a driver is providing the hint this is the driver's very
- * 	own &struct wiphy
- * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain
- * 	should be in. If @rd is set this should be NULL
- * @rd: a complete regulatory domain, if passed the caller need not worry
- * 	about freeing it
+ * ieee80211_get_response_rate - get basic rate for a given rate
  *
- * The Wireless subsystem can use this function to hint to the wireless core
- * what it believes should be the current regulatory domain by
- * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
- * domain should be in or by providing a completely build regulatory domain.
+ * @sband: the band to look for rates in
+ * @basic_rates: bitmap of basic rates
+ * @bitrate: the bitrate for which to find the basic rate
  *
- * Returns -EALREADY if *a regulatory domain* has already been set. Note that
- * this could be by another driver. It is safe for drivers to continue if
- * -EALREADY is returned, if drivers are not capable of world roaming they
- * should not register more channels than they support. Right now we only
- * support listening to the first driver hint. If the driver is capable
- * of world roaming but wants to respect its own EEPROM mappings for
- * specific regulatory domains it should register the @reg_notifier callback
- * on the &struct wiphy. Returns 0 if the hint went through fine or through an
- * intersection operation. Otherwise a standard error code is returned.
- *
+ * This function returns the basic rate corresponding to a given
+ * bitrate, that is the next lower bitrate contained in the basic
+ * rate map, which is, for this function, given as a bitmap of
+ * indices of rates in the band's bitrate table.
  */
-extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
-		const char *alpha2, struct ieee80211_regdomain *rd);
+struct ieee80211_rate *
+ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
+			    u64 basic_rates, int bitrate);
+
 /**
  * regulatory_hint - driver hint to the wireless core a regulatory domain
- * @wiphy: the driver's very own &struct wiphy
+ * @wiphy: the wireless device giving the hint (used only for reporting
+ *	conflicts)
  * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
  * 	should be in. If @rd is set this should be NULL. Note that if you
  * 	set this to NULL you should still set rd->alpha2 to some accepted
  * 	alpha2.
- * @rd: a complete regulatory domain provided by the driver. If passed
- * 	the driver does not need to worry about freeing it.
  *
  * Wireless drivers can use this function to hint to the wireless core
  * what it believes should be the current regulatory domain by
  * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
  * domain should be in or by providing a completely build regulatory domain.
  * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried
- * for a regulatory domain structure for the respective country. If
- * a regulatory domain is build and passed you should set the alpha2
- * if possible, otherwise set it to the special value of "99" which tells
- * the wireless core it is unknown. If you pass a built regulatory domain
- * and we return non zero you are in charge of kfree()'ing the structure.
- *
- * See __regulatory_hint() documentation for possible return values.
+ * for a regulatory domain structure for the respective country.
  */
-extern int regulatory_hint(struct wiphy *wiphy,
-		const char *alpha2, struct ieee80211_regdomain *rd);
+extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2);
 #endif /* __NET_WIRELESS_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 11c890a..45e11b3 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -467,7 +467,6 @@
 
 struct xfrm_policy
 {
-	struct xfrm_policy	*next;
 	struct hlist_node	bydst;
 	struct hlist_node	byidx;
 
@@ -882,6 +881,7 @@
 	u32 path_cookie;
 };
 
+#ifdef CONFIG_XFRM
 static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 {
 	dst_release(xdst->route);
@@ -894,6 +894,7 @@
 	xdst->partner = NULL;
 #endif
 }
+#endif
 
 extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
@@ -1536,9 +1537,11 @@
 }
 #endif
 
+#ifdef CONFIG_XFRM
 static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
 {
 	return skb->sp->xvec[skb->sp->len - 1];
 }
+#endif
 
 #endif	/* _NET_XFRM_H */
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a013bbc..6897724 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -581,6 +581,62 @@
 	return string(buf, end, sym, field_width, precision, flags);
 }
 
+static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
+				int precision, int flags)
+{
+	char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
+	char *p = mac_addr;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		p = pack_hex_byte(p, addr[i]);
+		if (!(flags & SPECIAL) && i != 5)
+			*p++ = ':';
+	}
+	*p = '\0';
+
+	return string(buf, end, mac_addr, field_width, precision, flags & ~SPECIAL);
+}
+
+static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
+			 int precision, int flags)
+{
+	char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
+	char *p = ip6_addr;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		p = pack_hex_byte(p, addr[2 * i]);
+		p = pack_hex_byte(p, addr[2 * i + 1]);
+		if (!(flags & SPECIAL) && i != 7)
+			*p++ = ':';
+	}
+	*p = '\0';
+
+	return string(buf, end, ip6_addr, field_width, precision, flags & ~SPECIAL);
+}
+
+static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
+			 int precision, int flags)
+{
+	char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
+	char temp[3];	/* hold each IP quad in reverse order */
+	char *p = ip4_addr;
+	int i, digits;
+
+	for (i = 0; i < 4; i++) {
+		digits = put_dec_trunc(temp, addr[i]) - temp;
+		/* reverse the digits in the quad */
+		while (digits--)
+			*p++ = temp[digits];
+		if (i != 3)
+			*p++ = '.';
+	}
+	*p = '\0';
+
+	return string(buf, end, ip4_addr, field_width, precision, flags & ~SPECIAL);
+}
+
 /*
  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
  * by an extra set of alphanumeric characters that are extended format
@@ -592,6 +648,12 @@
  * - 'S' For symbolic direct pointers
  * - 'R' For a struct resource pointer, it prints the range of
  *       addresses (not the name nor the flags)
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+ *       usual colon-separated hex notation
+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
+ *       decimal for v4 and colon separated network-order 16 bit hex for v6)
+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
+ *       currently the same
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -607,6 +669,18 @@
 		return symbol_string(buf, end, ptr, field_width, precision, flags);
 	case 'R':
 		return resource_string(buf, end, ptr, field_width, precision, flags);
+	case 'M':
+		return mac_address_string(buf, end, ptr, field_width, precision, flags);
+	case 'i':
+		flags |= SPECIAL;
+		/* Fallthrough */
+	case 'I':
+		if (fmt[1] == '6')
+			return ip6_addr_string(buf, end, ptr, field_width, precision, flags);
+		if (fmt[1] == '4')
+			return ip4_addr_string(buf, end, ptr, field_width, precision, flags);
+		flags &= ~SPECIAL;
+		break;
 	}
 	flags |= SMALL;
 	if (field_width == -1) {
diff --git a/net/802/tr.c b/net/802/tr.c
index 18c6647..158150f 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -285,10 +285,7 @@
 		if(entry)
 		{
 #if TR_SR_DEBUG
-{
-DECLARE_MAC_BUF(mac);
-printk("source routing for %s\n",print_mac(mac, trh->daddr));
-}
+printk("source routing for %pM\n", trh->daddr);
 #endif
 			if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
 			{
@@ -370,9 +367,8 @@
 	if(entry==NULL)
 	{
 #if TR_SR_DEBUG
-		DECLARE_MAC_BUF(mac);
-		printk("adding rif_entry: addr:%s rcf:%04X\n",
-		       print_mac(mac, trh->saddr), ntohs(trh->rcf));
+		printk("adding rif_entry: addr:%pM rcf:%04X\n",
+		       trh->saddr, ntohs(trh->rcf));
 #endif
 		/*
 		 *	Allocate our new entry. A failure to allocate loses
@@ -417,11 +413,8 @@
 			 !(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
 		    {
 #if TR_SR_DEBUG
-{
-DECLARE_MAC_BUF(mac);
-printk("updating rif_entry: addr:%s rcf:%04X\n",
-		print_mac(mac, trh->saddr), ntohs(trh->rcf));
-}
+printk("updating rif_entry: addr:%pM rcf:%04X\n",
+		trh->saddr, ntohs(trh->rcf));
 #endif
 			    entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
 			    memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
@@ -532,7 +525,6 @@
 {
 	int j, rcf_len, segment, brdgnmb;
 	struct rif_cache *entry = v;
-	DECLARE_MAC_BUF(mac);
 
 	if (v == SEQ_START_TOKEN)
 		seq_puts(seq,
@@ -542,9 +534,9 @@
 		long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout)
 				- (long) jiffies;
 
-		seq_printf(seq, "%s %s %7li ",
+		seq_printf(seq, "%s %pM %7li ",
 			   dev?dev->name:"?",
-			   print_mac(mac, entry->addr),
+			   entry->addr,
 			   ttl/HZ);
 
 			if (entry->local_ring)
@@ -643,7 +635,7 @@
 		.data		= &sysctl_tr_rif_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ 0 },
 };
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index f0e335a..72326b9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -46,10 +46,10 @@
 /* Our listing of VLAN group(s) */
 static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
 
-static char vlan_fullname[] = "802.1Q VLAN Support";
-static char vlan_version[] = DRV_VERSION;
-static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
-static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
+const char vlan_fullname[] = "802.1Q VLAN Support";
+const char vlan_version[] = DRV_VERSION;
+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),
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index a6603a4..82570bc 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -108,8 +108,10 @@
 static inline void vlan_gvrp_uninit(void) {}
 #endif
 
-int vlan_netlink_init(void);
-void vlan_netlink_fini(void);
+extern const char vlan_fullname[];
+extern const char vlan_version[];
+extern int vlan_netlink_init(void);
+extern void vlan_netlink_fini(void);
 
 extern struct rtnl_link_ops vlan_link_ops;
 
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 68ced4b..dd86a1d 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -47,8 +47,6 @@
 	skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
 	skb->vlan_tci = 0;
 
-	dev->last_rx = jiffies;
-
 	stats = &dev->stats;
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 8883e9c..e4bf39f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -163,8 +163,6 @@
 		goto err_unlock;
 	}
 
-	skb->dev->last_rx = jiffies;
-
 	stats = &skb->dev->stats;
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
@@ -648,6 +646,26 @@
 	}
 }
 
+static int vlan_ethtool_get_settings(struct net_device *dev,
+				     struct ethtool_cmd *cmd)
+{
+	const struct vlan_dev_info *vlan = vlan_dev_info(dev);
+	struct net_device *real_dev = vlan->real_dev;
+
+	if (!real_dev->ethtool_ops->get_settings)
+		return -EOPNOTSUPP;
+
+	return real_dev->ethtool_ops->get_settings(real_dev, cmd);
+}
+
+static void vlan_ethtool_get_drvinfo(struct net_device *dev,
+				     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, vlan_fullname);
+	strcpy(info->version, vlan_version);
+	strcpy(info->fw_version, "N/A");
+}
+
 static u32 vlan_ethtool_get_rx_csum(struct net_device *dev)
 {
 	const struct vlan_dev_info *vlan = vlan_dev_info(dev);
@@ -672,6 +690,8 @@
 }
 
 static const struct ethtool_ops vlan_ethtool_ops = {
+	.get_settings	        = vlan_ethtool_get_settings,
+	.get_drvinfo	        = vlan_ethtool_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_rx_csum		= vlan_ethtool_get_rx_csum,
 	.get_flags		= vlan_ethtool_get_flags,
diff --git a/net/Kconfig b/net/Kconfig
index d789d79..8c3d97c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -27,7 +27,7 @@
 config NET_NS
 	bool "Network namespace support"
 	default n
-	depends on EXPERIMENTAL && !SYSFS && NAMESPACES
+	depends on EXPERIMENTAL && NAMESPACES
 	help
 	  Allow user space to create what appear to be multiple instances
 	  of the network stack.
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index b25c1e9..b03ff58 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -995,7 +995,6 @@
 	struct aarp_iter_state *iter = seq->private;
 	struct aarp_entry *entry = v;
 	unsigned long now = jiffies;
-	DECLARE_MAC_BUF(mac);
 
 	if (v == SEQ_START_TOKEN)
 		seq_puts(seq,
@@ -1006,7 +1005,7 @@
 			   ntohs(entry->target_addr.s_net),
 			   (unsigned int) entry->target_addr.s_node,
 			   entry->dev ? entry->dev->name : "????");
-		seq_printf(seq, "%s", print_mac(mac, entry->hwaddr));
+		seq_printf(seq, "%pM", entry->hwaddr);
 		seq_printf(seq, " %8s",
 			   dt2str((long)entry->expires_at - (long)now));
 		if (iter->table == unresolved)
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index 621805d..8d237b1 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -17,8 +17,8 @@
 		.data		= &sysctl_aarp_expiry_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_ATALK_AARP_TICK_TIME,
@@ -26,8 +26,8 @@
 		.data		= &sysctl_aarp_tick_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_ATALK_AARP_RETRANSMIT_LIMIT,
@@ -35,7 +35,7 @@
 		.data		= &sysctl_aarp_retransmit_limit,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_ATALK_AARP_RESOLVE_TIME,
@@ -43,8 +43,8 @@
 		.data		= &sysctl_aarp_resolve_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{ 0 },
 };
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index 1b88311..b5674dc 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -149,7 +149,7 @@
 	cdev->class = &atm_class;
 	dev_set_drvdata(cdev, adev);
 
-	snprintf(cdev->bus_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number);
+	dev_set_name(cdev, "%s%d", adev->type, adev->number);
 	err = device_register(cdev);
 	if (err < 0)
 		return err;
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 280de48..29ef8dc 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -698,12 +698,11 @@
 						    br2684_devs);
 	const struct net_device *net_dev = brdev->net_dev;
 	const struct br2684_vcc *brvcc;
-	DECLARE_MAC_BUF(mac);
 
-	seq_printf(seq, "dev %.16s: num=%d, mac=%s (%s)\n",
+	seq_printf(seq, "dev %.16s: num=%d, mac=%pM (%s)\n",
 		   net_dev->name,
 		   brdev->number,
-		   print_mac(mac, net_dev->dev_addr),
+		   net_dev->dev_addr,
 		   brdev->mac_was_set ? "set" : "auto");
 
 	list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 5b5b963..2d33a83 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -822,8 +822,8 @@
 	seq_printf(seq, "%-6s%-4s%-4s%5ld ",
 		   dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
 
-	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
-			NIPQUAD(entry->ip));
+	off = scnprintf(buf, sizeof(buf) - 1, "%pI4",
+			&entry->ip);
 	while (off < 16)
 		buf[off++] = ' ';
 	buf[off] = '\0';
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 8f701cd..1def62d 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -373,19 +373,13 @@
 		if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
 			pr_debug("%s:lec_start_xmit: queuing packet, ",
 				dev->name);
-			pr_debug("MAC address " MAC_FMT "\n",
-				 lec_h->h_dest[0], lec_h->h_dest[1],
-				 lec_h->h_dest[2], lec_h->h_dest[3],
-				 lec_h->h_dest[4], lec_h->h_dest[5]);
+			pr_debug("MAC address %pM\n", lec_h->h_dest);
 			skb_queue_tail(&entry->tx_wait, skb);
 		} else {
 			pr_debug
 			    ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
 			     dev->name);
-			pr_debug("MAC address " MAC_FMT "\n",
-				 lec_h->h_dest[0], lec_h->h_dest[1],
-				 lec_h->h_dest[2], lec_h->h_dest[3],
-				 lec_h->h_dest[4], lec_h->h_dest[5]);
+			pr_debug("MAC address %pM\n", lec_h->h_dest);
 			priv->stats.tx_dropped++;
 			dev_kfree_skb(skb);
 		}
@@ -397,10 +391,7 @@
 
 	while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
 		pr_debug("lec.c: emptying tx queue, ");
-		pr_debug("MAC address " MAC_FMT "\n",
-			 lec_h->h_dest[0], lec_h->h_dest[1],
-			 lec_h->h_dest[2], lec_h->h_dest[3],
-			 lec_h->h_dest[4], lec_h->h_dest[5]);
+		pr_debug("MAC address %pM\n", lec_h->h_dest);
 		lec_send(vcc, skb2, priv);
 	}
 
@@ -539,15 +530,8 @@
 		{
 			struct net_bridge_fdb_entry *f;
 
-			pr_debug
-			    ("%s: bridge zeppelin asks about " MAC_FMT "\n",
-			     dev->name,
-			     mesg->content.proxy.mac_addr[0],
-			     mesg->content.proxy.mac_addr[1],
-			     mesg->content.proxy.mac_addr[2],
-			     mesg->content.proxy.mac_addr[3],
-			     mesg->content.proxy.mac_addr[4],
-			     mesg->content.proxy.mac_addr[5]);
+			pr_debug("%s: bridge zeppelin asks about %pM\n",
+				 dev->name, mesg->content.proxy.mac_addr);
 
 			if (br_fdb_get_hook == NULL || dev->br_port == NULL)
 				break;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 11b16d1..010b1d2 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -232,8 +232,8 @@
 	seq_printf(m, "IP address\n  TX:max_pcr pcr     min_pcr max_cdv max_sdu\n  RX:max_pcr pcr     min_pcr max_cdv max_sdu\n");
 
 	while (qos != NULL) {
-		seq_printf(m, "%u.%u.%u.%u\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
-				NIPQUAD(qos->ipaddr),
+		seq_printf(m, "%pI4\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
+				&qos->ipaddr,
 				qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
 				qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
 		qos = qos->next;
@@ -595,8 +595,8 @@
 			if (in_entry != NULL) mpc->in_ops->put(in_entry);
 			return -EINVAL;
 		}
-		printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
-		       mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
+		printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %pI4\n",
+		       mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
 		in_entry->shortcut = vcc;
 		mpc->in_ops->put(in_entry);
 	} else {
@@ -627,8 +627,8 @@
 	dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
 	in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
 	if (in_entry) {
-		dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
-		       mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
+		dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %pI4\n",
+		       mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
 		in_entry->shortcut = NULL;
 		mpc->in_ops->put(in_entry);
 	}
@@ -1098,7 +1098,8 @@
 				    entry->shortcut = eg_entry->shortcut;
 		}
 		if(entry->shortcut){
-			dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip));
+			dprintk("mpoa: (%s) using egress SVC to reach %pI4\n",
+				client->dev->name, &dst_ip);
 			client->eg_ops->put(eg_entry);
 			return;
 		}
@@ -1123,7 +1124,8 @@
 	__be32 dst_ip = msg->content.in_info.in_dst_ip;
 	in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
 
-	dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
+	dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %pI4\n",
+		mpc->dev->name, &dst_ip);
 	ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
 	if(entry == NULL){
 		printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
@@ -1171,14 +1173,14 @@
 	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
 
 	if(entry == NULL){
-		printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
-		printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
+		printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ip = %pI4\n",
+		       mpc->dev->name, &dst_ip);
 		return;
 	}
 
 	do {
-		dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
-			mpc->dev->name, NIPQUAD(dst_ip));
+		dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %pI4\n",
+			mpc->dev->name, &dst_ip);
 		write_lock_bh(&mpc->ingress_lock);
 		mpc->in_ops->remove_entry(entry, mpc);
 		write_unlock_bh(&mpc->ingress_lock);
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 24799e3..4504a4b 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -94,7 +94,7 @@
 		return NULL;
 	}
 
-	dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
+	dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %pI4\n", &dst_ip);
 
 	atomic_set(&entry->use, 1);
 	dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
@@ -150,7 +150,8 @@
 
 	if( entry->count > mpc->parameters.mpc_p1 &&
 	    entry->entry_state == INGRESS_INVALID){
-		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, NIPQUAD(entry->ctrl_info.in_dst_ip));
+		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %pI4, sending MPOA res req\n",
+			mpc->dev->name, &entry->ctrl_info.in_dst_ip);
 		entry->entry_state = INGRESS_RESOLVING;
 		msg.type =  SND_MPOA_RES_RQST;
 		memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
@@ -184,7 +185,8 @@
 	struct k_message msg;
 
 	vcc = entry->shortcut;
-	dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",NIPQUAD(entry->ctrl_info.in_dst_ip));
+	dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %pI4\n",
+		&entry->ctrl_info.in_dst_ip);
 
 	if (entry->prev != NULL)
 		entry->prev->next = entry->next;
@@ -228,7 +230,8 @@
 		next_entry = entry->next;
 		if((now.tv_sec - entry->tv.tv_sec)
 		   > entry->ctrl_info.holding_time){
-			dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(entry->ctrl_info.in_dst_ip));
+			dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %pI4\n",
+				&entry->ctrl_info.in_dst_ip);
 			client->in_ops->remove_entry(entry, client);
 		}
 		entry = next_entry;
@@ -453,7 +456,8 @@
 		return NULL;
 	}
 
-	dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip));
+	dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %pI4, this should be our IP\n",
+		&msg->content.eg_info.eg_dst_ip);
 
 	atomic_set(&entry->use, 1);
 	dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
@@ -469,8 +473,8 @@
 	do_gettimeofday(&(entry->tv));
 	entry->entry_state = EGRESS_RESOLVED;
 	dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
-	dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n",
-		NIPQUAD(entry->ctrl_info.mps_ip));
+	dprintk("mpoa: mpoa_caches.c: mps_ip = %pI4\n",
+		&entry->ctrl_info.mps_ip);
 	atomic_inc(&entry->use);
 
 	write_unlock_irq(&client->egress_lock);
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index f288fc4..c1d877b 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -43,8 +43,8 @@
 		.procname	= "ip_default_mode",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_ipdefmode,
 		.extra2		= &max_ipdefmode
 	},
@@ -53,8 +53,8 @@
 		.procname	= "ax25_default_mode",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_axdefmode,
 		.extra2		= &max_axdefmode
 	},
@@ -63,8 +63,8 @@
 		.procname	= "backoff_type",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_backoff,
 		.extra2		= &max_backoff
 	},
@@ -73,8 +73,8 @@
 		.procname	= "connect_mode",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_conmode,
 		.extra2		= &max_conmode
 	},
@@ -83,8 +83,8 @@
 		.procname	= "standard_window_size",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_window,
 		.extra2		= &max_window
 	},
@@ -93,8 +93,8 @@
 		.procname	= "extended_window_size",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_ewindow,
 		.extra2		= &max_ewindow
 	},
@@ -103,8 +103,8 @@
 		.procname	= "t1_timeout",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t1,
 		.extra2		= &max_t1
 	},
@@ -113,8 +113,8 @@
 		.procname	= "t2_timeout",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t2,
 		.extra2		= &max_t2
 	},
@@ -123,8 +123,8 @@
 		.procname	= "t3_timeout",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t3,
 		.extra2		= &max_t3
 	},
@@ -133,8 +133,8 @@
 		.procname	= "idle_timeout",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_idle,
 		.extra2		= &max_idle
 	},
@@ -143,8 +143,8 @@
 		.procname	= "maximum_retry_count",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_n2,
 		.extra2		= &max_n2
 	},
@@ -153,8 +153,8 @@
 		.procname	= "maximum_packet_length",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_paclen,
 		.extra2		= &max_paclen
 	},
@@ -163,8 +163,8 @@
 		.procname	= "protocol",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_proto,
 		.extra2		= &max_proto
 	},
@@ -174,8 +174,8 @@
 		.procname	= "dama_slave_timeout",
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_ds_timeout,
 		.extra2		= &max_ds_timeout
 	},
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 80ba30c..7a4d530 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -311,7 +311,6 @@
 	struct sk_buff *nskb;
 	u8 type;
 
-	dev->last_rx = jiffies;
 	s->stats.rx_bytes += skb->len;
 
 	type = *(u8 *) skb->data; skb_pull(skb, 1);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index f4f6615..f2bbb2f 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -113,8 +113,7 @@
 	conn->dev.class = bt_class;
 	conn->dev.parent = &hdev->dev;
 
-	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d",
-					hdev->name, conn->handle);
+	dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
 
 	dev_set_drvdata(&conn->dev, conn);
 
@@ -132,7 +131,7 @@
  */
 static int __match_tty(struct device *dev, void *data)
 {
-	return !strncmp(dev->bus_id, "rfcomm", 6);
+	return !strncmp(dev_name(dev), "rfcomm", 6);
 }
 
 static void del_conn(struct work_struct *work)
@@ -421,7 +420,7 @@
 	dev->class = bt_class;
 	dev->parent = hdev->parent;
 
-	strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
+	dev_set_name(dev, hdev->name);
 
 	dev_set_drvdata(dev, hdev);
 
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index fa5cda4..db6176d 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -938,35 +938,35 @@
 		.data		= &brnf_call_arptables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &brnf_sysctl_call_tables,
+		.proc_handler	= brnf_sysctl_call_tables,
 	},
 	{
 		.procname	= "bridge-nf-call-iptables",
 		.data		= &brnf_call_iptables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &brnf_sysctl_call_tables,
+		.proc_handler	= brnf_sysctl_call_tables,
 	},
 	{
 		.procname	= "bridge-nf-call-ip6tables",
 		.data		= &brnf_call_ip6tables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &brnf_sysctl_call_tables,
+		.proc_handler	= brnf_sysctl_call_tables,
 	},
 	{
 		.procname	= "bridge-nf-filter-vlan-tagged",
 		.data		= &brnf_filter_vlan_tagged,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &brnf_sysctl_call_tables,
+		.proc_handler	= brnf_sysctl_call_tables,
 	},
 	{
 		.procname	= "bridge-nf-filter-pppoe-tagged",
 		.data		= &brnf_filter_pppoe_tagged,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &brnf_sysctl_call_tables,
+		.proc_handler	= brnf_sysctl_call_tables,
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 3d33c60..d44cbf8 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -79,7 +79,6 @@
 	}
 }
 
-#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
 static void
 ebt_log_packet(u_int8_t pf, unsigned int hooknum,
    const struct sk_buff *skb, const struct net_device *in,
@@ -113,9 +112,8 @@
 			printk(" INCOMPLETE IP header");
 			goto out;
 		}
-		printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
-		       "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
-		       NIPQUAD(ih->daddr), ih->tos, ih->protocol);
+		printk(" IP SRC=%pI4 IP DST=%pI4, IP tos=0x%02X, IP proto=%d",
+		       &ih->saddr, &ih->daddr, ih->tos, ih->protocol);
 		print_ports(skb, ih->protocol, ih->ihl*4);
 		goto out;
 	}
@@ -133,10 +131,8 @@
 			printk(" INCOMPLETE IPv6 header");
 			goto out;
 		}
-		printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x "
-		       "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 "
-		       "priority=0x%01X, Next Header=%d", NIP6(ih->saddr),
-		       NIP6(ih->daddr), ih->priority, ih->nexthdr);
+		printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
+		       &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
 		nexthdr = ih->nexthdr;
 		offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr);
 		if (offset_ph == -1)
@@ -177,12 +173,10 @@
 			}
 			printk(" ARP MAC SRC=");
 			print_MAC(ap->mac_src);
-			printk(" ARP IP SRC=%u.%u.%u.%u",
-			       myNIPQUAD(ap->ip_src));
+			printk(" ARP IP SRC=%pI4", ap->ip_src);
 			printk(" ARP MAC DST=");
 			print_MAC(ap->mac_dst);
-			printk(" ARP IP DST=%u.%u.%u.%u",
-			       myNIPQUAD(ap->ip_dst));
+			printk(" ARP IP DST=%pI4", ap->ip_dst);
 		}
 	}
 out:
diff --git a/net/core/datagram.c b/net/core/datagram.c
index ee63184..5e2ac0c 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -209,7 +209,7 @@
 void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
 {
 	kfree_skb(skb);
-	sk_mem_reclaim(sk);
+	sk_mem_reclaim_partial(sk);
 }
 
 /**
@@ -248,8 +248,7 @@
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 	}
 
-	kfree_skb(skb);
-	sk_mem_reclaim(sk);
+	skb_free_datagram(sk, skb);
 	return err;
 }
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 9174c77..31568b2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -924,10 +924,15 @@
 		strlcpy(dev->name, newname, IFNAMSIZ);
 
 rollback:
-	ret = device_rename(&dev->dev, dev->name);
-	if (ret) {
-		memcpy(dev->name, oldname, IFNAMSIZ);
-		return ret;
+	/* For now only devices in the initial network namespace
+	 * are in sysfs.
+	 */
+	if (net == &init_net) {
+		ret = device_rename(&dev->dev, dev->name);
+		if (ret) {
+			memcpy(dev->name, oldname, IFNAMSIZ);
+			return ret;
+		}
 	}
 
 	write_lock_bh(&dev_base_lock);
@@ -2251,8 +2256,10 @@
 	rcu_read_lock();
 
 	/* Don't receive packets in an exiting network namespace */
-	if (!net_alive(dev_net(skb->dev)))
+	if (!net_alive(dev_net(skb->dev))) {
+		kfree_skb(skb);
 		goto out;
+	}
 
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
@@ -2371,7 +2378,7 @@
 static void net_rx_action(struct softirq_action *h)
 {
 	struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
-	unsigned long start_time = jiffies;
+	unsigned long time_limit = jiffies + 2;
 	int budget = netdev_budget;
 	void *have;
 
@@ -2382,13 +2389,10 @@
 		int work, weight;
 
 		/* If softirq window is exhuasted then punt.
-		 *
-		 * Note that this is a slight policy change from the
-		 * previous NAPI code, which would allow up to 2
-		 * jiffies to pass before breaking out.  The test
-		 * used to be "jiffies - start_time > 1".
+		 * Allow this to run for 2 jiffies since which will allow
+		 * an average latency of 1.5/HZ.
 		 */
-		if (unlikely(budget <= 0 || jiffies != start_time))
+		if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
 			goto softnet_break;
 
 		local_irq_enable();
@@ -4463,6 +4467,15 @@
 	if (dev->features & NETIF_F_NETNS_LOCAL)
 		goto out;
 
+#ifdef CONFIG_SYSFS
+	/* Don't allow real devices to be moved when sysfs
+	 * is enabled.
+	 */
+	err = -EINVAL;
+	if (dev->dev.parent)
+		goto out;
+#endif
+
 	/* Ensure the device has been registrered */
 	err = -EINVAL;
 	if (dev->reg_state != NETREG_REGISTERED)
@@ -4520,6 +4533,8 @@
 	 */
 	dev_addr_discard(dev);
 
+	netdev_unregister_kobject(dev);
+
 	/* Actually switch the network namespace */
 	dev_net_set(dev, net);
 
@@ -4536,7 +4551,6 @@
 	}
 
 	/* Fixup kobjects */
-	netdev_unregister_kobject(dev);
 	err = netdev_register_kobject(dev);
 	WARN_ON(err);
 
@@ -4843,6 +4857,12 @@
 		if (dev->features & NETIF_F_NETNS_LOCAL)
 			continue;
 
+		/* Delete virtual devices */
+		if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) {
+			dev->rtnl_link_ops->dellink(dev);
+			continue;
+		}
+
 		/* Push remaing network devices to init_net */
 		snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
 		err = dev_change_net_namespace(dev, &init_net, fb_name);
@@ -4889,9 +4909,6 @@
 	if (register_pernet_subsys(&netdev_net_ops))
 		goto out;
 
-	if (register_pernet_device(&default_device_ops))
-		goto out;
-
 	/*
 	 *	Initialise the packet receive queues.
 	 */
@@ -4908,10 +4925,25 @@
 		queue->backlog.weight = weight_p;
 	}
 
-	netdev_dma_register();
-
 	dev_boot_phase = 0;
 
+	/* The loopback device is special if any other network devices
+	 * is present in a network namespace the loopback device must
+	 * be present. Since we now dynamically allocate and free the
+	 * loopback device ensure this invariant is maintained by
+	 * keeping the loopback device as the first device on the
+	 * list of network devices.  Ensuring the loopback devices
+	 * is the first device that appears and the last network device
+	 * that disappears.
+	 */
+	if (register_pernet_device(&loopback_net_ops))
+		goto out;
+
+	if (register_pernet_device(&default_device_ops))
+		goto out;
+
+	netdev_dma_register();
+
 	open_softirq(NET_TX_SOFTIRQ, net_tx_action);
 	open_softirq(NET_RX_SOFTIRQ, net_rx_action);
 
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 79de3b1..32b3a01 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -664,17 +664,18 @@
 	rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
 	rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
 
-	err = register_netdevice_notifier(&fib_rules_notifier);
+	err = register_pernet_subsys(&fib_rules_net_ops);
 	if (err < 0)
 		goto fail;
 
-	err = register_pernet_subsys(&fib_rules_net_ops);
+	err = register_netdevice_notifier(&fib_rules_notifier);
 	if (err < 0)
 		goto fail_unregister;
+
 	return 0;
 
 fail_unregister:
-	unregister_netdevice_notifier(&fib_rules_notifier);
+	unregister_pernet_subsys(&fib_rules_net_ops);
 fail:
 	rtnl_unregister(PF_UNSPEC, RTM_NEWRULE);
 	rtnl_unregister(PF_UNSPEC, RTM_DELRULE);
diff --git a/net/core/flow.c b/net/core/flow.c
index 5cf8105..d323388 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -307,7 +307,7 @@
 	put_online_cpus();
 }
 
-static void __devinit flow_cache_cpu_prepare(int cpu)
+static void __init flow_cache_cpu_prepare(int cpu)
 {
 	struct tasklet_struct *tasklet;
 	unsigned long order;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1dc728b..d9bbe01 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1340,7 +1340,6 @@
 	if (p) {
 		p->tbl		  = tbl;
 		atomic_set(&p->refcnt, 1);
-		INIT_RCU_HEAD(&p->rcu_head);
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
 
@@ -1412,7 +1411,6 @@
 	tbl->parms.net = &init_net;
 #endif
 	atomic_set(&tbl->parms.refcnt, 1);
-	INIT_RCU_HEAD(&tbl->parms.rcu_head);
 	tbl->parms.reachable_time =
 			  neigh_rand_reach_time(tbl->parms.base_reachable_time);
 
@@ -2568,128 +2566,128 @@
 			.procname	= "mcast_solicit",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.ctl_name	= NET_NEIGH_UCAST_SOLICIT,
 			.procname	= "ucast_solicit",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.ctl_name	= NET_NEIGH_APP_SOLICIT,
 			.procname	= "app_solicit",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.procname	= "retrans_time",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_userhz_jiffies,
+			.proc_handler	= proc_dointvec_userhz_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_REACHABLE_TIME,
 			.procname	= "base_reachable_time",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_jiffies,
-			.strategy	= &sysctl_jiffies,
+			.proc_handler	= proc_dointvec_jiffies,
+			.strategy	= sysctl_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_DELAY_PROBE_TIME,
 			.procname	= "delay_first_probe_time",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_jiffies,
-			.strategy	= &sysctl_jiffies,
+			.proc_handler	= proc_dointvec_jiffies,
+			.strategy	= sysctl_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_GC_STALE_TIME,
 			.procname	= "gc_stale_time",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_jiffies,
-			.strategy	= &sysctl_jiffies,
+			.proc_handler	= proc_dointvec_jiffies,
+			.strategy	= sysctl_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_UNRES_QLEN,
 			.procname	= "unres_qlen",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.ctl_name	= NET_NEIGH_PROXY_QLEN,
 			.procname	= "proxy_qlen",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.procname	= "anycast_delay",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_userhz_jiffies,
+			.proc_handler	= proc_dointvec_userhz_jiffies,
 		},
 		{
 			.procname	= "proxy_delay",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_userhz_jiffies,
+			.proc_handler	= proc_dointvec_userhz_jiffies,
 		},
 		{
 			.procname	= "locktime",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_userhz_jiffies,
+			.proc_handler	= proc_dointvec_userhz_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_RETRANS_TIME_MS,
 			.procname	= "retrans_time_ms",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_ms_jiffies,
-			.strategy	= &sysctl_ms_jiffies,
+			.proc_handler	= proc_dointvec_ms_jiffies,
+			.strategy	= sysctl_ms_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_REACHABLE_TIME_MS,
 			.procname	= "base_reachable_time_ms",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_ms_jiffies,
-			.strategy	= &sysctl_ms_jiffies,
+			.proc_handler	= proc_dointvec_ms_jiffies,
+			.strategy	= sysctl_ms_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_GC_INTERVAL,
 			.procname	= "gc_interval",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec_jiffies,
-			.strategy	= &sysctl_jiffies,
+			.proc_handler	= proc_dointvec_jiffies,
+			.strategy	= sysctl_jiffies,
 		},
 		{
 			.ctl_name	= NET_NEIGH_GC_THRESH1,
 			.procname	= "gc_thresh1",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.ctl_name	= NET_NEIGH_GC_THRESH2,
 			.procname	= "gc_thresh2",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{
 			.ctl_name	= NET_NEIGH_GC_THRESH3,
 			.procname	= "gc_thresh3",
 			.maxlen		= sizeof(int),
 			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
+			.proc_handler	= proc_dointvec,
 		},
 		{},
 	},
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 92d6b94..146dcfe 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -476,6 +476,10 @@
 	struct device *dev = &(net->dev);
 
 	kobject_get(&dev->kobj);
+
+	if (dev_net(net) != &init_net)
+		return;
+
 	device_del(dev);
 }
 
@@ -490,7 +494,7 @@
 	dev->groups = groups;
 
 	BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
-	strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
+	dev_set_name(dev, net->name);
 
 #ifdef CONFIG_SYSFS
 	*groups++ = &netstat_group;
@@ -501,6 +505,9 @@
 #endif
 #endif /* CONFIG_SYSFS */
 
+	if (dev_net(net) != &init_net)
+		return 0;
+
 	return device_add(dev);
 }
 
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 1895a4c..55cffad 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -47,7 +47,6 @@
 		goto out;
 
 	ng->len = INITIAL_NET_GEN_PTRS;
-	INIT_RCU_HEAD(&ng->rcu);
 	rcu_assign_pointer(net->gen, ng);
 
 	error = 0;
@@ -478,7 +477,6 @@
 	 */
 
 	ng->len = id;
-	INIT_RCU_HEAD(&ng->rcu);
 	memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
 
 	rcu_assign_pointer(net->gen, ng);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 6c7af39..34f5d07 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -553,7 +553,6 @@
 
 void netpoll_print_options(struct netpoll *np)
 {
-	DECLARE_MAC_BUF(mac);
 	printk(KERN_INFO "%s: local port %d\n",
 			 np->name, np->local_port);
 	printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
@@ -564,8 +563,8 @@
 			 np->name, np->remote_port);
 	printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
 			 np->name, HIPQUAD(np->remote_ip));
-	printk(KERN_INFO "%s: remote ethernet address %s\n",
-	                 np->name, print_mac(mac, np->remote_mac));
+	printk(KERN_INFO "%s: remote ethernet address %pM\n",
+	                 np->name, np->remote_mac);
 }
 
 int netpoll_parse_options(struct netpoll *np, char *opt)
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index a47f5ba..a4f5ad1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -422,6 +422,7 @@
 					  const char *ifname);
 static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
 static void pktgen_run_all_threads(void);
+static void pktgen_reset_all_threads(void);
 static void pktgen_stop_all_threads_ifs(void);
 static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
 static void pktgen_stop(struct pktgen_thread *t);
@@ -480,6 +481,9 @@
 	else if (!strcmp(data, "start"))
 		pktgen_run_all_threads();
 
+	else if (!strcmp(data, "reset"))
+		pktgen_reset_all_threads();
+
 	else
 		printk(KERN_WARNING "pktgen: Unknown command: %s\n", data);
 
@@ -509,7 +513,6 @@
 	__u64 sa;
 	__u64 stopped;
 	__u64 now = getCurUs();
-	DECLARE_MAC_BUF(mac);
 
 	seq_printf(seq,
 		   "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
@@ -554,12 +557,12 @@
 
 	seq_puts(seq, "     src_mac: ");
 
-	seq_printf(seq, "%s ",
-		   print_mac(mac, is_zero_ether_addr(pkt_dev->src_mac) ?
-			     pkt_dev->odev->dev_addr : pkt_dev->src_mac));
+	seq_printf(seq, "%pM ",
+		   is_zero_ether_addr(pkt_dev->src_mac) ?
+			     pkt_dev->odev->dev_addr : pkt_dev->src_mac);
 
 	seq_printf(seq, "dst_mac: ");
-	seq_printf(seq, "%s\n", print_mac(mac, pkt_dev->dst_mac));
+	seq_printf(seq, "%pM\n", pkt_dev->dst_mac);
 
 	seq_printf(seq,
 		   "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
@@ -3174,6 +3177,24 @@
 	pktgen_wait_all_threads_run();
 }
 
+static void pktgen_reset_all_threads(void)
+{
+	struct pktgen_thread *t;
+
+	pr_debug("pktgen: entering pktgen_reset_all_threads.\n");
+
+	mutex_lock(&pktgen_thread_lock);
+
+	list_for_each_entry(t, &pktgen_threads, th_list)
+		t->control |= (T_REMDEVALL);
+
+	mutex_unlock(&pktgen_thread_lock);
+
+	schedule_timeout_interruptible(msecs_to_jiffies(125));	/* Propagate thread->control  */
+
+	pktgen_wait_all_threads_run();
+}
+
 static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
 {
 	__u64 total_us, bps, mbps, pps, idle;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d49ef83..267185a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -501,7 +501,7 @@
 	new->network_header	= old->network_header;
 	new->mac_header		= old->mac_header;
 	new->dst		= dst_clone(old->dst);
-#ifdef CONFIG_INET
+#ifdef CONFIG_XFRM
 	new->sp			= secpath_get(old->sp);
 #endif
 	memcpy(new->cb, old->cb, sizeof(old->cb));
@@ -556,6 +556,7 @@
 	C(truesize);
 #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
 	C(do_not_encrypt);
+	C(requeue);
 #endif
 	atomic_set(&n->users, 1);
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 5e2a313..ded1eb5 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2042,7 +2042,8 @@
 
 	if (alloc_slab) {
 		prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
-					       SLAB_HWCACHE_ALIGN, NULL);
+					SLAB_HWCACHE_ALIGN | prot->slab_flags,
+					NULL);
 
 		if (prot->slab == NULL) {
 			printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index f686467..2bc0384 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -22,7 +22,7 @@
 		.data		= &sysctl_wmem_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_RMEM_MAX,
@@ -30,7 +30,7 @@
 		.data		= &sysctl_rmem_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_WMEM_DEFAULT,
@@ -38,7 +38,7 @@
 		.data		= &sysctl_wmem_default,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_RMEM_DEFAULT,
@@ -46,7 +46,7 @@
 		.data		= &sysctl_rmem_default,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_DEV_WEIGHT,
@@ -54,7 +54,7 @@
 		.data		= &weight_p,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_MAX_BACKLOG,
@@ -62,7 +62,7 @@
 		.data		= &netdev_max_backlog,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_MSG_COST,
@@ -70,8 +70,8 @@
 		.data		= &net_ratelimit_state.interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_CORE_MSG_BURST,
@@ -79,7 +79,7 @@
 		.data		= &net_ratelimit_state.burst,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_CORE_OPTMEM_MAX,
@@ -87,7 +87,7 @@
 		.data		= &sysctl_optmem_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #ifdef CONFIG_XFRM
 	{
@@ -96,7 +96,7 @@
 		.data		= &sysctl_xfrm_aevent_etime,
 		.maxlen		= sizeof(u32),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_AEVENT_RSEQTH,
@@ -104,7 +104,7 @@
 		.data		= &sysctl_xfrm_aevent_rseqth,
 		.maxlen		= sizeof(u32),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -112,7 +112,7 @@
 		.data		= &sysctl_xfrm_larval_drop,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -120,7 +120,7 @@
 		.data		= &sysctl_xfrm_acq_expires,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #endif /* CONFIG_XFRM */
 #endif /* CONFIG_NET */
@@ -130,7 +130,7 @@
 		.data		= &netdev_budget,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_CORE_WARNINGS,
@@ -138,7 +138,7 @@
 		.data		= &net_msg_warn,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ .ctl_name = 0 }
 };
@@ -150,7 +150,7 @@
 		.data		= &init_net.core.sysctl_somaxconn,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index b4bc6e0..dee4a908 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -252,7 +252,8 @@
 extern void dccp_set_state(struct sock *sk, const int state);
 extern void dccp_done(struct sock *sk);
 
-extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb);
+extern int  dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,
+			    struct sk_buff const *skb);
 
 extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
 
@@ -441,6 +442,8 @@
 	       inet_csk_ack_scheduled(sk);
 }
 
+extern void dccp_feat_list_purge(struct list_head *fn_list);
+
 extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
 extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
 extern int dccp_insert_option_elapsed_time(struct sock *sk,
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 933a0ec..069d8ff 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -23,6 +23,171 @@
 
 #define DCCP_FEAT_SP_NOAGREE (-123)
 
+static const struct {
+	u8			feat_num;		/* DCCPF_xxx */
+	enum dccp_feat_type	rxtx;			/* RX or TX  */
+	enum dccp_feat_type	reconciliation;		/* SP or NN  */
+	u8			default_value;		/* as in 6.4 */
+/*
+ *    Lookup table for location and type of features (from RFC 4340/4342)
+ *  +--------------------------+----+-----+----+----+---------+-----------+
+ *  | Feature                  | Location | Reconc. | Initial |  Section  |
+ *  |                          | RX | TX  | SP | NN |  Value  | Reference |
+ *  +--------------------------+----+-----+----+----+---------+-----------+
+ *  | DCCPF_CCID               |    |  X  | X  |    |   2     | 10        |
+ *  | DCCPF_SHORT_SEQNOS       |    |  X  | X  |    |   0     |  7.6.1    |
+ *  | DCCPF_SEQUENCE_WINDOW    |    |  X  |    | X  | 100     |  7.5.2    |
+ *  | DCCPF_ECN_INCAPABLE      | X  |     | X  |    |   0     | 12.1      |
+ *  | DCCPF_ACK_RATIO          |    |  X  |    | X  |   2     | 11.3      |
+ *  | DCCPF_SEND_ACK_VECTOR    | X  |     | X  |    |   0     | 11.5      |
+ *  | DCCPF_SEND_NDP_COUNT     |    |  X  | X  |    |   0     |  7.7.2    |
+ *  | DCCPF_MIN_CSUM_COVER     | X  |     | X  |    |   0     |  9.2.1    |
+ *  | DCCPF_DATA_CHECKSUM      | X  |     | X  |    |   0     |  9.3.1    |
+ *  | DCCPF_SEND_LEV_RATE      | X  |     | X  |    |   0     | 4342/8.4  |
+ *  +--------------------------+----+-----+----+----+---------+-----------+
+ */
+} dccp_feat_table[] = {
+	{ DCCPF_CCID,		 FEAT_AT_TX, FEAT_SP, 2 },
+	{ DCCPF_SHORT_SEQNOS,	 FEAT_AT_TX, FEAT_SP, 0 },
+	{ DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100 },
+	{ DCCPF_ECN_INCAPABLE,	 FEAT_AT_RX, FEAT_SP, 0 },
+	{ DCCPF_ACK_RATIO,	 FEAT_AT_TX, FEAT_NN, 2 },
+	{ DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0 },
+	{ DCCPF_SEND_NDP_COUNT,  FEAT_AT_TX, FEAT_SP, 0 },
+	{ DCCPF_MIN_CSUM_COVER,  FEAT_AT_RX, FEAT_SP, 0 },
+	{ DCCPF_DATA_CHECKSUM,	 FEAT_AT_RX, FEAT_SP, 0 },
+	{ DCCPF_SEND_LEV_RATE,	 FEAT_AT_RX, FEAT_SP, 0 },
+};
+#define DCCP_FEAT_SUPPORTED_MAX		ARRAY_SIZE(dccp_feat_table)
+
+/**
+ * dccp_feat_index  -  Hash function to map feature number into array position
+ * Returns consecutive array index or -1 if the feature is not understood.
+ */
+static int dccp_feat_index(u8 feat_num)
+{
+	/* The first 9 entries are occupied by the types from RFC 4340, 6.4 */
+	if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM)
+		return feat_num - 1;
+
+	/*
+	 * Other features: add cases for new feature types here after adding
+	 * them to the above table.
+	 */
+	switch (feat_num) {
+	case DCCPF_SEND_LEV_RATE:
+			return DCCP_FEAT_SUPPORTED_MAX - 1;
+	}
+	return -1;
+}
+
+static u8 dccp_feat_type(u8 feat_num)
+{
+	int idx = dccp_feat_index(feat_num);
+
+	if (idx < 0)
+		return FEAT_UNKNOWN;
+	return dccp_feat_table[idx].reconciliation;
+}
+
+/* copy constructor, fval must not already contain allocated memory */
+static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len)
+{
+	fval->sp.len = len;
+	if (fval->sp.len > 0) {
+		fval->sp.vec = kmemdup(val, len, gfp_any());
+		if (fval->sp.vec == NULL) {
+			fval->sp.len = 0;
+			return -ENOBUFS;
+		}
+	}
+	return 0;
+}
+
+static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
+{
+	if (unlikely(val == NULL))
+		return;
+	if (dccp_feat_type(feat_num) == FEAT_SP)
+		kfree(val->sp.vec);
+	memset(val, 0, sizeof(*val));
+}
+
+static struct dccp_feat_entry *
+	      dccp_feat_clone_entry(struct dccp_feat_entry const *original)
+{
+	struct dccp_feat_entry *new;
+	u8 type = dccp_feat_type(original->feat_num);
+
+	if (type == FEAT_UNKNOWN)
+		return NULL;
+
+	new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any());
+	if (new == NULL)
+		return NULL;
+
+	if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val,
+						      original->val.sp.vec,
+						      original->val.sp.len)) {
+		kfree(new);
+		return NULL;
+	}
+	return new;
+}
+
+static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
+{
+	if (entry != NULL) {
+		dccp_feat_val_destructor(entry->feat_num, &entry->val);
+		kfree(entry);
+	}
+}
+
+/*
+ * List management functions
+ *
+ * Feature negotiation lists rely on and maintain the following invariants:
+ * - each feat_num in the list is known, i.e. we know its type and default value
+ * - each feat_num/is_local combination is unique (old entries are overwritten)
+ * - SP values are always freshly allocated
+ * - list is sorted in increasing order of feature number (faster lookup)
+ */
+
+static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry)
+{
+	list_del(&entry->node);
+	dccp_feat_entry_destructor(entry);
+}
+
+void dccp_feat_list_purge(struct list_head *fn_list)
+{
+	struct dccp_feat_entry *entry, *next;
+
+	list_for_each_entry_safe(entry, next, fn_list, node)
+		dccp_feat_entry_destructor(entry);
+	INIT_LIST_HEAD(fn_list);
+}
+EXPORT_SYMBOL_GPL(dccp_feat_list_purge);
+
+/* generate @to as full clone of @from - @to must not contain any nodes */
+int dccp_feat_clone_list(struct list_head const *from, struct list_head *to)
+{
+	struct dccp_feat_entry *entry, *new;
+
+	INIT_LIST_HEAD(to);
+	list_for_each_entry(entry, from, node) {
+		new = dccp_feat_clone_entry(entry);
+		if (new == NULL)
+			goto cloning_failed;
+		list_add_tail(&new->node, to);
+	}
+	return 0;
+
+cloning_failed:
+	dccp_feat_list_purge(to);
+	return -ENOMEM;
+}
+
 int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
 		     u8 *val, u8 len, gfp_t gfp)
 {
@@ -639,6 +804,8 @@
 	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";
 
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index e272222..f5e99b3 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -14,6 +14,67 @@
 #include <linux/types.h>
 #include "dccp.h"
 
+enum dccp_feat_type {
+	FEAT_AT_RX   = 1,	/* located at RX side of half-connection  */
+	FEAT_AT_TX   = 2,	/* located at TX side of half-connection  */
+	FEAT_SP      = 4,	/* server-priority reconciliation (6.3.1) */
+	FEAT_NN	     = 8,	/* non-negotiable reconciliation (6.3.2)  */
+	FEAT_UNKNOWN = 0xFF	/* not understood or invalid feature	  */
+};
+
+enum dccp_feat_state {
+	FEAT_DEFAULT = 0,	/* using default values from 6.4 */
+	FEAT_INITIALISING,	/* feature is being initialised  */
+	FEAT_CHANGING,		/* Change sent but not confirmed yet */
+	FEAT_UNSTABLE,		/* local modification in state CHANGING */
+	FEAT_STABLE		/* both ends (think they) agree */
+};
+
+/**
+ * dccp_feat_val  -  Container for SP or NN feature values
+ * @nn:     single NN value
+ * @sp.vec: single SP value plus optional preference list
+ * @sp.len: length of @sp.vec in bytes
+ */
+typedef union {
+	u64 nn;
+	struct {
+		u8	*vec;
+		u8	len;
+	}   sp;
+} dccp_feat_val;
+
+/**
+ * struct feat_entry  -  Data structure to perform feature negotiation
+ * @val: feature's current value (SP features may have preference list)
+ * @state: feature's current state
+ * @feat_num: one of %dccp_feature_numbers
+ * @needs_mandatory: whether Mandatory options should be sent
+ * @needs_confirm: whether to send a Confirm instead of a Change
+ * @empty_confirm: whether to send an empty Confirm (depends on @needs_confirm)
+ * @is_local: feature location (1) or feature-remote (0)
+ * @node: list pointers, entries arranged in FIFO order
+ */
+struct dccp_feat_entry {
+	dccp_feat_val           val;
+	enum dccp_feat_state    state:8;
+	u8                      feat_num;
+
+	bool			needs_mandatory,
+				needs_confirm,
+				empty_confirm,
+				is_local;
+
+	struct list_head	node;
+};
+
+static inline u8 dccp_feat_genopt(struct dccp_feat_entry *entry)
+{
+	if (entry->needs_confirm)
+		return entry->is_local ? DCCPO_CONFIRM_L : DCCPO_CONFIRM_R;
+	return entry->is_local ? DCCPO_CHANGE_L : DCCPO_CHANGE_R;
+}
+
 #ifdef CONFIG_IP_DCCP_DEBUG
 extern const char *dccp_feat_typename(const u8 type);
 extern const char *dccp_feat_name(const u8 feat);
@@ -35,6 +96,7 @@
 				   u8 *val, u8 len);
 extern void dccp_feat_clean(struct dccp_minisock *dmsk);
 extern int  dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
+extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
 extern int  dccp_feat_init(struct dccp_minisock *dmsk);
 
 #endif /* _DCCP_FEAT_H */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 779d0ed..3070015 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -590,8 +590,6 @@
 			if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
 								    skb) < 0)
 				return 1;
-
-			/* FIXME: do congestion control initialization */
 			goto discard;
 		}
 		if (dh->dccph_type == DCCP_PKT_RESET)
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index e3dfdda..528baa2 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -545,6 +545,7 @@
 
 static void dccp_v4_reqsk_destructor(struct request_sock *req)
 {
+	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
 	kfree(inet_rsk(req)->opt);
 }
 
@@ -595,7 +596,8 @@
 	if (req == NULL)
 		goto drop;
 
-	dccp_reqsk_init(req, skb);
+	if (dccp_reqsk_init(req, dccp_sk(sk), skb))
+		goto drop_and_free;
 
 	dreq = dccp_rsk(req);
 	if (dccp_parse_options(sk, dreq, skb))
@@ -792,12 +794,10 @@
 	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(dh);
 	DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
 
-	dccp_pr_debug("%8.8s "
-		      "src=%u.%u.%u.%u@%-5d "
-		      "dst=%u.%u.%u.%u@%-5d seq=%llu",
+	dccp_pr_debug("%8.8s src=%pI4@%-5d dst=%pI4@%-5d seq=%llu",
 		      dccp_packet_name(dh->dccph_type),
-		      NIPQUAD(iph->saddr), ntohs(dh->dccph_sport),
-		      NIPQUAD(iph->daddr), ntohs(dh->dccph_dport),
+		      &iph->saddr, ntohs(dh->dccph_sport),
+		      &iph->daddr, ntohs(dh->dccph_dport),
 		      (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
 
 	if (dccp_packet_without_ack(skb)) {
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index d4ce122..4aa1148 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -304,6 +304,7 @@
 
 static void dccp_v6_reqsk_destructor(struct request_sock *req)
 {
+	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
 	if (inet6_rsk(req)->pktopts != NULL)
 		kfree_skb(inet6_rsk(req)->pktopts);
 }
@@ -426,7 +427,8 @@
 	if (req == NULL)
 		goto drop;
 
-	dccp_reqsk_init(req, skb);
+	if (dccp_reqsk_init(req, dccp_sk(sk), skb))
+		goto drop_and_free;
 
 	dreq = dccp_rsk(req);
 	if (dccp_parse_options(sk, dreq, skb))
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index e6bf99e..afdacbb 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -125,6 +125,7 @@
 		newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;
 		newicsk->icsk_rto	    = DCCP_TIMEOUT_INIT;
 
+		INIT_LIST_HEAD(&newdp->dccps_featneg);
 		if (dccp_feat_clone(sk, newsk))
 			goto out_free;
 
@@ -304,7 +305,8 @@
 
 EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);
 
-void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)
+int dccp_reqsk_init(struct request_sock *req,
+		    struct dccp_sock const *dp, struct sk_buff const *skb)
 {
 	struct dccp_request_sock *dreq = dccp_rsk(req);
 
@@ -313,6 +315,9 @@
 	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 */
+	return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg);
 }
 
 EXPORT_SYMBOL_GPL(dccp_reqsk_init);
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 81368a7..49ba8d5 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -86,18 +86,18 @@
 	if (port == 0 || ntohs(inet->dport) == port ||
 	    ntohs(inet->sport) == port) {
 		if (hctx)
-			printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %d %d %d %u "
+			printl("%pI4:%u %pI4:%u %d %d %d %d %u "
 			       "%llu %llu %d\n",
-			       NIPQUAD(inet->saddr), ntohs(inet->sport),
-			       NIPQUAD(inet->daddr), ntohs(inet->dport), size,
+			       &inet->saddr, ntohs(inet->sport),
+			       &inet->daddr, ntohs(inet->dport), size,
 			       hctx->ccid3hctx_s, hctx->ccid3hctx_rtt,
 			       hctx->ccid3hctx_p, hctx->ccid3hctx_x_calc,
 			       hctx->ccid3hctx_x_recv >> 6,
 			       hctx->ccid3hctx_x >> 6, hctx->ccid3hctx_t_ipi);
 		else
-			printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d\n",
-			       NIPQUAD(inet->saddr), ntohs(inet->sport),
-			       NIPQUAD(inet->daddr), ntohs(inet->dport), size);
+			printl("%pI4:%u %pI4:%u %d\n",
+			       &inet->saddr, ntohs(inet->sport),
+			       &inet->daddr, ntohs(inet->dport), size);
 	}
 
 	jprobe_return();
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index d0bd348..dafcefd 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -193,6 +193,7 @@
 
 	dccp_init_xmit_timers(sk);
 
+	INIT_LIST_HEAD(&dp->dccps_featneg);
 	/*
 	 * FIXME: We're hardcoding the CCID, and doing this at this point makes
 	 * the listening (master) sock get CCID control blocks, which is not
@@ -267,7 +268,7 @@
 	dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
 
 	/* clean up feature negotiation state */
-	dccp_feat_clean(dmsk);
+	dccp_feat_list_purge(&dp->dccps_featneg);
 }
 
 EXPORT_SYMBOL_GPL(dccp_destroy_sock);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 36400b2..2f360a1 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -354,8 +354,8 @@
 		.data = node_name,
 		.maxlen = 7,
 		.mode = 0644,
-		.proc_handler = &proc_dostring,
-		.strategy = &sysctl_string,
+		.proc_handler = proc_dostring,
+		.strategy = sysctl_string,
 	},
 	{
 		.ctl_name = NET_DECNET_DEFAULT_DEVICE,
@@ -371,8 +371,8 @@
 		.data = &decnet_time_wait,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_decnet_time_wait,
 		.extra2 = &max_decnet_time_wait
 	},
@@ -382,8 +382,8 @@
 		.data = &decnet_dn_count,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_state_count,
 		.extra2 = &max_state_count
 	},
@@ -393,8 +393,8 @@
 		.data = &decnet_di_count,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_state_count,
 		.extra2 = &max_state_count
 	},
@@ -404,8 +404,8 @@
 		.data = &decnet_dr_count,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_state_count,
 		.extra2 = &max_state_count
 	},
@@ -415,8 +415,8 @@
 		.data = &decnet_dst_gc_interval,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_decnet_dst_gc_interval,
 		.extra2 = &max_decnet_dst_gc_interval
 	},
@@ -426,8 +426,8 @@
 		.data = &decnet_no_fc_max_cwnd,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec_minmax,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec_minmax,
+		.strategy = sysctl_intvec,
 		.extra1 = &min_decnet_no_fc_max_cwnd,
 		.extra2 = &max_decnet_no_fc_max_cwnd
 	},
@@ -437,8 +437,8 @@
 		.data = &sysctl_decnet_mem,
 		.maxlen = sizeof(sysctl_decnet_mem),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec,
+		.strategy = sysctl_intvec,
 	},
 	{
 		.ctl_name = NET_DECNET_RMEM,
@@ -446,8 +446,8 @@
 		.data = &sysctl_decnet_rmem,
 		.maxlen = sizeof(sysctl_decnet_rmem),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec,
+		.strategy = sysctl_intvec,
 	},
 	{
 		.ctl_name = NET_DECNET_WMEM,
@@ -455,8 +455,8 @@
 		.data = &sysctl_decnet_wmem,
 		.maxlen = sizeof(sysctl_decnet_wmem),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec,
+		.strategy = sysctl_intvec,
 	},
 	{
 		.ctl_name = NET_DECNET_DEBUG_LEVEL,
@@ -464,8 +464,8 @@
 		.data = &decnet_debug_level,
 		.maxlen = sizeof(int),
 		.mode = 0644,
-		.proc_handler = &proc_dointvec,
-		.strategy = &sysctl_intvec,
+		.proc_handler = proc_dointvec,
+		.strategy = sysctl_intvec,
 	},
 	{0}
 };
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1af5a79..a3a410d 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -352,7 +352,7 @@
 	netif_carrier_off(slave_dev);
 
 	if (p->phy != NULL) {
-		phy_attach(slave_dev, p->phy->dev.bus_id,
+		phy_attach(slave_dev, dev_name(&p->phy->dev),
 			   0, PHY_INTERFACE_MODE_GMII);
 
 		p->phy->autoneg = AUTONEG_ENABLE;
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index 3186654..f99a019 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -162,7 +162,6 @@
 	skb->pkt_type = PACKET_HOST;
 	skb->protocol = eth_type_trans(skb, skb->dev);
 
-	skb->dev->last_rx = jiffies;
 	skb->dev->stats.rx_packets++;
 	skb->dev->stats.rx_bytes += skb->len;
 
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index 9f4ce55..328ec95 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -181,7 +181,6 @@
 	skb->pkt_type = PACKET_HOST;
 	skb->protocol = eth_type_trans(skb, skb->dev);
 
-	skb->dev->last_rx = jiffies;
 	skb->dev->stats.rx_packets++;
 	skb->dev->stats.rx_bytes += skb->len;
 
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index efd2669..b591328 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -98,7 +98,6 @@
 	skb->pkt_type = PACKET_HOST;
 	skb->protocol = eth_type_trans(skb, skb->dev);
 
-	skb->dev->last_rx = jiffies;
 	skb->dev->stats.rx_packets++;
 	skb->dev->stats.rx_bytes += skb->len;
 
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index 94ed7d3..d2282bb 100644
--- a/net/ieee80211/Kconfig
+++ b/net/ieee80211/Kconfig
@@ -1,12 +1,24 @@
 config IEEE80211
-	tristate "Generic IEEE 802.11 Networking Stack (DEPRECATED)"
+	tristate
+	select WIRELESS_EXT
+	select CRYPTO
+	select CRYPTO_ARC4
+	select CRYPTO_ECB
+	select CRYPTO_AES
+	select CRYPTO_MICHAEL_MIC
+	select CRYPTO_ECB
+	select CRC32
+	select IEEE80211_CRYPT_WEP
+	select IEEE80211_CRYPT_TKIP
+	select IEEE80211_CRYPT_CCMP
+	select LIB80211
 	---help---
 	This option enables the hardware independent IEEE 802.11
 	networking stack.  This component is deprecated in favor of the
 	mac80211 component.
 
 config IEEE80211_DEBUG
-	bool "Enable full debugging output"
+	bool "Full debugging output for the old IEEE80211 stack"
 	depends on IEEE80211
 	---help---
 	  This option will enable debug tracing output for the
@@ -29,45 +41,10 @@
 	  subsystem, you most likely want to say N here.
 
 config IEEE80211_CRYPT_WEP
-	tristate "IEEE 802.11 WEP encryption (802.1x)"
-	depends on IEEE80211
-	select CRYPTO
-	select CRYPTO_ARC4
-	select CRYPTO_ECB
-	select CRC32
-	---help---
-	Include software based cipher suites in support of IEEE
-	802.11's WEP.  This is needed for WEP as well as 802.1x.
-
-	This can be compiled as a module and it will be called
-	"ieee80211_crypt_wep".
+	tristate
 
 config IEEE80211_CRYPT_CCMP
-	tristate "IEEE 802.11i CCMP support"
-	depends on IEEE80211
-	select CRYPTO
-	select CRYPTO_AES
-	---help---
-	Include software based cipher suites in support of IEEE 802.11i
-	(aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled
-	networks.
-
-	This can be compiled as a module and it will be called
-	"ieee80211_crypt_ccmp".
+	tristate
 
 config IEEE80211_CRYPT_TKIP
-	tristate "IEEE 802.11i TKIP encryption"
-	depends on IEEE80211
-	select WIRELESS_EXT
-	select CRYPTO
-	select CRYPTO_MICHAEL_MIC
-	select CRYPTO_ECB
-	select CRC32
-	---help---
-	Include software based cipher suites in support of IEEE 802.11i
-	(aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
-	networks.
-
-	This can be compiled as a module and it will be called
-	"ieee80211_crypt_tkip".
-
+	tristate
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 208bf35..bea04af 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -296,7 +296,6 @@
 	int i, blocks, last, len;
 	size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
 	u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
-	DECLARE_MAC_BUF(mac);
 
 	if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
 		key->dot11RSNAStatsCCMPFormatErrors++;
@@ -309,7 +308,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from %s\n", print_mac(mac, hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
@@ -322,9 +321,9 @@
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from %s"
+			printk(KERN_DEBUG "CCMP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", print_mac(mac, hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -339,10 +338,10 @@
 
 	if (ccmp_replay_check(pn, key->rx_pn)) {
 		if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
-			IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%s "
+			IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%pM "
 				 "previous PN %02x%02x%02x%02x%02x%02x "
 				 "received PN %02x%02x%02x%02x%02x%02x\n",
-				 print_mac(mac, hdr->addr2),
+				 hdr->addr2,
 				 key->rx_pn[0], key->rx_pn[1], key->rx_pn[2],
 				 key->rx_pn[3], key->rx_pn[4], key->rx_pn[5],
 				 pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
@@ -373,7 +372,7 @@
 	if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-			       "%s\n", print_mac(mac, hdr->addr2));
+			       "%pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPDecryptErrors++;
 		return -5;
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index bba0152..d12da1d 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -359,15 +359,13 @@
 	u8 rc4key[16], *pos, *icv;
 	u32 crc;
 	struct scatterlist sg;
-	DECLARE_MAC_BUF(mac);
 
 	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
 		if (net_ratelimit()) {
 			struct ieee80211_hdr_4addr *hdr =
 			    (struct ieee80211_hdr_4addr *)skb->data;
 			printk(KERN_DEBUG ": TKIP countermeasures: dropped "
-			       "TX packet to %s\n",
-			       print_mac(mac, hdr->addr1));
+			       "TX packet to %pM\n", hdr->addr1);
 		}
 		return -1;
 	}
@@ -420,15 +418,13 @@
 	u32 crc;
 	struct scatterlist sg;
 	int plen;
-	DECLARE_MAC_BUF(mac);
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
 	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG ": TKIP countermeasures: dropped "
-			       "received packet from %s\n",
-			       print_mac(mac, hdr->addr2));
+			       "received packet from %pM\n", hdr->addr2);
 		}
 		return -1;
 	}
@@ -441,7 +437,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from %s\n", print_mac(mac, hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		return -2;
 	}
@@ -453,9 +449,9 @@
 	}
 	if (!tkey->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from %s"
+			printk(KERN_DEBUG "TKIP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", print_mac(mac, hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -465,9 +461,9 @@
 
 	if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
 		if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
-			IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%s"
+			IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%pM"
 			       " previous TSC %08x%04x received TSC "
-			       "%08x%04x\n", print_mac(mac, hdr->addr2),
+			       "%08x%04x\n", hdr->addr2,
 			       tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
 		}
 		tkey->dot11RSNAStatsTKIPReplays++;
@@ -487,8 +483,8 @@
 	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG ": TKIP: failed to decrypt "
-			       "received packet from %s\n",
-			       print_mac(mac, hdr->addr2));
+			       "received packet from %pM\n",
+			       hdr->addr2);
 		}
 		return -7;
 	}
@@ -506,7 +502,7 @@
 		}
 		if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
 			IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA="
-			       "%s\n", print_mac(mac, hdr->addr2));
+			       "%pM\n", hdr->addr2);
 		}
 		tkey->dot11RSNAStatsTKIPICVErrors++;
 		return -5;
@@ -633,7 +629,6 @@
 {
 	struct ieee80211_tkip_data *tkey = priv;
 	u8 mic[8];
-	DECLARE_MAC_BUF(mac);
 
 	if (!tkey->key_set)
 		return -1;
@@ -646,8 +641,8 @@
 		struct ieee80211_hdr_4addr *hdr;
 		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from %s keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", print_mac(mac, hdr->addr2),
+		       "MSDU from %pM keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
 		       keyidx);
 		if (skb->dev)
 			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 949772a..d34d4e7 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -308,31 +308,5 @@
 module_exit(ieee80211_exit);
 module_init(ieee80211_init);
 
-const char *escape_essid(const char *essid, u8 essid_len)
-{
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (ieee80211_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else {
-			*d++ = *s++;
-		}
-	}
-	*d = '\0';
-	return escaped;
-}
-
 EXPORT_SYMBOL(alloc_ieee80211);
 EXPORT_SYMBOL(free_ieee80211);
-EXPORT_SYMBOL(escape_essid);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 69dbc34..3dd58b5 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -32,6 +32,7 @@
 #include <asm/uaccess.h>
 #include <linux/ctype.h>
 
+#include <net/lib80211.h>
 #include <net/ieee80211.h>
 
 static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
@@ -39,7 +40,7 @@
 					struct ieee80211_rx_stats *rx_stats)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	u16 fc = le16_to_cpu(hdr->frame_control);
 
 	skb->dev = ieee->dev;
 	skb_reset_mac_header(skb);
@@ -282,12 +283,8 @@
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
-		IEEE80211_DEBUG_DROP("decryption failed (SA=" MAC_FMT
-				     ") res=%d\n",
-				     hdr->addr2[0], hdr->addr2[1],
-				     hdr->addr2[2], hdr->addr2[3],
-				     hdr->addr2[4], hdr->addr2[5],
-				     res);
+		IEEE80211_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n",
+				     hdr->addr2, res);
 		if (res == -2)
 			IEEE80211_DEBUG_DROP("Decryption failed ICV "
 					     "mismatch (key %d)\n",
@@ -319,11 +316,7 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=" MAC_FMT " keyidx=%d)\n",
-		       ieee->dev->name,
-		       hdr->addr2[0], hdr->addr2[1],
-		       hdr->addr2[2], hdr->addr2[3],
-		       hdr->addr2[4], hdr->addr2[5],
+		       " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2,
 		       keyidx);
 		return -1;
 	}
@@ -358,7 +351,6 @@
 	struct ieee80211_crypt_data *crypt = NULL;
 	int keyidx = 0;
 	int can_be_decrypted = 0;
-	DECLARE_MAC_BUF(mac);
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	stats = &ieee->stats;
@@ -468,10 +460,7 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=" MAC_FMT ")\n",
-					     hdr->addr2[0], hdr->addr2[1],
-					     hdr->addr2[2], hdr->addr2[3],
-					     hdr->addr2[4], hdr->addr2[5]);
+					     " (SA=%pM)\n", hdr->addr2);
 			ieee->ieee_stats.rx_discards_undecryptable++;
 			goto rx_dropped;
 		}
@@ -482,10 +471,7 @@
 		    fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt &&
 		    (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) {
 			printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
-			       "from " MAC_FMT "\n", dev->name,
-			       hdr->addr2[0], hdr->addr2[1],
-			       hdr->addr2[2], hdr->addr2[3],
-			       hdr->addr2[4], hdr->addr2[5]);
+			       "from %pM\n", dev->name, hdr->addr2);
 			/* TODO: could inform hostapd about this so that it
 			 * could send auth failure report */
 			goto rx_dropped;
@@ -547,8 +533,6 @@
 	}
 #endif
 
-	dev->last_rx = jiffies;
-
 #ifdef NOT_YET
 	if ((ieee->iw_mode == IW_MODE_MASTER ||
 	     ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) {
@@ -663,11 +647,8 @@
 			 * configured */
 		} else {
 			IEEE80211_DEBUG_DROP("encryption configured, but RX "
-					     "frame not encrypted (SA="
-					     MAC_FMT ")\n",
-					     hdr->addr2[0], hdr->addr2[1],
-					     hdr->addr2[2], hdr->addr2[3],
-					     hdr->addr2[4], hdr->addr2[5]);
+					     "frame not encrypted (SA=%pM)\n",
+					     hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -675,11 +656,8 @@
 	if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep &&
 	    !ieee80211_is_eapol_frame(ieee, skb)) {
 		IEEE80211_DEBUG_DROP("dropped unencrypted RX data "
-				     "frame from " MAC_FMT
-				     " (drop_unencrypted=1)\n",
-				     hdr->addr2[0], hdr->addr2[1],
-				     hdr->addr2[2], hdr->addr2[3],
-				     hdr->addr2[4], hdr->addr2[5]);
+				     "frame from %pM (drop_unencrypted=1)\n",
+				     hdr->addr2);
 		goto rx_dropped;
 	}
 
@@ -1144,6 +1122,7 @@
 				      *info_element, u16 length,
 				      struct ieee80211_network *network)
 {
+	DECLARE_SSID_BUF(ssid);
 	u8 i;
 #ifdef CONFIG_IEEE80211_DEBUG
 	char rates_str[64];
@@ -1166,12 +1145,6 @@
 
 		switch (info_element->id) {
 		case MFIE_TYPE_SSID:
-			if (ieee80211_is_empty_essid(info_element->data,
-						     info_element->len)) {
-				network->flags |= NETWORK_EMPTY_ESSID;
-				break;
-			}
-
 			network->ssid_len = min(info_element->len,
 						(u8) IW_ESSID_MAX_SIZE);
 			memcpy(network->ssid, info_element->data,
@@ -1181,7 +1154,9 @@
 				       IW_ESSID_MAX_SIZE - network->ssid_len);
 
 			IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
-					     network->ssid, network->ssid_len);
+					     print_ssid(ssid, network->ssid,
+							network->ssid_len),
+					     network->ssid_len);
 			break;
 
 		case MFIE_TYPE_RATES:
@@ -1411,9 +1386,6 @@
 			network->mode |= IEEE_B;
 	}
 
-	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
-		network->flags |= NETWORK_EMPTY_ESSID;
-
 	memcpy(&network->stats, stats, sizeof(network->stats));
 
 	if (ieee->handle_assoc_response != NULL)
@@ -1429,7 +1401,7 @@
 					 struct ieee80211_network *network,
 					 struct ieee80211_rx_stats *stats)
 {
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	network->qos_data.active = 0;
 	network->qos_data.supported = 0;
@@ -1477,17 +1449,14 @@
 	}
 
 	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (%s)' "
+		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
 				     "network.\n",
-				     escape_essid(network->ssid,
-						  network->ssid_len),
-				     print_mac(mac, network->bssid));
+				     print_ssid(ssid, network->ssid,
+						 network->ssid_len),
+				     network->bssid);
 		return 1;
 	}
 
-	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
-		network->flags |= NETWORK_EMPTY_ESSID;
-
 	memcpy(&network->stats, stats, sizeof(network->stats));
 
 	return 0;
@@ -1510,7 +1479,6 @@
 {
 	int qos_active;
 	u8 old_param;
-	DECLARE_MAC_BUF(mac);
 
 	ieee80211_network_reset(dst);
 	dst->ibss_dfs = src->ibss_dfs;
@@ -1524,8 +1492,8 @@
 		memcpy(&dst->stats, &src->stats,
 		       sizeof(struct ieee80211_rx_stats));
 	else
-		IEEE80211_DEBUG_SCAN("Network %s info received "
-			"off channel (%d vs. %d)\n", print_mac(mac, src->bssid),
+		IEEE80211_DEBUG_SCAN("Network %pM info received "
+			"off channel (%d vs. %d)\n", src->bssid,
 			dst->channel, src->stats.received_channel);
 
 	dst->capability = src->capability;
@@ -1597,12 +1565,12 @@
 	struct ieee80211_info_element *info_element = beacon->info_element;
 #endif
 	unsigned long flags;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
-	IEEE80211_DEBUG_SCAN("'%s' (%s"
+	IEEE80211_DEBUG_SCAN("'%s' (%pM"
 		     "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
-		     escape_essid(info_element->data, info_element->len),
-		     print_mac(mac, beacon->header.addr3),
+		     print_ssid(ssid, info_element->data, info_element->len),
+		     beacon->header.addr3,
 		     (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
 		     (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
 		     (beacon->capability & cpu_to_le16(1 << 0xd)) ? '1' : '0',
@@ -1621,10 +1589,10 @@
 		     (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
 
 	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (%s) via %s.\n",
-				     escape_essid(info_element->data,
-						  info_element->len),
-				     print_mac(mac, beacon->header.addr3),
+		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
+				     print_ssid(ssid, info_element->data,
+						 info_element->len),
+				     beacon->header.addr3,
 				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 		return;
@@ -1658,11 +1626,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (%s) from "
+			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
 					     "network list.\n",
-					     escape_essid(target->ssid,
-							  target->ssid_len),
-					     print_mac(mac, target->bssid));
+					     print_ssid(ssid, target->ssid,
+							 target->ssid_len),
+					     target->bssid);
 			ieee80211_network_reset(target);
 		} else {
 			/* Otherwise just pull from the free list */
@@ -1672,10 +1640,10 @@
 		}
 
 #ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (%s) via %s.\n",
-				     escape_essid(network.ssid,
-						  network.ssid_len),
-				     print_mac(mac, network.bssid),
+		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
+				     print_ssid(ssid, network.ssid,
+						 network.ssid_len),
+				     network.bssid,
 				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 #endif
@@ -1683,10 +1651,10 @@
 		network.ibss_dfs = NULL;
 		list_add_tail(&target->list, &ieee->network_list);
 	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (%s) via %s.\n",
-				     escape_essid(target->ssid,
-						  target->ssid_len),
-				     print_mac(mac, target->bssid),
+		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
+				     print_ssid(ssid, target->ssid,
+						 target->ssid_len),
+				     target->bssid,
 				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 		update_network(target, &network);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 973832d..7cc4e5e 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 
+#include <net/lib80211.h>
 #include <net/ieee80211.h>
 #include <linux/wireless.h>
 
@@ -65,15 +66,9 @@
 	/* Add the ESSID */
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.flags = 1;
-	if (network->flags & NETWORK_EMPTY_ESSID) {
-		iwe.u.data.length = sizeof("<hidden>");
-		start = iwe_stream_add_point(info, start, stop,
-					     &iwe, "<hidden>");
-	} else {
-		iwe.u.data.length = min(network->ssid_len, (u8) 32);
-		start = iwe_stream_add_point(info, start, stop,
-					     &iwe, network->ssid);
-	}
+	iwe.u.data.length = min(network->ssid_len, (u8) 32);
+	start = iwe_stream_add_point(info, start, stop,
+				     &iwe, network->ssid);
 
 	/* Add the protocol name */
 	iwe.cmd = SIOCGIWNAME;
@@ -264,7 +259,7 @@
 	char *ev = extra;
 	char *stop = ev + wrqu->data.length;
 	int i = 0;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_SSID_BUF(ssid);
 
 	IEEE80211_DEBUG_WX("Getting scan\n");
 
@@ -283,10 +278,10 @@
 						      info);
 		else
 			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
-					     "%s)' due to age (%dms).\n",
-					     escape_essid(network->ssid,
-							  network->ssid_len),
-					     print_mac(mac, network->bssid),
+					     "%pM)' due to age (%dms).\n",
+					     print_ssid(ssid, network->ssid,
+							 network->ssid_len),
+					     network->bssid,
 					     jiffies_to_msecs(jiffies -
 							      network->
 							      last_scanned));
@@ -314,6 +309,7 @@
 	int i, key, key_provided, len;
 	struct ieee80211_crypt_data **crypt;
 	int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
+	DECLARE_SSID_BUF(ssid);
 
 	IEEE80211_DEBUG_WX("SET_ENCODE\n");
 
@@ -403,13 +399,17 @@
 
 	/* If a new key was provided, set it up */
 	if (erq->length > 0) {
+#ifdef CONFIG_IEEE80211_DEBUG
+		DECLARE_SSID_BUF(ssid);
+#endif
+
 		len = erq->length <= 5 ? 5 : 13;
 		memcpy(sec.keys[key], keybuf, erq->length);
 		if (len > erq->length)
 			memset(sec.keys[key] + erq->length, 0,
 			       len - erq->length);
 		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
-				   key, escape_essid(sec.keys[key], len),
+				   key, print_ssid(ssid, sec.keys[key], len),
 				   erq->length, len);
 		sec.key_sizes[key] = len;
 		if (*crypt)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 1fbff5f..e328681 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1070,11 +1070,8 @@
 		return 0;
 
 	if (sysctl_ip_dynaddr > 1) {
-		printk(KERN_INFO "%s(): shifting inet->"
-				 "saddr from " NIPQUAD_FMT " to " NIPQUAD_FMT "\n",
-		       __func__,
-		       NIPQUAD(old_saddr),
-		       NIPQUAD(new_saddr));
+		printk(KERN_INFO "%s(): shifting inet->saddr from %pI4 to %pI4\n",
+		       __func__, &old_saddr, &new_saddr);
 	}
 
 	inet->saddr = inet->rcv_saddr = new_saddr;
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 8219b7e..3f20518 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -201,8 +201,8 @@
 
 static void ah4_err(struct sk_buff *skb, u32 info)
 {
-	struct iphdr *iph = (struct iphdr*)skb->data;
-	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2));
+	struct iphdr *iph = (struct iphdr *)skb->data;
+	struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
 	struct xfrm_state *x;
 
 	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 1a9dd66..957c87d 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -506,7 +506,7 @@
 	if (dev == NULL)
 		return -EINVAL;
 	if (n == NULL) {
-		__be32 nexthop = ((struct rtable*)dst)->rt_gateway;
+		__be32 nexthop = ((struct rtable *)dst)->rt_gateway;
 		if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
 			nexthop = 0;
 		n = __neigh_lookup_errno(
@@ -640,14 +640,14 @@
 	arp_ptr=(unsigned char *)(arp+1);
 
 	memcpy(arp_ptr, src_hw, dev->addr_len);
-	arp_ptr+=dev->addr_len;
-	memcpy(arp_ptr, &src_ip,4);
-	arp_ptr+=4;
+	arp_ptr += dev->addr_len;
+	memcpy(arp_ptr, &src_ip, 4);
+	arp_ptr += 4;
 	if (target_hw != NULL)
 		memcpy(arp_ptr, target_hw, dev->addr_len);
 	else
 		memset(arp_ptr, 0, dev->addr_len);
-	arp_ptr+=dev->addr_len;
+	arp_ptr += dev->addr_len;
 	memcpy(arp_ptr, &dest_ip, 4);
 
 	return skb;
@@ -823,9 +823,9 @@
 				int dont_send = 0;
 
 				if (!dont_send)
-					dont_send |= arp_ignore(in_dev,sip,tip);
+					dont_send |= arp_ignore(in_dev, sip, tip);
 				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-					dont_send |= arp_filter(sip,tip,dev);
+					dont_send |= arp_filter(sip, tip, dev);
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
 
@@ -1308,7 +1308,7 @@
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 	}
 #endif
-	sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->primary_key));
+	sprintf(tbuf, "%pI4", n->primary_key);
 	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
 		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
 	read_unlock(&n->lock);
@@ -1321,7 +1321,7 @@
 	int hatype = dev ? dev->type : 0;
 	char tbuf[16];
 
-	sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->key));
+	sprintf(tbuf, "%pI4", n->key);
 	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
 		   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
 		   dev ? dev->name : "*");
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 2e78f6b..e527990 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -490,7 +490,6 @@
 	}
 
 	atomic_set(&doi_def->refcount, 1);
-	INIT_RCU_HEAD(&doi_def->rcu);
 
 	spin_lock(&cipso_v4_doi_list_lock);
 	if (cipso_v4_doi_search(doi_def->doi) != NULL)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 56fce3a..309997e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -112,13 +112,7 @@
 
 static struct in_ifaddr *inet_alloc_ifa(void)
 {
-	struct in_ifaddr *ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
-
-	if (ifa) {
-		INIT_RCU_HEAD(&ifa->rcu_head);
-	}
-
-	return ifa;
+	return kzalloc(sizeof(struct in_ifaddr), GFP_KERNEL);
 }
 
 static void inet_rcu_free_ifa(struct rcu_head *head)
@@ -161,7 +155,6 @@
 	in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL);
 	if (!in_dev)
 		goto out;
-	INIT_RCU_HEAD(&in_dev->rcu_head);
 	memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
 			sizeof(in_dev->cnf));
 	in_dev->cnf.sysctl = NULL;
@@ -1108,7 +1101,7 @@
 }
 
 static struct notifier_block ip_netdev_notifier = {
-	.notifier_call =inetdev_event,
+	.notifier_call = inetdev_event,
 };
 
 static inline size_t inet_nlmsg_size(void)
@@ -1195,7 +1188,7 @@
 	return skb->len;
 }
 
-static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
+static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 		      u32 pid)
 {
 	struct sk_buff *skb;
@@ -1262,7 +1255,7 @@
 }
 
 static int devinet_conf_proc(ctl_table *ctl, int write,
-			     struct file* filp, void __user *buffer,
+			     struct file *filp, void __user *buffer,
 			     size_t *lenp, loff_t *ppos)
 {
 	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
@@ -1334,7 +1327,7 @@
 }
 
 static int devinet_sysctl_forward(ctl_table *ctl, int write,
-				  struct file* filp, void __user *buffer,
+				  struct file *filp, void __user *buffer,
 				  size_t *lenp, loff_t *ppos)
 {
 	int *valp = ctl->data;
@@ -1363,7 +1356,7 @@
 }
 
 int ipv4_doint_and_flush(ctl_table *ctl, int write,
-			 struct file* filp, void __user *buffer,
+			 struct file *filp, void __user *buffer,
 			 size_t *lenp, loff_t *ppos)
 {
 	int *valp = ctl->data;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 21515d4..95a9c65 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -413,8 +413,8 @@
 
 static void esp4_err(struct sk_buff *skb, u32 info)
 {
-	struct iphdr *iph = (struct iphdr*)skb->data;
-	struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
+	struct iphdr *iph = (struct iphdr *)skb->data;
+	struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
 	struct xfrm_state *x;
 
 	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 65c1503..741e4fa 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -578,7 +578,7 @@
 	return err;
 }
 
-static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_config cfg;
@@ -600,7 +600,7 @@
 	return err;
 }
 
-static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_config cfg;
@@ -903,7 +903,7 @@
 
 static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;
+	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
 	struct net_device *dev = ifa->ifa_dev->dev;
 
 	switch (event) {
@@ -964,11 +964,11 @@
 }
 
 static struct notifier_block fib_inetaddr_notifier = {
-	.notifier_call =fib_inetaddr_event,
+	.notifier_call = fib_inetaddr_event,
 };
 
 static struct notifier_block fib_netdev_notifier = {
-	.notifier_call =fib_netdev_event,
+	.notifier_call = fib_netdev_event,
 };
 
 static int __net_init ip_fib_net_init(struct net *net)
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index c8cac6c..ded8c44 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -247,7 +247,7 @@
 {
 	int err;
 	struct fn_zone *fz;
-	struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *t = (struct fn_hash *)tb->tb_data;
 
 	read_lock(&fib_hash_lock);
 	for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
@@ -283,7 +283,7 @@
 	struct fib_node *f;
 	struct fib_info *fi = NULL;
 	struct fib_info *last_resort;
-	struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *t = (struct fn_hash *)tb->tb_data;
 	struct fn_zone *fz = t->fn_zones[0];
 
 	if (fz == NULL)
@@ -548,7 +548,7 @@
 
 static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg)
 {
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *table = (struct fn_hash *)tb->tb_data;
 	struct fib_node *f;
 	struct fib_alias *fa, *fa_to_delete;
 	struct fn_zone *fz;
@@ -748,7 +748,7 @@
 {
 	int m, s_m;
 	struct fn_zone *fz;
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *table = (struct fn_hash *)tb->tb_data;
 
 	s_m = cb->args[2];
 	read_lock(&fib_hash_lock);
@@ -845,10 +845,10 @@
 			struct hlist_node *node;
 			struct fib_node *fn;
 
-			hlist_for_each_entry(fn,node,iter->hash_head,fn_hash) {
+			hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
 				struct fib_alias *fa;
 
-				list_for_each_entry(fa,&fn->fn_alias,fa_list) {
+				list_for_each_entry(fa, &fn->fn_alias, fa_list) {
 					iter->fn = fn;
 					iter->fa = fa;
 					goto out;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index ded2ae3..4817dea 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -63,16 +63,16 @@
 for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
 #define change_nexthops(fi) { int nhsel; struct fib_nh * nh; \
-for (nhsel=0, nh = (struct fib_nh*)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
+for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
 #else /* CONFIG_IP_ROUTE_MULTIPATH */
 
 /* Hope, that gcc will optimize it to get rid of dummy loop */
 
-#define for_nexthops(fi) { int nhsel=0; const struct fib_nh * nh = (fi)->fib_nh; \
+#define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \
 for (nhsel=0; nhsel < 1; nhsel++)
 
-#define change_nexthops(fi) { int nhsel=0; struct fib_nh * nh = (struct fib_nh*)((fi)->fib_nh); \
+#define change_nexthops(fi) { int nhsel = 0; struct fib_nh * nh = (struct fib_nh *)((fi)->fib_nh); \
 for (nhsel=0; nhsel < 1; nhsel++)
 
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
@@ -358,7 +358,7 @@
 		state = n->nud_state;
 		neigh_release(n);
 	}
-	if (state==NUD_REACHABLE)
+	if (state == NUD_REACHABLE)
 		return 0;
 	if ((state&NUD_VALID) && order != dflt)
 		return 0;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 5cb7278..ec0ae49 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2399,8 +2399,8 @@
 		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
 
 		seq_indent(seq, iter->depth-1);
-		seq_printf(seq, "  +-- " NIPQUAD_FMT "/%d %d %d %d\n",
-			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
+		seq_printf(seq, "  +-- %pI4/%d %d %d %d\n",
+			   &prf, tn->pos, tn->bits, tn->full_children,
 			   tn->empty_children);
 
 	} else {
@@ -2410,7 +2410,7 @@
 		__be32 val = htonl(l->key);
 
 		seq_indent(seq, iter->depth);
-		seq_printf(seq, "  |-- " NIPQUAD_FMT "\n", NIPQUAD(val));
+		seq_printf(seq, "  |-- %pI4\n", &val);
 
 		hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
 			struct fib_alias *fa;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 72b2de7..21e497e 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -683,10 +683,8 @@
 			break;
 		case ICMP_FRAG_NEEDED:
 			if (ipv4_config.no_pmtu_disc) {
-				LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": "
-							 "fragmentation needed "
-							 "and DF set.\n",
-					       NIPQUAD(iph->daddr));
+				LIMIT_NETDEBUG(KERN_INFO "ICMP: %pI4: fragmentation needed and DF set.\n",
+					       &iph->daddr);
 			} else {
 				info = ip_rt_frag_needed(net, iph,
 							 ntohs(icmph->un.frag.mtu),
@@ -696,9 +694,8 @@
 			}
 			break;
 		case ICMP_SR_FAILED:
-			LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": Source "
-						 "Route Failed.\n",
-				       NIPQUAD(iph->daddr));
+			LIMIT_NETDEBUG(KERN_INFO "ICMP: %pI4: Source Route Failed.\n",
+				       &iph->daddr);
 			break;
 		default:
 			break;
@@ -729,12 +726,12 @@
 	if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses &&
 	    inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
 		if (net_ratelimit())
-			printk(KERN_WARNING NIPQUAD_FMT " sent an invalid ICMP "
+			printk(KERN_WARNING "%pI4 sent an invalid ICMP "
 					    "type %u, code %u "
-					    "error to a broadcast: " NIPQUAD_FMT " on %s\n",
-			       NIPQUAD(ip_hdr(skb)->saddr),
+					    "error to a broadcast: %pI4 on %s\n",
+			       &ip_hdr(skb)->saddr,
 			       icmph->type, icmph->code,
-			       NIPQUAD(iph->daddr),
+			       &iph->daddr,
 			       skb->dev->name);
 		goto out;
 	}
@@ -952,9 +949,8 @@
 				break;
 		}
 		if (!ifa && net_ratelimit()) {
-			printk(KERN_INFO "Wrong address mask " NIPQUAD_FMT " from "
-					 "%s/" NIPQUAD_FMT "\n",
-			       NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
+			printk(KERN_INFO "Wrong address mask %pI4 from %s/%pI4\n",
+			       mp, dev->name, &rt->rt_src);
 		}
 	}
 	rcu_read_unlock();
@@ -976,9 +972,10 @@
 	struct net *net = dev_net(rt->u.dst.dev);
 
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+		struct sec_path *sp = skb_sec_path(skb);
 		int nh;
 
-		if (!(skb->sp && skb->sp->xvec[skb->sp->len - 1]->props.flags &
+		if (!(sp && sp->xvec[sp->len - 1]->props.flags &
 				 XFRM_STATE_ICMP))
 			goto drop;
 
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index a0d8645..f92733e 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -167,7 +167,7 @@
 	spin_lock_bh(&im->lock);
 	if (del_timer(&im->timer))
 		atomic_dec(&im->refcnt);
-	im->tm_running=0;
+	im->tm_running = 0;
 	im->reporter = 0;
 	im->unsolicit_count = 0;
 	spin_unlock_bh(&im->lock);
@@ -176,9 +176,9 @@
 /* It must be called with locked im->lock */
 static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
 {
-	int tv=net_random() % max_delay;
+	int tv = net_random() % max_delay;
 
-	im->tm_running=1;
+	im->tm_running = 1;
 	if (!mod_timer(&im->timer, jiffies+tv+2))
 		atomic_inc(&im->refcnt);
 }
@@ -207,7 +207,7 @@
 	if (del_timer(&im->timer)) {
 		if ((long)(im->timer.expires-jiffies) < max_delay) {
 			add_timer(&im->timer);
-			im->tm_running=1;
+			im->tm_running = 1;
 			spin_unlock_bh(&im->lock);
 			return;
 		}
@@ -358,7 +358,7 @@
 
 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
 {
-	return sizeof(struct igmpv3_grec) + 4*igmp_scount(pmc,type,gdel,sdel);
+	return sizeof(struct igmpv3_grec) + 4*igmp_scount(pmc, type, gdel, sdel);
 }
 
 static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc,
@@ -653,7 +653,7 @@
 		return -1;
 	}
 
-	skb=alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
+	skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
 	if (skb == NULL) {
 		ip_rt_put(rt);
 		return -1;
@@ -682,11 +682,11 @@
 	((u8*)&iph[1])[3] = 0;
 
 	ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
-	ih->type=type;
-	ih->code=0;
-	ih->csum=0;
-	ih->group=group;
-	ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
+	ih->type = type;
+	ih->code = 0;
+	ih->csum = 0;
+	ih->group = group;
+	ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr));
 
 	return ip_local_out(skb);
 }
@@ -728,7 +728,7 @@
 	struct in_device *in_dev = im->interface;
 
 	spin_lock(&im->lock);
-	im->tm_running=0;
+	im->tm_running = 0;
 
 	if (im->unsolicit_count) {
 		im->unsolicit_count--;
@@ -997,7 +997,7 @@
 	   --ANK
 	   */
 	if (arp_mc_map(addr, buf, dev, 0) == 0)
-		dev_mc_add(dev,buf,dev->addr_len,0);
+		dev_mc_add(dev, buf, dev->addr_len, 0);
 }
 
 /*
@@ -1010,7 +1010,7 @@
 	struct net_device *dev = in_dev->dev;
 
 	if (arp_mc_map(addr, buf, dev, 0) == 0)
-		dev_mc_delete(dev,buf,dev->addr_len,0);
+		dev_mc_delete(dev, buf, dev->addr_len, 0);
 }
 
 #ifdef CONFIG_IP_MULTICAST
@@ -1210,10 +1210,10 @@
 	if (!im)
 		goto out;
 
-	im->users=1;
-	im->interface=in_dev;
+	im->users = 1;
+	im->interface = in_dev;
 	in_dev_hold(in_dev);
-	im->multiaddr=addr;
+	im->multiaddr = addr;
 	/* initial mode is (EX, empty) */
 	im->sfmode = MCAST_EXCLUDE;
 	im->sfcount[MCAST_INCLUDE] = 0;
@@ -1224,7 +1224,7 @@
 	atomic_set(&im->refcnt, 1);
 	spin_lock_init(&im->lock);
 #ifdef CONFIG_IP_MULTICAST
-	im->tm_running=0;
+	im->tm_running = 0;
 	setup_timer(&im->timer, &igmp_timer_expire, (unsigned long)im);
 	im->unsolicit_count = IGMP_Unsolicited_Report_Count;
 	im->reporter = 0;
@@ -1232,8 +1232,8 @@
 #endif
 	im->loaded = 0;
 	write_lock_bh(&in_dev->mc_list_lock);
-	im->next=in_dev->mc_list;
-	in_dev->mc_list=im;
+	im->next = in_dev->mc_list;
+	in_dev->mc_list = im;
 	in_dev->mc_count++;
 	write_unlock_bh(&in_dev->mc_list_lock);
 #ifdef CONFIG_IP_MULTICAST
@@ -1279,7 +1279,7 @@
 	ASSERT_RTNL();
 
 	for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
-		if (i->multiaddr==addr) {
+		if (i->multiaddr == addr) {
 			if (--i->users == 0) {
 				write_lock_bh(&in_dev->mc_list_lock);
 				*ip = i->next;
@@ -1738,7 +1738,7 @@
 {
 	int err;
 	__be32 addr = imr->imr_multiaddr.s_addr;
-	struct ip_mc_socklist *iml=NULL, *i;
+	struct ip_mc_socklist *iml = NULL, *i;
 	struct in_device *in_dev;
 	struct inet_sock *inet = inet_sk(sk);
 	struct net *net = sock_net(sk);
@@ -1769,7 +1769,7 @@
 	err = -ENOBUFS;
 	if (count >= sysctl_igmp_max_memberships)
 		goto done;
-	iml = sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL);
+	iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
 	if (iml == NULL)
 		goto done;
 
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index bd1278a..36f4cbc 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -323,7 +323,7 @@
 
 EXPORT_SYMBOL(inet_csk_reset_keepalive_timer);
 
-struct dst_entry* inet_csk_route_req(struct sock *sk,
+struct dst_entry *inet_csk_route_req(struct sock *sk,
 				     const struct request_sock *req)
 {
 	struct rtable *rt;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index a456cee..b1fbe18 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -144,7 +144,7 @@
  * _stack is known to be NULL or not at compile time,
  * so compiler will optimize the if (_stack) tests.
  */
-#define lookup(_daddr,_stack) 					\
+#define lookup(_daddr, _stack) 					\
 ({								\
 	struct inet_peer *u, **v;				\
 	if (_stack != NULL) {					\
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 450016b..df3fe50 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -106,7 +106,7 @@
 	 *	We now generate an ICMP HOST REDIRECT giving the route
 	 *	we calculated.
 	 */
-	if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb->sp)
+	if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb))
 		ip_rt_send_redirect(skb);
 
 	skb->priority = rt_tos2priority(iph->tos);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index e4f81f5..6659ac0 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -56,7 +56,7 @@
 	int			offset;
 };
 
-#define FRAG_CB(skb)	((struct ipfrag_skb_cb*)((skb)->cb))
+#define FRAG_CB(skb)	((struct ipfrag_skb_cb *)((skb)->cb))
 
 /* Describe an entry in the "incomplete datagrams" queue. */
 struct ipq {
@@ -559,9 +559,8 @@
 	goto out_fail;
 out_oversize:
 	if (net_ratelimit())
-		printk(KERN_INFO
-			"Oversized IP packet from " NIPQUAD_FMT ".\n",
-			NIPQUAD(qp->saddr));
+		printk(KERN_INFO "Oversized IP packet from %pI4.\n",
+			&qp->saddr);
 out_fail:
 	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_REASMFAILS);
 	return err;
@@ -608,7 +607,7 @@
 		.data		= &init_net.ipv4.frags.high_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_IPFRAG_LOW_THRESH,
@@ -616,7 +615,7 @@
 		.data		= &init_net.ipv4.frags.low_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_IPFRAG_TIME,
@@ -624,8 +623,8 @@
 		.data		= &init_net.ipv4.frags.timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{ }
 };
@@ -637,15 +636,15 @@
 		.data		= &ip4_frags.secret_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.procname	= "ipfrag_max_dist",
 		.data		= &sysctl_ipfrag_max_dist,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
+		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= &zero
 	},
 	{ }
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 85c487b..191ef75 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -371,7 +371,7 @@
    by themself???
  */
 
-	struct iphdr *iph = (struct iphdr*)skb->data;
+	struct iphdr *iph = (struct iphdr *)skb->data;
 	__be16	     *p = (__be16*)(skb->data+(iph->ihl<<2));
 	int grehlen = (iph->ihl<<2) + 4;
 	const int type = icmp_hdr(skb)->type;
@@ -632,7 +632,7 @@
 
 	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
 		gre_hlen = 0;
-		tiph = (struct iphdr*)skb->data;
+		tiph = (struct iphdr *)skb->data;
 	} else {
 		gre_hlen = tunnel->hlen;
 		tiph = &tunnel->parms.iph;
@@ -660,7 +660,7 @@
 			if (neigh == NULL)
 				goto tx_error;
 
-			addr6 = (struct in6_addr*)&neigh->primary_key;
+			addr6 = (struct in6_addr *)&neigh->primary_key;
 			addr_type = ipv6_addr_type(addr6);
 
 			if (addr_type == IPV6_ADDR_ANY) {
@@ -726,7 +726,7 @@
 	}
 #ifdef CONFIG_IPV6
 	else if (skb->protocol == htons(ETH_P_IPV6)) {
-		struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
+		struct rt6_info *rt6 = (struct rt6_info *)skb->dst;
 
 		if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
 			if ((tunnel->parms.iph.daddr &&
@@ -800,7 +800,7 @@
 			iph->ttl = old_iph->ttl;
 #ifdef CONFIG_IPV6
 		else if (skb->protocol == htons(ETH_P_IPV6))
-			iph->ttl = ((struct ipv6hdr*)old_iph)->hop_limit;
+			iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;
 #endif
 		else
 			iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
@@ -962,7 +962,7 @@
 					break;
 				}
 			} else {
-				unsigned nflags=0;
+				unsigned nflags = 0;
 
 				t = netdev_priv(dev);
 
@@ -1104,7 +1104,7 @@
 
 static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 {
-	struct iphdr *iph = (struct iphdr*) skb_mac_header(skb);
+	struct iphdr *iph = (struct iphdr *) skb_mac_header(skb);
 	memcpy(haddr, &iph->saddr, 4);
 	return 4;
 }
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 861978a..70bedab 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -294,10 +294,8 @@
 			if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
 				if (IN_DEV_LOG_MARTIANS(in_dev) &&
 				    net_ratelimit())
-					printk(KERN_INFO "source route option "
-					       NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
-					       NIPQUAD(iph->saddr),
-					       NIPQUAD(iph->daddr));
+					printk(KERN_INFO "source route option %pI4 -> %pI4\n",
+					       &iph->saddr, &iph->daddr);
 				in_dev_put(in_dev);
 				goto drop;
 			}
@@ -342,9 +340,9 @@
 		struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id());
 		u32 idx = skb->dst->tclassid;
 		st[idx&0xFF].o_packets++;
-		st[idx&0xFF].o_bytes+=skb->len;
+		st[idx&0xFF].o_bytes += skb->len;
 		st[(idx>>16)&0xFF].i_packets++;
-		st[(idx>>16)&0xFF].i_bytes+=skb->len;
+		st[(idx>>16)&0xFF].i_bytes += skb->len;
 	}
 #endif
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index d2a8f8b..46d7be2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -430,7 +430,7 @@
  *	single device frame, and queue such a frame for sending.
  */
 
-int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
 	struct iphdr *iph;
 	int raw = 0;
@@ -720,7 +720,7 @@
 			int getfrag(void *from, char *to, int offset, int len,
 			       int odd, struct sk_buff *skb),
 			void *from, int length, int hh_len, int fragheaderlen,
-			int transhdrlen, int mtu,unsigned int flags)
+			int transhdrlen, int mtu, unsigned int flags)
 {
 	struct sk_buff *skb;
 	int err;
@@ -741,7 +741,7 @@
 		skb_reserve(skb, hh_len);
 
 		/* create space for UDP/IP header */
-		skb_put(skb,fragheaderlen + transhdrlen);
+		skb_put(skb, fragheaderlen + transhdrlen);
 
 		/* initialize network header pointer */
 		skb_reset_network_header(skb);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 465abf0..e976efe 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -94,7 +94,7 @@
 static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
 {
 	unsigned char optbuf[sizeof(struct ip_options) + 40];
-	struct ip_options * opt = (struct ip_options*)optbuf;
+	struct ip_options * opt = (struct ip_options *)optbuf;
 
 	if (IPCB(skb)->opt.optlen == 0)
 		return;
@@ -411,7 +411,7 @@
 			    int optname, char __user *optval, int optlen)
 {
 	struct inet_sock *inet = inet_sk(sk);
-	int val=0,err;
+	int val = 0, err;
 
 	if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
 			     (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
@@ -437,7 +437,7 @@
 	/* If optlen==0, it is equivalent to val == 0 */
 
 	if (ip_mroute_opt(optname))
-		return ip_mroute_setsockopt(sk,optname,optval,optlen);
+		return ip_mroute_setsockopt(sk, optname, optval, optlen);
 
 	err = 0;
 	lock_sock(sk);
@@ -549,7 +549,7 @@
 			goto e_inval;
 		if (optlen<1)
 			goto e_inval;
-		if (val==-1)
+		if (val == -1)
 			val = 1;
 		if (val < 0 || val > 255)
 			goto e_inval;
@@ -573,12 +573,12 @@
 
 		err = -EFAULT;
 		if (optlen >= sizeof(struct ip_mreqn)) {
-			if (copy_from_user(&mreq,optval,sizeof(mreq)))
+			if (copy_from_user(&mreq, optval, sizeof(mreq)))
 				break;
 		} else {
 			memset(&mreq, 0, sizeof(mreq));
 			if (optlen >= sizeof(struct in_addr) &&
-			    copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))
+			    copy_from_user(&mreq.imr_address, optval, sizeof(struct in_addr)))
 				break;
 		}
 
@@ -626,11 +626,11 @@
 			goto e_inval;
 		err = -EFAULT;
 		if (optlen >= sizeof(struct ip_mreqn)) {
-			if (copy_from_user(&mreq,optval,sizeof(mreq)))
+			if (copy_from_user(&mreq, optval, sizeof(mreq)))
 				break;
 		} else {
 			memset(&mreq, 0, sizeof(mreq));
-			if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
+			if (copy_from_user(&mreq, optval, sizeof(struct ip_mreq)))
 				break;
 		}
 
@@ -808,7 +808,7 @@
 			err = -ENOBUFS;
 			break;
 		}
-		gsf = kmalloc(optlen,GFP_KERNEL);
+		gsf = kmalloc(optlen, GFP_KERNEL);
 		if (!gsf) {
 			err = -ENOBUFS;
 			break;
@@ -828,7 +828,7 @@
 			goto mc_msf_out;
 		}
 		msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);
-		msf = kmalloc(msize,GFP_KERNEL);
+		msf = kmalloc(msize, GFP_KERNEL);
 		if (!msf) {
 			err = -ENOBUFS;
 			goto mc_msf_out;
@@ -971,9 +971,9 @@
 		return -EOPNOTSUPP;
 
 	if (ip_mroute_opt(optname))
-		return ip_mroute_getsockopt(sk,optname,optval,optlen);
+		return ip_mroute_getsockopt(sk, optname, optval, optlen);
 
-	if (get_user(len,optlen))
+	if (get_user(len, optlen))
 		return -EFAULT;
 	if (len < 0)
 		return -EINVAL;
@@ -984,7 +984,7 @@
 	case IP_OPTIONS:
 	{
 		unsigned char optbuf[sizeof(struct ip_options)+40];
-		struct ip_options * opt = (struct ip_options*)optbuf;
+		struct ip_options * opt = (struct ip_options *)optbuf;
 		opt->optlen = 0;
 		if (inet->opt)
 			memcpy(optbuf, inet->opt,
@@ -1154,13 +1154,13 @@
 		len = 1;
 		if (put_user(len, optlen))
 			return -EFAULT;
-		if (copy_to_user(optval,&ucval,1))
+		if (copy_to_user(optval, &ucval, 1))
 			return -EFAULT;
 	} else {
 		len = min_t(unsigned int, sizeof(int), len);
 		if (put_user(len, optlen))
 			return -EFAULT;
-		if (copy_to_user(optval,&val,len))
+		if (copy_to_user(optval, &val, len))
 			return -EFAULT;
 	}
 	return 0;
@@ -1178,7 +1178,7 @@
 			!ip_mroute_opt(optname)) {
 		int len;
 
-		if (get_user(len,optlen))
+		if (get_user(len, optlen))
 			return -EFAULT;
 
 		lock_sock(sk);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 38ccb6d..ec8264a 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -39,8 +39,8 @@
 			      spi, IPPROTO_COMP, AF_INET);
 	if (!x)
 		return;
-	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIPQUAD_FMT "\n",
-		 spi, NIPQUAD(iph->daddr));
+	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI4\n",
+		 spi, &iph->daddr);
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 42065ff..42a0f3d 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -374,7 +374,7 @@
 	 */
 
 	if (!ic_host_name_set)
-		sprintf(init_utsname()->nodename, NIPQUAD_FMT, NIPQUAD(ic_myaddr));
+		sprintf(init_utsname()->nodename, "%pI4", &ic_myaddr);
 
 	if (root_server_addr == NONE)
 		root_server_addr = ic_servaddr;
@@ -387,11 +387,11 @@
 		else if (IN_CLASSC(ntohl(ic_myaddr)))
 			ic_netmask = htonl(IN_CLASSC_NET);
 		else {
-			printk(KERN_ERR "IP-Config: Unable to guess netmask for address " NIPQUAD_FMT "\n",
-				NIPQUAD(ic_myaddr));
+			printk(KERN_ERR "IP-Config: Unable to guess netmask for address %pI4\n",
+				&ic_myaddr);
 			return -1;
 		}
-		printk("IP-Config: Guessing netmask " NIPQUAD_FMT "\n", NIPQUAD(ic_netmask));
+		printk("IP-Config: Guessing netmask %pI4\n", &ic_netmask);
 	}
 
 	return 0;
@@ -979,10 +979,8 @@
 				ic_myaddr = b->your_ip;
 				ic_servaddr = server_id;
 #ifdef IPCONFIG_DEBUG
-				printk("DHCP: Offered address " NIPQUAD_FMT,
-				       NIPQUAD(ic_myaddr));
-				printk(" by server " NIPQUAD_FMT "\n",
-				       NIPQUAD(ic_servaddr));
+				printk("DHCP: Offered address %pI4 by server %pI4\n",
+				       &ic_myaddr, &ic_servaddr);
 #endif
 				/* The DHCP indicated server address takes
 				 * precedence over the bootp header one if
@@ -1177,11 +1175,11 @@
 		return -1;
 	}
 
-	printk("IP-Config: Got %s answer from " NIPQUAD_FMT ", ",
+	printk("IP-Config: Got %s answer from %pI4, ",
 		((ic_got_reply & IC_RARP) ? "RARP"
 		 : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
-		NIPQUAD(ic_servaddr));
-	printk("my address is " NIPQUAD_FMT "\n", NIPQUAD(ic_myaddr));
+		&ic_servaddr);
+	printk("my address is %pI4\n", &ic_myaddr);
 
 	return 0;
 }
@@ -1206,14 +1204,12 @@
 			   "domain %s\n", ic_domain);
 	for (i = 0; i < CONF_NAMESERVERS_MAX; i++) {
 		if (ic_nameservers[i] != NONE)
-			seq_printf(seq,
-				   "nameserver " NIPQUAD_FMT "\n",
-				   NIPQUAD(ic_nameservers[i]));
+			seq_printf(seq, "nameserver %pI4\n",
+				   &ic_nameservers[i]);
 	}
 	if (ic_servaddr != NONE)
-		seq_printf(seq,
-			   "bootserver " NIPQUAD_FMT "\n",
-			   NIPQUAD(ic_servaddr));
+		seq_printf(seq, "bootserver %pI4\n",
+			   &ic_servaddr);
 	return 0;
 }
 
@@ -1387,13 +1383,13 @@
 	 */
 	printk("IP-Config: Complete:");
 	printk("\n     device=%s", ic_dev->name);
-	printk(", addr=" NIPQUAD_FMT, NIPQUAD(ic_myaddr));
-	printk(", mask=" NIPQUAD_FMT, NIPQUAD(ic_netmask));
-	printk(", gw=" NIPQUAD_FMT, NIPQUAD(ic_gateway));
+	printk(", addr=%pI4", &ic_myaddr);
+	printk(", mask=%pI4", &ic_netmask);
+	printk(", gw=%pI4", &ic_gateway);
 	printk(",\n     host=%s, domain=%s, nis-domain=%s",
 	       utsname()->nodename, ic_domain, utsname()->domainname);
-	printk(",\n     bootserver=" NIPQUAD_FMT, NIPQUAD(ic_servaddr));
-	printk(", rootserver=" NIPQUAD_FMT, NIPQUAD(root_server_addr));
+	printk(",\n     bootserver=%pI4", &ic_servaddr);
+	printk(", rootserver=%pI4", &root_server_addr);
 	printk(", rootpath=%s", root_server_path);
 	printk("\n");
 #endif /* !SILENT */
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 29609d2..b3c3d7b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -281,7 +281,7 @@
    8 bytes of packet payload. It means, that precise relaying of
    ICMP in the real Internet is absolutely infeasible.
  */
-	struct iphdr *iph = (struct iphdr*)skb->data;
+	struct iphdr *iph = (struct iphdr *)skb->data;
 	const int type = icmp_hdr(skb)->type;
 	const int code = icmp_hdr(skb)->code;
 	struct ip_tunnel *t;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index b42e082..05ed336 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -331,7 +331,7 @@
 
 	atomic_dec(&cache_resolve_queue_len);
 
-	while ((skb=skb_dequeue(&c->mfc_un.unres.unresolved))) {
+	while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) {
 		if (ip_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 			nlh->nlmsg_type = NLMSG_ERROR;
@@ -477,13 +477,13 @@
 	/*
 	 *	Fill in the VIF structures
 	 */
-	v->rate_limit=vifc->vifc_rate_limit;
-	v->local=vifc->vifc_lcl_addr.s_addr;
-	v->remote=vifc->vifc_rmt_addr.s_addr;
-	v->flags=vifc->vifc_flags;
+	v->rate_limit = vifc->vifc_rate_limit;
+	v->local = vifc->vifc_lcl_addr.s_addr;
+	v->remote = vifc->vifc_rmt_addr.s_addr;
+	v->flags = vifc->vifc_flags;
 	if (!mrtsock)
 		v->flags |= VIFF_STATIC;
-	v->threshold=vifc->vifc_threshold;
+	v->threshold = vifc->vifc_threshold;
 	v->bytes_in = 0;
 	v->bytes_out = 0;
 	v->pkt_in = 0;
@@ -494,7 +494,7 @@
 
 	/* And finish update writing critical data */
 	write_lock_bh(&mrt_lock);
-	v->dev=dev;
+	v->dev = dev;
 #ifdef CONFIG_IP_PIMSM
 	if (v->flags&VIFF_REGISTER)
 		reg_vif_num = vifi;
@@ -507,7 +507,7 @@
 
 static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp)
 {
-	int line=MFC_HASH(mcastgrp,origin);
+	int line = MFC_HASH(mcastgrp, origin);
 	struct mfc_cache *c;
 
 	for (c=mfc_cache_array[line]; c; c = c->next) {
@@ -522,8 +522,8 @@
  */
 static struct mfc_cache *ipmr_cache_alloc(void)
 {
-	struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
-	if (c==NULL)
+	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
+	if (c == NULL)
 		return NULL;
 	c->mfc_un.res.minvif = MAXVIFS;
 	return c;
@@ -531,8 +531,8 @@
 
 static struct mfc_cache *ipmr_cache_alloc_unres(void)
 {
-	struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
-	if (c==NULL)
+	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;
@@ -552,7 +552,7 @@
 	 *	Play the pending entries through our router
 	 */
 
-	while ((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) {
+	while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
 		if (ip_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 
@@ -637,7 +637,7 @@
 	 *	Add our header
 	 */
 
-	igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
+	igmp=(struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
 	igmp->type	=
 	msg->im_msgtype = assert;
 	igmp->code 	=	0;
@@ -653,7 +653,7 @@
 	/*
 	 *	Deliver to mrouted
 	 */
-	if ((ret=sock_queue_rcv_skb(mroute_socket,skb))<0) {
+	if ((ret = sock_queue_rcv_skb(mroute_socket, skb))<0) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n");
 		kfree_skb(skb);
@@ -685,7 +685,7 @@
 		 *	Create a new entry if allowable
 		 */
 
-		if (atomic_read(&cache_resolve_queue_len)>=10 ||
+		if (atomic_read(&cache_resolve_queue_len) >= 10 ||
 		    (c=ipmr_cache_alloc_unres())==NULL) {
 			spin_unlock_bh(&mfc_unres_lock);
 
@@ -728,7 +728,7 @@
 		kfree_skb(skb);
 		err = -ENOBUFS;
 	} else {
-		skb_queue_tail(&c->mfc_un.unres.unresolved,skb);
+		skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
 		err = 0;
 	}
 
@@ -745,7 +745,7 @@
 	int line;
 	struct mfc_cache *c, **cp;
 
-	line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
+	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) {
 		if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
@@ -766,7 +766,7 @@
 	int line;
 	struct mfc_cache *uc, *c, **cp;
 
-	line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
+	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) {
 		if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
@@ -787,13 +787,13 @@
 	if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
 		return -EINVAL;
 
-	c=ipmr_cache_alloc();
-	if (c==NULL)
+	c = ipmr_cache_alloc();
+	if (c == NULL)
 		return -ENOMEM;
 
-	c->mfc_origin=mfc->mfcc_origin.s_addr;
-	c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
-	c->mfc_parent=mfc->mfcc_parent;
+	c->mfc_origin = mfc->mfcc_origin.s_addr;
+	c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr;
+	c->mfc_parent = mfc->mfcc_parent;
 	ipmr_update_thresholds(c, mfc->mfcc_ttls);
 	if (!mrtsock)
 		c->mfc_flags |= MFC_STATIC;
@@ -846,7 +846,7 @@
 	/*
 	 *	Wipe the cache
 	 */
-	for (i=0;i<MFC_LINES;i++) {
+	for (i=0; i<MFC_LINES; i++) {
 		struct mfc_cache *c, **cp;
 
 		cp = &mfc_cache_array[i];
@@ -887,7 +887,7 @@
 		IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--;
 
 		write_lock_bh(&mrt_lock);
-		mroute_socket=NULL;
+		mroute_socket = NULL;
 		write_unlock_bh(&mrt_lock);
 
 		mroute_clean_tables(sk);
@@ -902,7 +902,7 @@
  *	MOSPF/PIM router set up we can clean this up.
  */
 
-int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int optlen)
+int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
 {
 	int ret;
 	struct vifctl vif;
@@ -918,7 +918,7 @@
 		if (sk->sk_type != SOCK_RAW ||
 		    inet_sk(sk)->num != IPPROTO_IGMP)
 			return -EOPNOTSUPP;
-		if (optlen!=sizeof(int))
+		if (optlen != sizeof(int))
 			return -ENOPROTOOPT;
 
 		rtnl_lock();
@@ -930,7 +930,7 @@
 		ret = ip_ra_control(sk, 1, mrtsock_destruct);
 		if (ret == 0) {
 			write_lock_bh(&mrt_lock);
-			mroute_socket=sk;
+			mroute_socket = sk;
 			write_unlock_bh(&mrt_lock);
 
 			IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++;
@@ -938,19 +938,19 @@
 		rtnl_unlock();
 		return ret;
 	case MRT_DONE:
-		if (sk!=mroute_socket)
+		if (sk != mroute_socket)
 			return -EACCES;
 		return ip_ra_control(sk, 0, NULL);
 	case MRT_ADD_VIF:
 	case MRT_DEL_VIF:
-		if (optlen!=sizeof(vif))
+		if (optlen != sizeof(vif))
 			return -EINVAL;
-		if (copy_from_user(&vif,optval,sizeof(vif)))
+		if (copy_from_user(&vif, optval, sizeof(vif)))
 			return -EFAULT;
 		if (vif.vifc_vifi >= MAXVIFS)
 			return -ENFILE;
 		rtnl_lock();
-		if (optname==MRT_ADD_VIF) {
+		if (optname == MRT_ADD_VIF) {
 			ret = vif_add(&vif, sk==mroute_socket);
 		} else {
 			ret = vif_delete(vif.vifc_vifi, 0);
@@ -964,12 +964,12 @@
 		 */
 	case MRT_ADD_MFC:
 	case MRT_DEL_MFC:
-		if (optlen!=sizeof(mfc))
+		if (optlen != sizeof(mfc))
 			return -EINVAL;
-		if (copy_from_user(&mfc,optval, sizeof(mfc)))
+		if (copy_from_user(&mfc, optval, sizeof(mfc)))
 			return -EFAULT;
 		rtnl_lock();
-		if (optname==MRT_DEL_MFC)
+		if (optname == MRT_DEL_MFC)
 			ret = ipmr_mfc_delete(&mfc);
 		else
 			ret = ipmr_mfc_add(&mfc, sk==mroute_socket);
@@ -1028,12 +1028,12 @@
  *	Getsock opt support for the multicast routing system.
  */
 
-int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __user *optlen)
+int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen)
 {
 	int olr;
 	int val;
 
-	if (optname!=MRT_VERSION &&
+	if (optname != MRT_VERSION &&
 #ifdef CONFIG_IP_PIMSM
 	   optname!=MRT_PIM &&
 #endif
@@ -1047,17 +1047,17 @@
 	if (olr < 0)
 		return -EINVAL;
 
-	if (put_user(olr,optlen))
+	if (put_user(olr, optlen))
 		return -EFAULT;
-	if (optname==MRT_VERSION)
-		val=0x0305;
+	if (optname == MRT_VERSION)
+		val = 0x0305;
 #ifdef CONFIG_IP_PIMSM
-	else if (optname==MRT_PIM)
-		val=mroute_do_pim;
+	else if (optname == MRT_PIM)
+		val = mroute_do_pim;
 #endif
 	else
-		val=mroute_do_assert;
-	if (copy_to_user(optval,&val,olr))
+		val = mroute_do_assert;
+	if (copy_to_user(optval, &val, olr))
 		return -EFAULT;
 	return 0;
 }
@@ -1075,27 +1075,27 @@
 
 	switch (cmd) {
 	case SIOCGETVIFCNT:
-		if (copy_from_user(&vr,arg,sizeof(vr)))
+		if (copy_from_user(&vr, arg, sizeof(vr)))
 			return -EFAULT;
-		if (vr.vifi>=maxvif)
+		if (vr.vifi >= maxvif)
 			return -EINVAL;
 		read_lock(&mrt_lock);
 		vif=&vif_table[vr.vifi];
 		if (VIF_EXISTS(vr.vifi))	{
-			vr.icount=vif->pkt_in;
-			vr.ocount=vif->pkt_out;
-			vr.ibytes=vif->bytes_in;
-			vr.obytes=vif->bytes_out;
+			vr.icount = vif->pkt_in;
+			vr.ocount = vif->pkt_out;
+			vr.ibytes = vif->bytes_in;
+			vr.obytes = vif->bytes_out;
 			read_unlock(&mrt_lock);
 
-			if (copy_to_user(arg,&vr,sizeof(vr)))
+			if (copy_to_user(arg, &vr, sizeof(vr)))
 				return -EFAULT;
 			return 0;
 		}
 		read_unlock(&mrt_lock);
 		return -EADDRNOTAVAIL;
 	case SIOCGETSGCNT:
-		if (copy_from_user(&sr,arg,sizeof(sr)))
+		if (copy_from_user(&sr, arg, sizeof(sr)))
 			return -EFAULT;
 
 		read_lock(&mrt_lock);
@@ -1106,7 +1106,7 @@
 			sr.wrong_if = c->mfc_un.res.wrong_if;
 			read_unlock(&mrt_lock);
 
-			if (copy_to_user(arg,&sr,sizeof(sr)))
+			if (copy_to_user(arg, &sr, sizeof(sr)))
 				return -EFAULT;
 			return 0;
 		}
@@ -1130,15 +1130,15 @@
 	if (event != NETDEV_UNREGISTER)
 		return NOTIFY_DONE;
 	v=&vif_table[0];
-	for (ct=0;ct<maxvif;ct++,v++) {
-		if (v->dev==dev)
+	for (ct=0; ct<maxvif; ct++,v++) {
+		if (v->dev == dev)
 			vif_delete(ct, 1);
 	}
 	return NOTIFY_DONE;
 }
 
 
-static struct notifier_block ip_mr_notifier={
+static struct notifier_block ip_mr_notifier = {
 	.notifier_call = ipmr_device_event,
 };
 
@@ -1204,7 +1204,7 @@
 #ifdef CONFIG_IP_PIMSM
 	if (vif->flags & VIFF_REGISTER) {
 		vif->pkt_out++;
-		vif->bytes_out+=skb->len;
+		vif->bytes_out += skb->len;
 		vif->dev->stats.tx_bytes += skb->len;
 		vif->dev->stats.tx_packets++;
 		ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT);
@@ -1254,7 +1254,7 @@
 	}
 
 	vif->pkt_out++;
-	vif->bytes_out+=skb->len;
+	vif->bytes_out += skb->len;
 
 	dst_release(skb->dst);
 	skb->dst = &rt->u.dst;
@@ -1352,7 +1352,7 @@
 	}
 
 	vif_table[vif].pkt_in++;
-	vif_table[vif].bytes_in+=skb->len;
+	vif_table[vif].bytes_in += skb->len;
 
 	/*
 	 *	Forward the frame
@@ -1364,7 +1364,7 @@
 				if (skb2)
 					ipmr_queue_xmit(skb2, cache, psend);
 			}
-			psend=ct;
+			psend = ct;
 		}
 	}
 	if (psend != -1) {
@@ -1428,7 +1428,7 @@
 	/*
 	 *	No usable cache entry
 	 */
-	if (cache==NULL) {
+	if (cache == NULL) {
 		int vif;
 
 		if (local) {
@@ -1602,13 +1602,13 @@
 	if (dev)
 		RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
 
-	mp_head = (struct rtattr*)skb_put(skb, RTA_LENGTH(0));
+	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
 
 	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
 		if (c->mfc_un.res.ttls[ct] < 255) {
 			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
 				goto rtattr_failure;
-			nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+			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;
@@ -1634,7 +1634,7 @@
 	read_lock(&mrt_lock);
 	cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
 
-	if (cache==NULL) {
+	if (cache == NULL) {
 		struct sk_buff *skb2;
 		struct iphdr *iph;
 		struct net_device *dev;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 8d70d29..7ea88b6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -142,15 +142,15 @@
 		  ARPT_INV_TGTIP)) {
 		dprintf("Source or target IP address mismatch.\n");
 
-		dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(src_ipaddr),
-			NIPQUAD(arpinfo->smsk.s_addr),
-			NIPQUAD(arpinfo->src.s_addr),
+		dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
+			&src_ipaddr,
+			&arpinfo->smsk.s_addr,
+			&arpinfo->src.s_addr,
 			arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : "");
-		dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(tgt_ipaddr),
-			NIPQUAD(arpinfo->tmsk.s_addr),
-			NIPQUAD(arpinfo->tgt.s_addr),
+		dprintf("TGT: %pI4 Mask: %pI4 Target: %pI4.%s\n",
+			&tgt_ipaddr,
+			&arpinfo->tmsk.s_addr,
+			&arpinfo->tgt.s_addr,
 			arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : "");
 		return 0;
 	}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 213fb27..ef8b6ca 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -94,15 +94,11 @@
 		     IPT_INV_DSTIP)) {
 		dprintf("Source or dest mismatch.\n");
 
-		dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(ip->saddr),
-			NIPQUAD(ipinfo->smsk.s_addr),
-			NIPQUAD(ipinfo->src.s_addr),
+		dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
+			&ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
 			ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
-		dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(ip->daddr),
-			NIPQUAD(ipinfo->dmsk.s_addr),
-			NIPQUAD(ipinfo->dst.s_addr),
+		dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
+			&ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
 			ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
 		return false;
 	}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7ac1677..2e4f98b 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -168,7 +168,7 @@
 		char buffer[16];
 
 		/* create proc dir entry */
-		sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+		sprintf(buffer, "%pI4", &ip);
 		c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR,
 					  clusterip_procdir,
 					  &clusterip_proc_fops, c);
@@ -373,7 +373,7 @@
 	config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
 	if (!config) {
 		if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
-			printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
+			printk(KERN_WARNING "CLUSTERIP: no config found for %pI4, need 'new'\n", &e->ip.dst.s_addr);
 			return false;
 		} else {
 			struct net_device *dev;
@@ -478,9 +478,8 @@
 	}
 	hbuffer[--k]='\0';
 
-	printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n",
-		NIPQUAD(payload->src_ip), hbuffer,
-		NIPQUAD(payload->dst_ip));
+	printk("src %pI4@%s, dst %pI4\n",
+		&payload->src_ip, hbuffer, &payload->dst_ip);
 }
 #endif
 
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index fc6ce04..4614a696f 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -54,8 +54,8 @@
 	/* Important fields:
 	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
 	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
-	printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
-	       NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
+	printk("SRC=%pI4 DST=%pI4 ",
+	       &ih->saddr, &ih->daddr);
 
 	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
 	printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
@@ -262,8 +262,7 @@
 			break;
 		case ICMP_REDIRECT:
 			/* Max length: 24 "GATEWAY=255.255.255.255 " */
-			printk("GATEWAY=%u.%u.%u.%u ",
-			       NIPQUAD(ich->un.gateway));
+			printk("GATEWAY=%pI4 ", &ich->un.gateway);
 			/* Fall through */
 		case ICMP_DEST_UNREACH:
 		case ICMP_SOURCE_QUENCH:
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 4a7c352..b2141e1 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -60,9 +60,8 @@
 static int ipv4_print_tuple(struct seq_file *s,
 			    const struct nf_conntrack_tuple *tuple)
 {
-	return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
-			  NIPQUAD(tuple->src.u3.ip),
-			  NIPQUAD(tuple->dst.u3.ip));
+	return seq_printf(s, "src=%pI4 dst=%pI4 ",
+			  &tuple->src.u3.ip, &tuple->dst.u3.ip);
 }
 
 static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
@@ -198,7 +197,7 @@
 		.data		= &nf_conntrack_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_COUNT,
@@ -206,7 +205,7 @@
 		.data		= &init_net.ct.count,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
@@ -214,7 +213,7 @@
 		.data		= &nf_conntrack_htable_size,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_CHECKSUM,
@@ -222,7 +221,7 @@
 		.data		= &init_net.ct.sysctl_checksum,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_LOG_INVALID,
@@ -230,8 +229,8 @@
 		.data		= &init_net.ct.sysctl_log_invalid,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
@@ -284,17 +283,17 @@
 			.tuple.dst.u3.ip;
 		memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
 
-		pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
-			 NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+		pr_debug("SO_ORIGINAL_DST: %pI4 %u\n",
+			 &sin.sin_addr.s_addr, ntohs(sin.sin_port));
 		nf_ct_put(ct);
 		if (copy_to_user(user, &sin, sizeof(sin)) != 0)
 			return -EFAULT;
 		else
 			return 0;
 	}
-	pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
-		 NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
-		 NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
+	pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",
+		 &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port),
+		 &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port));
 	return -ENOENT;
 }
 
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 4e88792..1fd3ef7 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -272,7 +272,7 @@
 		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name = 0
@@ -285,7 +285,7 @@
 		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name = 0
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index ee47bf2..7e8e6fc 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -119,10 +119,9 @@
 				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
 					i = 0;
 
-				pr_debug("nf_nat_ras: set signal address "
-					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-					 NIPQUAD(addr.ip), port,
-					 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
+					 &addr.ip, port,
+					 &ct->tuplehash[!dir].tuple.dst.u3.ip,
 					 info->sig_port[!dir]);
 				return set_h225_addr(skb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
@@ -131,10 +130,9 @@
 			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
 				   port == info->sig_port[dir]) {
 				/* GK->GW */
-				pr_debug("nf_nat_ras: set signal address "
-					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-					 NIPQUAD(addr.ip), port,
-					 NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
+				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
+					 &addr.ip, port,
+					 &ct->tuplehash[!dir].tuple.src.u3.ip,
 					 info->sig_port[!dir]);
 				return set_h225_addr(skb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
@@ -162,10 +160,9 @@
 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
 		    port == ct->tuplehash[dir].tuple.src.u.udp.port) {
-			pr_debug("nf_nat_ras: set rasAddress "
-				 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-				 NIPQUAD(addr.ip), ntohs(port),
-				 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+			pr_debug("nf_nat_ras: set rasAddress %pI4:%hu->%pI4:%hu\n",
+				 &addr.ip, ntohs(port),
+				 &ct->tuplehash[!dir].tuple.dst.u3.ip,
 				 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
 			return set_h225_addr(skb, data, 0, &taddr[i],
 					     &ct->tuplehash[!dir].tuple.dst.u3,
@@ -257,15 +254,15 @@
 	}
 
 	/* Success */
-	pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(rtp_exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n",
+		 &rtp_exp->tuple.src.u3.ip,
 		 ntohs(rtp_exp->tuple.src.u.udp.port),
-		 NIPQUAD(rtp_exp->tuple.dst.u3.ip),
+		 &rtp_exp->tuple.dst.u3.ip,
 		 ntohs(rtp_exp->tuple.dst.u.udp.port));
-	pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(rtcp_exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n",
+		 &rtcp_exp->tuple.src.u3.ip,
 		 ntohs(rtcp_exp->tuple.src.u.udp.port),
-		 NIPQUAD(rtcp_exp->tuple.dst.u3.ip),
+		 &rtcp_exp->tuple.dst.u3.ip,
 		 ntohs(rtcp_exp->tuple.dst.u.udp.port));
 
 	return 0;
@@ -307,10 +304,10 @@
 		return -1;
 	}
 
-	pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
+		 &exp->tuple.src.u3.ip,
 		 ntohs(exp->tuple.src.u.tcp.port),
-		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 &exp->tuple.dst.u3.ip,
 		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
@@ -361,10 +358,10 @@
 		return -1;
 	}
 
-	pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
+		 &exp->tuple.src.u3.ip,
 		 ntohs(exp->tuple.src.u.tcp.port),
-		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 &exp->tuple.dst.u3.ip,
 		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
@@ -455,10 +452,10 @@
 	}
 
 	/* Success */
-	pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
+		 &exp->tuple.src.u3.ip,
 		 ntohs(exp->tuple.src.u.tcp.port),
-		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 &exp->tuple.dst.u3.ip,
 		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
@@ -524,11 +521,10 @@
 	}
 
 	/* Success */
-	pr_debug("nf_nat_q931: expect Call Forwarding "
-		 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-		 NIPQUAD(exp->tuple.src.u3.ip),
+	pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
+		 &exp->tuple.src.u3.ip,
 		 ntohs(exp->tuple.src.u.tcp.port),
-		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 &exp->tuple.dst.u3.ip,
 		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index fe6f9ce..ea83a88 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -55,8 +55,8 @@
 
 	ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
 	sprintf(buffer, "%u %u", ip, port);
-	pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
-		 buffer, NIPQUAD(ip), port);
+	pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n",
+		 buffer, &ip, port);
 
 	ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
 				       matchoff, matchlen, buffer,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index bea54a6..a4f1c347 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -98,8 +98,7 @@
 
 	if (rt->rt_src != srcip && !warned) {
 		printk("NAT: no longer support implicit source local NAT\n");
-		printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n",
-		       NIPQUAD(srcip), NIPQUAD(dstip));
+		printk("NAT: packet src %pI4 -> dst %pI4\n", &srcip, &dstip);
 		warned = 1;
 	}
 	ip_rt_put(rt);
@@ -166,8 +165,7 @@
 	struct nf_nat_range range
 		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
 
-	pr_debug("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
-		 ct, NIPQUAD(ip));
+	pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, &ip);
 	return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 1454432..07d61a5 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -74,8 +74,7 @@
 	if (newaddr == addr->ip && newport == port)
 		return 1;
 
-	buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
-			 NIPQUAD(newaddr), ntohs(newport));
+	buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
 
 	return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
 			     buffer, buflen);
@@ -152,8 +151,8 @@
 					       &addr) > 0 &&
 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
 		    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
-			__be32 ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
-			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+			buflen = sprintf(buffer, "%pI4",
+					&ct->tuplehash[!dir].tuple.dst.u3.ip);
 			if (!mangle_packet(skb, dptr, datalen, poff, plen,
 					   buffer, buflen))
 				return NF_DROP;
@@ -166,8 +165,8 @@
 					       &addr) > 0 &&
 		    addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
 		    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
-			__be32 ip = ct->tuplehash[!dir].tuple.src.u3.ip;
-			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
+			buflen = sprintf(buffer, "%pI4",
+					&ct->tuplehash[!dir].tuple.src.u3.ip);
 			if (!mangle_packet(skb, dptr, datalen, poff, plen,
 					   buffer, buflen))
 				return NF_DROP;
@@ -279,8 +278,7 @@
 
 	if (exp->tuple.dst.u3.ip != exp->saved_ip ||
 	    exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
-		buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
-				 NIPQUAD(newip), port);
+		buflen = sprintf(buffer, "%pI4:%u", &newip, port);
 		if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
 				   buffer, buflen))
 			goto err;
@@ -345,7 +343,7 @@
 	char buffer[sizeof("nnn.nnn.nnn.nnn")];
 	unsigned int buflen;
 
-	buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
+	buflen = sprintf(buffer, "%pI4", &addr->ip);
 	if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
 			      buffer, buflen))
 		return 0;
@@ -380,7 +378,7 @@
 	unsigned int buflen;
 
 	/* Mangle session description owner and contact addresses */
-	buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
+	buflen = sprintf(buffer, "%pI4", &addr->ip);
 	if (mangle_sdp_packet(skb, dptr, dataoff, datalen,
 			       SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
 			       buffer, buflen))
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 8303e4b..182f845 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -930,8 +930,8 @@
 		}
 
 		if (debug)
-			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
-			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
+			printk(KERN_DEBUG "bsalg: mapped %pI4 to %pI4\n",
+			       &old, addr);
 	}
 }
 
@@ -1267,9 +1267,8 @@
 	 */
 	if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
 		 if (net_ratelimit())
-			 printk(KERN_WARNING "SNMP: dropping malformed packet "
-				"src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
-				NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+			 printk(KERN_WARNING "SNMP: dropping malformed packet src=%pI4 dst=%pI4\n",
+				&iph->saddr, &iph->daddr);
 		 return NF_DROP;
 	}
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index cd97574..998fcff 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -247,7 +247,7 @@
 	}
 
 	if (inet->recverr) {
-		struct iphdr *iph = (struct iphdr*)skb->data;
+		struct iphdr *iph = (struct iphdr *)skb->data;
 		u8 *payload = skb->data + (iph->ihl << 2);
 
 		if (inet->hdrincl)
@@ -465,7 +465,7 @@
 	 */
 
 	if (msg->msg_namelen) {
-		struct sockaddr_in *usin = (struct sockaddr_in*)msg->msg_name;
+		struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name;
 		err = -EINVAL;
 		if (msg->msg_namelen < sizeof(*usin))
 			goto out;
@@ -851,7 +851,7 @@
 static struct sock *raw_get_first(struct seq_file *seq)
 {
 	struct sock *sk;
-	struct raw_iter_state* state = raw_seq_private(seq);
+	struct raw_iter_state *state = raw_seq_private(seq);
 
 	for (state->bucket = 0; state->bucket < RAW_HTABLE_SIZE;
 			++state->bucket) {
@@ -868,7 +868,7 @@
 
 static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
 {
-	struct raw_iter_state* state = raw_seq_private(seq);
+	struct raw_iter_state *state = raw_seq_private(seq);
 
 	do {
 		sk = sk_next(sk);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2ea6dcc..0dc0c38 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -129,6 +129,7 @@
 static int ip_rt_min_pmtu __read_mostly		= 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly	= 256;
 static int ip_rt_secret_interval __read_mostly	= 10 * 60 * HZ;
+static int rt_chain_length_max __read_mostly	= 20;
 
 static void rt_worker_func(struct work_struct *work);
 static DECLARE_DELAYED_WORK(expires_work, rt_worker_func);
@@ -145,6 +146,7 @@
 static void		 ipv4_link_failure(struct sk_buff *skb);
 static void		 ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
 static int rt_garbage_collect(struct dst_ops *ops);
+static void rt_emergency_hash_rebuild(struct net *net);
 
 
 static struct dst_ops ipv4_dst_ops = {
@@ -201,6 +203,7 @@
 struct rt_hash_bucket {
 	struct rtable	*chain;
 };
+
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || \
 	defined(CONFIG_PROVE_LOCKING)
 /*
@@ -674,6 +677,20 @@
 	return score;
 }
 
+static inline bool rt_caching(const struct net *net)
+{
+	return net->ipv4.current_rt_cache_rebuild_count <=
+		net->ipv4.sysctl_rt_cache_rebuild_count;
+}
+
+static inline bool compare_hash_inputs(const struct flowi *fl1,
+					const struct flowi *fl2)
+{
+	return (__force u32)(((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+		(fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
+		(fl1->iif ^ fl2->iif)) == 0);
+}
+
 static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 {
 	return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
@@ -753,11 +770,24 @@
 	}
 }
 
+/*
+ * While freeing expired entries, we compute average chain length
+ * and standard deviation, using fixed-point arithmetic.
+ * This to have an estimation of rt_chain_length_max
+ *  rt_chain_length_max = max(elasticity, AVG + 4*SD)
+ * We use 3 bits for frational part, and 29 (or 61) for magnitude.
+ */
+
+#define FRACT_BITS 3
+#define ONE (1UL << FRACT_BITS)
+
 static void rt_check_expire(void)
 {
 	static unsigned int rover;
 	unsigned int i = rover, goal;
 	struct rtable *rth, **rthp;
+	unsigned long length = 0, samples = 0;
+	unsigned long sum = 0, sum2 = 0;
 	u64 mult;
 
 	mult = ((u64)ip_rt_gc_interval) << rt_hash_log;
@@ -766,6 +796,7 @@
 	goal = (unsigned int)mult;
 	if (goal > rt_hash_mask)
 		goal = rt_hash_mask + 1;
+	length = 0;
 	for (; goal > 0; goal--) {
 		unsigned long tmo = ip_rt_gc_timeout;
 
@@ -775,6 +806,8 @@
 		if (need_resched())
 			cond_resched();
 
+		samples++;
+
 		if (*rthp == NULL)
 			continue;
 		spin_lock_bh(rt_hash_lock_addr(i));
@@ -789,11 +822,29 @@
 				if (time_before_eq(jiffies, rth->u.dst.expires)) {
 					tmo >>= 1;
 					rthp = &rth->u.dst.rt_next;
+					/*
+					 * Only bump our length if the hash
+					 * inputs on entries n and n+1 are not
+					 * the same, we only count entries on
+					 * a chain with equal hash inputs once
+					 * so that entries for different QOS
+					 * levels, and other non-hash input
+					 * attributes don't unfairly skew
+					 * the length computation
+					 */
+					if ((*rthp == NULL) ||
+					    !compare_hash_inputs(&(*rthp)->fl,
+								 &rth->fl))
+						length += ONE;
 					continue;
 				}
 			} else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) {
 				tmo >>= 1;
 				rthp = &rth->u.dst.rt_next;
+				if ((*rthp == NULL) ||
+				    !compare_hash_inputs(&(*rthp)->fl,
+							 &rth->fl))
+					length += ONE;
 				continue;
 			}
 
@@ -802,6 +853,15 @@
 			rt_free(rth);
 		}
 		spin_unlock_bh(rt_hash_lock_addr(i));
+		sum += length;
+		sum2 += length*length;
+	}
+	if (samples) {
+		unsigned long avg = sum / samples;
+		unsigned long sd = int_sqrt(sum2 / samples - avg*avg);
+		rt_chain_length_max = max_t(unsigned long,
+					ip_rt_gc_elasticity,
+					(avg + 4*sd) >> FRACT_BITS);
 	}
 	rover = i;
 }
@@ -851,6 +911,26 @@
 	mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);
 }
 
+static void rt_secret_rebuild_oneshot(struct net *net)
+{
+	del_timer_sync(&net->ipv4.rt_secret_timer);
+	rt_cache_invalidate(net);
+	if (ip_rt_secret_interval) {
+		net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval;
+		add_timer(&net->ipv4.rt_secret_timer);
+	}
+}
+
+static void rt_emergency_hash_rebuild(struct net *net)
+{
+	if (net_ratelimit()) {
+		printk(KERN_WARNING "Route hash chain too long!\n");
+		printk(KERN_WARNING "Adjust your secret_interval!\n");
+	}
+
+	rt_secret_rebuild_oneshot(net);
+}
+
 /*
    Short description of GC goals.
 
@@ -989,6 +1069,7 @@
 static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
 {
 	struct rtable	*rth, **rthp;
+	struct rtable	*rthi;
 	unsigned long	now;
 	struct rtable *cand, **candp;
 	u32 		min_score;
@@ -1002,7 +1083,13 @@
 	candp = NULL;
 	now = jiffies;
 
+	if (!rt_caching(dev_net(rt->u.dst.dev))) {
+		rt_drop(rt);
+		return 0;
+	}
+
 	rthp = &rt_hash_table[hash].chain;
+	rthi = NULL;
 
 	spin_lock_bh(rt_hash_lock_addr(hash));
 	while ((rth = *rthp) != NULL) {
@@ -1048,6 +1135,17 @@
 		chain_length++;
 
 		rthp = &rth->u.dst.rt_next;
+
+		/*
+		 * check to see if the next entry in the chain
+		 * contains the same hash input values as rt.  If it does
+		 * This is where we will insert into the list, instead of
+		 * at the head.  This groups entries that differ by aspects not
+		 * relvant to the hash function together, which we use to adjust
+		 * our chain length
+		 */
+		if (*rthp && compare_hash_inputs(&(*rthp)->fl, &rt->fl))
+			rthi = rth;
 	}
 
 	if (cand) {
@@ -1061,6 +1159,16 @@
 			*candp = cand->u.dst.rt_next;
 			rt_free(cand);
 		}
+	} else {
+		if (chain_length > rt_chain_length_max) {
+			struct net *net = dev_net(rt->u.dst.dev);
+			int num = ++net->ipv4.current_rt_cache_rebuild_count;
+			if (!rt_caching(dev_net(rt->u.dst.dev))) {
+				printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",
+					rt->u.dst.dev->name, num);
+			}
+			rt_emergency_hash_rebuild(dev_net(rt->u.dst.dev));
+		}
 	}
 
 	/* Try to bind route to arp only if it is output
@@ -1098,14 +1206,17 @@
 		}
 	}
 
-	rt->u.dst.rt_next = rt_hash_table[hash].chain;
+	if (rthi)
+		rt->u.dst.rt_next = rthi->u.dst.rt_next;
+	else
+		rt->u.dst.rt_next = rt_hash_table[hash].chain;
+
 #if RT_CACHE_DEBUG >= 2
 	if (rt->u.dst.rt_next) {
 		struct rtable *trt;
-		printk(KERN_DEBUG "rt_cache @%02x: " NIPQUAD_FMT, hash,
-		       NIPQUAD(rt->rt_dst));
+		printk(KERN_DEBUG "rt_cache @%02x: %pI4", hash, &rt->rt_dst);
 		for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
-			printk(" . " NIPQUAD_FMT, NIPQUAD(trt->rt_dst));
+			printk(" . %pI4", &trt->rt_dst);
 		printk("\n");
 	}
 #endif
@@ -1114,7 +1225,11 @@
 	 * previous writes to rt are comitted to memory
 	 * before making rt visible to other CPUS.
 	 */
-	rcu_assign_pointer(rt_hash_table[hash].chain, rt);
+	if (rthi)
+		rcu_assign_pointer(rthi->u.dst.rt_next, rt);
+	else
+		rcu_assign_pointer(rt_hash_table[hash].chain, rt);
+
 	spin_unlock_bh(rt_hash_lock_addr(hash));
 	*rp = rt;
 	return 0;
@@ -1217,6 +1332,9 @@
 	    || ipv4_is_zeronet(new_gw))
 		goto reject_redirect;
 
+	if (!rt_caching(net))
+		goto reject_redirect;
+
 	if (!IN_DEV_SHARED_MEDIA(in_dev)) {
 		if (!inet_addr_onlink(in_dev, new_gw, old_gw))
 			goto reject_redirect;
@@ -1267,7 +1385,6 @@
 
 				/* Copy all the information. */
 				*rt = *rth;
-				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
 				rt->u.dst.__use		= 1;
 				atomic_set(&rt->u.dst.__refcnt, 1);
 				rt->u.dst.child		= NULL;
@@ -1280,7 +1397,9 @@
 				rt->u.dst.path		= &rt->u.dst;
 				rt->u.dst.neighbour	= NULL;
 				rt->u.dst.hh		= NULL;
+#ifdef CONFIG_XFRM
 				rt->u.dst.xfrm		= NULL;
+#endif
 				rt->rt_genid		= rt_genid(net);
 				rt->rt_flags		|= RTCF_REDIRECTED;
 
@@ -1324,11 +1443,10 @@
 reject_redirect:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_INFO "Redirect from " NIPQUAD_FMT " on %s about "
-			NIPQUAD_FMT " ignored.\n"
-			"  Advised path = " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
-		       NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
-		       NIPQUAD(saddr), NIPQUAD(daddr));
+		printk(KERN_INFO "Redirect from %pI4 on %s about %pI4 ignored.\n"
+			"  Advised path = %pI4 -> %pI4\n",
+		       &old_gw, dev->name, &new_gw,
+		       &saddr, &daddr);
 #endif
 	in_dev_put(in_dev);
 }
@@ -1348,9 +1466,8 @@
 						rt->fl.oif,
 						rt_genid(dev_net(dst->dev)));
 #if RT_CACHE_DEBUG >= 1
-			printk(KERN_DEBUG "ipv4_negative_advice: redirect to "
-					  NIPQUAD_FMT "/%02x dropped\n",
-				NIPQUAD(rt->rt_dst), rt->fl.fl4_tos);
+			printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n",
+				&rt->rt_dst, rt->fl.fl4_tos);
 #endif
 			rt_del(hash, rt);
 			ret = NULL;
@@ -1414,10 +1531,9 @@
 		if (IN_DEV_LOG_MARTIANS(in_dev) &&
 		    rt->u.dst.rate_tokens == ip_rt_redirect_number &&
 		    net_ratelimit())
-			printk(KERN_WARNING "host " NIPQUAD_FMT "/if%d ignores "
-				"redirects for " NIPQUAD_FMT " to " NIPQUAD_FMT ".\n",
-				NIPQUAD(rt->rt_src), rt->rt_iif,
-				NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
+			printk(KERN_WARNING "host %pI4/if%d ignores redirects for %pI4 to %pI4.\n",
+				&rt->rt_src, rt->rt_iif,
+				&rt->rt_dst, &rt->rt_gateway);
 #endif
 	}
 out:
@@ -1610,8 +1726,8 @@
 
 static int ip_rt_bug(struct sk_buff *skb)
 {
-	printk(KERN_DEBUG "ip_rt_bug: " NIPQUAD_FMT " -> " NIPQUAD_FMT ", %s\n",
-		NIPQUAD(ip_hdr(skb)->saddr), NIPQUAD(ip_hdr(skb)->daddr),
+	printk(KERN_DEBUG "ip_rt_bug: %pI4 -> %pI4, %s\n",
+		&ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
 		skb->dev ? skb->dev->name : "?");
 	kfree_skb(skb);
 	return 0;
@@ -1788,9 +1904,8 @@
 		 *	RFC1812 recommendation, if source is martian,
 		 *	the only hint is MAC header.
 		 */
-		printk(KERN_WARNING "martian source " NIPQUAD_FMT " from "
-			NIPQUAD_FMT", on dev %s\n",
-			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+		printk(KERN_WARNING "martian source %pI4 from %pI4, on dev %s\n",
+			&daddr, &saddr, dev->name);
 		if (dev->hard_header_len && skb_mac_header_was_set(skb)) {
 			int i;
 			const unsigned char *p = skb_mac_header(skb);
@@ -2099,9 +2214,8 @@
 	RT_CACHE_STAT_INC(in_martian_dst);
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_WARNING "martian destination " NIPQUAD_FMT " from "
-			NIPQUAD_FMT ", dev %s\n",
-			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+		printk(KERN_WARNING "martian destination %pI4 from %pI4, dev %s\n",
+			&daddr, &saddr, dev->name);
 #endif
 
 e_hostunreach:
@@ -2130,6 +2244,10 @@
 	struct net *net;
 
 	net = dev_net(dev);
+
+	if (!rt_caching(net))
+		goto skip_cache;
+
 	tos &= IPTOS_RT_MASK;
 	hash = rt_hash(daddr, saddr, iif, rt_genid(net));
 
@@ -2154,6 +2272,7 @@
 	}
 	rcu_read_unlock();
 
+skip_cache:
 	/* Multicast recognition logic is moved from route cache to here.
 	   The problem was that too many Ethernet cards have broken/missing
 	   hardware multicast filters :-( As result the host on multicasting
@@ -2539,6 +2658,9 @@
 	unsigned hash;
 	struct rtable *rth;
 
+	if (!rt_caching(net))
+		goto slow_output;
+
 	hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif, rt_genid(net));
 
 	rcu_read_lock_bh();
@@ -2563,6 +2685,7 @@
 	}
 	rcu_read_unlock_bh();
 
+slow_output:
 	return ip_route_output_slow(net, rp, flp);
 }
 
@@ -2995,7 +3118,7 @@
 		.data		= &ipv4_dst_ops.gc_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_MAX_SIZE,
@@ -3003,7 +3126,7 @@
 		.data		= &ip_rt_max_size,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		/*  Deprecated. Use gc_min_interval_ms */
@@ -3013,8 +3136,8 @@
 		.data		= &ip_rt_gc_min_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS,
@@ -3022,8 +3145,8 @@
 		.data		= &ip_rt_gc_min_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_ms_jiffies,
-		.strategy	= &sysctl_ms_jiffies,
+		.proc_handler	= proc_dointvec_ms_jiffies,
+		.strategy	= sysctl_ms_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_GC_TIMEOUT,
@@ -3031,8 +3154,8 @@
 		.data		= &ip_rt_gc_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_GC_INTERVAL,
@@ -3040,8 +3163,8 @@
 		.data		= &ip_rt_gc_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_LOAD,
@@ -3049,7 +3172,7 @@
 		.data		= &ip_rt_redirect_load,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_NUMBER,
@@ -3057,7 +3180,7 @@
 		.data		= &ip_rt_redirect_number,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_SILENCE,
@@ -3065,7 +3188,7 @@
 		.data		= &ip_rt_redirect_silence,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_ERROR_COST,
@@ -3073,7 +3196,7 @@
 		.data		= &ip_rt_error_cost,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_ERROR_BURST,
@@ -3081,7 +3204,7 @@
 		.data		= &ip_rt_error_burst,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_GC_ELASTICITY,
@@ -3089,7 +3212,7 @@
 		.data		= &ip_rt_gc_elasticity,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_MTU_EXPIRES,
@@ -3097,8 +3220,8 @@
 		.data		= &ip_rt_mtu_expires,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_MIN_PMTU,
@@ -3106,7 +3229,7 @@
 		.data		= &ip_rt_min_pmtu,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_MIN_ADVMSS,
@@ -3114,7 +3237,7 @@
 		.data		= &ip_rt_min_advmss,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_ROUTE_SECRET_INTERVAL,
@@ -3122,8 +3245,8 @@
 		.data		= &ip_rt_secret_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &ipv4_sysctl_rt_secret_interval,
-		.strategy	= &ipv4_sysctl_rt_secret_interval_strategy,
+		.proc_handler	= ipv4_sysctl_rt_secret_interval,
+		.strategy	= ipv4_sysctl_rt_secret_interval_strategy,
 	},
 	{ .ctl_name = 0 }
 };
@@ -3151,8 +3274,8 @@
 		.procname	= "flush",
 		.maxlen		= sizeof(int),
 		.mode		= 0200,
-		.proc_handler	= &ipv4_sysctl_rtcache_flush,
-		.strategy	= &ipv4_sysctl_rtcache_flush_strategy,
+		.proc_handler	= ipv4_sysctl_rtcache_flush,
+		.strategy	= ipv4_sysctl_rtcache_flush_strategy,
 	},
 	{ .ctl_name = 0 },
 };
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 1bb10df..4710d21 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -195,7 +195,7 @@
 		.data		= &sysctl_tcp_timestamps,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_WINDOW_SCALING,
@@ -203,7 +203,7 @@
 		.data		= &sysctl_tcp_window_scaling,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_SACK,
@@ -211,7 +211,7 @@
 		.data		= &sysctl_tcp_sack,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_RETRANS_COLLAPSE,
@@ -219,7 +219,7 @@
 		.data		= &sysctl_tcp_retrans_collapse,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_DEFAULT_TTL,
@@ -227,8 +227,8 @@
 		.data		= &sysctl_ip_default_ttl,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &ipv4_doint_and_flush,
-		.strategy	= &ipv4_doint_and_flush_strategy,
+		.proc_handler	= ipv4_doint_and_flush,
+		.strategy	= ipv4_doint_and_flush_strategy,
 		.extra2		= &init_net,
 	},
 	{
@@ -237,7 +237,7 @@
 		.data		= &ipv4_config.no_pmtu_disc,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_NONLOCAL_BIND,
@@ -245,7 +245,7 @@
 		.data		= &sysctl_ip_nonlocal_bind,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_SYN_RETRIES,
@@ -253,7 +253,7 @@
 		.data		= &sysctl_tcp_syn_retries,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_SYNACK_RETRIES,
@@ -261,7 +261,7 @@
 		.data		= &sysctl_tcp_synack_retries,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_MAX_ORPHANS,
@@ -269,7 +269,7 @@
 		.data		= &sysctl_tcp_max_orphans,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_MAX_TW_BUCKETS,
@@ -277,7 +277,7 @@
 		.data		= &tcp_death_row.sysctl_max_tw_buckets,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_DYNADDR,
@@ -285,7 +285,7 @@
 		.data		= &sysctl_ip_dynaddr,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_KEEPALIVE_TIME,
@@ -293,8 +293,8 @@
 		.data		= &sysctl_tcp_keepalive_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_KEEPALIVE_PROBES,
@@ -302,7 +302,7 @@
 		.data		= &sysctl_tcp_keepalive_probes,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_KEEPALIVE_INTVL,
@@ -310,8 +310,8 @@
 		.data		= &sysctl_tcp_keepalive_intvl,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_RETRIES1,
@@ -319,8 +319,8 @@
 		.data		= &sysctl_tcp_retries1,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra2		= &tcp_retr1_max
 	},
 	{
@@ -329,7 +329,7 @@
 		.data		= &sysctl_tcp_retries2,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_FIN_TIMEOUT,
@@ -337,8 +337,8 @@
 		.data		= &sysctl_tcp_fin_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 #ifdef CONFIG_SYN_COOKIES
 	{
@@ -347,7 +347,7 @@
 		.data		= &sysctl_tcp_syncookies,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #endif
 	{
@@ -356,7 +356,7 @@
 		.data		= &tcp_death_row.sysctl_tw_recycle,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_ABORT_ON_OVERFLOW,
@@ -364,7 +364,7 @@
 		.data		= &sysctl_tcp_abort_on_overflow,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_STDURG,
@@ -372,7 +372,7 @@
 		.data		= &sysctl_tcp_stdurg,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_RFC1337,
@@ -380,7 +380,7 @@
 		.data		= &sysctl_tcp_rfc1337,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_MAX_SYN_BACKLOG,
@@ -388,7 +388,7 @@
 		.data		= &sysctl_max_syn_backlog,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_LOCAL_PORT_RANGE,
@@ -396,8 +396,8 @@
 		.data		= &sysctl_local_ports.range,
 		.maxlen		= sizeof(sysctl_local_ports.range),
 		.mode		= 0644,
-		.proc_handler	= &ipv4_local_port_range,
-		.strategy	= &ipv4_sysctl_local_port_range,
+		.proc_handler	= ipv4_local_port_range,
+		.strategy	= ipv4_sysctl_local_port_range,
 	},
 #ifdef CONFIG_IP_MULTICAST
 	{
@@ -406,7 +406,7 @@
 		.data		= &sysctl_igmp_max_memberships,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 
 #endif
@@ -416,7 +416,7 @@
 		.data		= &sysctl_igmp_max_msf,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_INET_PEER_THRESHOLD,
@@ -424,7 +424,7 @@
 		.data		= &inet_peer_threshold,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_INET_PEER_MINTTL,
@@ -432,8 +432,8 @@
 		.data		= &inet_peer_minttl,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_INET_PEER_MAXTTL,
@@ -441,8 +441,8 @@
 		.data		= &inet_peer_maxttl,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_INET_PEER_GC_MINTIME,
@@ -450,8 +450,8 @@
 		.data		= &inet_peer_gc_mintime,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_INET_PEER_GC_MAXTIME,
@@ -459,8 +459,8 @@
 		.data		= &inet_peer_gc_maxtime,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{
 		.ctl_name	= NET_TCP_ORPHAN_RETRIES,
@@ -468,7 +468,7 @@
 		.data		= &sysctl_tcp_orphan_retries,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_FACK,
@@ -476,7 +476,7 @@
 		.data		= &sysctl_tcp_fack,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_REORDERING,
@@ -484,7 +484,7 @@
 		.data		= &sysctl_tcp_reordering,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_ECN,
@@ -492,7 +492,7 @@
 		.data		= &sysctl_tcp_ecn,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_DSACK,
@@ -500,7 +500,7 @@
 		.data		= &sysctl_tcp_dsack,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_MEM,
@@ -508,7 +508,7 @@
 		.data		= &sysctl_tcp_mem,
 		.maxlen		= sizeof(sysctl_tcp_mem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_WMEM,
@@ -516,7 +516,7 @@
 		.data		= &sysctl_tcp_wmem,
 		.maxlen		= sizeof(sysctl_tcp_wmem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_RMEM,
@@ -524,7 +524,7 @@
 		.data		= &sysctl_tcp_rmem,
 		.maxlen		= sizeof(sysctl_tcp_rmem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_APP_WIN,
@@ -532,7 +532,7 @@
 		.data		= &sysctl_tcp_app_win,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_ADV_WIN_SCALE,
@@ -540,7 +540,7 @@
 		.data		= &sysctl_tcp_adv_win_scale,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_TW_REUSE,
@@ -548,7 +548,7 @@
 		.data		= &sysctl_tcp_tw_reuse,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_FRTO,
@@ -556,7 +556,7 @@
 		.data		= &sysctl_tcp_frto,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_FRTO_RESPONSE,
@@ -564,7 +564,7 @@
 		.data		= &sysctl_tcp_frto_response,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_LOW_LATENCY,
@@ -572,7 +572,7 @@
 		.data		= &sysctl_tcp_low_latency,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_TCP_NO_METRICS_SAVE,
@@ -580,7 +580,7 @@
 		.data		= &sysctl_tcp_nometrics_save,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
@@ -588,7 +588,7 @@
 		.data		= &sysctl_tcp_moderate_rcvbuf,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_TCP_TSO_WIN_DIVISOR,
@@ -596,15 +596,15 @@
 		.data		= &sysctl_tcp_tso_win_divisor,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_TCP_CONG_CONTROL,
 		.procname	= "tcp_congestion_control",
 		.mode		= 0644,
 		.maxlen		= TCP_CA_NAME_MAX,
-		.proc_handler	= &proc_tcp_congestion_control,
-		.strategy	= &sysctl_tcp_congestion_control,
+		.proc_handler	= proc_tcp_congestion_control,
+		.strategy	= sysctl_tcp_congestion_control,
 	},
 	{
 		.ctl_name	= NET_TCP_ABC,
@@ -612,7 +612,7 @@
 		.data		= &sysctl_tcp_abc,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_TCP_MTU_PROBING,
@@ -620,7 +620,7 @@
 		.data		= &sysctl_tcp_mtu_probing,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_TCP_BASE_MSS,
@@ -628,7 +628,7 @@
 		.data		= &sysctl_tcp_base_mss,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
@@ -636,7 +636,7 @@
 		.data		= &sysctl_tcp_workaround_signed_windows,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #ifdef CONFIG_NET_DMA
 	{
@@ -645,7 +645,7 @@
 		.data		= &sysctl_tcp_dma_copybreak,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #endif
 	{
@@ -654,7 +654,7 @@
 		.data		= &sysctl_tcp_slow_start_after_idle,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #ifdef CONFIG_NETLABEL
 	{
@@ -663,7 +663,7 @@
 		.data		= &cipso_v4_cache_enabled,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_CIPSOV4_CACHE_BUCKET_SIZE,
@@ -671,7 +671,7 @@
 		.data		= &cipso_v4_cache_bucketsize,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_CIPSOV4_RBM_OPTFMT,
@@ -679,7 +679,7 @@
 		.data		= &cipso_v4_rbm_optfmt,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_CIPSOV4_RBM_STRICTVALID,
@@ -687,22 +687,22 @@
 		.data		= &cipso_v4_rbm_strictvalid,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 #endif /* CONFIG_NETLABEL */
 	{
 		.procname	= "tcp_available_congestion_control",
 		.maxlen		= TCP_CA_BUF_MAX,
 		.mode		= 0444,
-		.proc_handler   = &proc_tcp_available_congestion_control,
+		.proc_handler   = proc_tcp_available_congestion_control,
 	},
 	{
 		.ctl_name	= NET_TCP_ALLOWED_CONG_CONTROL,
 		.procname	= "tcp_allowed_congestion_control",
 		.maxlen		= TCP_CA_BUF_MAX,
 		.mode		= 0644,
-		.proc_handler   = &proc_allowed_congestion_control,
-		.strategy	= &strategy_allowed_congestion_control,
+		.proc_handler   = proc_allowed_congestion_control,
+		.strategy	= strategy_allowed_congestion_control,
 	},
 	{
 		.ctl_name	= NET_TCP_MAX_SSTHRESH,
@@ -710,7 +710,7 @@
 		.data		= &sysctl_tcp_max_ssthresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -718,8 +718,8 @@
 		.data		= &sysctl_udp_mem,
 		.maxlen		= sizeof(sysctl_udp_mem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &zero
 	},
 	{
@@ -728,8 +728,8 @@
 		.data		= &sysctl_udp_rmem_min,
 		.maxlen		= sizeof(sysctl_udp_rmem_min),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &zero
 	},
 	{
@@ -738,8 +738,8 @@
 		.data		= &sysctl_udp_wmem_min,
 		.maxlen		= sizeof(sysctl_udp_wmem_min),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &zero
 	},
 	{ .ctl_name = 0 }
@@ -752,7 +752,7 @@
 		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_all,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
@@ -760,7 +760,7 @@
 		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
@@ -768,7 +768,7 @@
 		.data		= &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
@@ -776,7 +776,7 @@
 		.data		= &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV4_ICMP_RATELIMIT,
@@ -784,8 +784,8 @@
 		.data		= &init_net.ipv4.sysctl_icmp_ratelimit,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_ms_jiffies,
-		.strategy	= &sysctl_ms_jiffies
+		.proc_handler	= proc_dointvec_ms_jiffies,
+		.strategy	= sysctl_ms_jiffies
 	},
 	{
 		.ctl_name	= NET_IPV4_ICMP_RATEMASK,
@@ -793,7 +793,15 @@
 		.data		= &init_net.ipv4.sysctl_icmp_ratemask,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "rt_cache_rebuild_count",
+		.data		= &init_net.ipv4.sysctl_rt_cache_rebuild_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
 	},
 	{ }
 };
@@ -827,8 +835,12 @@
 			&net->ipv4.sysctl_icmp_ratelimit;
 		table[5].data =
 			&net->ipv4.sysctl_icmp_ratemask;
+		table[6].data =
+			&net->ipv4.sysctl_rt_cache_rebuild_count;
 	}
 
+	net->ipv4.sysctl_rt_cache_rebuild_count = 4;
+
 	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
 			net_ipv4_ctl_path, table);
 	if (net->ipv4.ipv4_hdr == NULL)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c5aca0b..f60a591 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1680,7 +1680,7 @@
 			inet_put_port(sk);
 		/* fall through */
 	default:
-		if (oldstate==TCP_ESTABLISHED)
+		if (oldstate == TCP_ESTABLISHED)
 			TCP_DEC_STATS(sock_net(sk), TCP_MIB_CURRESTAB);
 	}
 
@@ -1690,7 +1690,7 @@
 	sk->sk_state = state;
 
 #ifdef STATE_TRACE
-	SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]);
+	SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n", sk, statename[oldstate], statename[state]);
 #endif
 }
 EXPORT_SYMBOL_GPL(tcp_set_state);
@@ -2650,7 +2650,7 @@
 
 void tcp_done(struct sock *sk)
 {
-	if(sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
+	if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
 		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS);
 
 	tcp_set_state(sk, TCP_CLOSE);
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 4a1221e..ee467ec 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -1,13 +1,23 @@
 /*
- * TCP CUBIC: Binary Increase Congestion control for TCP v2.2
+ * TCP CUBIC: Binary Increase Congestion control for TCP v2.3
  * Home page:
  *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
  * This is from the implementation of CUBIC TCP in
- * Injong Rhee, Lisong Xu.
- *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant
- *  in PFLDnet 2005
+ * Sangtae Ha, Injong Rhee and Lisong Xu,
+ *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant"
+ *  in ACM SIGOPS Operating System Review, July 2008.
  * Available from:
- *  http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf
+ *  http://netsrv.csc.ncsu.edu/export/cubic_a_new_tcp_2008.pdf
+ *
+ * CUBIC integrates a new slow start algorithm, called HyStart.
+ * The details of HyStart are presented in
+ *  Sangtae Ha and Injong Rhee,
+ *  "Taming the Elephants: New TCP Slow Start", NCSU TechReport 2008.
+ * Available from:
+ *  http://netsrv.csc.ncsu.edu/export/hystart_techreport_2008.pdf
+ *
+ * All testing results are available from:
+ * http://netsrv.csc.ncsu.edu/wiki/index.php/TCP_Testing
  *
  * Unless CUBIC is enabled and congestion window is large
  * this behaves the same as the original Reno.
@@ -23,12 +33,26 @@
 					 */
 #define	BICTCP_HZ		10	/* BIC HZ 2^10 = 1024 */
 
+/* Two methods of hybrid slow start */
+#define HYSTART_ACK_TRAIN	0x1
+#define HYSTART_DELAY		0x2
+
+/* Number of delay samples for detecting the increase of delay */
+#define HYSTART_MIN_SAMPLES	8
+#define HYSTART_DELAY_MIN	(2U<<3)
+#define HYSTART_DELAY_MAX	(16U<<3)
+#define HYSTART_DELAY_THRESH(x)	clamp(x, HYSTART_DELAY_MIN, HYSTART_DELAY_MAX)
+
 static int fast_convergence __read_mostly = 1;
 static int beta __read_mostly = 717;	/* = 717/1024 (BICTCP_BETA_SCALE) */
 static int initial_ssthresh __read_mostly;
 static int bic_scale __read_mostly = 41;
 static int tcp_friendliness __read_mostly = 1;
 
+static int hystart __read_mostly = 1;
+static int hystart_detect __read_mostly = HYSTART_ACK_TRAIN | HYSTART_DELAY;
+static int hystart_low_window __read_mostly = 16;
+
 static u32 cube_rtt_scale __read_mostly;
 static u32 beta_scale __read_mostly;
 static u64 cube_factor __read_mostly;
@@ -44,6 +68,13 @@
 MODULE_PARM_DESC(bic_scale, "scale (scaled by 1024) value for bic function (bic_scale/1024)");
 module_param(tcp_friendliness, int, 0644);
 MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness");
+module_param(hystart, int, 0644);
+MODULE_PARM_DESC(hystart, "turn on/off hybrid slow start algorithm");
+module_param(hystart_detect, int, 0644);
+MODULE_PARM_DESC(hystart_detect, "hyrbrid slow start detection mechanisms"
+		 " 1: packet-train 2: delay 3: both packet-train and delay");
+module_param(hystart_low_window, int, 0644);
+MODULE_PARM_DESC(hystart_low_window, "lower bound cwnd for hybrid slow start");
 
 /* BIC TCP Parameters */
 struct bictcp {
@@ -59,7 +90,13 @@
 	u32	ack_cnt;	/* number of acks */
 	u32	tcp_cwnd;	/* estimated tcp cwnd */
 #define ACK_RATIO_SHIFT	4
-	u32	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
+	u16	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
+	u8	sample_cnt;	/* number of samples to decide curr_rtt */
+	u8	found;		/* the exit point is found? */
+	u32	round_start;	/* beginning of each round */
+	u32	end_seq;	/* end_seq of the round */
+	u32	last_jiffies;	/* last time when the ACK spacing is close */
+	u32	curr_rtt;	/* the minimum rtt of current round */
 };
 
 static inline void bictcp_reset(struct bictcp *ca)
@@ -76,12 +113,28 @@
 	ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
 	ca->ack_cnt = 0;
 	ca->tcp_cwnd = 0;
+	ca->found = 0;
+}
+
+static inline void bictcp_hystart_reset(struct sock *sk)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct bictcp *ca = inet_csk_ca(sk);
+
+	ca->round_start = ca->last_jiffies = jiffies;
+	ca->end_seq = tp->snd_nxt;
+	ca->curr_rtt = 0;
+	ca->sample_cnt = 0;
 }
 
 static void bictcp_init(struct sock *sk)
 {
 	bictcp_reset(inet_csk_ca(sk));
-	if (initial_ssthresh)
+
+	if (hystart)
+		bictcp_hystart_reset(sk);
+
+	if (!hystart && initial_ssthresh)
 		tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
 }
 
@@ -235,9 +288,11 @@
 	if (!tcp_is_cwnd_limited(sk, in_flight))
 		return;
 
-	if (tp->snd_cwnd <= tp->snd_ssthresh)
+	if (tp->snd_cwnd <= tp->snd_ssthresh) {
+		if (hystart && after(ack, ca->end_seq))
+			bictcp_hystart_reset(sk);
 		tcp_slow_start(tp);
-	else {
+	} else {
 		bictcp_update(ca, tp->snd_cwnd);
 
 		/* In dangerous area, increase slowly.
@@ -281,8 +336,45 @@
 
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
-	if (new_state == TCP_CA_Loss)
+	if (new_state == TCP_CA_Loss) {
 		bictcp_reset(inet_csk_ca(sk));
+		bictcp_hystart_reset(sk);
+	}
+}
+
+static void hystart_update(struct sock *sk, u32 delay)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct bictcp *ca = inet_csk_ca(sk);
+
+	if (!(ca->found & hystart_detect)) {
+		u32 curr_jiffies = jiffies;
+
+		/* first detection parameter - ack-train detection */
+		if (curr_jiffies - ca->last_jiffies <= msecs_to_jiffies(2)) {
+			ca->last_jiffies = curr_jiffies;
+			if (curr_jiffies - ca->round_start >= ca->delay_min>>4)
+				ca->found |= HYSTART_ACK_TRAIN;
+		}
+
+		/* obtain the minimum delay of more than sampling packets */
+		if (ca->sample_cnt < HYSTART_MIN_SAMPLES) {
+			if (ca->curr_rtt == 0 || ca->curr_rtt > delay)
+				ca->curr_rtt = delay;
+
+			ca->sample_cnt++;
+		} else {
+			if (ca->curr_rtt > ca->delay_min +
+			    HYSTART_DELAY_THRESH(ca->delay_min>>4))
+				ca->found |= HYSTART_DELAY;
+		}
+		/*
+		 * Either one of two conditions are met,
+		 * we exit from slow start immediately.
+		 */
+		if (ca->found & hystart_detect)
+			tp->snd_ssthresh = tp->snd_cwnd;
+	}
 }
 
 /* Track delayed acknowledgment ratio using sliding window
@@ -291,6 +383,7 @@
 static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
+	const struct tcp_sock *tp = tcp_sk(sk);
 	struct bictcp *ca = inet_csk_ca(sk);
 	u32 delay;
 
@@ -314,6 +407,11 @@
 	/* first time call or link delay decreases */
 	if (ca->delay_min == 0 || ca->delay_min > delay)
 		ca->delay_min = delay;
+
+	/* hystart triggers when cwnd is larger than some threshold */
+	if (hystart && tp->snd_cwnd <= tp->snd_ssthresh &&
+	    tp->snd_cwnd >= hystart_low_window)
+		hystart_update(sk, delay);
 }
 
 static struct tcp_congestion_ops cubictcp = {
@@ -372,4 +470,4 @@
 MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("CUBIC TCP");
-MODULE_VERSION("2.2");
+MODULE_VERSION("2.3");
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d77c0d2..097294b 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2336,9 +2336,9 @@
 	struct inet_sock *inet = inet_sk(sk);
 
 	if (sk->sk_family == AF_INET) {
-		printk(KERN_DEBUG "Undo %s " NIPQUAD_FMT "/%u c%u l%u ss%u/%u p%u\n",
+		printk(KERN_DEBUG "Undo %s %pI4/%u c%u l%u ss%u/%u p%u\n",
 		       msg,
-		       NIPQUAD(inet->daddr), ntohs(inet->dport),
+		       &inet->daddr, ntohs(inet->dport),
 		       tp->snd_cwnd, tcp_left_out(tp),
 		       tp->snd_ssthresh, tp->prior_ssthresh,
 		       tp->packets_out);
@@ -2346,9 +2346,9 @@
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	else if (sk->sk_family == AF_INET6) {
 		struct ipv6_pinfo *np = inet6_sk(sk);
-		printk(KERN_DEBUG "Undo %s " NIP6_FMT "/%u c%u l%u ss%u/%u p%u\n",
+		printk(KERN_DEBUG "Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n",
 		       msg,
-		       NIP6(np->daddr), ntohs(inet->dport),
+		       &np->daddr, ntohs(inet->dport),
 		       tp->snd_cwnd, tcp_left_out(tp),
 		       tp->snd_ssthresh, tp->prior_ssthresh,
 		       tp->packets_out);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5c8fa7f..d49233f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1139,10 +1139,9 @@
 
 	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
 		if (net_ratelimit()) {
-			printk(KERN_INFO "MD5 Hash failed for "
-			       "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
-			       NIPQUAD(iph->saddr), ntohs(th->source),
-			       NIPQUAD(iph->daddr), ntohs(th->dest),
+			printk(KERN_INFO "MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s\n",
+			       &iph->saddr, ntohs(th->source),
+			       &iph->daddr, ntohs(th->dest),
 			       genhash ? " tcp_v4_calc_md5_hash failed" : "");
 		}
 		return 1;
@@ -1297,10 +1296,8 @@
 			 * to destinations, already remembered
 			 * to the moment of synflood.
 			 */
-			LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
-				       "request from " NIPQUAD_FMT "/%u\n",
-				       NIPQUAD(saddr),
-				       ntohs(tcp_hdr(skb)->source));
+			LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI4/%u\n",
+				       &saddr, ntohs(tcp_hdr(skb)->source));
 			goto drop_and_release;
 		}
 
@@ -1877,7 +1874,7 @@
 	struct inet_connection_sock *icsk;
 	struct hlist_node *node;
 	struct sock *sk = cur;
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 	struct net *net = seq_file_net(seq);
 
 	if (!sk) {
@@ -1963,7 +1960,7 @@
 
 static void *established_get_first(struct seq_file *seq)
 {
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 	struct net *net = seq_file_net(seq);
 	void *rc = NULL;
 
@@ -2008,7 +2005,7 @@
 	struct sock *sk = cur;
 	struct inet_timewait_sock *tw;
 	struct hlist_node *node;
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 	struct net *net = seq_file_net(seq);
 
 	++st->num;
@@ -2067,7 +2064,7 @@
 static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
 {
 	void *rc;
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 
 	inet_listen_lock(&tcp_hashinfo);
 	st->state = TCP_SEQ_STATE_LISTENING;
@@ -2084,7 +2081,7 @@
 
 static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 	st->state = TCP_SEQ_STATE_LISTENING;
 	st->num = 0;
 	return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
@@ -2093,7 +2090,7 @@
 static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	void *rc = NULL;
-	struct tcp_iter_state* st;
+	struct tcp_iter_state *st;
 
 	if (v == SEQ_START_TOKEN) {
 		rc = tcp_get_idx(seq, 0);
@@ -2123,7 +2120,7 @@
 
 static void tcp_seq_stop(struct seq_file *seq, void *v)
 {
-	struct tcp_iter_state* st = seq->private;
+	struct tcp_iter_state *st = seq->private;
 
 	switch (st->state) {
 	case TCP_SEQ_STATE_OPENREQ:
@@ -2284,7 +2281,7 @@
 
 static int tcp4_seq_show(struct seq_file *seq, void *v)
 {
-	struct tcp_iter_state* st;
+	struct tcp_iter_state *st;
 	int len;
 
 	if (v == SEQ_START_TOKEN) {
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 779f2e9..f67effb 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -491,7 +491,7 @@
  *	as a request_sock.
  */
 
-struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 			   struct request_sock *req,
 			   struct request_sock **prev)
 {
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ba85d88..a524627 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -42,7 +42,7 @@
 /* People can turn this off for buggy TCP's found in printers etc. */
 int sysctl_tcp_retrans_collapse __read_mostly = 1;
 
-/* People can turn this on to  work with those rare, broken TCPs that
+/* People can turn this on to work with those rare, broken TCPs that
  * interpret the window field as a signed quantity.
  */
 int sysctl_tcp_workaround_signed_windows __read_mostly = 0;
@@ -484,7 +484,7 @@
 	}
 	if (likely(sysctl_tcp_window_scaling)) {
 		opts->ws = tp->rx_opt.rcv_wscale;
-		if(likely(opts->ws))
+		if (likely(opts->ws))
 			size += TCPOLEN_WSCALE_ALIGNED;
 	}
 	if (likely(sysctl_tcp_sack)) {
@@ -526,7 +526,7 @@
 
 	if (likely(ireq->wscale_ok)) {
 		opts->ws = ireq->rcv_wscale;
-		if(likely(opts->ws))
+		if (likely(opts->ws))
 			size += TCPOLEN_WSCALE_ALIGNED;
 	}
 	if (likely(doing_ts)) {
@@ -1172,7 +1172,7 @@
 
 static inline int tcp_minshall_check(const struct tcp_sock *tp)
 {
-	return after(tp->snd_sml,tp->snd_una) &&
+	return after(tp->snd_sml, tp->snd_una) &&
 		!after(tp->snd_sml, tp->snd_nxt);
 }
 
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 7ddc30f..25524d4 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -153,12 +153,11 @@
 		= ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
 
 	return snprintf(tbuf, n,
-			"%lu.%09lu " NIPQUAD_FMT ":%u " NIPQUAD_FMT ":%u"
-			" %d %#x %#x %u %u %u %u\n",
+			"%lu.%09lu %pI4:%u %pI4:%u %d %#x %#x %u %u %u %u\n",
 			(unsigned long) tv.tv_sec,
 			(unsigned long) tv.tv_nsec,
-			NIPQUAD(p->saddr), ntohs(p->sport),
-			NIPQUAD(p->daddr), ntohs(p->dport),
+			&p->saddr, ntohs(p->sport),
+			&p->daddr, ntohs(p->dport),
 			p->length, p->snd_nxt, p->snd_una,
 			p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt);
 }
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 6b6dff1..3df339e 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -171,7 +171,7 @@
 
 static void tcp_delack_timer(unsigned long data)
 {
-	struct sock *sk = (struct sock*)data;
+	struct sock *sk = (struct sock *)data;
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
@@ -299,15 +299,15 @@
 #ifdef TCP_DEBUG
 		struct inet_sock *inet = inet_sk(sk);
 		if (sk->sk_family == AF_INET) {
-			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIPQUAD_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
-			       NIPQUAD(inet->daddr), ntohs(inet->dport),
+			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %pI4:%u/%u shrinks window %u:%u. Repaired.\n",
+			       &inet->daddr, ntohs(inet->dport),
 			       inet->num, tp->snd_una, tp->snd_nxt);
 		}
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		else if (sk->sk_family == AF_INET6) {
 			struct ipv6_pinfo *np = inet6_sk(sk);
-			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIP6_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
-			       NIP6(np->daddr), ntohs(inet->dport),
+			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %pI6:%u/%u shrinks window %u:%u. Repaired.\n",
+			       &np->daddr, ntohs(inet->dport),
 			       inet->num, tp->snd_una, tp->snd_nxt);
 		}
 #endif
@@ -396,7 +396,7 @@
 
 static void tcp_write_timer(unsigned long data)
 {
-	struct sock *sk = (struct sock*)data;
+	struct sock *sk = (struct sock *)data;
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	int event;
 
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c
index e03b101..9ec843a 100644
--- a/net/ipv4/tcp_yeah.c
+++ b/net/ipv4/tcp_yeah.c
@@ -83,7 +83,7 @@
 	else if (!yeah->doing_reno_now) {
 		/* Scalable */
 
-		tp->snd_cwnd_cnt+=yeah->pkts_acked;
+		tp->snd_cwnd_cnt += yeah->pkts_acked;
 		if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
 				tp->snd_cwnd++;
@@ -224,7 +224,7 @@
 
 		reduction = max( reduction, tp->snd_cwnd >> TCP_YEAH_DELTA);
 	} else
-		reduction = max(tp->snd_cwnd>>1,2U);
+		reduction = max(tp->snd_cwnd>>1, 2U);
 
 	yeah->fast_count = 0;
 	yeah->reno_count = max(yeah->reno_count>>1, 2U);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cf02701..54badc9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -81,6 +81,8 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/swap.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/module.h>
@@ -104,12 +106,8 @@
 #include <net/xfrm.h>
 #include "udp_impl.h"
 
-/*
- *	Snmp MIB for the UDP layer
- */
-
-struct hlist_head udp_hash[UDP_HTABLE_SIZE];
-DEFINE_RWLOCK(udp_hash_lock);
+struct udp_table udp_table;
+EXPORT_SYMBOL(udp_table);
 
 int sysctl_udp_mem[3] __read_mostly;
 int sysctl_udp_rmem_min __read_mostly;
@@ -123,7 +121,7 @@
 EXPORT_SYMBOL(udp_memory_allocated);
 
 static int udp_lib_lport_inuse(struct net *net, __u16 num,
-			       const struct hlist_head udptable[],
+			       const struct udp_hslot *hslot,
 			       struct sock *sk,
 			       int (*saddr_comp)(const struct sock *sk1,
 						 const struct sock *sk2))
@@ -131,7 +129,7 @@
 	struct sock *sk2;
 	struct hlist_node *node;
 
-	sk_for_each(sk2, node, &udptable[udp_hashfn(net, num)])
+	sk_for_each(sk2, node, &hslot->head)
 		if (net_eq(sock_net(sk2), net)			&&
 		    sk2 != sk					&&
 		    sk2->sk_hash == num				&&
@@ -154,12 +152,11 @@
 		       int (*saddr_comp)(const struct sock *sk1,
 					 const struct sock *sk2 )    )
 {
-	struct hlist_head *udptable = sk->sk_prot->h.udp_hash;
+	struct udp_hslot *hslot;
+	struct udp_table *udptable = sk->sk_prot->h.udp_table;
 	int    error = 1;
 	struct net *net = sock_net(sk);
 
-	write_lock_bh(&udp_hash_lock);
-
 	if (!snum) {
 		int low, high, remaining;
 		unsigned rand;
@@ -171,26 +168,39 @@
 		rand = net_random();
 		snum = first = rand % remaining + low;
 		rand |= 1;
-		while (udp_lib_lport_inuse(net, snum, udptable, sk,
-					   saddr_comp)) {
+		for (;;) {
+			hslot = &udptable->hash[udp_hashfn(net, snum)];
+			spin_lock_bh(&hslot->lock);
+			if (!udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp))
+				break;
+			spin_unlock_bh(&hslot->lock);
 			do {
 				snum = snum + rand;
 			} while (snum < low || snum > high);
 			if (snum == first)
 				goto fail;
 		}
-	} else if (udp_lib_lport_inuse(net, snum, udptable, sk, saddr_comp))
-		goto fail;
-
+	} else {
+		hslot = &udptable->hash[udp_hashfn(net, snum)];
+		spin_lock_bh(&hslot->lock);
+		if (udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp))
+			goto fail_unlock;
+	}
 	inet_sk(sk)->num = snum;
 	sk->sk_hash = snum;
 	if (sk_unhashed(sk)) {
-		sk_add_node(sk, &udptable[udp_hashfn(net, snum)]);
+		/*
+		 * We need that previous write to sk->sk_hash committed
+		 * before write to sk->next done in following add_node() variant
+		 */
+		smp_wmb();
+		sk_add_node_rcu(sk, &hslot->head);
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
 	}
 	error = 0;
+fail_unlock:
+	spin_unlock_bh(&hslot->lock);
 fail:
-	write_unlock_bh(&udp_hash_lock);
 	return error;
 }
 
@@ -208,63 +218,89 @@
 	return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal);
 }
 
+static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr,
+			 unsigned short hnum,
+			 __be16 sport, __be32 daddr, __be16 dport, int dif)
+{
+	int score = -1;
+
+	if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+			!ipv6_only_sock(sk)) {
+		struct inet_sock *inet = inet_sk(sk);
+
+		score = (sk->sk_family == PF_INET ? 1 : 0);
+		if (inet->rcv_saddr) {
+			if (inet->rcv_saddr != daddr)
+				return -1;
+			score += 2;
+		}
+		if (inet->daddr) {
+			if (inet->daddr != saddr)
+				return -1;
+			score += 2;
+		}
+		if (inet->dport) {
+			if (inet->dport != sport)
+				return -1;
+			score += 2;
+		}
+		if (sk->sk_bound_dev_if) {
+			if (sk->sk_bound_dev_if != dif)
+				return -1;
+			score += 2;
+		}
+	}
+	return score;
+}
+
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
  * harder than this. -DaveM
  */
 static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
 		__be16 sport, __be32 daddr, __be16 dport,
-		int dif, struct hlist_head udptable[])
+		int dif, struct udp_table *udptable)
 {
-	struct sock *sk, *result = NULL;
-	struct hlist_node *node;
+	struct sock *sk, *result;
+	struct hlist_node *node, *next;
 	unsigned short hnum = ntohs(dport);
-	int badness = -1;
+	unsigned int hash = udp_hashfn(net, hnum);
+	struct udp_hslot *hslot = &udptable->hash[hash];
+	int score, badness;
 
-	read_lock(&udp_hash_lock);
-	sk_for_each(sk, node, &udptable[udp_hashfn(net, hnum)]) {
-		struct inet_sock *inet = inet_sk(sk);
-
-		if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
-				!ipv6_only_sock(sk)) {
-			int score = (sk->sk_family == PF_INET ? 1 : 0);
-			if (inet->rcv_saddr) {
-				if (inet->rcv_saddr != daddr)
-					continue;
-				score+=2;
-			}
-			if (inet->daddr) {
-				if (inet->daddr != saddr)
-					continue;
-				score+=2;
-			}
-			if (inet->dport) {
-				if (inet->dport != sport)
-					continue;
-				score+=2;
-			}
-			if (sk->sk_bound_dev_if) {
-				if (sk->sk_bound_dev_if != dif)
-					continue;
-				score+=2;
-			}
-			if (score == 9) {
-				result = sk;
-				break;
-			} else if (score > badness) {
-				result = sk;
-				badness = score;
-			}
+	rcu_read_lock();
+begin:
+	result = NULL;
+	badness = -1;
+	sk_for_each_rcu_safenext(sk, node, &hslot->head, next) {
+		/*
+		 * lockless reader, and SLAB_DESTROY_BY_RCU items:
+		 * We must check this item was not moved to another chain
+		 */
+		if (udp_hashfn(net, sk->sk_hash) != hash)
+			goto begin;
+		score = compute_score(sk, net, saddr, hnum, sport,
+				      daddr, dport, dif);
+		if (score > badness) {
+			result = sk;
+			badness = score;
 		}
 	}
-	if (result)
-		sock_hold(result);
-	read_unlock(&udp_hash_lock);
+	if (result) {
+		if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
+			result = NULL;
+		else if (unlikely(compute_score(result, net, saddr, hnum, sport,
+				  daddr, dport, dif) < badness)) {
+			sock_put(result);
+			goto begin;
+		}
+	}
+	rcu_read_unlock();
 	return result;
 }
 
 static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 						 __be16 sport, __be16 dport,
-						 struct hlist_head udptable[])
+						 struct udp_table *udptable)
 {
 	struct sock *sk;
 	const struct iphdr *iph = ip_hdr(skb);
@@ -280,7 +316,7 @@
 struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 			     __be32 daddr, __be16 dport, int dif)
 {
-	return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash);
+	return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);
 }
 EXPORT_SYMBOL_GPL(udp4_lib_lookup);
 
@@ -324,7 +360,7 @@
  * to find the appropriate port.
  */
 
-void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
+void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 {
 	struct inet_sock *inet;
 	struct iphdr *iph = (struct iphdr*)skb->data;
@@ -393,7 +429,7 @@
 
 void udp_err(struct sk_buff *skb, u32 info)
 {
-	__udp4_lib_err(skb, info, udp_hash);
+	__udp4_lib_err(skb, info, &udp_table);
 }
 
 /*
@@ -934,6 +970,21 @@
 	return 0;
 }
 
+void udp_lib_unhash(struct sock *sk)
+{
+	struct udp_table *udptable = sk->sk_prot->h.udp_table;
+	unsigned int hash = udp_hashfn(sock_net(sk), sk->sk_hash);
+	struct udp_hslot *hslot = &udptable->hash[hash];
+
+	spin_lock_bh(&hslot->lock);
+	if (sk_del_node_init_rcu(sk)) {
+		inet_sk(sk)->num = 0;
+		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+	}
+	spin_unlock_bh(&hslot->lock);
+}
+EXPORT_SYMBOL(udp_lib_unhash);
+
 static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
 	int is_udplite = IS_UDPLITE(sk);
@@ -1072,13 +1123,14 @@
 static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
 				    struct udphdr  *uh,
 				    __be32 saddr, __be32 daddr,
-				    struct hlist_head udptable[])
+				    struct udp_table *udptable)
 {
 	struct sock *sk;
+	struct udp_hslot *hslot = &udptable->hash[udp_hashfn(net, ntohs(uh->dest))];
 	int dif;
 
-	read_lock(&udp_hash_lock);
-	sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]);
+	spin_lock(&hslot->lock);
+	sk = sk_head(&hslot->head);
 	dif = skb->dev->ifindex;
 	sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif);
 	if (sk) {
@@ -1104,7 +1156,7 @@
 		} while (sknext);
 	} else
 		kfree_skb(skb);
-	read_unlock(&udp_hash_lock);
+	spin_unlock(&hslot->lock);
 	return 0;
 }
 
@@ -1150,7 +1202,7 @@
  *	All we need to do is get the socket, and then do a checksum.
  */
 
-int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
 		   int proto)
 {
 	struct sock *sk;
@@ -1218,13 +1270,13 @@
 	return 0;
 
 short_packet:
-	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From " NIPQUAD_FMT ":%u %d/%d to " NIPQUAD_FMT ":%u\n",
+	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %pI4:%u %d/%d to %pI4:%u\n",
 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
-		       NIPQUAD(saddr),
+		       &saddr,
 		       ntohs(uh->source),
 		       ulen,
 		       skb->len,
-		       NIPQUAD(daddr),
+		       &daddr,
 		       ntohs(uh->dest));
 	goto drop;
 
@@ -1233,11 +1285,11 @@
 	 * RFC1122: OK.  Discards the bad packet silently (as far as
 	 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
 	 */
-	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From " NIPQUAD_FMT ":%u to " NIPQUAD_FMT ":%u ulen %d\n",
+	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",
 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
-		       NIPQUAD(saddr),
+		       &saddr,
 		       ntohs(uh->source),
-		       NIPQUAD(daddr),
+		       &daddr,
 		       ntohs(uh->dest),
 		       ulen);
 drop:
@@ -1248,7 +1300,7 @@
 
 int udp_rcv(struct sk_buff *skb)
 {
-	return __udp4_lib_rcv(skb, udp_hash, IPPROTO_UDP);
+	return __udp4_lib_rcv(skb, &udp_table, IPPROTO_UDP);
 }
 
 void udp_destroy_sock(struct sock *sk)
@@ -1490,7 +1542,8 @@
 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
 	.obj_size	   = sizeof(struct udp_sock),
-	.h.udp_hash	   = udp_hash,
+	.slab_flags	   = SLAB_DESTROY_BY_RCU,
+	.h.udp_table	   = &udp_table,
 #ifdef CONFIG_COMPAT
 	.compat_setsockopt = compat_udp_setsockopt,
 	.compat_getsockopt = compat_udp_getsockopt,
@@ -1500,20 +1553,23 @@
 /* ------------------------------------------------------------------------ */
 #ifdef CONFIG_PROC_FS
 
-static struct sock *udp_get_first(struct seq_file *seq)
+static struct sock *udp_get_first(struct seq_file *seq, int start)
 {
 	struct sock *sk;
 	struct udp_iter_state *state = seq->private;
 	struct net *net = seq_file_net(seq);
 
-	for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
+	for (state->bucket = start; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
 		struct hlist_node *node;
-		sk_for_each(sk, node, state->hashtable + state->bucket) {
+		struct udp_hslot *hslot = &state->udp_table->hash[state->bucket];
+		spin_lock_bh(&hslot->lock);
+		sk_for_each(sk, node, &hslot->head) {
 			if (!net_eq(sock_net(sk), net))
 				continue;
 			if (sk->sk_family == state->family)
 				goto found;
 		}
+		spin_unlock_bh(&hslot->lock);
 	}
 	sk = NULL;
 found:
@@ -1527,20 +1583,18 @@
 
 	do {
 		sk = sk_next(sk);
-try_again:
-		;
 	} while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));
 
-	if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
-		sk = sk_head(state->hashtable + state->bucket);
-		goto try_again;
+	if (!sk) {
+		spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);
+		return udp_get_first(seq, state->bucket + 1);
 	}
 	return sk;
 }
 
 static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)
 {
-	struct sock *sk = udp_get_first(seq);
+	struct sock *sk = udp_get_first(seq, 0);
 
 	if (sk)
 		while (pos && (sk = udp_get_next(seq, sk)) != NULL)
@@ -1549,9 +1603,7 @@
 }
 
 static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(udp_hash_lock)
 {
-	read_lock(&udp_hash_lock);
 	return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
 }
 
@@ -1569,9 +1621,11 @@
 }
 
 static void udp_seq_stop(struct seq_file *seq, void *v)
-	__releases(udp_hash_lock)
 {
-	read_unlock(&udp_hash_lock);
+	struct udp_iter_state *state = seq->private;
+
+	if (state->bucket < UDP_HTABLE_SIZE)
+		spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);
 }
 
 static int udp_seq_open(struct inode *inode, struct file *file)
@@ -1587,7 +1641,7 @@
 
 	s = ((struct seq_file *)file->private_data)->private;
 	s->family		= afinfo->family;
-	s->hashtable		= afinfo->hashtable;
+	s->udp_table		= afinfo->udp_table;
 	return err;
 }
 
@@ -1659,7 +1713,7 @@
 static struct udp_seq_afinfo udp4_seq_afinfo = {
 	.name		= "udp",
 	.family		= AF_INET,
-	.hashtable	= udp_hash,
+	.udp_table	= &udp_table,
 	.seq_fops	= {
 		.owner	=	THIS_MODULE,
 	},
@@ -1694,16 +1748,28 @@
 }
 #endif /* CONFIG_PROC_FS */
 
+void __init udp_table_init(struct udp_table *table)
+{
+	int i;
+
+	for (i = 0; i < UDP_HTABLE_SIZE; i++) {
+		INIT_HLIST_HEAD(&table->hash[i].head);
+		spin_lock_init(&table->hash[i].lock);
+	}
+}
+
 void __init udp_init(void)
 {
-	unsigned long limit;
+	unsigned long nr_pages, limit;
 
+	udp_table_init(&udp_table);
 	/* Set the pressure threshold up by the same strategy of TCP. It is a
 	 * fraction of global memory that is up to 1/2 at 256 MB, decreasing
 	 * toward zero with the amount of memory, with a floor of 128 pages.
 	 */
-	limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
-	limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
+	nr_pages = totalram_pages - totalhigh_pages;
+	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
+	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
 	limit = max(limit, 128UL);
 	sysctl_udp_mem[0] = limit / 4 * 3;
 	sysctl_udp_mem[1] = limit;
@@ -1714,8 +1780,6 @@
 }
 
 EXPORT_SYMBOL(udp_disconnect);
-EXPORT_SYMBOL(udp_hash);
-EXPORT_SYMBOL(udp_hash_lock);
 EXPORT_SYMBOL(udp_ioctl);
 EXPORT_SYMBOL(udp_prot);
 EXPORT_SYMBOL(udp_sendmsg);
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 2e9bad2..9f4a616 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,8 +5,8 @@
 #include <net/protocol.h>
 #include <net/inet_common.h>
 
-extern int  	__udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
-extern void 	__udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
+extern int  	__udp4_lib_rcv(struct sk_buff *, struct udp_table *, int );
+extern void 	__udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
 
 extern int	udp_v4_get_port(struct sock *sk, unsigned short snum);
 
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index 3c80796..c784891 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -12,16 +12,17 @@
  */
 #include "udp_impl.h"
 
-struct hlist_head 	udplite_hash[UDP_HTABLE_SIZE];
+struct udp_table 	udplite_table;
+EXPORT_SYMBOL(udplite_table);
 
 static int udplite_rcv(struct sk_buff *skb)
 {
-	return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
+	return __udp4_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
 }
 
 static void udplite_err(struct sk_buff *skb, u32 info)
 {
-	__udp4_lib_err(skb, info, udplite_hash);
+	__udp4_lib_err(skb, info, &udplite_table);
 }
 
 static	struct net_protocol udplite_protocol = {
@@ -50,7 +51,8 @@
 	.unhash		   = udp_lib_unhash,
 	.get_port	   = udp_v4_get_port,
 	.obj_size	   = sizeof(struct udp_sock),
-	.h.udp_hash	   = udplite_hash,
+	.slab_flags	   = SLAB_DESTROY_BY_RCU,
+	.h.udp_table	   = &udplite_table,
 #ifdef CONFIG_COMPAT
 	.compat_setsockopt = compat_udp_setsockopt,
 	.compat_getsockopt = compat_udp_getsockopt,
@@ -71,7 +73,7 @@
 static struct udp_seq_afinfo udplite4_seq_afinfo = {
 	.name		= "udplite",
 	.family		= AF_INET,
-	.hashtable	= udplite_hash,
+	.udp_table 	= &udplite_table,
 	.seq_fops	= {
 		.owner	=	THIS_MODULE,
 	},
@@ -108,6 +110,7 @@
 
 void __init udplite4_register(void)
 {
+	udp_table_init(&udplite_table);
 	if (proto_register(&udplite_prot, 1))
 		goto out_register_err;
 
@@ -126,5 +129,4 @@
 	printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __func__);
 }
 
-EXPORT_SYMBOL(udplite_hash);
 EXPORT_SYMBOL(udplite_prot);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index c63de0a..f9a775b 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -65,7 +65,7 @@
 
 	read_lock_bh(&policy->lock);
 	for (dst = policy->bundles; dst; dst = dst->next) {
-		struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+		struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 		    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d9da5eb..0e41f1b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2988,9 +2988,8 @@
 static int if6_seq_show(struct seq_file *seq, void *v)
 {
 	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
-	seq_printf(seq,
-		   NIP6_SEQFMT " %02x %02x %02x %02x %8s\n",
-		   NIP6(ifp->addr),
+	seq_printf(seq, "%pi6 %02x %02x %02x %02x %8s\n",
+		   &ifp->addr,
 		   ifp->idev->dev->ifindex,
 		   ifp->prefix_len,
 		   ifp->scope,
@@ -4033,8 +4032,8 @@
 			.data		=	&ipv6_devconf.forwarding,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&addrconf_sysctl_forward,
-			.strategy	=	&addrconf_sysctl_forward_strategy,
+			.proc_handler	=	addrconf_sysctl_forward,
+			.strategy	=	addrconf_sysctl_forward_strategy,
 		},
 		{
 			.ctl_name	=	NET_IPV6_HOP_LIMIT,
@@ -4050,7 +4049,7 @@
 			.data		=	&ipv6_devconf.mtu6,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA,
@@ -4058,7 +4057,7 @@
 			.data		=	&ipv6_devconf.accept_ra,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_REDIRECTS,
@@ -4066,7 +4065,7 @@
 			.data		=	&ipv6_devconf.accept_redirects,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_AUTOCONF,
@@ -4074,7 +4073,7 @@
 			.data		=	&ipv6_devconf.autoconf,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_DAD_TRANSMITS,
@@ -4082,7 +4081,7 @@
 			.data		=	&ipv6_devconf.dad_transmits,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICITS,
@@ -4090,7 +4089,7 @@
 			.data		=	&ipv6_devconf.rtr_solicits,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICIT_INTERVAL,
@@ -4098,8 +4097,8 @@
 			.data		=	&ipv6_devconf.rtr_solicit_interval,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec_jiffies,
-			.strategy	=	&sysctl_jiffies,
+			.proc_handler	=	proc_dointvec_jiffies,
+			.strategy	=	sysctl_jiffies,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICIT_DELAY,
@@ -4107,8 +4106,8 @@
 			.data		=	&ipv6_devconf.rtr_solicit_delay,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec_jiffies,
-			.strategy	=	&sysctl_jiffies,
+			.proc_handler	=	proc_dointvec_jiffies,
+			.strategy	=	sysctl_jiffies,
 		},
 		{
 			.ctl_name	=	NET_IPV6_FORCE_MLD_VERSION,
@@ -4116,7 +4115,7 @@
 			.data		=	&ipv6_devconf.force_mld_version,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #ifdef CONFIG_IPV6_PRIVACY
 		{
@@ -4125,7 +4124,7 @@
 			.data		=	&ipv6_devconf.use_tempaddr,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_TEMP_VALID_LFT,
@@ -4133,7 +4132,7 @@
 			.data		=	&ipv6_devconf.temp_valid_lft,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_TEMP_PREFERED_LFT,
@@ -4141,7 +4140,7 @@
 			.data		=	&ipv6_devconf.temp_prefered_lft,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_REGEN_MAX_RETRY,
@@ -4149,7 +4148,7 @@
 			.data		=	&ipv6_devconf.regen_max_retry,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_MAX_DESYNC_FACTOR,
@@ -4157,7 +4156,7 @@
 			.data		=	&ipv6_devconf.max_desync_factor,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #endif
 		{
@@ -4166,7 +4165,7 @@
 			.data		=	&ipv6_devconf.max_addresses,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA_DEFRTR,
@@ -4174,7 +4173,7 @@
 			.data		=	&ipv6_devconf.accept_ra_defrtr,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA_PINFO,
@@ -4182,7 +4181,7 @@
 			.data		=	&ipv6_devconf.accept_ra_pinfo,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #ifdef CONFIG_IPV6_ROUTER_PREF
 		{
@@ -4191,7 +4190,7 @@
 			.data		=	&ipv6_devconf.accept_ra_rtr_pref,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_PROBE_INTERVAL,
@@ -4199,8 +4198,8 @@
 			.data		=	&ipv6_devconf.rtr_probe_interval,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec_jiffies,
-			.strategy	=	&sysctl_jiffies,
+			.proc_handler	=	proc_dointvec_jiffies,
+			.strategy	=	sysctl_jiffies,
 		},
 #ifdef CONFIG_IPV6_ROUTE_INFO
 		{
@@ -4209,7 +4208,7 @@
 			.data		=	&ipv6_devconf.accept_ra_rt_info_max_plen,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #endif
 #endif
@@ -4219,7 +4218,7 @@
 			.data		=	&ipv6_devconf.proxy_ndp,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_SOURCE_ROUTE,
@@ -4227,7 +4226,7 @@
 			.data		=	&ipv6_devconf.accept_source_route,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
 		{
@@ -4236,7 +4235,7 @@
 			.data           =       &ipv6_devconf.optimistic_dad,
 			.maxlen         =       sizeof(int),
 			.mode           =       0644,
-			.proc_handler   =       &proc_dointvec,
+			.proc_handler   =       proc_dointvec,
 
 		},
 #endif
@@ -4247,7 +4246,7 @@
 			.data		=	&ipv6_devconf.mc_forwarding,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 #endif
 		{
@@ -4256,7 +4255,7 @@
 			.data		=	&ipv6_devconf.disable_ipv6,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	CTL_UNNUMBERED,
@@ -4264,7 +4263,7 @@
 			.data		=	&ipv6_devconf.accept_dad,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-			.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	proc_dointvec,
 		},
 		{
 			.ctl_name	=	0,	/* sentinel */
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index 0890903..6ff73c4 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -186,10 +186,8 @@
 	label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT;
 	rcu_read_unlock();
 
-	ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n",
-			__func__,
-			NIP6(*addr), type, ifindex,
-			label);
+	ADDRLABEL(KERN_DEBUG "%s(addr=%pI6, type=%d, ifindex=%d) => %08x\n",
+		  __func__, addr, type, ifindex, label);
 
 	return label;
 }
@@ -203,11 +201,8 @@
 	struct ip6addrlbl_entry *newp;
 	int addrtype;
 
-	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n",
-			__func__,
-			NIP6(*prefix), prefixlen,
-			ifindex,
-			(unsigned int)label);
+	ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u)\n",
+		  __func__, prefix, prefixlen, ifindex, (unsigned int)label);
 
 	addrtype = ipv6_addr_type(prefix) & (IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK);
 
@@ -294,12 +289,9 @@
 	struct ip6addrlbl_entry *newp;
 	int ret = 0;
 
-	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
-			__func__,
-			NIP6(*prefix), prefixlen,
-			ifindex,
-			(unsigned int)label,
-			replace);
+	ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
+		  __func__, prefix, prefixlen, ifindex, (unsigned int)label,
+		  replace);
 
 	newp = ip6addrlbl_alloc(net, prefix, prefixlen, ifindex, label);
 	if (IS_ERR(newp))
@@ -321,10 +313,8 @@
 	struct hlist_node *pos, *n;
 	int ret = -ESRCH;
 
-	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
-			__func__,
-			NIP6(*prefix), prefixlen,
-			ifindex);
+	ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n",
+		  __func__, prefix, prefixlen, ifindex);
 
 	hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) {
 		if (p->prefixlen == prefixlen &&
@@ -347,10 +337,8 @@
 	struct in6_addr prefix_buf;
 	int ret;
 
-	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
-			__func__,
-			NIP6(*prefix), prefixlen,
-			ifindex);
+	ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n",
+		  __func__, prefix, prefixlen, ifindex);
 
 	ipv6_addr_prefix(&prefix_buf, prefix, prefixlen);
 	spin_lock(&ip6addrlbl_table.lock);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 2ff0c82..7a8a013 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -419,8 +419,8 @@
 	if (!x)
 		return;
 
-	NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n",
-		 ntohl(ah->spi), NIP6(iph->daddr));
+	NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/%pI6\n",
+		 ntohl(ah->spi), &iph->daddr);
 
 	xfrm_state_put(x);
 }
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 8336cd8..1ae58be 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -512,11 +512,9 @@
 	struct ifacaddr6 *im = (struct ifacaddr6 *)v;
 	struct ac6_iter_state *state = ac6_seq_private(seq);
 
-	seq_printf(seq,
-		   "%-4d %-15s " NIP6_SEQFMT " %5d\n",
+	seq_printf(seq, "%-4d %-15s %pi6 %5d\n",
 		   state->dev->ifindex, state->dev->name,
-		   NIP6(im->aca_addr),
-		   im->aca_users);
+		   &im->aca_addr, im->aca_users);
 	return 0;
 }
 
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index b181b08..c02a630 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -367,8 +367,8 @@
 	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
 	if (!x)
 		return;
-	printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n",
-			ntohl(esph->spi), NIP6(iph->daddr));
+	printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n",
+			ntohl(esph->spi), &iph->daddr);
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6bfffec..1c7f400 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -219,7 +219,7 @@
 
 	if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
 		LIMIT_NETDEBUG(
-			KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
+			KERN_DEBUG "hao is not an unicast addr: %pI6\n", &hao->addr);
 		goto discard;
 	}
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 9b7d19a..be35100 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -646,9 +646,10 @@
 	int type;
 
 	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+		struct sec_path *sp = skb_sec_path(skb);
 		int nh;
 
-		if (!(skb->sp && skb->sp->xvec[skb->sp->len - 1]->props.flags &
+		if (!(sp && sp->xvec[sp->len - 1]->props.flags &
 				 XFRM_STATE_ICMP))
 			goto drop_no_count;
 
@@ -680,8 +681,8 @@
 		skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
 					     IPPROTO_ICMPV6, 0));
 		if (__skb_checksum_complete(skb)) {
-			LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n",
-				       NIP6(*saddr), NIP6(*daddr));
+			LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n",
+				       saddr, daddr);
 			goto discard_it;
 		}
 	}
@@ -955,8 +956,8 @@
 		.data		= &init_net.ipv6.sysctl.icmpv6_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_ms_jiffies,
-		.strategy	= &sysctl_ms_jiffies
+		.proc_handler	= proc_dointvec_ms_jiffies,
+		.strategy	= sysctl_ms_jiffies
 	},
 	{ .ctl_name = 0 },
 };
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 37a4e77..7927a84 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -696,14 +696,14 @@
 	else {
 		struct ip6_flowlabel *fl = v;
 		seq_printf(seq,
-			   "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
+			   "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
 			   (unsigned)ntohl(fl->label),
 			   fl->share,
 			   (unsigned)fl->owner,
 			   atomic_read(&fl->users),
 			   fl->linger/HZ,
 			   (long)(fl->expires - jiffies)/HZ,
-			   NIP6(fl->dst),
+			   &fl->dst,
 			   fl->opt ? fl->opt->opt_nflen : 0);
 	}
 	return 0;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c77db0b..7d92fd9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -490,7 +490,7 @@
 	   We don't send redirects to frames decapsulated from IPsec.
 	 */
 	if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
-	    !skb->sp) {
+	    !skb_sec_path(skb)) {
 		struct in6_addr *target = NULL;
 		struct rt6_info *rt;
 		struct neighbour *n = dst->neighbour;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 52a7eb0..b17377d 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -297,9 +297,8 @@
 		const struct mfc6_cache *mfc = v;
 		const struct ipmr_mfc_iter *it = seq->private;
 
-		seq_printf(seq,
-			   NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld",
-			   NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin),
+		seq_printf(seq, "%pI6 %pI6 %-3d %8ld %8ld %8ld",
+			   &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
 			   mfc->mf6c_parent,
 			   mfc->mfc_un.res.pkt,
 			   mfc->mfc_un.res.bytes,
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 4545e43..d4576a9 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -67,8 +67,8 @@
 	if (!x)
 		return;
 
-	printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n",
-			spi, NIP6(iph->daddr));
+	printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI6\n",
+			spi, &iph->daddr);
 	xfrm_state_put(x);
 }
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index d7b3c6d..a76199e 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2430,9 +2430,9 @@
 	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
 	seq_printf(seq,
-		   "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n",
+		   "%-4d %-15s %pi6 %5d %08X %ld\n",
 		   state->dev->ifindex, state->dev->name,
-		   NIP6(im->mca_addr),
+		   &im->mca_addr,
 		   im->mca_users, im->mca_flags,
 		   (im->mca_flags&MAF_TIMER_RUNNING) ?
 		   jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0);
@@ -2591,10 +2591,10 @@
 			   "Source Address", "INC", "EXC");
 	} else {
 		seq_printf(seq,
-			   "%3d %6.6s " NIP6_SEQFMT " " NIP6_SEQFMT " %6lu %6lu\n",
+			   "%3d %6.6s %pi6 %pi6 %6lu %6lu\n",
 			   state->dev->ifindex, state->dev->name,
-			   NIP6(state->im->mca_addr),
-			   NIP6(psf->sf_addr),
+			   &state->im->mca_addr,
+			   &psf->sf_addr,
 			   psf->sf_count[MCAST_INCLUDE],
 			   psf->sf_count[MCAST_EXCLUDE]);
 	}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 1724383..fbf451c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -437,38 +437,20 @@
 	ipv6_dev_mc_dec(dev, &maddr);
 }
 
-/*
- *	Send a Neighbour Advertisement
- */
-static void __ndisc_send(struct net_device *dev,
-			 struct neighbour *neigh,
-			 const struct in6_addr *daddr,
-			 const struct in6_addr *saddr,
-			 struct icmp6hdr *icmp6h, const struct in6_addr *target,
-			 int llinfo)
+struct sk_buff *ndisc_build_skb(struct net_device *dev,
+				const struct in6_addr *daddr,
+				const struct in6_addr *saddr,
+				struct icmp6hdr *icmp6h,
+				const struct in6_addr *target,
+				int llinfo)
 {
-	struct flowi fl;
-	struct dst_entry *dst;
 	struct net *net = dev_net(dev);
 	struct sock *sk = net->ipv6.ndisc_sk;
 	struct sk_buff *skb;
 	struct icmp6hdr *hdr;
-	struct inet6_dev *idev;
 	int len;
 	int err;
-	u8 *opt, type;
-
-	type = icmp6h->icmp6_type;
-
-	icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
-
-	dst = icmp6_dst_alloc(dev, neigh, daddr);
-	if (!dst)
-		return;
-
-	err = xfrm_lookup(&dst, &fl, NULL, 0);
-	if (err < 0)
-		return;
+	u8 *opt;
 
 	if (!dev->addr_len)
 		llinfo = 0;
@@ -485,8 +467,7 @@
 		ND_PRINTK0(KERN_ERR
 			   "ICMPv6 ND: %s() failed to allocate an skb.\n",
 			   __func__);
-		dst_release(dst);
-		return;
+		return NULL;
 	}
 
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -513,6 +494,42 @@
 					   csum_partial((__u8 *) hdr,
 							len, 0));
 
+	return skb;
+}
+
+EXPORT_SYMBOL(ndisc_build_skb);
+
+void ndisc_send_skb(struct sk_buff *skb,
+		    struct net_device *dev,
+		    struct neighbour *neigh,
+		    const struct in6_addr *daddr,
+		    const struct in6_addr *saddr,
+		    struct icmp6hdr *icmp6h)
+{
+	struct flowi fl;
+	struct dst_entry *dst;
+	struct net *net = dev_net(dev);
+	struct sock *sk = net->ipv6.ndisc_sk;
+	struct inet6_dev *idev;
+	int err;
+	u8 type;
+
+	type = icmp6h->icmp6_type;
+
+	icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
+
+	dst = icmp6_dst_alloc(dev, neigh, daddr);
+	if (!dst) {
+		kfree_skb(skb);
+		return;
+	}
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		kfree_skb(skb);
+		return;
+	}
+
 	skb->dst = dst;
 
 	idev = in6_dev_get(dst->dev);
@@ -529,6 +546,27 @@
 		in6_dev_put(idev);
 }
 
+EXPORT_SYMBOL(ndisc_send_skb);
+
+/*
+ *	Send a Neighbour Discover packet
+ */
+static void __ndisc_send(struct net_device *dev,
+			 struct neighbour *neigh,
+			 const struct in6_addr *daddr,
+			 const struct in6_addr *saddr,
+			 struct icmp6hdr *icmp6h, const struct in6_addr *target,
+			 int llinfo)
+{
+	struct sk_buff *skb;
+
+	skb = ndisc_build_skb(dev, daddr, saddr, icmp6h, target, llinfo);
+	if (!skb)
+		return;
+
+	ndisc_send_skb(skb, dev, neigh, daddr, saddr, icmp6h);
+}
+
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 			  const struct in6_addr *daddr,
 			  const struct in6_addr *solicited_addr,
@@ -647,11 +685,8 @@
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
 		if (!(neigh->nud_state & NUD_VALID)) {
-			ND_PRINTK1(KERN_DEBUG
-				   "%s(): trying to ucast probe in NUD_INVALID: "
-				   NIP6_FMT "\n",
-				   __func__,
-				   NIP6(*target));
+			ND_PRINTK1(KERN_DEBUG "%s(): trying to ucast probe in NUD_INVALID: %pI6\n",
+				   __func__, target);
 		}
 		ndisc_send_ns(dev, neigh, target, target, saddr);
 	} else if ((probes -= neigh->parms->app_probes) < 0) {
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index caa441d..7c668c6 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -61,7 +61,7 @@
 	}
 
 	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
-	printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr));
+	printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
 	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
@@ -424,9 +424,8 @@
 			if (skb->dev->type == ARPHRD_SIT) {
 				const struct iphdr *iph =
 					(struct iphdr *)skb_mac_header(skb);
-				printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
-				       NIPQUAD(iph->saddr),
-				       NIPQUAD(iph->daddr));
+				printk("TUNNEL=%pI4->%pI4 ",
+				       &iph->saddr, &iph->daddr);
 			}
 		} else
 			printk(" ");
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e91db16..727b953 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -56,9 +56,8 @@
 static int ipv6_print_tuple(struct seq_file *s,
 			    const struct nf_conntrack_tuple *tuple)
 {
-	return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ",
-			  NIP6(*((struct in6_addr *)tuple->src.u3.ip6)),
-			  NIP6(*((struct in6_addr *)tuple->dst.u3.ip6)));
+	return seq_printf(s, "src=%pI6 dst=%pI6 ",
+			  tuple->src.u3.ip6, tuple->dst.u3.ip6);
 }
 
 /*
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 0572617..bd52151 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -253,7 +253,7 @@
 		.data		= &nf_ct_icmpv6_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 9967ac7..ed4d79a 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -80,7 +80,7 @@
 		.data		= &nf_init_frags.timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_FRAG6_LOW_THRESH,
@@ -88,7 +88,7 @@
 		.data		= &nf_init_frags.low_thresh,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_FRAG6_HIGH_THRESH,
@@ -96,7 +96,7 @@
 		.data		= &nf_init_frags.high_thresh,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index af12de0..3c57511 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -642,7 +642,7 @@
 		.data		= &init_net.ipv6.frags.high_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV6_IP6FRAG_LOW_THRESH,
@@ -650,7 +650,7 @@
 		.data		= &init_net.ipv6.frags.low_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IPV6_IP6FRAG_TIME,
@@ -658,8 +658,8 @@
 		.data		= &init_net.ipv6.frags.timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies,
 	},
 	{ }
 };
@@ -671,8 +671,8 @@
 		.data		= &ip6_frags.secret_interval,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
-		.strategy	= &sysctl_jiffies
+		.proc_handler	= proc_dointvec_jiffies,
+		.strategy	= sysctl_jiffies
 	},
 	{ }
 };
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 89dc699..4d40dc2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2408,19 +2408,16 @@
 {
 	struct seq_file *m = p_arg;
 
-	seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_dst.addr),
-		   rt->rt6i_dst.plen);
+	seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
 
 #ifdef CONFIG_IPV6_SUBTREES
-	seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_src.addr),
-		   rt->rt6i_src.plen);
+	seq_printf(m, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
 #else
 	seq_puts(m, "00000000000000000000000000000000 00 ");
 #endif
 
 	if (rt->rt6i_nexthop) {
-		seq_printf(m, NIP6_SEQFMT,
-			   NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
+		seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key);
 	} else {
 		seq_puts(m, "00000000000000000000000000000000");
 	}
@@ -2502,7 +2499,7 @@
 		.data		=	&init_net.ipv6.sysctl.flush_delay,
 		.maxlen		=	sizeof(int),
 		.mode		=	0200,
-		.proc_handler	=	&ipv6_sysctl_rtcache_flush
+		.proc_handler	=	ipv6_sysctl_rtcache_flush
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_THRESH,
@@ -2510,7 +2507,7 @@
 		.data		=	&ip6_dst_ops_template.gc_thresh,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec,
+		.proc_handler	=	proc_dointvec,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MAX_SIZE,
@@ -2518,7 +2515,7 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_max_size,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec,
+		.proc_handler	=	proc_dointvec,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL,
@@ -2526,8 +2523,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_TIMEOUT,
@@ -2535,8 +2532,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_timeout,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_INTERVAL,
@@ -2544,8 +2541,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_ELASTICITY,
@@ -2553,8 +2550,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MTU_EXPIRES,
@@ -2562,8 +2559,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_mtu_expires,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MIN_ADVMSS,
@@ -2571,8 +2568,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_min_advmss,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_jiffies,
-		.strategy	=	&sysctl_jiffies,
+		.proc_handler	=	proc_dointvec_jiffies,
+		.strategy	=	sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
@@ -2580,8 +2577,8 @@
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	&proc_dointvec_ms_jiffies,
-		.strategy	=	&sysctl_ms_jiffies,
+		.proc_handler	=	proc_dointvec_ms_jiffies,
+		.strategy	=	sysctl_ms_jiffies,
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 587f8f6..9048fe7 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -35,7 +35,7 @@
 		.data		= &init_net.ipv6.sysctl.bindv6only,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ .ctl_name = 0 }
 };
@@ -47,7 +47,7 @@
 		.data		= &sysctl_mld_max_msf,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b6b356b..9842764 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -872,12 +872,10 @@
 
 	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
 		if (net_ratelimit()) {
-			printk(KERN_INFO "MD5 Hash %s for "
-			       "(" NIP6_FMT ", %u)->"
-			       "(" NIP6_FMT ", %u)\n",
+			printk(KERN_INFO "MD5 Hash %s for (%pI6, %u)->(%pI6, %u)\n",
 			       genhash ? "failed" : "mismatch",
-			       NIP6(ip6h->saddr), ntohs(th->source),
-			       NIP6(ip6h->daddr), ntohs(th->dest));
+			       &ip6h->saddr, ntohs(th->source),
+			       &ip6h->daddr, ntohs(th->dest));
 		}
 		return 1;
 	}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 8b48512..8dafa36 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -54,62 +54,89 @@
 	return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal);
 }
 
+static inline int compute_score(struct sock *sk, struct net *net,
+				unsigned short hnum,
+				struct in6_addr *saddr, __be16 sport,
+				struct in6_addr *daddr, __be16 dport,
+				int dif)
+{
+	int score = -1;
+
+	if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+			sk->sk_family == PF_INET6) {
+		struct ipv6_pinfo *np = inet6_sk(sk);
+		struct inet_sock *inet = inet_sk(sk);
+
+		score = 0;
+		if (inet->dport) {
+			if (inet->dport != sport)
+				return -1;
+			score++;
+		}
+		if (!ipv6_addr_any(&np->rcv_saddr)) {
+			if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
+				return -1;
+			score++;
+		}
+		if (!ipv6_addr_any(&np->daddr)) {
+			if (!ipv6_addr_equal(&np->daddr, saddr))
+				return -1;
+			score++;
+		}
+		if (sk->sk_bound_dev_if) {
+			if (sk->sk_bound_dev_if != dif)
+				return -1;
+			score++;
+		}
+	}
+	return score;
+}
+
 static struct sock *__udp6_lib_lookup(struct net *net,
 				      struct in6_addr *saddr, __be16 sport,
 				      struct in6_addr *daddr, __be16 dport,
-				      int dif, struct hlist_head udptable[])
+				      int dif, struct udp_table *udptable)
 {
-	struct sock *sk, *result = NULL;
-	struct hlist_node *node;
+	struct sock *sk, *result;
+	struct hlist_node *node, *next;
 	unsigned short hnum = ntohs(dport);
-	int badness = -1;
+	unsigned int hash = udp_hashfn(net, hnum);
+	struct udp_hslot *hslot = &udptable->hash[hash];
+	int score, badness;
 
-	read_lock(&udp_hash_lock);
-	sk_for_each(sk, node, &udptable[udp_hashfn(net, hnum)]) {
-		struct inet_sock *inet = inet_sk(sk);
-
-		if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
-				sk->sk_family == PF_INET6) {
-			struct ipv6_pinfo *np = inet6_sk(sk);
-			int score = 0;
-			if (inet->dport) {
-				if (inet->dport != sport)
-					continue;
-				score++;
-			}
-			if (!ipv6_addr_any(&np->rcv_saddr)) {
-				if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
-					continue;
-				score++;
-			}
-			if (!ipv6_addr_any(&np->daddr)) {
-				if (!ipv6_addr_equal(&np->daddr, saddr))
-					continue;
-				score++;
-			}
-			if (sk->sk_bound_dev_if) {
-				if (sk->sk_bound_dev_if != dif)
-					continue;
-				score++;
-			}
-			if (score == 4) {
-				result = sk;
-				break;
-			} else if (score > badness) {
-				result = sk;
-				badness = score;
-			}
+	rcu_read_lock();
+begin:
+	result = NULL;
+	badness = -1;
+	sk_for_each_rcu_safenext(sk, node, &hslot->head, next) {
+		/*
+		 * lockless reader, and SLAB_DESTROY_BY_RCU items:
+		 * We must check this item was not moved to another chain
+		 */
+		if (udp_hashfn(net, sk->sk_hash) != hash)
+			goto begin;
+		score = compute_score(sk, net, hnum, saddr, sport, daddr, dport, dif);
+		if (score > badness) {
+			result = sk;
+			badness = score;
 		}
 	}
-	if (result)
-		sock_hold(result);
-	read_unlock(&udp_hash_lock);
+	if (result) {
+		if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
+			result = NULL;
+		else if (unlikely(compute_score(result, net, hnum, saddr, sport,
+					daddr, dport, dif) < badness)) {
+			sock_put(result);
+			goto begin;
+		}
+	}
+	rcu_read_unlock();
 	return result;
 }
 
 static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
 					  __be16 sport, __be16 dport,
-					  struct hlist_head udptable[])
+					  struct udp_table *udptable)
 {
 	struct sock *sk;
 	struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -253,7 +280,7 @@
 
 void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		    int type, int code, int offset, __be32 info,
-		    struct hlist_head udptable[]                    )
+		    struct udp_table *udptable)
 {
 	struct ipv6_pinfo *np;
 	struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
@@ -289,7 +316,7 @@
 				 struct inet6_skb_parm *opt, int type,
 				 int code, int offset, __be32 info     )
 {
-	__udp6_lib_err(skb, opt, type, code, offset, info, udp_hash);
+	__udp6_lib_err(skb, opt, type, code, offset, info, &udp_table);
 }
 
 int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
@@ -388,14 +415,15 @@
  */
 static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
 		struct in6_addr *saddr, struct in6_addr *daddr,
-		struct hlist_head udptable[])
+		struct udp_table *udptable)
 {
 	struct sock *sk, *sk2;
 	const struct udphdr *uh = udp_hdr(skb);
+	struct udp_hslot *hslot = &udptable->hash[udp_hashfn(net, ntohs(uh->dest))];
 	int dif;
 
-	read_lock(&udp_hash_lock);
-	sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]);
+	spin_lock(&hslot->lock);
+	sk = sk_head(&hslot->head);
 	dif = inet6_iif(skb);
 	sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif);
 	if (!sk) {
@@ -423,7 +451,7 @@
 		sk_add_backlog(sk, skb);
 	bh_unlock_sock(sk);
 out:
-	read_unlock(&udp_hash_lock);
+	spin_unlock(&hslot->lock);
 	return 0;
 }
 
@@ -461,7 +489,7 @@
 	return 0;
 }
 
-int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
 		   int proto)
 {
 	struct sock *sk;
@@ -558,7 +586,7 @@
 
 static __inline__ int udpv6_rcv(struct sk_buff *skb)
 {
-	return __udp6_lib_rcv(skb, udp_hash, IPPROTO_UDP);
+	return __udp6_lib_rcv(skb, &udp_table, IPPROTO_UDP);
 }
 
 /*
@@ -1022,7 +1050,7 @@
 static struct udp_seq_afinfo udp6_seq_afinfo = {
 	.name		= "udp6",
 	.family		= AF_INET6,
-	.hashtable	= udp_hash,
+	.udp_table	= &udp_table,
 	.seq_fops	= {
 		.owner	=	THIS_MODULE,
 	},
@@ -1064,7 +1092,8 @@
 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
 	.obj_size	   = sizeof(struct udp6_sock),
-	.h.udp_hash	   = udp_hash,
+	.slab_flags	   = SLAB_DESTROY_BY_RCU,
+	.h.udp_table	   = &udp_table,
 #ifdef CONFIG_COMPAT
 	.compat_setsockopt = compat_udpv6_setsockopt,
 	.compat_getsockopt = compat_udpv6_getsockopt,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 92dd7da..2377920 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -7,9 +7,9 @@
 #include <net/inet_common.h>
 #include <net/transp_v6.h>
 
-extern int  	__udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+extern int  	__udp6_lib_rcv(struct sk_buff *, struct udp_table *, int );
 extern void 	__udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
-			       int , int , int , __be32 , struct hlist_head []);
+			       int , int , int , __be32 , struct udp_table *);
 
 extern int	udp_v6_get_port(struct sock *sk, unsigned short snum);
 
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index 3cd1a1a..ba162a8 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -15,14 +15,14 @@
 
 static int udplitev6_rcv(struct sk_buff *skb)
 {
-	return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
+	return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
 }
 
 static void udplitev6_err(struct sk_buff *skb,
 			  struct inet6_skb_parm *opt,
 			  int type, int code, int offset, __be32 info)
 {
-	__udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash);
+	__udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table);
 }
 
 static struct inet6_protocol udplitev6_protocol = {
@@ -49,7 +49,8 @@
 	.unhash		   = udp_lib_unhash,
 	.get_port	   = udp_v6_get_port,
 	.obj_size	   = sizeof(struct udp6_sock),
-	.h.udp_hash	   = udplite_hash,
+	.slab_flags	   = SLAB_DESTROY_BY_RCU,
+	.h.udp_table	   = &udplite_table,
 #ifdef CONFIG_COMPAT
 	.compat_setsockopt = compat_udpv6_setsockopt,
 	.compat_getsockopt = compat_udpv6_getsockopt,
@@ -95,7 +96,7 @@
 static struct udp_seq_afinfo udplite6_seq_afinfo = {
 	.name		= "udplite6",
 	.family		= AF_INET6,
-	.hashtable	= udplite_hash,
+	.udp_table	= &udplite_table,
 	.seq_fops	= {
 		.owner	=	THIS_MODULE,
 	},
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 08e4cbb..604bc0a 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -144,6 +144,7 @@
 static inline void
 _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 {
+	int onlyproto = 0;
 	u16 offset = skb_network_header_len(skb);
 	struct ipv6hdr *hdr = ipv6_hdr(skb);
 	struct ipv6_opt_hdr *exthdr;
@@ -159,6 +160,8 @@
 		exthdr = (struct ipv6_opt_hdr *)(nh + offset);
 
 		switch (nexthdr) {
+		case NEXTHDR_FRAGMENT:
+			onlyproto = 1;
 		case NEXTHDR_ROUTING:
 		case NEXTHDR_HOP:
 		case NEXTHDR_DEST:
@@ -172,7 +175,7 @@
 		case IPPROTO_TCP:
 		case IPPROTO_SCTP:
 		case IPPROTO_DCCP:
-			if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
+			if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
 				__be16 *ports = (__be16 *)exthdr;
 
 				fl->fl_ip_sport = ports[!!reverse];
@@ -182,7 +185,7 @@
 			return;
 
 		case IPPROTO_ICMPV6:
-			if (pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
+			if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
 				u8 *icmp = (u8 *)exthdr;
 
 				fl->fl_icmp_type = icmp[0];
@@ -193,7 +196,7 @@
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPPROTO_MH:
-			if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
+			if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
 				struct ip6_mh *mh;
 				mh = (struct ip6_mh *)exthdr;
 
diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c
index 92fef86..633fcab 100644
--- a/net/ipx/sysctl_net_ipx.c
+++ b/net/ipx/sysctl_net_ipx.c
@@ -23,7 +23,7 @@
 		.data		= &sysctl_ipx_pprop_broadcasting,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{ 0 },
 };
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 6be1ec2..42f7d96 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -436,7 +436,6 @@
 	__u16 tmp_cpu; /* Temporary value in host order */
 	__u8 *bytes;
 	int i;
-	DECLARE_MAC_BUF(mac);
 
 	IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
 
@@ -521,8 +520,7 @@
 	/* FILTER_ENTRY, have we got an ethernet address? */
 	if (strcmp(param, "FILTER_ENTRY") == 0) {
 		bytes = value;
-		IRDA_DEBUG(4, "Ethernet address = %s\n",
-			   print_mac(mac, bytes));
+		IRDA_DEBUG(4, "Ethernet address = %pM\n", bytes);
 		for (i = 0; i < 6; i++)
 			self->dev->dev_addr[i] = bytes[i];
 	}
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 9ab3df1..57f8817 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -118,8 +118,8 @@
 		.data		= &sysctl_discovery,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &do_discovery,
-		.strategy       = &sysctl_intvec
+		.proc_handler	= do_discovery,
+		.strategy       = sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_IRDA_DEVNAME,
@@ -127,8 +127,8 @@
 		.data		= sysctl_devname,
 		.maxlen		= 65,
 		.mode		= 0644,
-		.proc_handler	= &do_devname,
-		.strategy	= &sysctl_string
+		.proc_handler	= do_devname,
+		.strategy	= sysctl_string
 	},
 #ifdef CONFIG_IRDA_DEBUG
 	{
@@ -137,7 +137,7 @@
 		.data		= &irda_debug,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #endif
 #ifdef CONFIG_IRDA_FAST_RR
@@ -147,7 +147,7 @@
 		.data		= &sysctl_fast_poll_increase,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 #endif
 	{
@@ -156,8 +156,8 @@
 		.data		= &sysctl_discovery_slots,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_discovery_slots,
 		.extra2		= &max_discovery_slots
 	},
@@ -167,7 +167,7 @@
 		.data		= &sysctl_discovery_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{
 		.ctl_name	= NET_IRDA_SLOT_TIMEOUT,
@@ -175,8 +175,8 @@
 		.data		= &sysctl_slot_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_slot_timeout,
 		.extra2		= &max_slot_timeout
 	},
@@ -186,8 +186,8 @@
 		.data		= &sysctl_max_baud_rate,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_max_baud_rate,
 		.extra2		= &max_max_baud_rate
 	},
@@ -197,8 +197,8 @@
 		.data		= &sysctl_min_tx_turn_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_min_tx_turn_time,
 		.extra2		= &max_min_tx_turn_time
 	},
@@ -208,8 +208,8 @@
 		.data		= &sysctl_max_tx_data_size,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_max_tx_data_size,
 		.extra2		= &max_max_tx_data_size
 	},
@@ -219,8 +219,8 @@
 		.data		= &sysctl_max_tx_window,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_max_tx_window,
 		.extra2		= &max_max_tx_window
 	},
@@ -230,8 +230,8 @@
 		.data		= &sysctl_max_noreply_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_max_noreply_time,
 		.extra2		= &max_max_noreply_time
 	},
@@ -241,8 +241,8 @@
 		.data		= &sysctl_warn_noreply_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_warn_noreply_time,
 		.extra2		= &max_warn_noreply_time
 	},
@@ -252,8 +252,8 @@
 		.data		= &sysctl_lap_keepalive_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_lap_keepalive_time,
 		.extra2		= &max_lap_keepalive_time
 	},
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 48212c0..b58bd7c 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -27,8 +27,7 @@
 
 static void llc_ui_format_mac(struct seq_file *seq, u8 *addr)
 {
-	DECLARE_MAC_BUF(mac);
-	seq_printf(seq, "%s", print_mac(mac, addr));
+	seq_printf(seq, "%pM", addr);
 }
 
 static struct sock *llc_get_sk_idx(loff_t pos)
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c
index 5bef1dc..57b9304 100644
--- a/net/llc/sysctl_net_llc.c
+++ b/net/llc/sysctl_net_llc.c
@@ -20,8 +20,8 @@
 		.data		= &sysctl_llc2_ack_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler   = &proc_dointvec_jiffies,
-		.strategy       = &sysctl_jiffies,
+		.proc_handler   = proc_dointvec_jiffies,
+		.strategy       = sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_LLC2_BUSY_TIMEOUT,
@@ -29,8 +29,8 @@
 		.data		= &sysctl_llc2_busy_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler   = &proc_dointvec_jiffies,
-		.strategy       = &sysctl_jiffies,
+		.proc_handler   = proc_dointvec_jiffies,
+		.strategy       = sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_LLC2_P_TIMEOUT,
@@ -38,8 +38,8 @@
 		.data		= &sysctl_llc2_p_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler   = &proc_dointvec_jiffies,
-		.strategy       = &sysctl_jiffies,
+		.proc_handler   = proc_dointvec_jiffies,
+		.strategy       = sysctl_jiffies,
 	},
 	{
 		.ctl_name	= NET_LLC2_REJ_TIMEOUT,
@@ -47,8 +47,8 @@
 		.data		= &sysctl_llc2_rej_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler   = &proc_dointvec_jiffies,
-		.strategy       = &sysctl_jiffies,
+		.proc_handler   = proc_dointvec_jiffies,
+		.strategy       = sysctl_jiffies,
 	},
 	{ 0 },
 };
@@ -60,8 +60,8 @@
 		.data		= &sysctl_llc_station_ack_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler   = &proc_dointvec_jiffies,
-		.strategy       = &sysctl_jiffies,
+		.proc_handler   = proc_dointvec_jiffies,
+		.strategy       = sysctl_jiffies,
 	},
 	{ 0 },
 };
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 855126a..16423f9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,13 +17,6 @@
 #include "rate.h"
 #include "mesh.h"
 
-struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
-{
-	struct ieee80211_local *local = wiphy_priv(wiphy);
-	return &local->hw;
-}
-EXPORT_SYMBOL(wiphy_to_hw);
-
 static bool nl80211_type_check(enum nl80211_iftype type)
 {
 	switch (type) {
@@ -33,6 +26,8 @@
 #ifdef CONFIG_MAC80211_MESH
 	case NL80211_IFTYPE_MESH_POINT:
 #endif
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_WDS:
 		return true;
 	default:
@@ -401,8 +396,8 @@
 	 */
 	if (params->interval) {
 		sdata->local->hw.conf.beacon_int = params->interval;
-		if (ieee80211_hw_config(sdata->local))
-			return -EINVAL;
+		ieee80211_hw_config(sdata->local,
+				    IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
 		/*
 		 * We updated some parameter so if below bails out
 		 * it's not an error.
@@ -589,6 +584,8 @@
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
+	sband = local->hw.wiphy->bands[local->oper_channel->band];
+
 	/*
 	 * FIXME: updating the flags is racy when this function is
 	 *	  called from ieee80211_change_station(), this will
@@ -629,7 +626,6 @@
 
 	if (params->supported_rates) {
 		rates = 0;
-		sband = local->hw.wiphy->bands[local->oper_channel->band];
 
 		for (i = 0; i < params->supported_rates_len; i++) {
 			int rate = (params->supported_rates[i] & 0x7f) * 5;
@@ -641,10 +637,10 @@
 		sta->sta.supp_rates[local->oper_channel->band] = rates;
 	}
 
-	if (params->ht_capa) {
-		ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
-					       &sta->sta.ht_info);
-	}
+	if (params->ht_capa)
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+						  params->ht_capa,
+						  &sta->sta.ht_cap);
 
 	if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
 		switch (params->plink_action) {
@@ -957,6 +953,72 @@
 	rcu_read_unlock();
 	return 0;
 }
+
+static int ieee80211_get_mesh_params(struct wiphy *wiphy,
+				struct net_device *dev,
+				struct mesh_config *conf)
+{
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+		return -ENOTSUPP;
+	memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config));
+	return 0;
+}
+
+static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
+{
+	return (mask >> (parm-1)) & 0x1;
+}
+
+static int ieee80211_set_mesh_params(struct wiphy *wiphy,
+				struct net_device *dev,
+				const struct mesh_config *nconf, u32 mask)
+{
+	struct mesh_config *conf;
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+		return -ENOTSUPP;
+
+	/* Set the config options which we are interested in setting */
+	conf = &(sdata->u.mesh.mshcfg);
+	if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask))
+		conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask))
+		conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask))
+		conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask))
+		conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks;
+	if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask))
+		conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
+	if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
+		conf->dot11MeshTTL = nconf->dot11MeshTTL;
+	if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
+		conf->auto_open_plinks = nconf->auto_open_plinks;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
+		conf->dot11MeshHWMPmaxPREQretries =
+			nconf->dot11MeshHWMPmaxPREQretries;
+	if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
+		conf->path_refresh_time = nconf->path_refresh_time;
+	if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
+		conf->min_discovery_timeout = nconf->min_discovery_timeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
+		conf->dot11MeshHWMPactivePathTimeout =
+			nconf->dot11MeshHWMPactivePathTimeout;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
+		conf->dot11MeshHWMPpreqMinInterval =
+			nconf->dot11MeshHWMPpreqMinInterval;
+	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+			   mask))
+		conf->dot11MeshHWMPnetDiameterTraversalTime =
+			nconf->dot11MeshHWMPnetDiameterTraversalTime;
+	return 0;
+}
+
 #endif
 
 static int ieee80211_change_bss(struct wiphy *wiphy,
@@ -972,25 +1034,67 @@
 		return -EINVAL;
 
 	if (params->use_cts_prot >= 0) {
-		sdata->bss_conf.use_cts_prot = params->use_cts_prot;
+		sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
 		changed |= BSS_CHANGED_ERP_CTS_PROT;
 	}
 	if (params->use_short_preamble >= 0) {
-		sdata->bss_conf.use_short_preamble =
+		sdata->vif.bss_conf.use_short_preamble =
 			params->use_short_preamble;
 		changed |= BSS_CHANGED_ERP_PREAMBLE;
 	}
 	if (params->use_short_slot_time >= 0) {
-		sdata->bss_conf.use_short_slot =
+		sdata->vif.bss_conf.use_short_slot =
 			params->use_short_slot_time;
 		changed |= BSS_CHANGED_ERP_SLOT;
 	}
 
+	if (params->basic_rates) {
+		int i, j;
+		u32 rates = 0;
+		struct ieee80211_local *local = wiphy_priv(wiphy);
+		struct ieee80211_supported_band *sband =
+			wiphy->bands[local->oper_channel->band];
+
+		for (i = 0; i < params->basic_rates_len; i++) {
+			int rate = (params->basic_rates[i] & 0x7f) * 5;
+			for (j = 0; j < sband->n_bitrates; j++) {
+				if (sband->bitrates[j].bitrate == rate)
+					rates |= BIT(j);
+			}
+		}
+		sdata->vif.bss_conf.basic_rates = rates;
+		changed |= BSS_CHANGED_BASIC_RATES;
+	}
+
 	ieee80211_bss_info_change_notify(sdata, changed);
 
 	return 0;
 }
 
+static int ieee80211_set_txq_params(struct wiphy *wiphy,
+				    struct ieee80211_txq_params *params)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_tx_queue_params p;
+
+	if (!local->ops->conf_tx)
+		return -EOPNOTSUPP;
+
+	memset(&p, 0, sizeof(p));
+	p.aifs = params->aifs;
+	p.cw_max = params->cwmax;
+	p.cw_min = params->cwmin;
+	p.txop = params->txop;
+	if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) {
+		printk(KERN_DEBUG "%s: failed to set TX queue "
+		       "parameters for queue %d\n", local->mdev->name,
+		       params->queue);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1013,6 +1117,9 @@
 	.change_mpath = ieee80211_change_mpath,
 	.get_mpath = ieee80211_get_mpath,
 	.dump_mpath = ieee80211_dump_mpath,
+	.set_mesh_params = ieee80211_set_mesh_params,
+	.get_mesh_params = ieee80211_get_mesh_params,
 #endif
 	.change_bss = ieee80211_change_bss,
+	.set_txq_params = ieee80211_set_txq_params,
 };
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 24ce544..2697a2f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -47,18 +47,14 @@
 
 DEBUGFS_READONLY_FILE(frequency, 20, "%d",
 		      local->hw.conf.channel->center_freq);
-DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
-		      local->hw.conf.antenna_sel_tx);
-DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
-		      local->hw.conf.antenna_sel_rx);
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
 		      local->rts_threshold);
 DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
 		      local->fragmentation_threshold);
 DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
-		      local->short_retry_limit);
+		      local->hw.conf.short_frame_max_tx_count);
 DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
-		      local->long_retry_limit);
+		      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",
@@ -202,8 +198,6 @@
 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
 
 	DEBUGFS_ADD(frequency);
-	DEBUGFS_ADD(antenna_sel_tx);
-	DEBUGFS_ADD(antenna_sel_rx);
 	DEBUGFS_ADD(rts_threshold);
 	DEBUGFS_ADD(fragmentation_threshold);
 	DEBUGFS_ADD(short_retry_limit);
@@ -258,8 +252,6 @@
 void debugfs_hw_del(struct ieee80211_local *local)
 {
 	DEBUGFS_DEL(frequency);
-	DEBUGFS_DEL(antenna_sel_tx);
-	DEBUGFS_DEL(antenna_sel_rx);
 	DEBUGFS_DEL(rts_threshold);
 	DEBUGFS_DEL(fragmentation_threshold);
 	DEBUGFS_DEL(short_retry_limit);
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index a3294d1..6424ac5 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -188,7 +188,6 @@
   {
 	static int keycount;
 	char buf[50];
-	DECLARE_MAC_BUF(mac);
 	struct sta_info *sta;
 
 	if (!key->local->debugfs.keys)
@@ -206,8 +205,7 @@
 	rcu_read_lock();
 	sta = rcu_dereference(key->sta);
 	if (sta)
-		sprintf(buf, "../../stations/%s",
-			print_mac(mac, sta->sta.addr));
+		sprintf(buf, "../../stations/%pM", sta->sta.addr);
 	rcu_read_unlock();
 
 	/* using sta as a boolean is fine outside RCU lock */
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 2ad504f..c542193 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -41,29 +41,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_MAC80211_MESH
-static ssize_t ieee80211_if_write(
-	struct ieee80211_sub_if_data *sdata,
-	char const __user *userbuf,
-	size_t count, loff_t *ppos,
-	int (*format)(struct ieee80211_sub_if_data *, char *))
-{
-	char buf[10];
-	int buf_size;
-
-	memset(buf, 0x00, sizeof(buf));
-	buf_size = min(count, (sizeof(buf)-1));
-	if (copy_from_user(buf, userbuf, buf_size))
-		return count;
-	read_lock(&dev_base_lock);
-	if (sdata->dev->reg_state == NETREG_REGISTERED)
-		(*format)(sdata, buf);
-	read_unlock(&dev_base_lock);
-
-	return count;
-}
-#endif
-
 #define IEEE80211_IF_FMT(name, field, format_string)			\
 static ssize_t ieee80211_if_fmt_##name(					\
 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
@@ -71,19 +48,6 @@
 {									\
 	return scnprintf(buf, buflen, format_string, sdata->field);	\
 }
-#define IEEE80211_IF_WFMT(name, field, type)				\
-static int ieee80211_if_wfmt_##name(					\
-	struct ieee80211_sub_if_data *sdata, char *buf)			\
-{									\
-	unsigned long tmp;						\
-	char *endp;							\
-									\
-	tmp = simple_strtoul(buf, &endp, 0);				\
-	if ((endp == buf) || ((type)tmp != tmp))			\
-		return -EINVAL;						\
-	sdata->field = tmp;						\
-	return 0;							\
-}
 #define IEEE80211_IF_FMT_DEC(name, field)				\
 		IEEE80211_IF_FMT(name, field, "%d\n")
 #define IEEE80211_IF_FMT_HEX(name, field)				\
@@ -104,8 +68,7 @@
 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
 	int buflen)							\
 {									\
-	DECLARE_MAC_BUF(mac);						\
-	return scnprintf(buf, buflen, "%s\n", print_mac(mac, sdata->field));\
+	return scnprintf(buf, buflen, "%pM\n", sdata->field);		\
 }
 
 #define __IEEE80211_IF_FILE(name)					\
@@ -126,34 +89,6 @@
 		IEEE80211_IF_FMT_##format(name, field)			\
 		__IEEE80211_IF_FILE(name)
 
-#define __IEEE80211_IF_WFILE(name)					\
-static ssize_t ieee80211_if_read_##name(struct file *file,		\
-					char __user *userbuf,		\
-					size_t count, loff_t *ppos)	\
-{									\
-	return ieee80211_if_read(file->private_data,			\
-				 userbuf, count, ppos,			\
-				 ieee80211_if_fmt_##name);		\
-}									\
-static ssize_t ieee80211_if_write_##name(struct file *file,		\
-					const char __user *userbuf,	\
-					size_t count, loff_t *ppos)	\
-{									\
-	return ieee80211_if_write(file->private_data,			\
-				 userbuf, count, ppos,			\
-				 ieee80211_if_wfmt_##name);		\
-}									\
-static const struct file_operations name##_ops = {			\
-	.read = ieee80211_if_read_##name,				\
-	.write = ieee80211_if_write_##name,				\
-	.open = mac80211_open_file_generic,				\
-}
-
-#define IEEE80211_IF_WFILE(name, field, format, type)			\
-		IEEE80211_IF_FMT_##format(name, field)			\
-		IEEE80211_IF_WFMT(name, field, type)			\
-		__IEEE80211_IF_WFILE(name)
-
 /* common attributes */
 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
 IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
@@ -184,7 +119,7 @@
 		 sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
 		 sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
 		 sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
-		 sdata->bss_conf.use_cts_prot ? "CTS prot\n" : "");
+		 sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : "");
 }
 __IEEE80211_IF_FILE(flags);
 
@@ -212,30 +147,30 @@
 IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
 
 /* Mesh parameters */
-IEEE80211_IF_WFILE(dot11MeshMaxRetries,
-		u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8);
-IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
-		u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
-		u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
-		u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8);
-IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8);
-IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
-		u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
-		u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
-IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
-		u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
-		u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
-IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
-		u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
-IEEE80211_IF_WFILE(path_refresh_time,
-		u.mesh.mshcfg.path_refresh_time, DEC, u32);
-IEEE80211_IF_WFILE(min_discovery_timeout,
-		u.mesh.mshcfg.min_discovery_timeout, DEC, u16);
+IEEE80211_IF_FILE(dot11MeshMaxRetries,
+		u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
+IEEE80211_IF_FILE(dot11MeshRetryTimeout,
+		u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
+		u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
+		u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
+IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
+IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
+		u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
+		u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
+		u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
+		u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
+		u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
+IEEE80211_IF_FILE(path_refresh_time,
+		u.mesh.mshcfg.path_refresh_time, DEC);
+IEEE80211_IF_FILE(min_discovery_timeout,
+		u.mesh.mshcfg.min_discovery_timeout, DEC);
 #endif
 
 
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index b85c4f2..a2fbe01 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -39,13 +39,6 @@
 	.open = mac80211_open_file_generic,				\
 }
 
-#define STA_OPS_WR(name)						\
-static const struct file_operations sta_ ##name## _ops = {		\
-	.read = sta_##name##_read,					\
-	.write = sta_##name##_write,					\
-	.open = mac80211_open_file_generic,				\
-}
-
 #define STA_FILE(name, field, format)					\
 		STA_READ_##format(name, field)				\
 		STA_OPS(name)
@@ -144,7 +137,7 @@
 	p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
 	for (i = 0; i < STA_TID_NUM; i++)
 		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-			sta->ampdu_mlme.tid_state_rx[i]?
+			sta->ampdu_mlme.tid_state_rx[i] ?
 			sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
 
 	p += scnprintf(p, sizeof(buf)+buf-p, "\n TX  :");
@@ -155,84 +148,20 @@
 	p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
 	for (i = 0; i < STA_TID_NUM; i++)
 		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-			sta->ampdu_mlme.tid_state_tx[i]?
+			sta->ampdu_mlme.tid_state_tx[i] ?
 			sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
 
 	p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
 	for (i = 0; i < STA_TID_NUM; i++)
 		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-			sta->ampdu_mlme.tid_state_tx[i]?
+			sta->ampdu_mlme.tid_state_tx[i] ?
 			sta->ampdu_mlme.tid_tx[i]->ssn : 0);
 
 	p += scnprintf(p, sizeof(buf)+buf-p, "\n");
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 }
-
-static ssize_t sta_agg_status_write(struct file *file,
-		const char __user *user_buf, size_t count, loff_t *ppos)
-{
-	struct sta_info *sta = file->private_data;
-	struct ieee80211_local *local = sta->sdata->local;
-	struct ieee80211_hw *hw = &local->hw;
-	u8 *da = sta->sta.addr;
-	static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0, 0, 0, 0, 0, 0, 0};
-	static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
-					1, 1, 1, 1, 1, 1, 1, 1};
-	char *endp;
-	char buf[32];
-	int buf_size, rs;
-	unsigned int tid_num;
-	char state[4];
-
-	memset(buf, 0x00, sizeof(buf));
-	buf_size = min(count, (sizeof(buf)-1));
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-
-	tid_num = simple_strtoul(buf, &endp, 0);
-	if (endp == buf)
-		return -EINVAL;
-
-	if ((tid_num >= 100) && (tid_num <= 115)) {
-		/* toggle Rx aggregation command */
-		tid_num = tid_num - 100;
-		if (tid_static_rx[tid_num] == 1) {
-			strcpy(state, "off");
-			ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0,
-					WLAN_REASON_QSTA_REQUIRE_SETUP);
-			sta->ampdu_mlme.tid_state_rx[tid_num] |=
-					HT_AGG_STATE_DEBUGFS_CTL;
-			tid_static_rx[tid_num] = 0;
-		} else {
-			strcpy(state, "on ");
-			sta->ampdu_mlme.tid_state_rx[tid_num] &=
-					~HT_AGG_STATE_DEBUGFS_CTL;
-			tid_static_rx[tid_num] = 1;
-		}
-		printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
-				tid_num, state);
-	} else if ((tid_num >= 0) && (tid_num <= 15)) {
-		/* toggle Tx aggregation command */
-		if (tid_static_tx[tid_num] == 0) {
-			strcpy(state, "on ");
-			rs =  ieee80211_start_tx_ba_session(hw, da, tid_num);
-			if (rs == 0)
-				tid_static_tx[tid_num] = 1;
-		} else {
-			strcpy(state, "off");
-			rs =  ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
-			if (rs == 0)
-				tid_static_tx[tid_num] = 0;
-		}
-		printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
-				tid_num, state, rs);
-	}
-
-	return count;
-}
-STA_OPS_WR(agg_status);
+STA_OPS(agg_status);
 
 #define DEBUGFS_ADD(name) \
 	sta->debugfs.name = debugfs_create_file(#name, 0400, \
@@ -246,15 +175,14 @@
 void ieee80211_sta_debugfs_add(struct sta_info *sta)
 {
 	struct dentry *stations_dir = sta->local->debugfs.stations;
-	DECLARE_MAC_BUF(mbuf);
-	u8 *mac;
+	u8 mac[3*ETH_ALEN];
 
 	sta->debugfs.add_has_run = true;
 
 	if (!stations_dir)
 		return;
 
-	mac = print_mac(mbuf, sta->sta.addr);
+	snprintf(mac, sizeof(mac), "%pM", sta->sta.addr);
 
 	/*
 	 * This might fail due to a race condition:
diff --git a/net/mac80211/event.c b/net/mac80211/event.c
index 8de60de..0d95561 100644
--- a/net/mac80211/event.c
+++ b/net/mac80211/event.c
@@ -21,14 +21,13 @@
 {
 	union iwreq_data wrqu;
 	char *buf = kmalloc(128, GFP_ATOMIC);
-	DECLARE_MAC_BUF(mac);
 
 	if (buf) {
 		/* TODO: needed parameters: count, key type, TSC */
 		sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
-			"keyid=%d %scast addr=%s)",
+			"keyid=%d %scast addr=%pM)",
 			keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-			print_mac(mac, hdr->addr2));
+			hdr->addr2);
 		memset(&wrqu, 0, sizeof(wrqu));
 		wrqu.data.length = strlen(buf);
 		wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index dc7d9a3..3e231d75 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -20,50 +20,125 @@
 #include "sta_info.h"
 #include "wme.h"
 
-int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
-				   struct ieee80211_ht_info *ht_info)
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+				       struct ieee80211_ht_cap *ht_cap_ie,
+				       struct ieee80211_sta_ht_cap *ht_cap)
 {
+	u8 ampdu_info, tx_mcs_set_cap;
+	int i, max_tx_streams;
 
-	if (ht_info == NULL)
-		return -EINVAL;
+	BUG_ON(!ht_cap);
 
-	memset(ht_info, 0, sizeof(*ht_info));
+	memset(ht_cap, 0, sizeof(*ht_cap));
 
-	if (ht_cap_ie) {
-		u8 ampdu_info = ht_cap_ie->ampdu_params_info;
+	if (!ht_cap_ie)
+		return;
 
-		ht_info->ht_supported = 1;
-		ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
-		ht_info->ampdu_factor =
-			ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
-		ht_info->ampdu_density =
-			(ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
-		memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
-	} else
-		ht_info->ht_supported = 0;
+	ht_cap->ht_supported = true;
 
-	return 0;
+	ht_cap->cap = ht_cap->cap & sband->ht_cap.cap;
+	ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS;
+	ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
+
+	ampdu_info = ht_cap_ie->ampdu_params_info;
+	ht_cap->ampdu_factor =
+		ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
+	ht_cap->ampdu_density =
+		(ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
+
+	/* own MCS TX capabilities */
+	tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
+
+	/* can we TX with MCS rates? */
+	if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
+		return;
+
+	/* Counting from 0, therefore +1 */
+	if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF)
+		max_tx_streams =
+			((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+				>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
+	else
+		max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS;
+
+	/*
+	 * 802.11n D5.0 20.3.5 / 20.6 says:
+	 * - indices 0 to 7 and 32 are single spatial stream
+	 * - 8 to 31 are multiple spatial streams using equal modulation
+	 *   [8..15 for two streams, 16..23 for three and 24..31 for four]
+	 * - remainder are multiple spatial streams using unequal modulation
+	 */
+	for (i = 0; i < max_tx_streams; i++)
+		ht_cap->mcs.rx_mask[i] =
+			sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
+
+	if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
+		for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
+		     i < IEEE80211_HT_MCS_MASK_LEN; i++)
+			ht_cap->mcs.rx_mask[i] =
+				sband->ht_cap.mcs.rx_mask[i] &
+					ht_cap_ie->mcs.rx_mask[i];
+
+	/* handle MCS rate 32 too */
+	if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
+		ht_cap->mcs.rx_mask[32/8] |= 1;
 }
 
-int ieee80211_ht_addt_info_ie_to_ht_bss_info(
-			struct ieee80211_ht_addt_info *ht_add_info_ie,
-			struct ieee80211_ht_bss_info *bss_info)
+/*
+ * ieee80211_enable_ht should be called only after the operating band
+ * has been determined as ht configuration depends on the hw's
+ * HT abilities for a specific band.
+ */
+u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
+			struct ieee80211_ht_info *hti,
+			u16 ap_ht_cap_flags)
 {
-	if (bss_info == NULL)
-		return -EINVAL;
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_bss_ht_conf ht;
+	u32 changed = 0;
+	bool enable_ht = true, ht_changed;
 
-	memset(bss_info, 0, sizeof(*bss_info));
+	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
-	if (ht_add_info_ie) {
-		u16 op_mode;
-		op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
+	memset(&ht, 0, sizeof(ht));
 
-		bss_info->primary_channel = ht_add_info_ie->control_chan;
-		bss_info->bss_cap = ht_add_info_ie->ht_param;
-		bss_info->bss_op_mode = (u8)(op_mode & 0xff);
+	/* HT is not supported */
+	if (!sband->ht_cap.ht_supported)
+		enable_ht = false;
+
+	/* check that channel matches the right operating channel */
+	if (local->hw.conf.channel->center_freq !=
+	    ieee80211_channel_to_frequency(hti->control_chan))
+		enable_ht = false;
+
+	/*
+	 * XXX: This is totally incorrect when there are multiple virtual
+	 *	interfaces, needs to be fixed later.
+	 */
+	ht_changed = local->hw.conf.ht.enabled != enable_ht;
+	local->hw.conf.ht.enabled = enable_ht;
+	if (ht_changed)
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
+
+	/* disable HT */
+	if (!enable_ht)
+		return 0;
+	ht.secondary_channel_offset =
+		hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
+	ht.width_40_ok =
+		!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
+		(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
+		(hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
+	ht.operation_mode = le16_to_cpu(hti->operation_mode);
+
+	/* if bss configuration changed store the new one */
+	if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
+		changed |= BSS_CHANGED_HT;
+		sdata->vif.bss_conf.ht = ht;
 	}
 
-	return 0;
+	return changed;
 }
 
 static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -241,7 +316,6 @@
 	struct ieee80211_hw *hw = &local->hw;
 	struct sta_info *sta;
 	int ret, i;
-	DECLARE_MAC_BUF(mac);
 
 	rcu_read_lock();
 
@@ -269,8 +343,8 @@
 	BUG_ON(!local->ops->ampdu_action);
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
-	printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
-				print_mac(mac, ra), tid);
+	printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
+	       ra, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
@@ -383,14 +457,13 @@
 	u16 start_seq_num;
 	u8 *state;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
-	if (tid >= STA_TID_NUM)
+	if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
 		return -EINVAL;
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
-	printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
-				print_mac(mac, ra), tid);
+	printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
+	       ra, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	rcu_read_lock();
@@ -442,17 +515,19 @@
 			(unsigned long)&sta->timer_to_tid[tid];
 	init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 
-	/* create a new queue for this aggregation */
-	ret = ieee80211_ht_agg_queue_add(local, sta, tid);
+	if (hw->ampdu_queues) {
+		/* create a new queue for this aggregation */
+		ret = ieee80211_ht_agg_queue_add(local, sta, tid);
 
-	/* case no queue is available to aggregation
-	 * don't switch to aggregation */
-	if (ret) {
+		/* case no queue is available to aggregation
+		 * don't switch to aggregation */
+		if (ret) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
-		printk(KERN_DEBUG "BA request denied - queue unavailable for"
-					" tid %d\n", tid);
+			printk(KERN_DEBUG "BA request denied - "
+			       "queue unavailable for tid %d\n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
-		goto err_unlock_queue;
+			goto err_unlock_queue;
+		}
 	}
 	sdata = sta->sdata;
 
@@ -471,7 +546,8 @@
 		/* No need to requeue the packets in the agg queue, since we
 		 * held the tx lock: no packet could be enqueued to the newly
 		 * allocated queue */
-		ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
+		if (hw->ampdu_queues)
+			ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "BA request denied - HW unavailable for"
 					" tid %d\n", tid);
@@ -481,7 +557,8 @@
 	}
 
 	/* Will put all the packets in the new SW queue */
-	ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
+	if (hw->ampdu_queues)
+		ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
 	spin_unlock_bh(&sta->lock);
 
 	/* send an addBA request */
@@ -524,7 +601,6 @@
 	struct sta_info *sta;
 	u8 *state;
 	int ret = 0;
-	DECLARE_MAC_BUF(mac);
 
 	if (tid >= STA_TID_NUM)
 		return -EINVAL;
@@ -546,11 +622,12 @@
 	}
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
-	printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
-				print_mac(mac, ra), tid);
+	printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
+	       ra, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
-	ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
+	if (hw->ampdu_queues)
+		ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
 
 	*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
 		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
@@ -563,7 +640,8 @@
 	if (ret) {
 		WARN_ON(ret != -EBUSY);
 		*state = HT_AGG_STATE_OPERATIONAL;
-		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
+		if (hw->ampdu_queues)
+			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
 		goto stop_BA_exit;
 	}
 
@@ -579,7 +657,6 @@
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct sta_info *sta;
 	u8 *state;
-	DECLARE_MAC_BUF(mac);
 
 	if (tid >= STA_TID_NUM) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -594,8 +671,7 @@
 	if (!sta) {
 		rcu_read_unlock();
 #ifdef CONFIG_MAC80211_HT_DEBUG
-		printk(KERN_DEBUG "Could not find station: %s\n",
-				print_mac(mac, ra));
+		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
 #endif
 		return;
 	}
@@ -621,7 +697,8 @@
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
 #endif
-		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
+		if (hw->ampdu_queues)
+			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
 	}
 	spin_unlock_bh(&sta->lock);
 	rcu_read_unlock();
@@ -634,7 +711,6 @@
 	struct sta_info *sta;
 	u8 *state;
 	int agg_queue;
-	DECLARE_MAC_BUF(mac);
 
 	if (tid >= STA_TID_NUM) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -645,16 +721,15 @@
 	}
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
-	printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
-				print_mac(mac, ra), tid);
+	printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n",
+	       ra, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	rcu_read_lock();
 	sta = sta_info_get(local, ra);
 	if (!sta) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
-		printk(KERN_DEBUG "Could not find station: %s\n",
-				print_mac(mac, ra));
+		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
 #endif
 		rcu_read_unlock();
 		return;
@@ -677,16 +752,18 @@
 		ieee80211_send_delba(sta->sdata, ra, tid,
 			WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
 
-	agg_queue = sta->tid_to_tx_q[tid];
+	if (hw->ampdu_queues) {
+		agg_queue = sta->tid_to_tx_q[tid];
+		ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
 
-	ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
-
-	/* We just requeued the all the frames that were in the
-	 * removed queue, and since we might miss a softirq we do
-	 * netif_schedule_queue.  ieee80211_wake_queue is not used
-	 * here as this queue is not necessarily stopped
-	 */
-	netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
+		/* We just requeued the all the frames that were in the
+		 * removed queue, and since we might miss a softirq we do
+		 * netif_schedule_queue.  ieee80211_wake_queue is not used
+		 * here as this queue is not necessarily stopped
+		 */
+		netif_schedule_queue(netdev_get_tx_queue(local->mdev,
+							 agg_queue));
+	}
 	spin_lock_bh(&sta->lock);
 	*state = HT_AGG_STATE_IDLE;
 	sta->ampdu_mlme.addba_req_num[tid] = 0;
@@ -783,7 +860,6 @@
 	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
 	u8 dialog_token;
 	int ret = -EOPNOTSUPP;
-	DECLARE_MAC_BUF(mac);
 
 	/* extract session parameters from addba request frame */
 	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
@@ -801,15 +877,16 @@
 	/* sanity check for incoming parameters:
 	 * check if configuration can support the BA policy
 	 * and if buffer size does not exceeds max value */
+	/* XXX: check own ht delayed BA capability?? */
 	if (((ba_policy != 1)
-		&& (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
+		&& (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA)))
 		|| (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
 		status = WLAN_STATUS_INVALID_QOS_PARAM;
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "AddBA Req with bad params from "
-				"%s on tid %u. policy %d, buffer size %d\n",
-				print_mac(mac, mgmt->sa), tid, ba_policy,
+				"%pM on tid %u. policy %d, buffer size %d\n",
+				mgmt->sa, tid, ba_policy,
 				buf_size);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 		goto end_no_lock;
@@ -820,7 +897,7 @@
 
 		sband = local->hw.wiphy->bands[conf->channel->band];
 		buf_size = IEEE80211_MIN_AMPDU_BUF;
-		buf_size = buf_size << sband->ht_info.ampdu_factor;
+		buf_size = buf_size << sband->ht_cap.ampdu_factor;
 	}
 
 
@@ -831,8 +908,8 @@
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "unexpected AddBA Req from "
-				"%s on tid %u\n",
-				print_mac(mac, mgmt->sa), tid);
+				"%pM on tid %u\n",
+				mgmt->sa, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 		goto end;
 	}
@@ -910,7 +987,7 @@
 {
 	struct ieee80211_hw *hw = &local->hw;
 	u16 capab;
-	u16 tid;
+	u16 tid, start_seq_num;
 	u8 *state;
 
 	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
@@ -943,9 +1020,18 @@
 		*state |= HT_ADDBA_RECEIVED_MSK;
 		sta->ampdu_mlme.addba_req_num[tid] = 0;
 
-		if (*state == HT_AGG_STATE_OPERATIONAL)
+		if (*state == HT_AGG_STATE_OPERATIONAL &&
+		    local->hw.ampdu_queues)
 			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
 
+		if (local->ops->ampdu_action) {
+			(void)local->ops->ampdu_action(hw,
+					       IEEE80211_AMPDU_TX_RESUME,
+					       &sta->sta, tid, &start_seq_num);
+		}
+#ifdef CONFIG_MAC80211_HT_DEBUG
+		printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid);
+#endif /* CONFIG_MAC80211_HT_DEBUG */
 		spin_unlock_bh(&sta->lock);
 	} else {
 		sta->ampdu_mlme.addba_req_num[tid]++;
@@ -964,7 +1050,6 @@
 	struct ieee80211_local *local = sdata->local;
 	u16 tid, params;
 	u16 initiator;
-	DECLARE_MAC_BUF(mac);
 
 	params = le16_to_cpu(mgmt->u.action.u.delba.params);
 	tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
@@ -972,9 +1057,8 @@
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
 	if (net_ratelimit())
-		printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n",
-			print_mac(mac, mgmt->sa),
-			initiator ? "initiator" : "recipient", tid,
+		printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n",
+			mgmt->sa, initiator ? "initiator" : "recipient", tid,
 			mgmt->u.action.u.delba.reason_code);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 156e42a..155a2041 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/etherdevice.h>
+#include <net/cfg80211.h>
 #include <net/wireless.h>
 #include <net/iw_handler.h>
 #include <net/mac80211.h>
@@ -142,7 +143,6 @@
 #define IEEE80211_TX_FRAGMENTED		BIT(0)
 #define IEEE80211_TX_UNICAST		BIT(1)
 #define IEEE80211_TX_PS_BUFFERED	BIT(2)
-#define IEEE80211_TX_PROBE_LAST_FRAG	BIT(3)
 
 struct ieee80211_tx_data {
 	struct sk_buff *skb;
@@ -153,11 +153,6 @@
 	struct ieee80211_key *key;
 
 	struct ieee80211_channel *channel;
-	s8 rate_idx;
-	/* use this rate (if set) for last fragment; rate can
-	 * be set to lower rate for the first fragments, e.g.,
-	 * when using CTS protection with IEEE 802.11g. */
-	s8 last_frag_rate_idx;
 
 	/* Extra fragments (in addition to the first fragment
 	 * in skb) */
@@ -203,9 +198,7 @@
 struct ieee80211_tx_stored_packet {
 	struct sk_buff *skb;
 	struct sk_buff **extra_frag;
-	s8 last_frag_rate_idx;
 	int num_extra_frag;
-	bool last_frag_rate_ctrl_probe;
 };
 
 struct beacon_data {
@@ -219,9 +212,6 @@
 
 	struct list_head vlans;
 
-	u8 ssid[IEEE80211_MAX_SSID_LEN];
-	size_t ssid_len;
-
 	/* yes, this looks ugly, but guarantees that we can later use
 	 * bitmap_empty :)
 	 * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
@@ -255,26 +245,6 @@
 	u8 flags;
 };
 
-struct mesh_config {
-	/* Timeouts in ms */
-	/* Mesh plink management parameters */
-	u16 dot11MeshRetryTimeout;
-	u16 dot11MeshConfirmTimeout;
-	u16 dot11MeshHoldingTimeout;
-	u16 dot11MeshMaxPeerLinks;
-	u8  dot11MeshMaxRetries;
-	u8  dot11MeshTTL;
-	bool auto_open_plinks;
-	/* HWMP parameters */
-	u8  dot11MeshHWMPmaxPREQretries;
-	u32 path_refresh_time;
-	u16 min_discovery_timeout;
-	u32 dot11MeshHWMPactivePathTimeout;
-	u16 dot11MeshHWMPpreqMinInterval;
-	u16 dot11MeshHWMPnetDiameterTraversalTime;
-};
-
-
 /* flags used in struct ieee80211_if_sta.flags */
 #define IEEE80211_STA_SSID_SET		BIT(0)
 #define IEEE80211_STA_BSSID_SET		BIT(1)
@@ -438,8 +408,7 @@
 	struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
 	struct ieee80211_key *default_key;
 
-	/* BSS configuration for this interface. */
-	struct ieee80211_bss_conf bss_conf;
+	u16 sequence_number;
 
 	/*
 	 * AP this belongs to: self in AP mode and
@@ -633,8 +602,6 @@
 
 	int rts_threshold;
 	int fragmentation_threshold;
-	int short_retry_limit; /* dot11ShortRetryLimit */
-	int long_retry_limit; /* dot11LongRetryLimit */
 
 	struct crypto_blkcipher *wep_tx_tfm;
 	struct crypto_blkcipher *wep_rx_tfm;
@@ -727,8 +694,6 @@
 		struct dentry *rcdir;
 		struct dentry *rcname;
 		struct dentry *frequency;
-		struct dentry *antenna_sel_tx;
-		struct dentry *antenna_sel_rx;
 		struct dentry *rts_threshold;
 		struct dentry *fragmentation_threshold;
 		struct dentry *short_retry_limit;
@@ -817,7 +782,7 @@
 	u8 *wmm_info;
 	u8 *wmm_param;
 	struct ieee80211_ht_cap *ht_cap_elem;
-	struct ieee80211_ht_addt_info *ht_info_elem;
+	struct ieee80211_ht_info *ht_info_elem;
 	u8 *mesh_config;
 	u8 *mesh_id;
 	u8 *peer_link;
@@ -869,11 +834,6 @@
 	return &local->hw;
 }
 
-struct sta_attribute {
-	struct attribute attr;
-	ssize_t (*show)(const struct sta_info *, char *buf);
-	ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
-};
 
 static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
 {
@@ -882,12 +842,9 @@
 }
 
 
-int ieee80211_hw_config(struct ieee80211_local *local);
+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
 int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
-u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
-			struct ieee80211_ht_info *req_ht_cap,
-			struct ieee80211_ht_bss_info *req_bss_cap);
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 				      u32 changed);
 void ieee80211_configure_filter(struct ieee80211_local *local);
@@ -968,11 +925,12 @@
 int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* HT */
-int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
-				   struct ieee80211_ht_info *ht_info);
-int ieee80211_ht_addt_info_ie_to_ht_bss_info(
-			struct ieee80211_ht_addt_info *ht_add_info_ie,
-			struct ieee80211_ht_bss_info *bss_info);
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+				       struct ieee80211_ht_cap *ht_cap_ie,
+				       struct ieee80211_sta_ht_cap *ht_cap);
+u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
+			struct ieee80211_ht_info *hti,
+			u16 ap_ht_cap_flags);
 void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn);
 
 void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8336fee..cde1452 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -65,7 +65,7 @@
 	struct ieee80211_if_init_conf conf;
 	u32 changed = 0;
 	int res;
-	bool need_hw_reconfig = 0;
+	u32 hw_reconf_flags = 0;
 	u8 null_addr[ETH_ALEN] = {0};
 
 	/* fail early if user set an invalid address */
@@ -152,7 +152,8 @@
 			res = local->ops->start(local_to_hw(local));
 		if (res)
 			goto err_del_bss;
-		need_hw_reconfig = 1;
+		/* we're brought up, everything changes */
+		hw_reconf_flags = ~0;
 		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
 	}
 
@@ -198,8 +199,10 @@
 
 		/* must be before the call to ieee80211_configure_filter */
 		local->monitors++;
-		if (local->monitors == 1)
+		if (local->monitors == 1) {
 			local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+			hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+		}
 
 		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
 			local->fif_fcsfail++;
@@ -279,8 +282,8 @@
 		atomic_inc(&local->iff_promiscs);
 
 	local->open_count++;
-	if (need_hw_reconfig) {
-		ieee80211_hw_config(local);
+	if (hw_reconf_flags) {
+		ieee80211_hw_config(local, hw_reconf_flags);
 		/*
 		 * set default queue parameters so drivers don't
 		 * need to initialise the hardware if the hardware
@@ -322,6 +325,7 @@
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_init_conf conf;
 	struct sta_info *sta;
+	u32 hw_reconf_flags = 0;
 
 	/*
 	 * Stop TX on this interface first.
@@ -405,8 +409,10 @@
 		}
 
 		local->monitors--;
-		if (local->monitors == 0)
+		if (local->monitors == 0) {
 			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+			hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+		}
 
 		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
 			local->fif_fcsfail--;
@@ -504,8 +510,15 @@
 
 		tasklet_disable(&local->tx_pending_tasklet);
 		tasklet_disable(&local->tasklet);
+
+		/* no reconfiguring after stop! */
+		hw_reconf_flags = 0;
 	}
 
+	/* do after stop to avoid reconfiguring when we stop anyway */
+	if (hw_reconf_flags)
+		ieee80211_hw_config(local, hw_reconf_flags);
+
 	return 0;
 }
 
@@ -682,7 +695,7 @@
 	ieee80211_setup_sdata(sdata, type);
 
 	/* reset some values that shouldn't be kept across type changes */
-	sdata->bss_conf.basic_rates =
+	sdata->vif.bss_conf.basic_rates =
 		ieee80211_mandatory_rates(sdata->local,
 			sdata->local->hw.conf.channel->band);
 	sdata->drop_unencrypted = 0;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index a5b06fe..999f7aa 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -132,7 +132,6 @@
 {
 	const u8 *addr;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	assert_key_lock();
 	might_sleep();
@@ -154,16 +153,15 @@
 
 	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
 		printk(KERN_ERR "mac80211-%s: failed to set key "
-		       "(%d, %s) to hardware (%d)\n",
+		       "(%d, %pM) to hardware (%d)\n",
 		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, print_mac(mac, addr), ret);
+		       key->conf.keyidx, addr, ret);
 }
 
 static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
 {
 	const u8 *addr;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 	assert_key_lock();
 	might_sleep();
@@ -186,9 +184,9 @@
 
 	if (ret)
 		printk(KERN_ERR "mac80211-%s: failed to remove key "
-		       "(%d, %s) from hardware (%d)\n",
+		       "(%d, %pM) from hardware (%d)\n",
 		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, print_mac(mac, addr), ret);
+		       key->conf.keyidx, addr, ret);
 
 	spin_lock(&todo_lock);
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ae62ad40..d631dc9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -41,6 +41,8 @@
  */
 struct ieee80211_tx_status_rtap_hdr {
 	struct ieee80211_radiotap_header hdr;
+	u8 rate;
+	u8 padding_for_rate;
 	__le16 tx_flags;
 	u8 data_retries;
 } __attribute__ ((packed));
@@ -169,19 +171,13 @@
 	conf.changed = changed;
 
 	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
-	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+	    sdata->vif.type == NL80211_IFTYPE_ADHOC)
 		conf.bssid = sdata->u.sta.bssid;
-		conf.ssid = sdata->u.sta.ssid;
-		conf.ssid_len = sdata->u.sta.ssid_len;
-	} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
+	else if (sdata->vif.type == NL80211_IFTYPE_AP)
 		conf.bssid = sdata->dev->dev_addr;
-		conf.ssid = sdata->u.ap.ssid;
-		conf.ssid_len = sdata->u.ap.ssid_len;
-	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
+	else if (ieee80211_vif_is_mesh(&sdata->vif)) {
 		u8 zero[ETH_ALEN] = { 0 };
 		conf.bssid = zero;
-		conf.ssid = zero;
-		conf.ssid_len = 0;
 	} else {
 		WARN_ON(1);
 		return -EINVAL;
@@ -190,138 +186,50 @@
 	if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
 		return -EINVAL;
 
-	if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID)))
-		return -EINVAL;
-
 	return local->ops->config_interface(local_to_hw(local),
 					    &sdata->vif, &conf);
 }
 
-int ieee80211_hw_config(struct ieee80211_local *local)
+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
 	struct ieee80211_channel *chan;
 	int ret = 0;
+	int power;
+
+	might_sleep();
 
 	if (local->sw_scanning)
 		chan = local->scan_channel;
 	else
 		chan = local->oper_channel;
 
-	local->hw.conf.channel = chan;
+	if (chan != local->hw.conf.channel) {
+		local->hw.conf.channel = chan;
+		changed |= IEEE80211_CONF_CHANGE_CHANNEL;
+	}
+
 
 	if (!local->hw.conf.power_level)
-		local->hw.conf.power_level = chan->max_power;
+		power = chan->max_power;
 	else
-		local->hw.conf.power_level = min(chan->max_power,
-					       local->hw.conf.power_level);
+		power = min(chan->max_power, local->hw.conf.power_level);
+	if (local->hw.conf.power_level != power) {
+		changed |= IEEE80211_CONF_CHANGE_POWER;
+		local->hw.conf.power_level = power;
+	}
 
-	local->hw.conf.max_antenna_gain = chan->max_antenna_gain;
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n",
-	       wiphy_name(local->hw.wiphy), chan->center_freq);
-#endif
-
-	if (local->open_count)
-		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
+	if (changed && local->open_count) {
+		ret = local->ops->config(local_to_hw(local), changed);
+		/*
+		 * HW reconfiguration should never fail, the driver has told
+		 * us what it can support so it should live up to that promise.
+		 */
+		WARN_ON(ret);
+	}
 
 	return ret;
 }
 
-/**
- * ieee80211_handle_ht should be used only after legacy configuration
- * has been determined namely band, as ht configuration depends upon
- * the hardware's HT abilities for a _specific_ band.
- */
-u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
-			   struct ieee80211_ht_info *req_ht_cap,
-			   struct ieee80211_ht_bss_info *req_bss_cap)
-{
-	struct ieee80211_conf *conf = &local->hw.conf;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_ht_info ht_conf;
-	struct ieee80211_ht_bss_info ht_bss_conf;
-	u32 changed = 0;
-	int i;
-	u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS;
-	u8 tx_mcs_set_cap;
-
-	sband = local->hw.wiphy->bands[conf->channel->band];
-
-	memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
-	memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
-
-	/* HT is not supported */
-	if (!sband->ht_info.ht_supported) {
-		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-		goto out;
-	}
-
-	/* disable HT */
-	if (!enable_ht) {
-		if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
-			changed |= BSS_CHANGED_HT;
-		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-		conf->ht_conf.ht_supported = 0;
-		goto out;
-	}
-
-
-	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
-		changed |= BSS_CHANGED_HT;
-
-	conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
-	ht_conf.ht_supported = 1;
-
-	ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
-	ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS);
-	ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS;
-	ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
-	ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
-	ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
-
-	ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
-	ht_conf.ampdu_density = req_ht_cap->ampdu_density;
-
-	/* Bits 96-100 */
-	tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12];
-
-	/* configure suppoerted Tx MCS according to requested MCS
-	 * (based in most cases on Rx capabilities of peer) and self
-	 * Tx MCS capabilities (as defined by low level driver HW
-	 * Tx capabilities) */
-	if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED))
-		goto check_changed;
-
-	/* Counting from 0 therfore + 1 */
-	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF)
-		max_tx_streams = ((tx_mcs_set_cap &
-				IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1;
-
-	for (i = 0; i < max_tx_streams; i++)
-		ht_conf.supp_mcs_set[i] =
-			sband->ht_info.supp_mcs_set[i] &
-					req_ht_cap->supp_mcs_set[i];
-
-	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM)
-		for (i = IEEE80211_SUPP_MCS_SET_UEQM;
-		     i < IEEE80211_SUPP_MCS_SET_LEN; i++)
-			ht_conf.supp_mcs_set[i] =
-				sband->ht_info.supp_mcs_set[i] &
-					req_ht_cap->supp_mcs_set[i];
-
-check_changed:
-	/* if bss configuration changed store the new one */
-	if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
-	    memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
-		changed |= BSS_CHANGED_HT;
-		memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
-		memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
-	}
-out:
-	return changed;
-}
-
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 				      u32 changed)
 {
@@ -336,15 +244,18 @@
 	if (local->ops->bss_info_changed)
 		local->ops->bss_info_changed(local_to_hw(local),
 					     &sdata->vif,
-					     &sdata->bss_conf,
+					     &sdata->vif.bss_conf,
 					     changed);
 }
 
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
 {
-	sdata->bss_conf.use_cts_prot = 0;
-	sdata->bss_conf.use_short_preamble = 0;
-	return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE;
+	sdata->vif.bss_conf.use_cts_prot = false;
+	sdata->vif.bss_conf.use_short_preamble = false;
+	sdata->vif.bss_conf.use_short_slot = false;
+	return BSS_CHANGED_ERP_CTS_PROT |
+	       BSS_CHANGED_ERP_PREAMBLE |
+	       BSS_CHANGED_ERP_SLOT;
 }
 
 void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
@@ -466,8 +377,6 @@
 					    struct sta_info *sta,
 					    struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
 	sta->tx_filtered_count++;
 
 	/*
@@ -514,10 +423,9 @@
 		return;
 	}
 
-	if (!test_sta_flags(sta, WLAN_STA_PS) &&
-	    !(info->flags & IEEE80211_TX_CTL_REQUEUE)) {
+	if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) {
 		/* Software retry the packet once */
-		info->flags |= IEEE80211_TX_CTL_REQUEUE;
+		skb->requeue = 1;
 		ieee80211_remove_tx_extra(local, sta->key, skb);
 		dev_queue_xmit(skb);
 		return;
@@ -547,13 +455,28 @@
 	struct ieee80211_sub_if_data *sdata;
 	struct net_device *prev_dev = NULL;
 	struct sta_info *sta;
+	int retry_count = -1, i;
+
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		/* the HW cannot have attempted that rate */
+		if (i >= hw->max_rates) {
+			info->status.rates[i].idx = -1;
+			info->status.rates[i].count = 0;
+		}
+
+		retry_count += info->status.rates[i].count;
+	}
+	if (retry_count < 0)
+		retry_count = 0;
 
 	rcu_read_lock();
 
+	sband = local->hw.wiphy->bands[info->band];
+
 	sta = sta_info_get(local, hdr->addr1);
 
 	if (sta) {
-		if (info->status.excessive_retries &&
+		if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
 		    test_sta_flags(sta, WLAN_STA_PS)) {
 			/*
 			 * The STA is in power save mode, so assume
@@ -584,12 +507,11 @@
 			rcu_read_unlock();
 			return;
 		} else {
-			if (info->status.excessive_retries)
+			if (!(info->flags & IEEE80211_TX_STAT_ACK))
 				sta->tx_retry_failed++;
-			sta->tx_retry_count += info->status.retry_count;
+			sta->tx_retry_count += retry_count;
 		}
 
-		sband = local->hw.wiphy->bands[info->band];
 		rate_control_tx_status(local, sband, sta, skb);
 	}
 
@@ -610,9 +532,9 @@
 			local->dot11TransmittedFrameCount++;
 			if (is_multicast_ether_addr(hdr->addr1))
 				local->dot11MulticastTransmittedFrameCount++;
-			if (info->status.retry_count > 0)
+			if (retry_count > 0)
 				local->dot11RetryCount++;
-			if (info->status.retry_count > 1)
+			if (retry_count > 1)
 				local->dot11MultipleRetryCount++;
 		}
 
@@ -656,19 +578,30 @@
 	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
 	rthdr->hdr.it_present =
 		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
-			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES) |
+			    (1 << IEEE80211_RADIOTAP_RATE));
 
 	if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
 	    !is_multicast_ether_addr(hdr->addr1))
 		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
 
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) &&
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
+	/*
+	 * XXX: Once radiotap gets the bitmap reset thing the vendor
+	 *	extensions proposal contains, we can actually report
+	 *	the whole set of tries we did.
+	 */
+	if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
 		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
-	else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+	else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+	if (info->status.rates[0].idx >= 0 &&
+	    !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
+		rthdr->rate = sband->bitrates[
+				info->status.rates[0].idx].bitrate / 5;
 
-	rthdr->data_retries = info->status.retry_count;
+	/* for now report the total retry_count */
+	rthdr->data_retries = retry_count;
 
 	/* XXX: is this sufficient for BPF? */
 	skb_set_mac_header(skb, 0);
@@ -753,13 +686,14 @@
 	BUG_ON(!ops->configure_filter);
 	local->ops = ops;
 
-	local->hw.queues = 1; /* default */
-
+	/* set up some defaults */
+	local->hw.queues = 1;
+	local->hw.max_rates = 1;
 	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-	local->short_retry_limit = 7;
-	local->long_retry_limit = 4;
-	local->hw.conf.radio_enabled = 1;
+	local->hw.conf.long_frame_max_tx_count = 4;
+	local->hw.conf.short_frame_max_tx_count = 7;
+	local->hw.conf.radio_enabled = true;
 
 	INIT_LIST_HEAD(&local->interfaces);
 
@@ -1013,7 +947,7 @@
 
 	BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
 	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
-	             IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
+		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
 
 	ret = rc80211_minstrel_init();
 	if (ret)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8013277..82f568e 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -238,7 +238,7 @@
 
 	pos = skb_put(skb, 21);
 	*pos++ = WLAN_EID_MESH_CONFIG;
-	*pos++ = MESH_CFG_LEN;
+	*pos++ = IEEE80211_MESH_CONFIG_LEN;
 	/* Version */
 	*pos++ = 1;
 
@@ -473,7 +473,7 @@
 					size_t len,
 					struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local= sdata->local;
+	struct ieee80211_local *local = sdata->local;
 	struct ieee802_11_elems elems;
 	struct ieee80211_channel *channel;
 	u64 supp_rates = 0;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index e10471c..c197ab5 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -145,9 +145,6 @@
 };
 
 
-/* Mesh IEs constants */
-#define MESH_CFG_LEN		19
-
 /*
  * MESH_CFG_COMP_LEN Includes:
  * 	- Active path selection protocol ID.
@@ -157,7 +154,7 @@
  * Does not include mesh capabilities, which may vary across nodes in the same
  * mesh
  */
-#define MESH_CFG_CMP_LEN 	17
+#define MESH_CFG_CMP_LEN 	(IEEE80211_MESH_CONFIG_LEN - 2)
 
 /* Default values, timeouts in ms */
 #define MESH_TTL 		5
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 501c783..e8d573d 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -218,12 +218,16 @@
 
 	if (sta->fail_avg >= 100)
 		return MAX_METRIC;
+
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		return MAX_METRIC;
+
 	err = (sta->fail_avg << ARITH_SHIFT) / 100;
 
 	/* bitrate is in units of 100 Kbps, while we need rate in units of
 	 * 1Mbps. This will be corrected on tx_time computation.
 	 */
-	rate = sband->bitrates[sta->last_txrate_idx].bitrate;
+	rate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
 	tx_time = (device_constant + 10 * test_frame_len / rate);
 	estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
 	result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index faac101..929ba54 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -257,9 +257,6 @@
 	struct sta_info *sta;
 	__le16 llid, plid, reason;
 	struct ieee80211_sub_if_data *sdata;
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
 
 	/*
 	 * This STA is valid because sta_info_destroy() will
@@ -274,8 +271,8 @@
 		spin_unlock_bh(&sta->lock);
 		return;
 	}
-	mpl_dbg("Mesh plink timer for %s fired on state %d\n",
-			print_mac(mac, sta->sta.addr), sta->plink_state);
+	mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
+		sta->sta.addr, sta->plink_state);
 	reason = 0;
 	llid = sta->llid;
 	plid = sta->plid;
@@ -287,9 +284,9 @@
 		/* retry timer */
 		if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
 			u32 rand;
-			mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
-					print_mac(mac, sta->sta.addr),
-					sta->plink_retries, sta->plink_timeout);
+			mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
+				sta->sta.addr, sta->plink_retries,
+				sta->plink_timeout);
 			get_random_bytes(&rand, sizeof(u32));
 			sta->plink_timeout = sta->plink_timeout +
 					     rand % sta->plink_timeout;
@@ -337,9 +334,6 @@
 {
 	__le16 llid;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
 
 	spin_lock_bh(&sta->lock);
 	get_random_bytes(&llid, 2);
@@ -351,8 +345,8 @@
 	sta->plink_state = PLINK_OPN_SNT;
 	mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
 	spin_unlock_bh(&sta->lock);
-	mpl_dbg("Mesh plink: starting establishment with %s\n",
-		print_mac(mac, sta->sta.addr));
+	mpl_dbg("Mesh plink: starting establishment with %pM\n",
+		sta->sta.addr);
 
 	return mesh_plink_frame_tx(sdata, PLINK_OPEN,
 				   sta->sta.addr, llid, 0, 0);
@@ -360,10 +354,6 @@
 
 void mesh_plink_block(struct sta_info *sta)
 {
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
-
 	spin_lock_bh(&sta->lock);
 	__mesh_plink_deactivate(sta);
 	sta->plink_state = PLINK_BLOCKED;
@@ -374,12 +364,8 @@
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	__le16 llid, plid, reason;
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
 
-	mpl_dbg("Mesh plink: closing link with %s\n",
-			print_mac(mac, sta->sta.addr));
+	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;
@@ -417,9 +403,6 @@
 	u8 ie_len;
 	u8 *baseaddr;
 	__le16 plid, llid, reason;
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-	DECLARE_MAC_BUF(mac);
-#endif
 
 	/* need action_code, aux */
 	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
@@ -557,10 +540,10 @@
 		}
 	}
 
-	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n",
-			print_mac(mac, mgmt->sa), sta->plink_state,
-			le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
-			event);
+	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %d %d %d %d\n",
+		mgmt->sa, sta->plink_state,
+		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
+		event);
 	reason = 0;
 	switch (sta->plink_state) {
 		/* spin_unlock as soon as state is updated at each case */
@@ -660,8 +643,8 @@
 			sta->plink_state = PLINK_ESTAB;
 			mesh_plink_inc_estab_count(sdata);
 			spin_unlock_bh(&sta->lock);
-			mpl_dbg("Mesh plink with %s ESTABLISHED\n",
-					print_mac(mac, sta->sta.addr));
+			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
+				sta->sta.addr);
 			break;
 		default:
 			spin_unlock_bh(&sta->lock);
@@ -693,8 +676,8 @@
 			sta->plink_state = PLINK_ESTAB;
 			mesh_plink_inc_estab_count(sdata);
 			spin_unlock_bh(&sta->lock);
-			mpl_dbg("Mesh plink with %s ESTABLISHED\n",
-					print_mac(mac, sta->sta.addr));
+			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
+				sta->sta.addr);
 			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
 					    plid, 0);
 			break;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 87665d7b..dee6448 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -236,7 +236,7 @@
 	struct ieee80211_local *local = sdata->local;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *mgmt;
-	u8 *pos, *ies, *ht_add_ie;
+	u8 *pos, *ies, *ht_ie;
 	int i, len, count, rates_len, supp_rates_len;
 	u16 capab;
 	struct ieee80211_bss *bss;
@@ -393,24 +393,25 @@
 
 	/* wmm support is a must to HT */
 	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
-	    sband->ht_info.ht_supported &&
-	    (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) {
-		struct ieee80211_ht_addt_info *ht_add_info =
-			(struct ieee80211_ht_addt_info *)ht_add_ie;
-		u16 cap = sband->ht_info.cap;
+	    sband->ht_cap.ht_supported &&
+	    (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
+	    ht_ie[1] >= sizeof(struct ieee80211_ht_info)) {
+		struct ieee80211_ht_info *ht_info =
+			(struct ieee80211_ht_info *)(ht_ie + 2);
+		u16 cap = sband->ht_cap.cap;
 		__le16 tmp;
 		u32 flags = local->hw.conf.channel->flags;
 
-		switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) {
-		case IEEE80211_HT_IE_CHA_SEC_ABOVE:
+		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 			if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
-				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
+				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 				cap &= ~IEEE80211_HT_CAP_SGI_40;
 			}
 			break;
-		case IEEE80211_HT_IE_CHA_SEC_BELOW:
+		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 			if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
-				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
+				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 				cap &= ~IEEE80211_HT_CAP_SGI_40;
 			}
 			break;
@@ -424,9 +425,9 @@
 		memcpy(pos, &tmp, sizeof(u16));
 		pos += sizeof(u16);
 		/* TODO: needs a define here for << 2 */
-		*pos++ = sband->ht_info.ampdu_factor |
-			 (sband->ht_info.ampdu_density << 2);
-		memcpy(pos, sband->ht_info.supp_mcs_set, 16);
+		*pos++ = sband->ht_cap.ampdu_factor |
+			 (sband->ht_cap.ampdu_density << 2);
+		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
 	}
 
 	kfree(ifsta->assocreq_ies);
@@ -568,25 +569,35 @@
 	}
 }
 
-static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
-					   bool use_protection,
-					   bool use_short_preamble)
+static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
+					   u16 capab, bool erp_valid, u8 erp)
 {
-	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-	DECLARE_MAC_BUF(mac);
 #endif
 	u32 changed = 0;
+	bool use_protection;
+	bool use_short_preamble;
+	bool use_short_slot;
+
+	if (erp_valid) {
+		use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0;
+		use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0;
+	} else {
+		use_protection = false;
+		use_short_preamble = !!(capab & WLAN_CAPABILITY_SHORT_PREAMBLE);
+	}
+
+	use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
 
 	if (use_protection != bss_conf->use_cts_prot) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
-			       "%s)\n",
+			printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
 			       sdata->dev->name,
 			       use_protection ? "enabled" : "disabled",
-			       print_mac(mac, ifsta->bssid));
+			       ifsta->bssid);
 		}
 #endif
 		bss_conf->use_cts_prot = use_protection;
@@ -597,40 +608,28 @@
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: switched to %s barker preamble"
-			       " (BSSID=%s)\n",
+			       " (BSSID=%pM)\n",
 			       sdata->dev->name,
 			       use_short_preamble ? "short" : "long",
-			       print_mac(mac, ifsta->bssid));
+			       ifsta->bssid);
 		}
 #endif
 		bss_conf->use_short_preamble = use_short_preamble;
 		changed |= BSS_CHANGED_ERP_PREAMBLE;
 	}
 
-	return changed;
-}
-
-static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
-				   u8 erp_value)
-{
-	bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
-	bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
-
-	return ieee80211_handle_protect_preamb(sdata,
-			use_protection, use_short_preamble);
-}
-
-static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
-					   struct ieee80211_bss *bss)
-{
-	u32 changed = 0;
-
-	if (bss->has_erp_value)
-		changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
-	else {
-		u16 capab = bss->capability;
-		changed |= ieee80211_handle_protect_preamb(sdata, false,
-				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+	if (use_short_slot != bss_conf->use_short_slot) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: switched to %s slot"
+			       " (BSSID=%s)\n",
+			       sdata->dev->name,
+			       use_short_slot ? "short" : "long",
+			       ifsta->bssid);
+		}
+#endif
+		bss_conf->use_short_slot = use_short_slot;
+		changed |= BSS_CHANGED_ERP_SLOT;
 	}
 
 	return changed;
@@ -701,14 +700,15 @@
 
 
 static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
-				     struct ieee80211_if_sta *ifsta)
+				     struct ieee80211_if_sta *ifsta,
+				     u32 bss_info_changed)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
-	u32 changed = BSS_CHANGED_ASSOC;
 
 	struct ieee80211_bss *bss;
 
+	bss_info_changed |= BSS_CHANGED_ASSOC;
 	ifsta->flags |= IEEE80211_STA_ASSOCIATED;
 
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -719,22 +719,16 @@
 				   ifsta->ssid, ifsta->ssid_len);
 	if (bss) {
 		/* set timing information */
-		sdata->bss_conf.beacon_int = bss->beacon_int;
-		sdata->bss_conf.timestamp = bss->timestamp;
-		sdata->bss_conf.dtim_period = bss->dtim_period;
+		sdata->vif.bss_conf.beacon_int = bss->beacon_int;
+		sdata->vif.bss_conf.timestamp = bss->timestamp;
+		sdata->vif.bss_conf.dtim_period = bss->dtim_period;
 
-		changed |= ieee80211_handle_bss_capability(sdata, bss);
+		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
+			bss->capability, bss->has_erp_value, bss->erp_value);
 
 		ieee80211_rx_bss_put(local, bss);
 	}
 
-	if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-		changed |= BSS_CHANGED_HT;
-		sdata->bss_conf.assoc_ht = 1;
-		sdata->bss_conf.ht_conf = &conf->ht_conf;
-		sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
-	}
-
 	ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
 	memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
 	ieee80211_sta_send_associnfo(sdata, ifsta);
@@ -742,14 +736,14 @@
 	ifsta->last_probe = jiffies;
 	ieee80211_led_assoc(local, 1);
 
-	sdata->bss_conf.assoc = 1;
+	sdata->vif.bss_conf.assoc = 1;
 	/*
 	 * For now just always ask the driver to update the basic rateset
 	 * when we have associated, we aren't checking whether it actually
 	 * changed or not.
 	 */
-	changed |= BSS_CHANGED_BASIC_RATES;
-	ieee80211_bss_info_change_notify(sdata, changed);
+	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
+	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
 	netif_tx_start_all_queues(sdata->dev);
 	netif_carrier_on(sdata->dev);
@@ -760,18 +754,17 @@
 static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
 				   struct ieee80211_if_sta *ifsta)
 {
-	DECLARE_MAC_BUF(mac);
-
 	ifsta->direct_probe_tries++;
 	if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
-		printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
-		       sdata->dev->name, print_mac(mac, ifsta->bssid));
+		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
+		       sdata->dev->name, ifsta->bssid);
 		ifsta->state = IEEE80211_STA_MLME_DISABLED;
+		ieee80211_sta_send_apinfo(sdata, ifsta);
 		return;
 	}
 
-	printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n",
-			sdata->dev->name, print_mac(mac, ifsta->bssid),
+	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
+			sdata->dev->name, ifsta->bssid,
 			ifsta->direct_probe_tries);
 
 	ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
@@ -791,20 +784,19 @@
 static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
 				   struct ieee80211_if_sta *ifsta)
 {
-	DECLARE_MAC_BUF(mac);
-
 	ifsta->auth_tries++;
 	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
-		printk(KERN_DEBUG "%s: authentication with AP %s"
+		printk(KERN_DEBUG "%s: authentication with AP %pM"
 		       " timed out\n",
-		       sdata->dev->name, print_mac(mac, ifsta->bssid));
+		       sdata->dev->name, ifsta->bssid);
 		ifsta->state = IEEE80211_STA_MLME_DISABLED;
+		ieee80211_sta_send_apinfo(sdata, ifsta);
 		return;
 	}
 
 	ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
-	printk(KERN_DEBUG "%s: authenticate with AP %s\n",
-	       sdata->dev->name, print_mac(mac, ifsta->bssid));
+	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
+	       sdata->dev->name, ifsta->bssid);
 
 	ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0);
 
@@ -817,7 +809,7 @@
 {
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
-	u32 changed = BSS_CHANGED_ASSOC;
+	u32 changed = 0;
 
 	rcu_read_lock();
 
@@ -851,15 +843,9 @@
 	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
 	changed |= ieee80211_reset_erp_info(sdata);
 
-	if (sdata->bss_conf.assoc_ht)
-		changed |= BSS_CHANGED_HT;
-
-	sdata->bss_conf.assoc_ht = 0;
-	sdata->bss_conf.ht_conf = NULL;
-	sdata->bss_conf.ht_bss_conf = NULL;
-
 	ieee80211_led_assoc(local, 0);
-	sdata->bss_conf.assoc = 0;
+	changed |= BSS_CHANGED_ASSOC;
+	sdata->vif.bss_conf.assoc = false;
 
 	ieee80211_sta_send_apinfo(sdata, ifsta);
 
@@ -871,6 +857,11 @@
 	rcu_read_unlock();
 
 	sta_info_destroy(sta);
+
+	local->hw.conf.ht.enabled = false;
+	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
+
+	ieee80211_bss_info_change_notify(sdata, changed);
 }
 
 static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
@@ -914,20 +905,19 @@
 static void ieee80211_associate(struct ieee80211_sub_if_data *sdata,
 				struct ieee80211_if_sta *ifsta)
 {
-	DECLARE_MAC_BUF(mac);
-
 	ifsta->assoc_tries++;
 	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
-		printk(KERN_DEBUG "%s: association with AP %s"
+		printk(KERN_DEBUG "%s: association with AP %pM"
 		       " timed out\n",
-		       sdata->dev->name, print_mac(mac, ifsta->bssid));
+		       sdata->dev->name, ifsta->bssid);
 		ifsta->state = IEEE80211_STA_MLME_DISABLED;
+		ieee80211_sta_send_apinfo(sdata, ifsta);
 		return;
 	}
 
 	ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
-	printk(KERN_DEBUG "%s: associate with AP %s\n",
-	       sdata->dev->name, print_mac(mac, ifsta->bssid));
+	printk(KERN_DEBUG "%s: associate with AP %pM\n",
+	       sdata->dev->name, ifsta->bssid);
 	if (ieee80211_privacy_mismatch(sdata, ifsta)) {
 		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
 		       "mixed-cell disabled - abort association\n", sdata->dev->name);
@@ -947,7 +937,6 @@
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 	int disassoc;
-	DECLARE_MAC_BUF(mac);
 
 	/* TODO: start monitoring current AP signal quality and number of
 	 * missed beacons. Scan other channels every now and then and search
@@ -960,8 +949,8 @@
 
 	sta = sta_info_get(local, ifsta->bssid);
 	if (!sta) {
-		printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
-		       sdata->dev->name, print_mac(mac, ifsta->bssid));
+		printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
+		       sdata->dev->name, ifsta->bssid);
 		disassoc = 1;
 	} else {
 		disassoc = 0;
@@ -969,9 +958,9 @@
 			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
 			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
 				printk(KERN_DEBUG "%s: No ProbeResp from "
-				       "current AP %s - assume out of "
+				       "current AP %pM - assume out of "
 				       "range\n",
-				       sdata->dev->name, print_mac(mac, ifsta->bssid));
+				       sdata->dev->name, ifsta->bssid);
 				disassoc = 1;
 			} else
 				ieee80211_send_probe_req(sdata, ifsta->bssid,
@@ -1032,7 +1021,6 @@
 				   size_t len)
 {
 	u16 auth_alg, auth_transaction, status_code;
-	DECLARE_MAC_BUF(mac);
 
 	if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
 	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
@@ -1125,7 +1113,6 @@
 				     size_t len)
 {
 	u16 reason_code;
-	DECLARE_MAC_BUF(mac);
 
 	if (len < 24 + 2)
 		return;
@@ -1136,7 +1123,8 @@
 	reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 
 	if (ifsta->flags & IEEE80211_STA_AUTHENTICATED)
-		printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name);
+		printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
+				sdata->dev->name, reason_code);
 
 	if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE ||
 	    ifsta->state == IEEE80211_STA_MLME_ASSOCIATE ||
@@ -1157,7 +1145,6 @@
 				       size_t len)
 {
 	u16 reason_code;
-	DECLARE_MAC_BUF(mac);
 
 	if (len < 24 + 2)
 		return;
@@ -1168,7 +1155,8 @@
 	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
 	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
-		printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name);
+		printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
+				sdata->dev->name, reason_code);
 
 	if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
 		ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
@@ -1192,11 +1180,12 @@
 	u64 rates, basic_rates;
 	u16 capab_info, status_code, aid;
 	struct ieee802_11_elems elems;
-	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 	u8 *pos;
+	u32 changed = 0;
 	int i, j;
-	DECLARE_MAC_BUF(mac);
-	bool have_higher_than_11mbit = false;
+	bool have_higher_than_11mbit = false, newsta = false;
+	u16 ap_ht_cap_flags;
 
 	/* AssocResp and ReassocResp have identical structure, so process both
 	 * of them in this function. */
@@ -1214,9 +1203,9 @@
 	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
 	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
 
-	printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
+	printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
 	       "status=%d aid=%d)\n",
-	       sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
+	       sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
 	       capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 
 	if (status_code != WLAN_STATUS_SUCCESS) {
@@ -1259,7 +1248,8 @@
 	sta = sta_info_get(local, ifsta->bssid);
 	if (!sta) {
 		struct ieee80211_bss *bss;
-		int err;
+
+		newsta = true;
 
 		sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
 		if (!sta) {
@@ -1278,13 +1268,6 @@
 			ieee80211_rx_bss_put(local, bss);
 		}
 
-		err = sta_info_insert(sta);
-		if (err) {
-			printk(KERN_DEBUG "%s: failed to insert STA entry for"
-			       " the AP (error %d)\n", sdata->dev->name, err);
-			rcu_read_unlock();
-			return;
-		}
 		/* update new sta with its last rx activity */
 		sta->last_rx = jiffies;
 	}
@@ -1308,34 +1291,40 @@
 
 	for (i = 0; i < elems.supp_rates_len; i++) {
 		int rate = (elems.supp_rates[i] & 0x7f) * 5;
+		bool is_basic = !!(elems.supp_rates[i] & 0x80);
 
 		if (rate > 110)
 			have_higher_than_11mbit = true;
 
 		for (j = 0; j < sband->n_bitrates; j++) {
-			if (sband->bitrates[j].bitrate == rate)
+			if (sband->bitrates[j].bitrate == rate) {
 				rates |= BIT(j);
-			if (elems.supp_rates[i] & 0x80)
-				basic_rates |= BIT(j);
+				if (is_basic)
+					basic_rates |= BIT(j);
+				break;
+			}
 		}
 	}
 
 	for (i = 0; i < elems.ext_supp_rates_len; i++) {
 		int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
+		bool is_basic = !!(elems.supp_rates[i] & 0x80);
 
 		if (rate > 110)
 			have_higher_than_11mbit = true;
 
 		for (j = 0; j < sband->n_bitrates; j++) {
-			if (sband->bitrates[j].bitrate == rate)
+			if (sband->bitrates[j].bitrate == rate) {
 				rates |= BIT(j);
-			if (elems.ext_supp_rates[i] & 0x80)
-				basic_rates |= BIT(j);
+				if (is_basic)
+					basic_rates |= BIT(j);
+				break;
+			}
 		}
 	}
 
 	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
-	sdata->bss_conf.basic_rates = basic_rates;
+	sdata->vif.bss_conf.basic_rates = basic_rates;
 
 	/* cf. IEEE 802.11 9.2.12 */
 	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
@@ -1344,31 +1333,43 @@
 	else
 		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
 
-	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
-	    (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-		struct ieee80211_ht_bss_info bss_info;
-		ieee80211_ht_cap_ie_to_ht_info(
-				elems.ht_cap_elem, &sta->sta.ht_info);
-		ieee80211_ht_addt_info_ie_to_ht_bss_info(
-				elems.ht_info_elem, &bss_info);
-		ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info);
-	}
+	if (elems.ht_cap_elem)
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+				elems.ht_cap_elem, &sta->sta.ht_cap);
+
+	ap_ht_cap_flags = sta->sta.ht_cap.cap;
 
 	rate_control_rate_init(sta);
 
-	if (elems.wmm_param) {
+	if (elems.wmm_param)
 		set_sta_flags(sta, WLAN_STA_WME);
-		rcu_read_unlock();
+
+	if (newsta) {
+		int err = sta_info_insert(sta);
+		if (err) {
+			printk(KERN_DEBUG "%s: failed to insert STA entry for"
+			       " the AP (error %d)\n", sdata->dev->name, err);
+			rcu_read_unlock();
+			return;
+		}
+	}
+
+	rcu_read_unlock();
+
+	if (elems.wmm_param)
 		ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
 					 elems.wmm_param_len);
-	} else
-		rcu_read_unlock();
+
+	if (elems.ht_info_elem && elems.wmm_param &&
+	    (ifsta->flags & IEEE80211_STA_WMM_ENABLED))
+		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+					       ap_ht_cap_flags);
 
 	/* set AID and assoc capability,
 	 * ieee80211_set_associated() will tell the driver */
 	bss_conf->aid = aid;
 	bss_conf->assoc_capability = capab_info;
-	ieee80211_set_associated(sdata, ifsta);
+	ieee80211_set_associated(sdata, ifsta, changed);
 
 	ieee80211_associated(sdata, ifsta);
 }
@@ -1386,6 +1387,13 @@
 	struct ieee80211_supported_band *sband;
 	union iwreq_data wrqu;
 
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+		       "response\n", sdata->dev->name);
+		return -ENOMEM;
+	}
+
 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
 	/* Remove possible STA entries from other IBSS networks. */
@@ -1411,63 +1419,62 @@
 		return res;
 
 	/* Build IBSS probe response */
-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-	if (skb) {
-		skb_reserve(skb, local->hw.extra_tx_headroom);
 
-		mgmt = (struct ieee80211_mgmt *)
-			skb_put(skb, 24 + sizeof(mgmt->u.beacon));
-		memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
-		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-						  IEEE80211_STYPE_PROBE_RESP);
-		memset(mgmt->da, 0xff, ETH_ALEN);
-		memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
-		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-		mgmt->u.beacon.beacon_int =
-			cpu_to_le16(local->hw.conf.beacon_int);
-		mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp);
-		mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+	skb_reserve(skb, local->hw.extra_tx_headroom);
 
-		pos = skb_put(skb, 2 + ifsta->ssid_len);
-		*pos++ = WLAN_EID_SSID;
-		*pos++ = ifsta->ssid_len;
-		memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+	mgmt = (struct ieee80211_mgmt *)
+		skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+	memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+						IEEE80211_STYPE_PROBE_RESP);
+	memset(mgmt->da, 0xff, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+	mgmt->u.beacon.beacon_int =
+		cpu_to_le16(local->hw.conf.beacon_int);
+	mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp);
+	mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
 
-		rates = bss->supp_rates_len;
-		if (rates > 8)
-			rates = 8;
-		pos = skb_put(skb, 2 + rates);
-		*pos++ = WLAN_EID_SUPP_RATES;
-		*pos++ = rates;
-		memcpy(pos, bss->supp_rates, rates);
+	pos = skb_put(skb, 2 + ifsta->ssid_len);
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = ifsta->ssid_len;
+	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
 
-		if (bss->band == IEEE80211_BAND_2GHZ) {
-			pos = skb_put(skb, 2 + 1);
-			*pos++ = WLAN_EID_DS_PARAMS;
-			*pos++ = 1;
-			*pos++ = ieee80211_frequency_to_channel(bss->freq);
-		}
+	rates = bss->supp_rates_len;
+	if (rates > 8)
+		rates = 8;
+	pos = skb_put(skb, 2 + rates);
+	*pos++ = WLAN_EID_SUPP_RATES;
+	*pos++ = rates;
+	memcpy(pos, bss->supp_rates, rates);
 
-		pos = skb_put(skb, 2 + 2);
-		*pos++ = WLAN_EID_IBSS_PARAMS;
-		*pos++ = 2;
-		/* FIX: set ATIM window based on scan results */
-		*pos++ = 0;
-		*pos++ = 0;
-
-		if (bss->supp_rates_len > 8) {
-			rates = bss->supp_rates_len - 8;
-			pos = skb_put(skb, 2 + rates);
-			*pos++ = WLAN_EID_EXT_SUPP_RATES;
-			*pos++ = rates;
-			memcpy(pos, &bss->supp_rates[8], rates);
-		}
-
-		ifsta->probe_resp = skb;
-
-		ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+	if (bss->band == IEEE80211_BAND_2GHZ) {
+		pos = skb_put(skb, 2 + 1);
+		*pos++ = WLAN_EID_DS_PARAMS;
+		*pos++ = 1;
+		*pos++ = ieee80211_frequency_to_channel(bss->freq);
 	}
 
+	pos = skb_put(skb, 2 + 2);
+	*pos++ = WLAN_EID_IBSS_PARAMS;
+	*pos++ = 2;
+	/* FIX: set ATIM window based on scan results */
+	*pos++ = 0;
+	*pos++ = 0;
+
+	if (bss->supp_rates_len > 8) {
+		rates = bss->supp_rates_len - 8;
+		pos = skb_put(skb, 2 + rates);
+		*pos++ = WLAN_EID_EXT_SUPP_RATES;
+		*pos++ = rates;
+		memcpy(pos, &bss->supp_rates[8], rates);
+	}
+
+	ifsta->probe_resp = skb;
+
+	ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+
+
 	rates = 0;
 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 	for (i = 0; i < bss->supp_rates_len; i++) {
@@ -1507,8 +1514,6 @@
 	u64 beacon_timestamp, rx_timestamp;
 	u64 supp_rates = 0;
 	enum ieee80211_band band = rx_status->band;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	if (elems->ds_params && elems->ds_params_len == 1)
 		freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
@@ -1538,10 +1543,10 @@
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 			if (sta->sta.supp_rates[band] != prev_rates)
 				printk(KERN_DEBUG "%s: updated supp_rates set "
-				    "for %s based on beacon info (0x%llx | "
+				    "for %pM based on beacon info (0x%llx | "
 				    "0x%llx -> 0x%llx)\n",
 				    sdata->dev->name,
-				    print_mac(mac, sta->sta.addr),
+				    sta->sta.addr,
 				    (unsigned long long) prev_rates,
 				    (unsigned long long) supp_rates,
 				    (unsigned long long) sta->sta.supp_rates[band]);
@@ -1605,10 +1610,9 @@
 			/* can't merge without knowing the TSF */
 			rx_timestamp = -1LLU;
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-		printk(KERN_DEBUG "RX beacon SA=%s BSSID="
-		       "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
-		       print_mac(mac, mgmt->sa),
-		       print_mac(mac2, mgmt->bssid),
+		printk(KERN_DEBUG "RX beacon SA=%pM BSSID="
+		       "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
+		       mgmt->sa, mgmt->bssid,
 		       (unsigned long long)rx_timestamp,
 		       (unsigned long long)beacon_timestamp,
 		       (unsigned long long)(rx_timestamp - beacon_timestamp),
@@ -1617,8 +1621,8 @@
 		if (beacon_timestamp > rx_timestamp) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 			printk(KERN_DEBUG "%s: beacon TSF higher than "
-			       "local TSF - IBSS merge with BSSID %s\n",
-			       sdata->dev->name, print_mac(mac, mgmt->bssid));
+			       "local TSF - IBSS merge with BSSID %pM\n",
+			       sdata->dev->name, mgmt->bssid);
 #endif
 			ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
 			ieee80211_ibss_add_sta(sdata, NULL,
@@ -1671,8 +1675,9 @@
 	size_t baselen;
 	struct ieee802_11_elems elems;
 	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_conf *conf = &local->hw.conf;
 	u32 changed = 0;
+	bool erp_valid;
+	u8 erp_value = 0;
 
 	/* Process beacon from the current BSS */
 	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
@@ -1694,22 +1699,42 @@
 	ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
 				 elems.wmm_param_len);
 
-	if (elems.erp_info && elems.erp_info_len >= 1)
-		changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
-	else {
-		u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
-		changed |= ieee80211_handle_protect_preamb(sdata, false,
-				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+
+	if (elems.erp_info && elems.erp_info_len >= 1) {
+		erp_valid = true;
+		erp_value = elems.erp_info[0];
+	} else {
+		erp_valid = false;
 	}
+	changed |= ieee80211_handle_bss_capability(sdata,
+			le16_to_cpu(mgmt->u.beacon.capab_info),
+			erp_valid, erp_value);
 
-	if (elems.ht_cap_elem && elems.ht_info_elem &&
-	    elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-		struct ieee80211_ht_bss_info bss_info;
 
-		ieee80211_ht_addt_info_ie_to_ht_bss_info(
-				elems.ht_info_elem, &bss_info);
-		changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
-					       &bss_info);
+	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
+		struct sta_info *sta;
+		struct ieee80211_supported_band *sband;
+		u16 ap_ht_cap_flags;
+
+		rcu_read_lock();
+
+		sta = sta_info_get(local, ifsta->bssid);
+		if (!sta) {
+			rcu_read_unlock();
+			return;
+		}
+
+		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+				elems.ht_cap_elem, &sta->sta.ht_cap);
+
+		ap_ht_cap_flags = sta->sta.ht_cap.cap;
+
+		rcu_read_unlock();
+
+		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+					       ap_ht_cap_flags);
 	}
 
 	ieee80211_bss_info_change_notify(sdata, changed);
@@ -1727,11 +1752,6 @@
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *resp;
 	u8 *pos, *end;
-	DECLARE_MAC_BUF(mac);
-#ifdef CONFIG_MAC80211_IBSS_DEBUG
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
-#endif
 
 	if (sdata->vif.type != NL80211_IFTYPE_ADHOC ||
 	    ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
@@ -1744,10 +1764,10 @@
 		tx_last_beacon = 1;
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-	printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
-	       "%s (tx_last_beacon=%d)\n",
-	       sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
-	       print_mac(mac3, mgmt->bssid), tx_last_beacon);
+	printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM"
+	       " (tx_last_beacon=%d)\n",
+	       sdata->dev->name, mgmt->sa, mgmt->da,
+	       mgmt->bssid, tx_last_beacon);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
 	if (!tx_last_beacon)
@@ -1763,8 +1783,8 @@
 	    pos + 2 + pos[1] > end) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 		printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
-		       "from %s\n",
-		       sdata->dev->name, print_mac(mac, mgmt->sa));
+		       "from %pM\n",
+		       sdata->dev->name, mgmt->sa);
 #endif
 		return;
 	}
@@ -1783,8 +1803,8 @@
 	resp = (struct ieee80211_mgmt *) skb->data;
 	memcpy(resp->da, mgmt->sa, ETH_ALEN);
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-	printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
-	       sdata->dev->name, print_mac(mac, resp->da));
+	printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n",
+	       sdata->dev->name, resp->da);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 	ieee80211_tx_skb(sdata, skb, 0);
 }
@@ -1990,7 +2010,6 @@
 	u8 bssid[ETH_ALEN], *pos;
 	int i;
 	int ret;
-	DECLARE_MAC_BUF(mac);
 
 #if 0
 	/* Easier testing, use fixed BSSID. */
@@ -2006,8 +2025,8 @@
 	bssid[0] |= 0x02;
 #endif
 
-	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
-	       sdata->dev->name, print_mac(mac, bssid));
+	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
+	       sdata->dev->name, bssid);
 
 	bss = ieee80211_rx_bss_add(local, bssid,
 				   local->hw.conf.channel->center_freq,
@@ -2050,8 +2069,6 @@
 	int found = 0;
 	u8 bssid[ETH_ALEN];
 	int active_ibss;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	if (ifsta->ssid_len == 0)
 		return -EINVAL;
@@ -2068,8 +2085,7 @@
 		    || !(bss->capability & WLAN_CAPABILITY_IBSS))
 			continue;
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-		printk(KERN_DEBUG "   bssid=%s found\n",
-		       print_mac(mac, bss->bssid));
+		printk(KERN_DEBUG "   bssid=%pM found\n", bss->bssid);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 		memcpy(bssid, bss->bssid, ETH_ALEN);
 		found = 1;
@@ -2080,9 +2096,8 @@
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 	if (found)
-		printk(KERN_DEBUG "   sta_find_ibss: selected %s current "
-		       "%s\n", print_mac(mac, bssid),
-		       print_mac(mac2, ifsta->bssid));
+		printk(KERN_DEBUG "   sta_find_ibss: selected %pM current "
+		       "%pM\n", bssid, ifsta->bssid);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
 	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
@@ -2099,9 +2114,9 @@
 		if (!bss)
 			goto dont_join;
 
-		printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
+		printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
 		       " based on configured SSID\n",
-		       sdata->dev->name, print_mac(mac, bssid));
+		       sdata->dev->name, bssid);
 		ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
 		ieee80211_rx_bss_put(local, bss);
 		return ret;
@@ -2343,7 +2358,6 @@
 {
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
-	DECLARE_MAC_BUF(mac);
 	int band = local->hw.conf.channel->band;
 
 	/* TODO: Could consider removing the least recently used entry and
@@ -2351,7 +2365,7 @@
 	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
-			       "entry %s\n", sdata->dev->name, print_mac(mac, addr));
+			       "entry %pM\n", sdata->dev->name, addr);
 		}
 		return NULL;
 	}
@@ -2360,8 +2374,8 @@
 		return NULL;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
-	       wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name);
+	printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
+	       wiphy_name(local->hw.wiphy), addr, sdata->dev->name);
 #endif
 
 	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
@@ -2408,7 +2422,6 @@
 int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
 {
 	struct ieee80211_if_sta *ifsta;
-	int res;
 
 	if (len > IEEE80211_MAX_SSID_LEN)
 		return -EINVAL;
@@ -2420,19 +2433,6 @@
 		memcpy(ifsta->ssid, ssid, len);
 		ifsta->ssid_len = len;
 		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-
-		res = 0;
-		/*
-		 * Hack! MLME code needs to be cleaned up to have different
-		 * entry points for configuration and internal selection change
-		 */
-		if (netif_running(sdata->dev))
-			res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
-		if (res) {
-			printk(KERN_DEBUG "%s: Failed to config new SSID to "
-			       "the low-level driver\n", sdata->dev->name);
-			return res;
-		}
 	}
 
 	if (len)
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 5d78672..3fa7ab2 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -199,48 +199,44 @@
 }
 
 void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
-			   struct ieee80211_supported_band *sband,
-			   struct sta_info *sta, struct sk_buff *skb,
-			   struct rate_selection *sel)
+			   struct sta_info *sta,
+			   struct ieee80211_tx_rate_control *txrc)
 {
 	struct rate_control_ref *ref = sdata->local->rate_ctrl;
 	void *priv_sta = NULL;
 	struct ieee80211_sta *ista = NULL;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
 	int i;
 
-	sel->rate_idx = -1;
-	sel->nonerp_idx = -1;
-	sel->probe_idx = -1;
-	sel->max_rate_idx = sdata->max_ratectrl_rateidx;
-
 	if (sta) {
 		ista = &sta->sta;
 		priv_sta = sta->rate_ctrl_priv;
 	}
 
-	if (sta && sdata->force_unicast_rateidx > -1)
-		sel->rate_idx = sdata->force_unicast_rateidx;
-	else
-		ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel);
-
-	if (sdata->max_ratectrl_rateidx > -1 &&
-	    sel->rate_idx > sdata->max_ratectrl_rateidx)
-		sel->rate_idx = sdata->max_ratectrl_rateidx;
-
-	BUG_ON(sel->rate_idx < 0);
-
-	/* Select a non-ERP backup rate. */
-	if (sel->nonerp_idx < 0) {
-		for (i = 0; i < sband->n_bitrates; i++) {
-			struct ieee80211_rate *rate = &sband->bitrates[i];
-			if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)
-				break;
-
-			if (rate_supported(ista, sband->band, i) &&
-			    !(rate->flags & IEEE80211_RATE_ERP_G))
-				sel->nonerp_idx = i;
-		}
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		info->control.rates[i].idx = -1;
+		info->control.rates[i].flags = 0;
+		info->control.rates[i].count = 1;
 	}
+
+	if (sta && sdata->force_unicast_rateidx > -1)
+		info->control.rates[0].idx = sdata->force_unicast_rateidx;
+	else
+		ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+
+	/*
+	 * try to enforce the maximum rate the user wanted
+	 */
+	if (sdata->max_ratectrl_rateidx > -1)
+		for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+			if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
+				continue;
+			info->control.rates[i].idx =
+				min_t(s8, info->control.rates[i].idx,
+				      sdata->max_ratectrl_rateidx);
+	}
+
+	BUG_ON(info->control.rates[0].idx < 0);
 }
 
 struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index d0092f8..928da62 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -31,9 +31,8 @@
 struct rate_control_ref *rate_control_alloc(const char *name,
 					    struct ieee80211_local *local);
 void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
-			   struct ieee80211_supported_band *sband,
-			   struct sta_info *sta, struct sk_buff *skb,
-			   struct rate_selection *sel);
+			   struct sta_info *sta,
+			   struct ieee80211_tx_rate_control *txrc);
 struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
 void rate_control_put(struct rate_control_ref *ref);
 
@@ -64,12 +63,6 @@
 }
 
 
-static inline void rate_control_clear(struct ieee80211_local *local)
-{
-	struct rate_control_ref *ref = local->rate_ctrl;
-	ref->ops->clear(ref->priv);
-}
-
 static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
 					   struct ieee80211_sta *sta,
 					   gfp_t gfp)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index f6d69da..2b3b490 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -126,7 +126,9 @@
 			mr->adjusted_retry_count = mr->retry_count >> 1;
 			if (mr->adjusted_retry_count > 2)
 				mr->adjusted_retry_count = 2;
+			mr->sample_limit = 4;
 		} else {
+			mr->sample_limit = -1;
 			mr->adjusted_retry_count = mr->retry_count;
 		}
 		if (!mr->adjusted_retry_count)
@@ -169,30 +171,20 @@
 {
 	struct minstrel_sta_info *mi = priv_sta;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_altrate *ar = info->status.retries;
-	struct minstrel_priv *mp = priv;
-	int i, ndx, tries;
-	int success = 0;
+	struct ieee80211_tx_rate *ar = info->status.rates;
+	int i, ndx;
+	int success;
 
-	if (!info->status.excessive_retries)
-		success = 1;
+	success = !!(info->flags & IEEE80211_TX_STAT_ACK);
 
-	if (!mp->has_mrr || (ar[0].rate_idx < 0)) {
-		ndx = rix_to_ndx(mi, info->tx_rate_idx);
-		tries = info->status.retry_count + 1;
-		mi->r[ndx].success += success;
-		mi->r[ndx].attempts += tries;
-		return;
-	}
-
-	for (i = 0; i < 4; i++) {
-		if (ar[i].rate_idx < 0)
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		if (ar[i].idx < 0)
 			break;
 
-		ndx = rix_to_ndx(mi, ar[i].rate_idx);
-		mi->r[ndx].attempts += ar[i].limit + 1;
+		ndx = rix_to_ndx(mi, ar[i].idx);
+		mi->r[ndx].attempts += ar[i].count;
 
-		if ((i != 3) && (ar[i + 1].rate_idx < 0))
+		if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
 			mi->r[ndx].success += success;
 	}
 
@@ -210,9 +202,9 @@
 {
 	unsigned int retry = mr->adjusted_retry_count;
 
-	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
 		retry = max(2U, min(mr->retry_count_rtscts, retry));
-	else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+	else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		retry = max(2U, min(mr->retry_count_cts, retry));
 	return retry;
 }
@@ -233,15 +225,16 @@
 	return sample_ndx;
 }
 
-void
-minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband,
-                  struct ieee80211_sta *sta, void *priv_sta,
-                  struct sk_buff *skb, struct rate_selection *sel)
+static void
+minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
+		  void *priv_sta, struct ieee80211_tx_rate_control *txrc)
 {
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_supported_band *sband = txrc->sband;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct minstrel_sta_info *mi = priv_sta;
 	struct minstrel_priv *mp = priv;
-	struct ieee80211_tx_altrate *ar = info->control.retries;
+	struct ieee80211_tx_rate *ar = info->control.rates;
 	unsigned int ndx, sample_ndx = 0;
 	bool mrr;
 	bool sample_slower = false;
@@ -251,16 +244,12 @@
 	int sample_rate;
 
 	if (!sta || !mi || use_low_rate(skb)) {
-		sel->rate_idx = rate_lowest_index(sband, sta);
+		ar[0].idx = rate_lowest_index(sband, sta);
+		ar[0].count = mp->max_retry;
 		return;
 	}
 
-	mrr = mp->has_mrr;
-
-	/* mac80211 does not allow mrr for RTS/CTS */
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
-		mrr = false;
+	mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
 
 	if (time_after(jiffies, mi->stats_update + (mp->update_interval *
 			HZ) / 1000))
@@ -278,7 +267,8 @@
 			(mi->sample_count + mi->sample_deferred / 2);
 
 	/* delta > 0: sampling required */
-	if (delta > 0) {
+	if ((delta > 0) && (mrr || !mi->prev_sample)) {
+		struct minstrel_rate *msr;
 		if (mi->packet_count >= 10000) {
 			mi->sample_deferred = 0;
 			mi->sample_count = 0;
@@ -297,13 +287,20 @@
 		}
 
 		sample_ndx = minstrel_get_next_sample(mi);
+		msr = &mi->r[sample_ndx];
 		sample = true;
-		sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time >
+		sample_slower = mrr && (msr->perfect_tx_time >
 			mi->r[ndx].perfect_tx_time);
 
 		if (!sample_slower) {
-			ndx = sample_ndx;
-			mi->sample_count++;
+			if (msr->sample_limit != 0) {
+				ndx = sample_ndx;
+				mi->sample_count++;
+				if (msr->sample_limit > 0)
+					msr->sample_limit--;
+			} else {
+				sample = false;
+			}
 		} else {
 			/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
 			 * packets that have the sampling rate deferred to the
@@ -315,13 +312,22 @@
 			mi->sample_deferred++;
 		}
 	}
-	sel->rate_idx = mi->r[ndx].rix;
-	info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info);
+	mi->prev_sample = sample;
+
+	/* If we're not using MRR and the sampling rate already
+	 * has a probability of >95%, we shouldn't be attempting
+	 * to use it, as this only wastes precious airtime */
+	if (!mrr && sample && (mi->r[ndx].probability > 17100))
+		ndx = mi->max_tp_rate;
+
+	ar[0].idx = mi->r[ndx].rix;
+	ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
 
 	if (!mrr) {
-		ar[0].rate_idx = mi->lowest_rix;
-		ar[0].limit = mp->max_retry;
-		ar[1].rate_idx = -1;
+		if (!sample)
+			ar[0].count = mp->max_retry;
+		ar[1].idx = mi->lowest_rix;
+		ar[1].count = mp->max_retry;
 		return;
 	}
 
@@ -336,9 +342,9 @@
 	}
 	mrr_ndx[1] = mi->max_prob_rate;
 	mrr_ndx[2] = 0;
-	for (i = 0; i < 3; i++) {
-		ar[i].rate_idx = mi->r[mrr_ndx[i]].rix;
-		ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count;
+	for (i = 1; i < 4; i++) {
+		ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
+		ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
 	}
 }
 
@@ -415,6 +421,7 @@
 
 		/* calculate maximum number of retransmissions before
 		 * fallback (based on maximum segment size) */
+		mr->sample_limit = -1;
 		mr->retry_count = 1;
 		mr->retry_count_cts = 1;
 		mr->retry_count_rtscts = 1;
@@ -500,11 +507,6 @@
 	kfree(mi);
 }
 
-static void
-minstrel_clear(void *priv)
-{
-}
-
 static void *
 minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
@@ -532,13 +534,13 @@
 	/* maximum time that the hw is allowed to stay in one MRR segment */
 	mp->segment_size = 6000;
 
-	if (hw->max_altrate_tries > 0)
-		mp->max_retry = hw->max_altrate_tries;
+	if (hw->max_rate_tries > 0)
+		mp->max_retry = hw->max_rate_tries;
 	else
 		/* safe default, does not necessarily have to match hw properties */
 		mp->max_retry = 7;
 
-	if (hw->max_altrates >= 3)
+	if (hw->max_rates >= 4)
 		mp->has_mrr = true;
 
 	mp->hw = hw;
@@ -558,7 +560,6 @@
 	.tx_status = minstrel_tx_status,
 	.get_rate = minstrel_get_rate,
 	.rate_init = minstrel_rate_init,
-	.clear = minstrel_clear,
 	.alloc = minstrel_alloc,
 	.free = minstrel_free,
 	.alloc_sta = minstrel_alloc_sta,
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 9a90a6a..869fe0e 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -16,6 +16,7 @@
 	unsigned int perfect_tx_time;
 	unsigned int ack_time;
 
+	int sample_limit;
 	unsigned int retry_count;
 	unsigned int retry_count_cts;
 	unsigned int retry_count_rtscts;
@@ -57,6 +58,7 @@
 
 	int n_rates;
 	struct minstrel_rate *r;
+	bool prev_sample;
 
 	/* sampling table */
 	u8 *sample_table;
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h
index 01d64d5..1a873f0 100644
--- a/net/mac80211/rc80211_pid.h
+++ b/net/mac80211/rc80211_pid.h
@@ -49,7 +49,7 @@
 
 /* Arithmetic right shift for positive and negative values for ISO C. */
 #define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \
-	(x) < 0 ? -((-(x)) >> (y)) : (x) >> (y)
+	((x) < 0 ? -((-(x)) >> (y)) : (x) >> (y))
 
 enum rc_pid_event_type {
 	RC_PID_EVENT_TYPE_TX_STATUS,
@@ -61,6 +61,7 @@
 union rc_pid_event_data {
 	/* RC_PID_EVENT_TX_STATUS */
 	struct {
+		u32 flags;
 		struct ieee80211_tx_info tx_status;
 	};
 	/* RC_PID_EVENT_TYPE_RATE_CHANGE */
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index 86eb374..2328ba5 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -241,7 +241,7 @@
 
 	/* Ignore all frames that were sent with a different rate than the rate
 	 * we currently advise mac80211 to use. */
-	if (info->tx_rate_idx != spinfo->txrate_idx)
+	if (info->status.rates[0].idx != spinfo->txrate_idx)
 		return;
 
 	spinfo->tx_num_xmit++;
@@ -253,10 +253,10 @@
 	/* We count frames that totally failed to be transmitted as two bad
 	 * frames, those that made it out but had some retries as one good and
 	 * one bad frame. */
-	if (info->status.excessive_retries) {
+	if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
 		spinfo->tx_num_failed += 2;
 		spinfo->tx_num_xmit++;
-	} else if (info->status.retry_count) {
+	} else if (info->status.rates[0].count) {
 		spinfo->tx_num_failed++;
 		spinfo->tx_num_xmit++;
 	}
@@ -270,23 +270,32 @@
 }
 
 static void
-rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband,
-			  struct ieee80211_sta *sta, void *priv_sta,
-			  struct sk_buff *skb,
-			  struct rate_selection *sel)
+rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
+			  void *priv_sta,
+			  struct ieee80211_tx_rate_control *txrc)
 {
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_supported_band *sband = txrc->sband;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct rc_pid_sta_info *spinfo = priv_sta;
 	int rateidx;
 	u16 fc;
 
+	if (txrc->rts)
+		info->control.rates[0].count =
+			txrc->hw->conf.long_frame_max_tx_count;
+	else
+		info->control.rates[0].count =
+			txrc->hw->conf.short_frame_max_tx_count;
+
 	/* Send management frames and broadcast/multicast data using lowest
 	 * rate. */
 	fc = le16_to_cpu(hdr->frame_control);
 	if (!sta || !spinfo ||
 	    (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
 	    is_multicast_ether_addr(hdr->addr1)) {
-		sel->rate_idx = rate_lowest_index(sband, sta);
+		info->control.rates[0].idx = rate_lowest_index(sband, sta);
 		return;
 	}
 
@@ -295,7 +304,7 @@
 	if (rateidx >= sband->n_bitrates)
 		rateidx = sband->n_bitrates - 1;
 
-	sel->rate_idx = rateidx;
+	info->control.rates[0].idx = rateidx;
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	rate_control_pid_event_tx_rate(&spinfo->events,
@@ -437,10 +446,6 @@
 	kfree(pinfo);
 }
 
-static void rate_control_pid_clear(void *priv)
-{
-}
-
 static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta,
 					gfp_t gfp)
 {
@@ -471,7 +476,6 @@
 	.tx_status = rate_control_pid_tx_status,
 	.get_rate = rate_control_pid_get_rate,
 	.rate_init = rate_control_pid_rate_init,
-	.clear = rate_control_pid_clear,
 	.alloc = rate_control_pid_alloc,
 	.free = rate_control_pid_free,
 	.alloc_sta = rate_control_pid_alloc_sta,
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
index 8121d3b..a08a9b5 100644
--- a/net/mac80211/rc80211_pid_debugfs.c
+++ b/net/mac80211/rc80211_pid_debugfs.c
@@ -43,6 +43,7 @@
 {
 	union rc_pid_event_data evd;
 
+	evd.flags = stat->flags;
 	memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info));
 	rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd);
 }
@@ -167,8 +168,8 @@
 	switch (ev->type) {
 	case RC_PID_EVENT_TYPE_TX_STATUS:
 		p += snprintf(pb + p, length - p, "tx_status %u %u",
-			      ev->data.tx_status.status.excessive_retries,
-			      ev->data.tx_status.status.retry_count);
+			      !(ev->data.flags & IEEE80211_TX_STAT_ACK),
+			      ev->data.tx_status.status.rates[0].idx);
 		break;
 	case RC_PID_EVENT_TYPE_RATE_CHANGE:
 		p += snprintf(pb + p, length - p, "rate_change %d %d",
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index cf6b121..648a1d0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -26,10 +26,11 @@
 #include "tkip.h"
 #include "wme.h"
 
-u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
-				struct tid_ampdu_rx *tid_agg_rx,
-				struct sk_buff *skb, u16 mpdu_seq_num,
-				int bar_req);
+static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+					   struct tid_ampdu_rx *tid_agg_rx,
+					   struct sk_buff *skb,
+					   u16 mpdu_seq_num,
+					   int bar_req);
 /*
  * monitor mode reception
  *
@@ -653,13 +654,12 @@
 static void ap_sta_ps_start(struct sta_info *sta)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	DECLARE_MAC_BUF(mac);
 
 	atomic_inc(&sdata->bss->num_sta_ps);
 	set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-	printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
-	       sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
+	printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
+	       sdata->dev->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 }
 
@@ -669,8 +669,6 @@
 	struct ieee80211_local *local = sdata->local;
 	struct sk_buff *skb;
 	int sent = 0;
-	struct ieee80211_tx_info *info;
-	DECLARE_MAC_BUF(mac);
 
 	atomic_dec(&sdata->bss->num_sta_ps);
 
@@ -680,27 +678,25 @@
 		sta_info_clear_tim_bit(sta);
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-	printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
-	       sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
+	printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
+	       sdata->dev->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
 	/* Send all buffered frames to the station */
 	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
-		info = IEEE80211_SKB_CB(skb);
 		sent++;
-		info->flags |= IEEE80211_TX_CTL_REQUEUE;
+		skb->requeue = 1;
 		dev_queue_xmit(skb);
 	}
 	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
-		info = IEEE80211_SKB_CB(skb);
 		local->total_ps_buffered--;
 		sent++;
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-		printk(KERN_DEBUG "%s: STA %s aid %d send PS frame "
+		printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame "
 		       "since STA not sleeping anymore\n", sdata->dev->name,
-		       print_mac(mac, sta->sta.addr), sta->sta.aid);
+		       sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-		info->flags |= IEEE80211_TX_CTL_REQUEUE;
+		skb->requeue = 1;
 		dev_queue_xmit(skb);
 	}
 
@@ -789,15 +785,12 @@
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		struct ieee80211_hdr *hdr =
 			(struct ieee80211_hdr *) entry->skb_list.next->data;
-		DECLARE_MAC_BUF(mac);
-		DECLARE_MAC_BUF(mac2);
 		printk(KERN_DEBUG "%s: RX reassembly removed oldest "
 		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
-		       "addr1=%s addr2=%s\n",
+		       "addr1=%pM addr2=%pM\n",
 		       sdata->dev->name, idx,
 		       jiffies - entry->first_frag_time, entry->seq,
-		       entry->last_frag, print_mac(mac, hdr->addr1),
-		       print_mac(mac2, hdr->addr2));
+		       entry->last_frag, hdr->addr1, hdr->addr2);
 #endif
 		__skb_queue_purge(&entry->skb_list);
 	}
@@ -866,7 +859,6 @@
 	unsigned int frag, seq;
 	struct ieee80211_fragment_entry *entry;
 	struct sk_buff *skb;
-	DECLARE_MAC_BUF(mac);
 
 	hdr = (struct ieee80211_hdr *)rx->skb->data;
 	fc = hdr->frame_control;
@@ -970,7 +962,6 @@
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
 	struct sk_buff *skb;
 	int no_pending_pkts;
-	DECLARE_MAC_BUF(mac);
 	__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
 
 	if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
@@ -1001,8 +992,8 @@
 		set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-		printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
-		       print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid,
+		printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
+		       rx->sta->sta.addr, rx->sta->sta.aid,
 		       skb_queue_len(&rx->sta->ps_tx_buf));
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
@@ -1025,9 +1016,9 @@
 		 *	  Should we send it a null-func frame indicating we
 		 *	  have nothing buffered for it?
 		 */
-		printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
+		printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
 		       "though there are no buffered frames for it\n",
-		       rx->dev->name, print_mac(mac, rx->sta->sta.addr));
+		       rx->dev->name, rx->sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 	}
 
@@ -1097,10 +1088,6 @@
 	u8 src[ETH_ALEN] __aligned(2);
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
-	DECLARE_MAC_BUF(mac3);
-	DECLARE_MAC_BUF(mac4);
 
 	if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
 		return -1;
@@ -1279,7 +1266,6 @@
 	int remaining, err;
 	u8 dst[ETH_ALEN];
 	u8 src[ETH_ALEN];
-	DECLARE_MAC_BUF(mac);
 
 	if (unlikely(!ieee80211_is_data(fc)))
 		return RX_CONTINUE;
@@ -1552,14 +1538,6 @@
 	if (len < IEEE80211_MIN_ACTION_SIZE + 1)
 		return RX_DROP_MONITOR;
 
-	/*
-	 * FIXME: revisit this, I'm sure we should handle most
-	 *	  of these frames in other modes as well!
-	 */
-	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
-		return RX_CONTINUE;
-
 	switch (mgmt->u.action.category) {
 	case WLAN_CATEGORY_BACK:
 		switch (mgmt->u.action.u.addba_req.action_code) {
@@ -1632,8 +1610,6 @@
 {
 	int keyidx;
 	unsigned int hdrlen;
-	DECLARE_MAC_BUF(mac);
-	DECLARE_MAC_BUF(mac2);
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	if (rx->skb->len >= hdrlen + 4)
@@ -2002,17 +1978,17 @@
 
 static inline int seq_less(u16 sq1, u16 sq2)
 {
-	return (((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1));
+	return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
 }
 
 static inline u16 seq_inc(u16 sq)
 {
-	return ((sq + 1) & SEQ_MASK);
+	return (sq + 1) & SEQ_MASK;
 }
 
 static inline u16 seq_sub(u16 sq1, u16 sq2)
 {
-	return ((sq1 - sq2) & SEQ_MASK);
+	return (sq1 - sq2) & SEQ_MASK;
 }
 
 
@@ -2020,10 +1996,11 @@
  * As it function blongs to Rx path it must be called with
  * the proper rcu_read_lock protection for its flow.
  */
-u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
-				struct tid_ampdu_rx *tid_agg_rx,
-				struct sk_buff *skb, u16 mpdu_seq_num,
-				int bar_req)
+static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+					   struct tid_ampdu_rx *tid_agg_rx,
+					   struct sk_buff *skb,
+					   u16 mpdu_seq_num,
+					   int bar_req)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_rx_status status;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 416bb41..f5c7c33 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -159,7 +159,7 @@
 {
 	struct ieee80211_bss *bss;
 
-	if (mesh_config_len != MESH_CFG_LEN)
+	if (mesh_config_len != IEEE80211_MESH_CONFIG_LEN)
 		return NULL;
 
 	bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
@@ -448,18 +448,17 @@
 
 	if (local->hw_scanning) {
 		local->hw_scanning = false;
-		if (ieee80211_hw_config(local))
-			printk(KERN_DEBUG "%s: failed to restore operational "
-			       "channel after scan\n", wiphy_name(local->hw.wiphy));
-
+		/*
+		 * Somebody might have requested channel change during scan
+		 * that we won't have acted upon, try now. ieee80211_hw_config
+		 * will set the flag based on actual changes.
+		 */
+		ieee80211_hw_config(local, 0);
 		goto done;
 	}
 
 	local->sw_scanning = false;
-	if (ieee80211_hw_config(local))
-		printk(KERN_DEBUG "%s: failed to restore operational "
-		       "channel after scan\n", wiphy_name(local->hw.wiphy));
-
+	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
 	netif_tx_lock_bh(local->mdev);
 	netif_addr_lock(local->mdev);
@@ -546,12 +545,9 @@
 
 		if (!skip) {
 			local->scan_channel = chan;
-			if (ieee80211_hw_config(local)) {
-				printk(KERN_DEBUG "%s: failed to set freq to "
-				       "%d MHz for scan\n", wiphy_name(local->hw.wiphy),
-				       chan->center_freq);
+			if (ieee80211_hw_config(local,
+						IEEE80211_CONF_CHANGE_CHANNEL))
 				skip = 1;
-			}
 		}
 
 		/* advance state machine to next channel/band */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 7fef8ea..b22110a 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -137,14 +137,12 @@
 static void __sta_info_free(struct ieee80211_local *local,
 			    struct sta_info *sta)
 {
-	DECLARE_MAC_BUF(mbuf);
-
 	rate_control_free_sta(sta);
 	rate_control_put(sta->rate_ctrl);
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Destroyed STA %s\n",
-	       wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr));
+	printk(KERN_DEBUG "%s: Destroyed STA %pM\n",
+	       wiphy_name(local->hw.wiphy), sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 	kfree(sta);
@@ -222,7 +220,6 @@
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 	int i;
-	DECLARE_MAC_BUF(mbuf);
 
 	sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
 	if (!sta)
@@ -263,8 +260,8 @@
 	skb_queue_head_init(&sta->tx_filtered);
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Allocated STA %s\n",
-	       wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr));
+	printk(KERN_DEBUG "%s: Allocated STA %pM\n",
+	       wiphy_name(local->hw.wiphy), sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 #ifdef CONFIG_MAC80211_MESH
@@ -281,7 +278,6 @@
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	unsigned long flags;
 	int err = 0;
-	DECLARE_MAC_BUF(mac);
 
 	/*
 	 * Can't be a WARN_ON because it can be triggered through a race:
@@ -294,7 +290,7 @@
 	}
 
 	if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 ||
-	            is_multicast_ether_addr(sta->sta.addr))) {
+		    is_multicast_ether_addr(sta->sta.addr))) {
 		err = -EINVAL;
 		goto out_free;
 	}
@@ -322,8 +318,8 @@
 	}
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Inserted STA %s\n",
-	       wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr));
+	printk(KERN_DEBUG "%s: Inserted STA %pM\n",
+	       wiphy_name(local->hw.wiphy), sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 	spin_unlock_irqrestore(&local->sta_lock, flags);
@@ -423,9 +419,6 @@
 {
 	struct ieee80211_local *local = (*sta)->local;
 	struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	DECLARE_MAC_BUF(mbuf);
-#endif
 	/*
 	 * pull caller's reference if we're already gone.
 	 */
@@ -468,8 +461,8 @@
 	}
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Removed STA %s\n",
-	       wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr));
+	printk(KERN_DEBUG "%s: Removed STA %pM\n",
+	       wiphy_name(local->hw.wiphy), (*sta)->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 	/*
@@ -544,7 +537,6 @@
 	unsigned long flags;
 	struct sk_buff *skb;
 	struct ieee80211_sub_if_data *sdata;
-	DECLARE_MAC_BUF(mac);
 
 	if (skb_queue_empty(&sta->ps_tx_buf))
 		return;
@@ -564,8 +556,8 @@
 		sdata = sta->sdata;
 		local->total_ps_buffered--;
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-		printk(KERN_DEBUG "Buffered frame expired (STA "
-		       "%s)\n", print_mac(mac, sta->sta.addr));
+		printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n",
+		       sta->sta.addr);
 #endif
 		dev_kfree_skb(skb);
 
@@ -809,15 +801,14 @@
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta, *tmp;
 	LIST_HEAD(tmp_list);
-	DECLARE_MAC_BUF(mac);
 	unsigned long flags;
 
 	spin_lock_irqsave(&local->sta_lock, flags);
 	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
 		if (time_after(jiffies, sta->last_rx + exp_time)) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-			printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
-			       sdata->dev->name, print_mac(mac, sta->sta.addr));
+			printk(KERN_DEBUG "%s: expiring inactive STA %pM\n",
+			       sdata->dev->name, sta->sta.addr);
 #endif
 			__sta_info_unlink(&sta);
 			if (sta)
@@ -830,7 +821,7 @@
 }
 
 struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
-                                         const u8 *addr)
+					 const u8 *addr)
 {
 	struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 168a39a..5ad9250 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -160,18 +160,20 @@
  * @list: global linked list entry
  * @hnext: hash table linked list pointer
  * @local: pointer to the global information
- * @sdata: TBD
- * @key: TBD
- * @rate_ctrl: TBD
- * @rate_ctrl_priv: TBD
+ * @sdata: virtual interface this station belongs to
+ * @key: peer key negotiated with this station, if any
+ * @rate_ctrl: rate control algorithm reference
+ * @rate_ctrl_priv: rate control private per-STA pointer
+ * @last_tx_rate: rate used for last transmit, to report to userspace as
+ *	"the" transmit rate
  * @lock: used for locking all fields that require locking, see comments
  *	in the header file.
  * @flaglock: spinlock for flags accesses
  * @addr: MAC address of this STA
  * @aid: STA's unique AID (1..2007, 0 = not assigned yet),
  *	only used in AP (and IBSS?) mode
- * @listen_interval: TBD
- * @pin_status: TBD
+ * @listen_interval: listen interval of this station, when we're acting as AP
+ * @pin_status: used internally for pinning a STA struct into memory
  * @flags: STA flags, see &enum ieee80211_sta_info_flags
  * @ps_tx_buf: buffer of frames to transmit to this station
  *	when it leaves power saving state
@@ -180,8 +182,8 @@
  *	power saving state
  * @rx_packets: Number of MSDUs received from this STA
  * @rx_bytes: Number of bytes received from this STA
- * @wep_weak_iv_count: TBD
- * @last_rx: TBD
+ * @wep_weak_iv_count: number of weak WEP IVs received from this station
+ * @last_rx: time (in jiffies) when last frame was received from this STA
  * @num_duplicates: number of duplicate frames received from this STA
  * @rx_fragments: number of received MPDUs
  * @rx_dropped: number of dropped MPDUs from this STA
@@ -189,26 +191,26 @@
  * @last_qual: qual of last received frame from this STA
  * @last_noise: noise of last received frame from this STA
  * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
- * @tx_filtered_count: TBD
- * @tx_retry_failed: TBD
- * @tx_retry_count: TBD
+ * @tx_filtered_count: number of frames the hardware filtered for this STA
+ * @tx_retry_failed: number of frames that failed retry
+ * @tx_retry_count: total number of retries for frames to this STA
  * @fail_avg: moving percentage of failed MSDUs
  * @tx_packets: number of RX/TX MSDUs
- * @tx_bytes: TBD
+ * @tx_bytes: number of bytes transmitted to this STA
  * @tx_fragments: number of transmitted MPDUs
- * @last_txrate_idx: Index of the last used transmit rate
- * @tid_seq: TBD
- * @ampdu_mlme: TBD
+ * @last_txrate: description of the last used transmit rate
+ * @tid_seq: per-TID sequence numbers for sending to this STA
+ * @ampdu_mlme: A-MPDU state machine state
  * @timer_to_tid: identity mapping to ID timers
  * @tid_to_tx_q: map tid to tx queue
  * @llid: Local link ID
  * @plid: Peer link ID
  * @reason: Cancel reason on PLINK_HOLDING state
  * @plink_retries: Retries in establishment
- * @ignore_plink_timer: TBD
- * @plink_state plink_state: TBD
- * @plink_timeout: TBD
- * @plink_timer: TBD
+ * @ignore_plink_timer: ignore the peer-link timer (used internally)
+ * @plink_state: peer link state
+ * @plink_timeout: timeout of peer link
+ * @plink_timer: peer link watch timer
  * @debugfs: debug filesystem info
  * @sta: station information we share with the driver
  */
@@ -267,7 +269,7 @@
 	unsigned long tx_packets;
 	unsigned long tx_bytes;
 	unsigned long tx_fragments;
-	unsigned int last_txrate_idx;
+	struct ieee80211_tx_rate last_tx_rate;
 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
 
 	/*
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index 34b32bc..38fa111 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -263,10 +263,9 @@
 	     (iv32 == key->u.tkip.rx[queue].iv32 &&
 	      iv16 <= key->u.tkip.rx[queue].iv16))) {
 #ifdef CONFIG_MAC80211_TKIP_DEBUG
-		DECLARE_MAC_BUF(mac);
 		printk(KERN_DEBUG "TKIP replay detected for RX frame from "
-		       "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
-		       print_mac(mac, ta),
+		       "%pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
+		       ta,
 		       iv32, iv16, key->u.tkip.rx[queue].iv32,
 		       key->u.tkip.rx[queue].iv16);
 #endif
@@ -287,9 +286,8 @@
 		{
 			int i;
 			u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY;
-			DECLARE_MAC_BUF(mac);
-			printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s"
-			       " TK=", print_mac(mac, ta));
+			printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%pM"
+			       " TK=", ta);
 			for (i = 0; i < 16; i++)
 				printk("%02x ",
 				       key->conf.key[key_offset + i]);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1460537..0d81b2c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -46,13 +46,20 @@
 	struct ieee80211_local *local = tx->local;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_hdr *hdr;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
+	/* assume HW handles this */
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+		return 0;
+
+	/* uh huh? */
+	if (WARN_ON_ONCE(info->control.rates[0].idx < 0))
+		return 0;
 
 	sband = local->hw.wiphy->bands[tx->channel->band];
-	txrate = &sband->bitrates[tx->rate_idx];
+	txrate = &sband->bitrates[info->control.rates[0].idx];
 
-	erp = 0;
-	if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-		erp = txrate->flags & IEEE80211_RATE_ERP_G;
+	erp = txrate->flags & IEEE80211_RATE_ERP_G;
 
 	/*
 	 * data and mgmt (except PS Poll):
@@ -116,7 +123,7 @@
 		if (r->bitrate > txrate->bitrate)
 			break;
 
-		if (tx->sdata->bss_conf.basic_rates & BIT(i))
+		if (tx->sdata->vif.bss_conf.basic_rates & BIT(i))
 			rate = r->bitrate;
 
 		switch (sband->band) {
@@ -150,7 +157,7 @@
 	 * to closest integer */
 
 	dur = ieee80211_frame_duration(local, 10, rate, erp,
-				tx->sdata->bss_conf.use_short_preamble);
+				tx->sdata->vif.bss_conf.use_short_preamble);
 
 	if (next_frag_len) {
 		/* Frame is fragmented: duration increases with time needed to
@@ -159,7 +166,7 @@
 		/* next fragment */
 		dur += ieee80211_frame_duration(local, next_frag_len,
 				txrate->bitrate, erp,
-				tx->sdata->bss_conf.use_short_preamble);
+				tx->sdata->vif.bss_conf.use_short_preamble);
 	}
 
 	return cpu_to_le16(dur);
@@ -201,10 +208,9 @@
 			     tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
 			     ieee80211_is_data(hdr->frame_control))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-			DECLARE_MAC_BUF(mac);
 			printk(KERN_DEBUG "%s: dropped data frame to not "
-			       "associated station %s\n",
-			       tx->dev->name, print_mac(mac, hdr->addr1));
+			       "associated station %pM\n",
+			       tx->dev->name, hdr->addr1);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
 			return TX_DROP;
@@ -331,7 +337,6 @@
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 	u32 staflags;
-	DECLARE_MAC_BUF(mac);
 
 	if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control)))
 		return TX_CONTINUE;
@@ -341,9 +346,9 @@
 	if (unlikely((staflags & WLAN_STA_PS) &&
 		     !(staflags & WLAN_STA_PSPOLL))) {
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-		printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
+		printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries "
 		       "before %d)\n",
-		       print_mac(mac, sta->sta.addr), sta->sta.aid,
+		       sta->sta.addr, sta->sta.aid,
 		       skb_queue_len(&sta->ps_tx_buf));
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -352,9 +357,9 @@
 			struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 			if (net_ratelimit()) {
-				printk(KERN_DEBUG "%s: STA %s TX "
+				printk(KERN_DEBUG "%s: STA %pM TX "
 				       "buffer full - dropping oldest frame\n",
-				       tx->dev->name, print_mac(mac, sta->sta.addr));
+				       tx->dev->name, sta->sta.addr);
 			}
 #endif
 			dev_kfree_skb(old);
@@ -371,9 +376,9 @@
 	}
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) {
-		printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll "
+		printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll "
 		       "set -> send frame\n", tx->dev->name,
-		       print_mac(mac, sta->sta.addr));
+		       sta->sta.addr);
 	}
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 	clear_sta_flags(sta, WLAN_STA_PSPOLL);
@@ -439,47 +444,145 @@
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
 {
-	struct rate_selection rsel;
-	struct ieee80211_supported_band *sband;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+	struct ieee80211_hdr *hdr = (void *)tx->skb->data;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_rate *rate;
+	int i, len;
+	bool inval = false, rts = false, short_preamble = false;
+	struct ieee80211_tx_rate_control txrc;
+
+	memset(&txrc, 0, sizeof(txrc));
 
 	sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
-	if (likely(tx->rate_idx < 0)) {
-		rate_control_get_rate(tx->sdata, sband, tx->sta,
-				      tx->skb, &rsel);
-		if (tx->sta)
-			tx->sta->last_txrate_idx = rsel.rate_idx;
-		tx->rate_idx = rsel.rate_idx;
-		if (unlikely(rsel.probe_idx >= 0)) {
-			info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-			tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-			info->control.retries[0].rate_idx = tx->rate_idx;
-			info->control.retries[0].limit = tx->local->hw.max_altrate_tries;
-			tx->rate_idx = rsel.probe_idx;
-		} else if (info->control.retries[0].limit == 0)
-			info->control.retries[0].rate_idx = -1;
+	len = min_t(int, tx->skb->len + FCS_LEN,
+			 tx->local->fragmentation_threshold);
 
-		if (unlikely(tx->rate_idx < 0))
-			return TX_DROP;
-	} else
-		info->control.retries[0].rate_idx = -1;
+	/* set up the tx rate control struct we give the RC algo */
+	txrc.hw = local_to_hw(tx->local);
+	txrc.sband = sband;
+	txrc.bss_conf = &tx->sdata->vif.bss_conf;
+	txrc.skb = tx->skb;
+	txrc.reported_rate.idx = -1;
+	txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
 
-	if (tx->sdata->bss_conf.use_cts_prot &&
-	    (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
-		tx->last_frag_rate_idx = tx->rate_idx;
-		if (rsel.probe_idx >= 0)
-			tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
-		else
-			tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-		tx->rate_idx = rsel.nonerp_idx;
-		info->tx_rate_idx = rsel.nonerp_idx;
-		info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-	} else {
-		tx->last_frag_rate_idx = tx->rate_idx;
-		info->tx_rate_idx = tx->rate_idx;
+	/* set up RTS protection if desired */
+	if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD &&
+	    len > tx->local->rts_threshold) {
+		txrc.rts = rts = true;
 	}
-	info->tx_rate_idx = tx->rate_idx;
+
+	/*
+	 * Use short preamble if the BSS can handle it, but not for
+	 * management frames unless we know the receiver can handle
+	 * that -- the management frame might be to a station that
+	 * just wants a probe response.
+	 */
+	if (tx->sdata->vif.bss_conf.use_short_preamble &&
+	    (ieee80211_is_data(hdr->frame_control) ||
+	     (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
+		txrc.short_preamble = short_preamble = true;
+
+
+	rate_control_get_rate(tx->sdata, tx->sta, &txrc);
+
+	if (unlikely(info->control.rates[0].idx < 0))
+		return TX_DROP;
+
+	if (txrc.reported_rate.idx < 0)
+		txrc.reported_rate = info->control.rates[0];
+
+	if (tx->sta)
+		tx->sta->last_tx_rate = txrc.reported_rate;
+
+	if (unlikely(!info->control.rates[0].count))
+		info->control.rates[0].count = 1;
+
+	if (is_multicast_ether_addr(hdr->addr1)) {
+		/*
+		 * XXX: verify the rate is in the basic rateset
+		 */
+		return TX_CONTINUE;
+	}
+
+	/*
+	 * set up the RTS/CTS rate as the fastest basic rate
+	 * that is not faster than the data rate
+	 *
+	 * XXX: Should this check all retry rates?
+	 */
+	if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+		s8 baserate = 0;
+
+		rate = &sband->bitrates[info->control.rates[0].idx];
+
+		for (i = 0; i < sband->n_bitrates; i++) {
+			/* must be a basic rate */
+			if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i)))
+				continue;
+			/* must not be faster than the data rate */
+			if (sband->bitrates[i].bitrate > rate->bitrate)
+				continue;
+			/* maximum */
+			if (sband->bitrates[baserate].bitrate <
+			     sband->bitrates[i].bitrate)
+				baserate = i;
+		}
+
+		info->control.rts_cts_rate_idx = baserate;
+	}
+
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		/*
+		 * make sure there's no valid rate following
+		 * an invalid one, just in case drivers don't
+		 * take the API seriously to stop at -1.
+		 */
+		if (inval) {
+			info->control.rates[i].idx = -1;
+			continue;
+		}
+		if (info->control.rates[i].idx < 0) {
+			inval = true;
+			continue;
+		}
+
+		/*
+		 * For now assume MCS is already set up correctly, this
+		 * needs to be fixed.
+		 */
+		if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) {
+			WARN_ON(info->control.rates[i].idx > 76);
+			continue;
+		}
+
+		/* set up RTS protection if desired */
+		if (rts)
+			info->control.rates[i].flags |=
+				IEEE80211_TX_RC_USE_RTS_CTS;
+
+		/* RC is busted */
+		if (WARN_ON_ONCE(info->control.rates[i].idx >=
+				 sband->n_bitrates)) {
+			info->control.rates[i].idx = -1;
+			continue;
+		}
+
+		rate = &sband->bitrates[info->control.rates[i].idx];
+
+		/* set up short preamble */
+		if (short_preamble &&
+		    rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+			info->control.rates[i].flags |=
+				IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+
+		/* set up G protection */
+		if (!rts && tx->sdata->vif.bss_conf.use_cts_prot &&
+		    rate->flags & IEEE80211_RATE_ERP_G)
+			info->control.rates[i].flags |=
+				IEEE80211_TX_RC_USE_CTS_PROTECT;
+	}
 
 	return TX_CONTINUE;
 }
@@ -487,91 +590,7 @@
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-	struct ieee80211_supported_band *sband;
-
-	sband = tx->local->hw.wiphy->bands[tx->channel->band];
-
-	if (tx->sta)
-		info->control.sta = &tx->sta->sta;
-
-	if (!info->control.retry_limit) {
-		if (!is_multicast_ether_addr(hdr->addr1)) {
-			int len = min_t(int, tx->skb->len + FCS_LEN,
-					tx->local->fragmentation_threshold);
-			if (len > tx->local->rts_threshold
-			    && tx->local->rts_threshold <
-						IEEE80211_MAX_RTS_THRESHOLD) {
-				info->flags |= IEEE80211_TX_CTL_USE_RTS_CTS;
-				info->flags |=
-					IEEE80211_TX_CTL_LONG_RETRY_LIMIT;
-				info->control.retry_limit =
-					tx->local->long_retry_limit;
-			} else {
-				info->control.retry_limit =
-					tx->local->short_retry_limit;
-			}
-		} else {
-			info->control.retry_limit = 1;
-		}
-	}
-
-	if (tx->flags & IEEE80211_TX_FRAGMENTED) {
-		/* Do not use multiple retry rates when sending fragmented
-		 * frames.
-		 * TODO: The last fragment could still use multiple retry
-		 * rates. */
-		info->control.retries[0].rate_idx = -1;
-	}
-
-	/* Use CTS protection for unicast frames sent using extended rates if
-	 * there are associated non-ERP stations and RTS/CTS is not configured
-	 * for the frame. */
-	if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
-	    (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) &&
-	    (tx->flags & IEEE80211_TX_UNICAST) &&
-	    tx->sdata->bss_conf.use_cts_prot &&
-	    !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS))
-		info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT;
-
-	/* Transmit data frames using short preambles if the driver supports
-	 * short preambles at the selected rate and short preambles are
-	 * available on the network at the current point in time. */
-	if (ieee80211_is_data(hdr->frame_control) &&
-	    (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
-	    tx->sdata->bss_conf.use_short_preamble &&
-	    (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
-		info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
-	}
-
-	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
-	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
-		struct ieee80211_rate *rate;
-		s8 baserate = -1;
-		int idx;
-
-		/* Do not use multiple retry rates when using RTS/CTS */
-		info->control.retries[0].rate_idx = -1;
-
-		/* Use min(data rate, max base rate) as CTS/RTS rate */
-		rate = &sband->bitrates[tx->rate_idx];
-
-		for (idx = 0; idx < sband->n_bitrates; idx++) {
-			if (sband->bitrates[idx].bitrate > rate->bitrate)
-				continue;
-			if (tx->sdata->bss_conf.basic_rates & BIT(idx) &&
-			    (baserate < 0 ||
-			     (sband->bitrates[baserate].bitrate
-			      < sband->bitrates[idx].bitrate)))
-				baserate = idx;
-		}
-
-		if (baserate >= 0)
-			info->control.rts_cts_rate_idx = baserate;
-		else
-			info->control.rts_cts_rate_idx = 0;
-	}
 
 	if (tx->sta)
 		info->control.sta = &tx->sta->sta;
@@ -602,8 +621,18 @@
 	if (ieee80211_hdrlen(hdr->frame_control) < 24)
 		return TX_CONTINUE;
 
+	/*
+	 * Anything but QoS data that has a sequence number field
+	 * (is long enough) gets a sequence number from the global
+	 * counter.
+	 */
 	if (!ieee80211_is_data_qos(hdr->frame_control)) {
+		/* driver should assign sequence number */
 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
+		/* for pure STA mode without beacons, we can do it */
+		hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
+		tx->sdata->sequence_number += 0x10;
+		tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ;
 		return TX_CONTINUE;
 	}
 
@@ -632,6 +661,7 @@
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
 {
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 	size_t hdrlen, per_fragm, num_fragm, payload_len, left;
 	struct sk_buff **frags, *first, *frag;
@@ -648,9 +678,7 @@
 	 * This scenario is handled in __ieee80211_tx_prepare but extra
 	 * caution taken here as fragmented ampdu may cause Tx stop.
 	 */
-	if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU ||
-		    skb_get_queue_mapping(tx->skb) >=
-			ieee80211_num_regular_queues(&tx->local->hw)))
+	if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
 		return TX_DROP;
 
 	first = tx->skb;
@@ -684,20 +712,45 @@
 				      IEEE80211_ENCRYPT_TAILROOM);
 		if (!frag)
 			goto fail;
+
 		/* Make sure that all fragments use the same priority so
 		 * that they end up using the same TX queue */
 		frag->priority = first->priority;
+
 		skb_reserve(frag, tx->local->tx_headroom +
 				  IEEE80211_ENCRYPT_HEADROOM);
+
+		/* copy TX information */
+		info = IEEE80211_SKB_CB(frag);
+		memcpy(info, first->cb, sizeof(frag->cb));
+
+		/* copy/fill in 802.11 header */
 		fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
 		memcpy(fhdr, first->data, hdrlen);
-		if (i == num_fragm - 2)
-			fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
 		fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
+
+		if (i == num_fragm - 2) {
+			/* clear MOREFRAGS bit for the last fragment */
+			fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
+		} else {
+			/*
+			 * No multi-rate retries for fragmented frames, that
+			 * would completely throw off the NAV at other STAs.
+			 */
+			info->control.rates[1].idx = -1;
+			info->control.rates[2].idx = -1;
+			info->control.rates[3].idx = -1;
+			info->control.rates[4].idx = -1;
+			BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5);
+			info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+		}
+
+		/* copy data */
 		copylen = left > per_fragm ? per_fragm : left;
 		memcpy(skb_put(frag, copylen), pos, copylen);
-		memcpy(frag->cb, first->cb, sizeof(frag->cb));
+
 		skb_copy_queue_mapping(frag, first);
+
 		frag->do_not_encrypt = first->do_not_encrypt;
 
 		pos += copylen;
@@ -757,12 +810,10 @@
 					      tx->extra_frag[0]->len);
 
 	for (i = 0; i < tx->num_extra_frag; i++) {
-		if (i + 1 < tx->num_extra_frag) {
+		if (i + 1 < tx->num_extra_frag)
 			next_len = tx->extra_frag[i + 1]->len;
-		} else {
+		else
 			next_len = 0;
-			tx->rate_idx = tx->last_frag_rate_idx;
-		}
 
 		hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data;
 		hdr->duration_id = ieee80211_duration(tx, 0, next_len);
@@ -815,7 +866,6 @@
 		(struct ieee80211_radiotap_header *) skb->data;
 	struct ieee80211_supported_band *sband;
 	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 	sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
@@ -829,8 +879,6 @@
 	 */
 
 	while (!ret) {
-		int i, target_rate;
-
 		ret = ieee80211_radiotap_iterator_next(&iterator);
 
 		if (ret)
@@ -844,38 +892,6 @@
 		 * get_unaligned((type *)iterator.this_arg) to dereference
 		 * iterator.this_arg for type "type" safely on all arches.
 		*/
-		case IEEE80211_RADIOTAP_RATE:
-			/*
-			 * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps
-			 * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
-			 */
-			target_rate = (*iterator.this_arg) * 5;
-			for (i = 0; i < sband->n_bitrates; i++) {
-				struct ieee80211_rate *r;
-
-				r = &sband->bitrates[i];
-
-				if (r->bitrate == target_rate) {
-					tx->rate_idx = i;
-					break;
-				}
-			}
-			break;
-
-		case IEEE80211_RADIOTAP_ANTENNA:
-			/*
-			 * radiotap uses 0 for 1st ant, mac80211 is 1 for
-			 * 1st ant
-			 */
-			info->antenna_sel_tx = (*iterator.this_arg) + 1;
-			break;
-
-#if 0
-		case IEEE80211_RADIOTAP_DBM_TX_POWER:
-			control->power_level = *iterator.this_arg;
-			break;
-#endif
-
 		case IEEE80211_RADIOTAP_FLAGS:
 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
 				/*
@@ -933,7 +949,8 @@
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-	int hdrlen;
+	int hdrlen, tid;
+	u8 *qc, *state;
 
 	memset(tx, 0, sizeof(*tx));
 	tx->skb = skb;
@@ -941,8 +958,6 @@
 	tx->local = local;
 	tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	tx->channel = local->hw.conf.channel;
-	tx->rate_idx = -1;
-	tx->last_frag_rate_idx = -1;
 	/*
 	 * Set this flag (used below to indicate "automatic fragmentation"),
 	 * it will be cleared/left by radiotap as desired.
@@ -966,6 +981,15 @@
 
 	tx->sta = sta_info_get(local, hdr->addr1);
 
+	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+
+		state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
+		if (*state == HT_AGG_STATE_OPERATIONAL)
+			info->flags |= IEEE80211_TX_CTL_AMPDU;
+	}
+
 	if (is_multicast_ether_addr(hdr->addr1)) {
 		tx->flags &= ~IEEE80211_TX_UNICAST;
 		info->flags |= IEEE80211_TX_CTL_NO_ACK;
@@ -1043,23 +1067,11 @@
 			if (!tx->extra_frag[i])
 				continue;
 			info = IEEE80211_SKB_CB(tx->extra_frag[i]);
-			info->flags &= ~(IEEE80211_TX_CTL_USE_RTS_CTS |
-					 IEEE80211_TX_CTL_USE_CTS_PROTECT |
-					 IEEE80211_TX_CTL_CLEAR_PS_FILT |
+			info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
 					 IEEE80211_TX_CTL_FIRST_FRAGMENT);
 			if (netif_subqueue_stopped(local->mdev,
 						   tx->extra_frag[i]))
 				return IEEE80211_TX_FRAG_AGAIN;
-			if (i == tx->num_extra_frag) {
-				info->tx_rate_idx = tx->last_frag_rate_idx;
-
-				if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
-					info->flags |=
-						IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-				else
-					info->flags &=
-						~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-			}
 
 			ret = local->ops->tx(local_to_hw(local),
 					    tx->extra_frag[i]);
@@ -1168,7 +1180,7 @@
 		 * queues, there's no reason for a driver to reject
 		 * a frame there, warn and drop it.
 		 */
-		if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw)))
+		if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
 			goto drop;
 
 		store = &local->pending_packet[queue];
@@ -1196,9 +1208,6 @@
 		store->skb = skb;
 		store->extra_frag = tx.extra_frag;
 		store->num_extra_frag = tx.num_extra_frag;
-		store->last_frag_rate_idx = tx.last_frag_rate_idx;
-		store->last_frag_rate_ctrl_probe =
-			!!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
 	}
  out:
 	rcu_read_unlock();
@@ -1593,12 +1602,10 @@
 		       compare_ether_addr(dev->dev_addr,
 					  skb->data + ETH_ALEN) == 0))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-		DECLARE_MAC_BUF(mac);
-
 		if (net_ratelimit())
-			printk(KERN_DEBUG "%s: dropped frame to %s"
+			printk(KERN_DEBUG "%s: dropped frame to %pM"
 			       " (unauthorized port)\n", dev->name,
-			       print_mac(mac, hdr.addr1));
+			       hdr.addr1);
 #endif
 
 		I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
@@ -1757,10 +1764,7 @@
 		store = &local->pending_packet[i];
 		tx.extra_frag = store->extra_frag;
 		tx.num_extra_frag = store->num_extra_frag;
-		tx.last_frag_rate_idx = store->last_frag_rate_idx;
 		tx.flags = 0;
-		if (store->last_frag_rate_ctrl_probe)
-			tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
 		ret = __ieee80211_tx(local, store->skb, &tx);
 		if (ret) {
 			if (ret == IEEE80211_TX_FRAG_AGAIN)
@@ -1848,7 +1852,6 @@
 	struct ieee80211_sub_if_data *sdata = NULL;
 	struct ieee80211_if_ap *ap = NULL;
 	struct ieee80211_if_sta *ifsta = NULL;
-	struct rate_selection rsel;
 	struct beacon_data *beacon;
 	struct ieee80211_supported_band *sband;
 	enum ieee80211_band band = local->hw.conf.channel->band;
@@ -1952,33 +1955,23 @@
 	skb->do_not_encrypt = 1;
 
 	info->band = band;
-	rate_control_get_rate(sdata, sband, NULL, skb, &rsel);
-
-	if (unlikely(rsel.rate_idx < 0)) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
-			       "no rate found\n",
-			       wiphy_name(local->hw.wiphy));
-		}
-		dev_kfree_skb_any(skb);
-		skb = NULL;
-		goto out;
-	}
+	/*
+	 * XXX: For now, always use the lowest rate
+	 */
+	info->control.rates[0].idx = 0;
+	info->control.rates[0].count = 1;
+	info->control.rates[1].idx = -1;
+	info->control.rates[2].idx = -1;
+	info->control.rates[3].idx = -1;
+	info->control.rates[4].idx = -1;
+	BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5);
 
 	info->control.vif = vif;
-	info->tx_rate_idx = rsel.rate_idx;
 
 	info->flags |= IEEE80211_TX_CTL_NO_ACK;
 	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
 	info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
-	if (sdata->bss_conf.use_short_preamble &&
-	    sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
-		info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
-
-	info->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-	info->control.retry_limit = 1;
-
-out:
+ out:
 	rcu_read_unlock();
 	return skb;
 }
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index cee4884..0f84131 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -239,7 +239,7 @@
 	erp = 0;
 	if (vif) {
 		sdata = vif_to_sdata(vif);
-		short_preamble = sdata->bss_conf.use_short_preamble;
+		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
 	}
@@ -272,7 +272,7 @@
 	erp = 0;
 	if (vif) {
 		sdata = vif_to_sdata(vif);
-		short_preamble = sdata->bss_conf.use_short_preamble;
+		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
 	}
@@ -312,7 +312,7 @@
 	erp = 0;
 	if (vif) {
 		sdata = vif_to_sdata(vif);
-		short_preamble = sdata->bss_conf.use_short_preamble;
+		short_preamble = sdata->vif.bss_conf.use_short_preamble;
 		if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
 			erp = rate->flags & IEEE80211_RATE_ERP_G;
 	}
@@ -532,8 +532,8 @@
 			if (elen >= sizeof(struct ieee80211_ht_cap))
 				elems->ht_cap_elem = (void *)pos;
 			break;
-		case WLAN_EID_HT_EXTRA_INFO:
-			if (elen >= sizeof(struct ieee80211_ht_addt_info))
+		case WLAN_EID_HT_INFORMATION:
+			if (elen >= sizeof(struct ieee80211_ht_info))
 				elems->ht_info_elem = (void *)pos;
 			break;
 		case WLAN_EID_MESH_ID:
@@ -638,19 +638,15 @@
 
 	if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
 		if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-		    chan->flags & IEEE80211_CHAN_NO_IBSS) {
-			printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
-				"%d MHz\n", sdata->dev->name, chan->center_freq);
+		    chan->flags & IEEE80211_CHAN_NO_IBSS)
 			return ret;
-		}
 		local->oper_channel = chan;
 
 		if (local->sw_scanning || local->hw_scanning)
 			ret = 0;
 		else
-			ret = ieee80211_hw_config(local);
-
-		rate_control_clear(local);
+			ret = ieee80211_hw_config(
+				local, IEEE80211_CONF_CHANGE_CHANNEL);
 	}
 
 	return ret;
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index f0e2d3e..7bbb98e 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -49,17 +49,19 @@
 	crypto_free_blkcipher(local->wep_rx_tfm);
 }
 
-static inline int ieee80211_wep_weak_iv(u32 iv, int keylen)
+static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
 {
-	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the
+	/*
+	 * Fluhrer, Mantin, and Shamir have reported weaknesses in the
 	 * key scheduling algorithm of RC4. At least IVs (KeyByte + 3,
-	 * 0xff, N) can be used to speedup attacks, so avoid using them. */
+	 * 0xff, N) can be used to speedup attacks, so avoid using them.
+	 */
 	if ((iv & 0xff00) == 0xff00) {
 		u8 B = (iv >> 16) & 0xff;
 		if (B >= 3 && B < 3 + keylen)
-			return 1;
+			return true;
 	}
-	return 0;
+	return false;
 }
 
 
@@ -268,7 +270,7 @@
 }
 
 
-u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	unsigned int hdrlen;
@@ -276,16 +278,13 @@
 	u32 iv;
 
 	if (!ieee80211_has_protected(hdr->frame_control))
-		return NULL;
+		return false;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	ivpos = skb->data + hdrlen;
 	iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
 
-	if (ieee80211_wep_weak_iv(iv, key->conf.keylen))
-		return ivpos;
-
-	return NULL;
+	return ieee80211_wep_weak_iv(iv, key->conf.keylen);
 }
 
 ieee80211_rx_result
@@ -329,6 +328,8 @@
 ieee80211_tx_result
 ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
 {
+	int i;
+
 	ieee80211_tx_set_protected(tx);
 
 	if (wep_encrypt_skb(tx, tx->skb) < 0) {
@@ -337,9 +338,8 @@
 	}
 
 	if (tx->extra_frag) {
-		int i;
 		for (i = 0; i < tx->num_extra_frag; i++) {
-			if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) {
+			if (wep_encrypt_skb(tx, tx->extra_frag[i])) {
 				I802_DEBUG_INC(tx->local->
 					       tx_handlers_drop_wep);
 				return TX_DROP;
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index e587172..d3f0db4 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -26,7 +26,7 @@
 			  struct ieee80211_key *key);
 int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
 			  struct ieee80211_key *key);
-u8 *ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
 
 ieee80211_rx_result
 ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 742f811..63f36e9 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -147,7 +147,7 @@
 	sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ];
 	if (sband) {
 		is_a = 1;
-		is_ht |= sband->ht_info.ht_supported;
+		is_ht |= sband->ht_cap.ht_supported;
 	}
 
 	sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -160,7 +160,7 @@
 			if (sband->bitrates[i].bitrate == 60)
 				is_g = 1;
 		}
-		is_ht |= sband->ht_info.ht_supported;
+		is_ht |= sband->ht_cap.ht_supported;
 	}
 
 	strcpy(name, "IEEE 802.11");
@@ -407,13 +407,6 @@
 		return 0;
 	}
 
-	if (sdata->vif.type == NL80211_IFTYPE_AP) {
-		memcpy(sdata->u.ap.ssid, ssid, len);
-		memset(sdata->u.ap.ssid + len, 0,
-		       IEEE80211_MAX_SSID_LEN - len);
-		sdata->u.ap.ssid_len = len;
-		return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
-	}
 	return -EOPNOTSUPP;
 }
 
@@ -437,15 +430,6 @@
 		return res;
 	}
 
-	if (sdata->vif.type == NL80211_IFTYPE_AP) {
-		len = sdata->u.ap.ssid_len;
-		if (len > IW_ESSID_MAX_SIZE)
-			len = IW_ESSID_MAX_SIZE;
-		memcpy(ssid, sdata->u.ap.ssid, len);
-		data->length = len;
-		data->flags = 1;
-		return 0;
-	}
 	return -EOPNOTSUPP;
 }
 
@@ -636,8 +620,8 @@
 
 	sta = sta_info_get(local, sdata->u.sta.bssid);
 
-	if (sta && sta->last_txrate_idx < sband->n_bitrates)
-		rate->value = sband->bitrates[sta->last_txrate_idx].bitrate;
+	if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
+		rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
 	else
 		rate->value = 0;
 
@@ -656,45 +640,35 @@
 				      union iwreq_data *data, char *extra)
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-	bool need_reconfig = 0;
+	struct ieee80211_channel* chan = local->hw.conf.channel;
+	u32 reconf_flags = 0;
 	int new_power_level;
 
 	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 		return -EINVAL;
 	if (data->txpower.flags & IW_TXPOW_RANGE)
 		return -EINVAL;
+	if (!chan)
+		return -EINVAL;
 
-	if (data->txpower.fixed) {
-		new_power_level = data->txpower.value;
-	} else {
-		/*
-		 * Automatic power level. Use maximum power for the current
-		 * channel. Should be part of rate control.
-		 */
-		struct ieee80211_channel* chan = local->hw.conf.channel;
-		if (!chan)
-			return -EINVAL;
-
+	if (data->txpower.fixed)
+		new_power_level = min(data->txpower.value, chan->max_power);
+	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;
-		need_reconfig = 1;
+		reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
 	}
 
 	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
 		local->hw.conf.radio_enabled = !(data->txpower.disabled);
-		need_reconfig = 1;
+		reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
 		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
 	}
 
-	if (need_reconfig) {
-		ieee80211_hw_config(local);
-		/* The return value of hw_config is not of big interest here,
-		 * as it doesn't say that it failed because of _this_ config
-		 * change or something else. Ignore it. */
-	}
+	if (reconf_flags)
+		ieee80211_hw_config(local, reconf_flags);
 
 	return 0;
 }
@@ -806,21 +780,16 @@
 	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
 		return -EINVAL;
 
-	if (retry->flags & IW_RETRY_MAX)
-		local->long_retry_limit = retry->value;
-	else if (retry->flags & IW_RETRY_MIN)
-		local->short_retry_limit = retry->value;
-	else {
-		local->long_retry_limit = retry->value;
-		local->short_retry_limit = retry->value;
+	if (retry->flags & IW_RETRY_MAX) {
+		local->hw.conf.long_frame_max_tx_count = retry->value;
+	} else if (retry->flags & IW_RETRY_MIN) {
+		local->hw.conf.short_frame_max_tx_count = retry->value;
+	} else {
+		local->hw.conf.long_frame_max_tx_count = retry->value;
+		local->hw.conf.short_frame_max_tx_count = retry->value;
 	}
 
-	if (local->ops->set_retry_limit) {
-		return local->ops->set_retry_limit(
-			local_to_hw(local),
-			local->short_retry_limit,
-			local->long_retry_limit);
-	}
+	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
 
 	return 0;
 }
@@ -837,14 +806,15 @@
 		/* first return min value, iwconfig will ask max value
 		 * later if needed */
 		retry->flags |= IW_RETRY_LIMIT;
-		retry->value = local->short_retry_limit;
-		if (local->long_retry_limit != local->short_retry_limit)
+		retry->value = local->hw.conf.short_frame_max_tx_count;
+		if (local->hw.conf.long_frame_max_tx_count !=
+		    local->hw.conf.short_frame_max_tx_count)
 			retry->flags |= IW_RETRY_MIN;
 		return 0;
 	}
 	if (retry->flags & IW_RETRY_MAX) {
 		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-		retry->value = local->long_retry_limit;
+		retry->value = local->hw.conf.long_frame_max_tx_count;
 	}
 
 	return 0;
@@ -980,7 +950,7 @@
 
 	if (wrq->disabled) {
 		conf->flags &= ~IEEE80211_CONF_PS;
-		return ieee80211_hw_config(local);
+		return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 
 	switch (wrq->flags & IW_POWER_MODE) {
@@ -993,7 +963,7 @@
 		return -EINVAL;
 	}
 
-	return ieee80211_hw_config(local);
+	return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 }
 
 static int ieee80211_ioctl_giwpower(struct net_device *dev,
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 139b5f2..ac71b38 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -114,8 +114,8 @@
 {
 	struct ieee80211_master_priv *mpriv = netdev_priv(dev);
 	struct ieee80211_local *local = mpriv->local;
+	struct ieee80211_hw *hw = &local->hw;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct sta_info *sta;
 	u16 queue;
 	u8 tid;
@@ -124,21 +124,19 @@
 	if (unlikely(queue >= local->hw.queues))
 		queue = local->hw.queues - 1;
 
-	if (info->flags & IEEE80211_TX_CTL_REQUEUE) {
+	if (skb->requeue) {
+		if (!hw->ampdu_queues)
+			return queue;
+
 		rcu_read_lock();
 		sta = sta_info_get(local, hdr->addr1);
 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 		if (sta) {
-			struct ieee80211_hw *hw = &local->hw;
 			int ampdu_queue = sta->tid_to_tx_q[tid];
 
 			if ((ampdu_queue < ieee80211_num_queues(hw)) &&
-			    test_bit(ampdu_queue, local->queue_pool)) {
+			    test_bit(ampdu_queue, local->queue_pool))
 				queue = ampdu_queue;
-				info->flags |= IEEE80211_TX_CTL_AMPDU;
-			} else {
-				info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-			}
 		}
 		rcu_read_unlock();
 
@@ -159,20 +157,18 @@
 		*p++ = ack_policy | tid;
 		*p = 0;
 
+		if (!hw->ampdu_queues)
+			return queue;
+
 		rcu_read_lock();
 
 		sta = sta_info_get(local, hdr->addr1);
 		if (sta) {
 			int ampdu_queue = sta->tid_to_tx_q[tid];
-			struct ieee80211_hw *hw = &local->hw;
 
 			if ((ampdu_queue < ieee80211_num_queues(hw)) &&
-			    test_bit(ampdu_queue, local->queue_pool)) {
+			    test_bit(ampdu_queue, local->queue_pool))
 				queue = ampdu_queue;
-				info->flags |= IEEE80211_TX_CTL_AMPDU;
-			} else {
-				info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-			}
 		}
 
 		rcu_read_unlock();
@@ -206,13 +202,11 @@
 			 * on the previous queue
 			 * since HT is strict in order */
 #ifdef CONFIG_MAC80211_HT_DEBUG
-			if (net_ratelimit()) {
-				DECLARE_MAC_BUF(mac);
+			if (net_ratelimit())
 				printk(KERN_DEBUG "allocated aggregation queue"
-					" %d tid %d addr %s pool=0x%lX\n",
-					i, tid, print_mac(mac, sta->sta.addr),
+					" %d tid %d addr %pM pool=0x%lX\n",
+					i, tid, sta->sta.addr,
 					local->queue_pool[0]);
-			}
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 			return 0;
 		}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 6db6494..7aa63ca 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -49,8 +49,7 @@
 	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
 	    !wpa_test) {
-		/* hwaccel - with no need for preallocated room for Michael MIC
-		 */
+		/* hwaccel - with no need for preallocated room for MMIC */
 		return TX_CONTINUE;
 	}
 
@@ -67,8 +66,6 @@
 #else
 	authenticator = 1;
 #endif
-	/* At this point we know we're using ALG_TKIP. To get the MIC key
-	 * we now will rely on the offset from the ieee80211_key_conf::key */
 	key_offset = authenticator ?
 		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY :
 		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
@@ -90,11 +87,8 @@
 	u8 mic[MICHAEL_MIC_LEN];
 	struct sk_buff *skb = rx->skb;
 	int authenticator = 1, wpa_test = 0;
-	DECLARE_MAC_BUF(mac);
 
-	/*
-	 * No way to verify the MIC if the hardware stripped it
-	 */
+	/* No way to verify the MIC if the hardware stripped it */
 	if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
 		return RX_CONTINUE;
 
@@ -116,8 +110,6 @@
 #else
 	authenticator = 1;
 #endif
-	/* At this point we know we're using ALG_TKIP. To get the MIC key
-	 * we now will rely on the offset from the ieee80211_key_conf::key */
 	key_offset = authenticator ?
 		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY :
 		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
@@ -202,6 +194,7 @@
 ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
 {
 	struct sk_buff *skb = tx->skb;
+	int i;
 
 	ieee80211_tx_set_protected(tx);
 
@@ -209,9 +202,8 @@
 		return TX_DROP;
 
 	if (tx->extra_frag) {
-		int i;
 		for (i = 0; i < tx->num_extra_frag; i++) {
-			if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0)
+			if (tkip_encrypt_skb(tx, tx->extra_frag[i]))
 				return TX_DROP;
 		}
 	}
@@ -227,7 +219,6 @@
 	int hdrlen, res, hwaccel = 0, wpa_test = 0;
 	struct ieee80211_key *key = rx->key;
 	struct sk_buff *skb = rx->skb;
-	DECLARE_MAC_BUF(mac);
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
@@ -350,7 +341,7 @@
 }
 
 
-static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
+static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr)
 {
 	pn[0] = hdr[7];
 	pn[1] = hdr[6];
@@ -358,7 +349,6 @@
 	pn[3] = hdr[4];
 	pn[4] = hdr[1];
 	pn[5] = hdr[0];
-	return (hdr[3] >> 6) & 0x03;
 }
 
 
@@ -373,7 +363,7 @@
 
 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-		/* hwaccel - with no need for preallocated room for CCMP "
+		/* hwaccel - with no need for preallocated room for CCMP
 		 * header or MIC fields */
 		info->control.hw_key = &tx->key->conf;
 		return 0;
@@ -426,6 +416,7 @@
 ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
 {
 	struct sk_buff *skb = tx->skb;
+	int i;
 
 	ieee80211_tx_set_protected(tx);
 
@@ -433,9 +424,8 @@
 		return TX_DROP;
 
 	if (tx->extra_frag) {
-		int i;
 		for (i = 0; i < tx->num_extra_frag; i++) {
-			if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0)
+			if (ccmp_encrypt_skb(tx, tx->extra_frag[i]))
 				return TX_DROP;
 		}
 	}
@@ -453,7 +443,6 @@
 	struct sk_buff *skb = rx->skb;
 	u8 pn[CCMP_PN_LEN];
 	int data_len;
-	DECLARE_MAC_BUF(mac);
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
@@ -468,7 +457,7 @@
 	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
 		return RX_CONTINUE;
 
-	(void) ccmp_hdr2pn(pn, skb->data + hdrlen);
+	ccmp_hdr2pn(pn, skb->data + hdrlen);
 
 	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
 		key->u.ccmp.replays++;
@@ -483,9 +472,8 @@
 			    key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
 			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
 			    skb->data + skb->len - CCMP_MIC_LEN,
-			    skb->data + hdrlen + CCMP_HDR_LEN)) {
+			    skb->data + hdrlen + CCMP_HDR_LEN))
 			return RX_DROP_UNUSABLE;
-		}
 	}
 
 	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 9a24332..60aba45 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -820,13 +820,11 @@
 
 #ifdef CONFIG_IP_VS_IPV6
 		if (cp->af == AF_INET6)
-			seq_printf(seq,
-				"%-3s " NIP6_FMT " %04X " NIP6_FMT
-				" %04X " NIP6_FMT " %04X %-11s %7lu\n",
+			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %7lu\n",
 				ip_vs_proto_name(cp->protocol),
-				NIP6(cp->caddr.in6), ntohs(cp->cport),
-				NIP6(cp->vaddr.in6), ntohs(cp->vport),
-				NIP6(cp->daddr.in6), ntohs(cp->dport),
+				&cp->caddr.in6, ntohs(cp->cport),
+				&cp->vaddr.in6, ntohs(cp->vport),
+				&cp->daddr.in6, ntohs(cp->dport),
 				ip_vs_state_name(cp->protocol, cp->state),
 				(cp->timer.expires-jiffies)/HZ);
 		else
@@ -883,13 +881,11 @@
 
 #ifdef CONFIG_IP_VS_IPV6
 		if (cp->af == AF_INET6)
-			seq_printf(seq,
-				"%-3s " NIP6_FMT " %04X " NIP6_FMT
-				" %04X " NIP6_FMT " %04X %-11s %-6s %7lu\n",
+			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %-6s %7lu\n",
 				ip_vs_proto_name(cp->protocol),
-				NIP6(cp->caddr.in6), ntohs(cp->cport),
-				NIP6(cp->vaddr.in6), ntohs(cp->vport),
-				NIP6(cp->daddr.in6), ntohs(cp->dport),
+				&cp->caddr.in6, ntohs(cp->cport),
+				&cp->vaddr.in6, ntohs(cp->vport),
+				&cp->daddr.in6, ntohs(cp->dport),
 				ip_vs_state_name(cp->protocol, cp->state),
 				ip_vs_origin_name(cp->flags),
 				(cp->timer.expires-jiffies)/HZ);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 958abf3..cb3e031 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -730,9 +730,9 @@
 	if (ic == NULL)
 		return NF_DROP;
 
-	IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
+	IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %pI4->%pI4\n",
 		  ic->type, ntohs(icmp_id(ic)),
-		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+		  &iph->saddr, &iph->daddr);
 
 	/*
 	 * Work through seeing if this is for us.
@@ -805,9 +805,9 @@
 	if (ic == NULL)
 		return NF_DROP;
 
-	IP_VS_DBG(12, "Outgoing ICMPv6 (%d,%d) " NIP6_FMT "->" NIP6_FMT "\n",
+	IP_VS_DBG(12, "Outgoing ICMPv6 (%d,%d) %pI6->%pI6\n",
 		  ic->icmp6_type, ntohs(icmpv6_id(ic)),
-		  NIP6(iph->saddr), NIP6(iph->daddr));
+		  &iph->saddr, &iph->daddr);
 
 	/*
 	 * Work through seeing if this is for us.
@@ -1070,9 +1070,9 @@
 	if (ic == NULL)
 		return NF_DROP;
 
-	IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
+	IP_VS_DBG(12, "Incoming ICMP (%d,%d) %pI4->%pI4\n",
 		  ic->type, ntohs(icmp_id(ic)),
-		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+		  &iph->saddr, &iph->daddr);
 
 	/*
 	 * Work through seeing if this is for us.
@@ -1127,8 +1127,8 @@
 	/* Ensure the checksum is correct */
 	if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
 		/* Failed checksum! */
-		IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n",
-			  NIPQUAD(iph->saddr));
+		IP_VS_DBG(1, "Incoming ICMP: failed checksum from %pI4!\n",
+			  &iph->saddr);
 		goto out;
 	}
 
@@ -1175,9 +1175,9 @@
 	if (ic == NULL)
 		return NF_DROP;
 
-	IP_VS_DBG(12, "Incoming ICMPv6 (%d,%d) " NIP6_FMT "->" NIP6_FMT "\n",
+	IP_VS_DBG(12, "Incoming ICMPv6 (%d,%d) %pI6->%pI6\n",
 		  ic->icmp6_type, ntohs(icmpv6_id(ic)),
-		  NIP6(iph->saddr), NIP6(iph->daddr));
+		  &iph->saddr, &iph->daddr);
 
 	/*
 	 * Work through seeing if this is for us.
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 0302cf3..e01061f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1168,15 +1168,9 @@
 	}
 
 #ifdef CONFIG_IP_VS_IPV6
-	if (u->af == AF_INET6) {
-		if (!sched->supports_ipv6) {
-			ret = -EAFNOSUPPORT;
-			goto out_err;
-		}
-		if ((u->netmask < 1) || (u->netmask > 128)) {
-			ret = -EINVAL;
-			goto out_err;
-		}
+	if (u->af == AF_INET6 && (u->netmask < 1 || u->netmask > 128)) {
+		ret = -EINVAL;
+		goto out_err;
 	}
 #endif
 
@@ -1272,15 +1266,9 @@
 	old_sched = sched;
 
 #ifdef CONFIG_IP_VS_IPV6
-	if (u->af == AF_INET6) {
-		if (!sched->supports_ipv6) {
-			ret = -EAFNOSUPPORT;
-			goto out;
-		}
-		if ((u->netmask < 1) || (u->netmask > 128)) {
-			ret = -EINVAL;
-			goto out;
-		}
+	if (u->af == AF_INET6 && (u->netmask < 1 || u->netmask > 128)) {
+		ret = -EINVAL;
+		goto out;
 	}
 #endif
 
@@ -1557,7 +1545,7 @@
 		.data		= &sysctl_ip_vs_amemthresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 #ifdef CONFIG_IP_VS_DEBUG
 	{
@@ -1565,7 +1553,7 @@
 		.data		= &sysctl_ip_vs_debug_level,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 #endif
 	{
@@ -1573,28 +1561,28 @@
 		.data		= &sysctl_ip_vs_am_droprate,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "drop_entry",
 		.data		= &sysctl_ip_vs_drop_entry,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_do_defense_mode,
+		.proc_handler	= proc_do_defense_mode,
 	},
 	{
 		.procname	= "drop_packet",
 		.data		= &sysctl_ip_vs_drop_packet,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_do_defense_mode,
+		.proc_handler	= proc_do_defense_mode,
 	},
 	{
 		.procname	= "secure_tcp",
 		.data		= &sysctl_ip_vs_secure_tcp,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_do_defense_mode,
+		.proc_handler	= proc_do_defense_mode,
 	},
 #if 0
 	{
@@ -1602,84 +1590,84 @@
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_synsent",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_synrecv",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_finwait",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_timewait",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_close",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_closewait",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_lastack",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_listen",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_synack",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_udp",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_UDP],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "timeout_icmp",
 		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_ICMP],
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 #endif
 	{
@@ -1687,35 +1675,35 @@
 		.data		= &sysctl_ip_vs_cache_bypass,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "expire_nodest_conn",
 		.data		= &sysctl_ip_vs_expire_nodest_conn,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "expire_quiescent_template",
 		.data		= &sysctl_ip_vs_expire_quiescent_template,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "sync_threshold",
 		.data		= &sysctl_ip_vs_sync_threshold,
 		.maxlen		= sizeof(sysctl_ip_vs_sync_threshold),
 		.mode		= 0644,
-		.proc_handler	= &proc_do_sync_threshold,
+		.proc_handler	= proc_do_sync_threshold,
 	},
 	{
 		.procname	= "nat_icmp_send",
 		.data		= &sysctl_ip_vs_nat_icmp_send,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{ .ctl_name = 0 }
 };
@@ -1867,9 +1855,9 @@
 		if (iter->table == ip_vs_svc_table) {
 #ifdef CONFIG_IP_VS_IPV6
 			if (svc->af == AF_INET6)
-				seq_printf(seq, "%s  [" NIP6_FMT "]:%04X %s ",
+				seq_printf(seq, "%s  [%pI6]:%04X %s ",
 					   ip_vs_proto_name(svc->protocol),
-					   NIP6(svc->addr.in6),
+					   &svc->addr.in6,
 					   ntohs(svc->port),
 					   svc->scheduler->name);
 			else
@@ -1895,9 +1883,9 @@
 #ifdef CONFIG_IP_VS_IPV6
 			if (dest->af == AF_INET6)
 				seq_printf(seq,
-					   "  -> [" NIP6_FMT "]:%04X"
+					   "  -> [%pI6]:%04X"
 					   "      %-7s %-6d %-10d %-10d\n",
-					   NIP6(dest->addr.in6),
+					   &dest->addr.in6,
 					   ntohs(dest->port),
 					   ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
 					   atomic_read(&dest->weight),
@@ -2141,8 +2129,8 @@
 
 	/* Check for valid protocol: TCP or UDP, even for fwmark!=0 */
 	if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) {
-		IP_VS_ERR("set_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s\n",
-			  usvc.protocol, NIPQUAD(usvc.addr.ip),
+		IP_VS_ERR("set_ctl: invalid protocol: %d %pI4:%d %s\n",
+			  usvc.protocol, &usvc.addr.ip,
 			  ntohs(usvc.port), usvc.sched_name);
 		ret = -EFAULT;
 		goto out_unlock;
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index a16943f..a9dac74 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -64,9 +64,16 @@
 /*
  *	Returns hash value for IPVS DH entry
  */
-static inline unsigned ip_vs_dh_hashkey(__be32 addr)
+static inline unsigned ip_vs_dh_hashkey(int af, const union nf_inet_addr *addr)
 {
-	return (ntohl(addr)*2654435761UL) & IP_VS_DH_TAB_MASK;
+	__be32 addr_fold = addr->ip;
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6)
+		addr_fold = addr->ip6[0]^addr->ip6[1]^
+			    addr->ip6[2]^addr->ip6[3];
+#endif
+	return (ntohl(addr_fold)*2654435761UL) & IP_VS_DH_TAB_MASK;
 }
 
 
@@ -74,9 +81,10 @@
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_dh_get(struct ip_vs_dh_bucket *tbl, __be32 addr)
+ip_vs_dh_get(int af, struct ip_vs_dh_bucket *tbl,
+	     const union nf_inet_addr *addr)
 {
-	return (tbl[ip_vs_dh_hashkey(addr)]).dest;
+	return (tbl[ip_vs_dh_hashkey(af, addr)]).dest;
 }
 
 
@@ -202,12 +210,14 @@
 {
 	struct ip_vs_dest *dest;
 	struct ip_vs_dh_bucket *tbl;
-	struct iphdr *iph = ip_hdr(skb);
+	struct ip_vs_iphdr iph;
+
+	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
 
 	IP_VS_DBG(6, "ip_vs_dh_schedule(): Scheduling...\n");
 
 	tbl = (struct ip_vs_dh_bucket *)svc->sched_data;
-	dest = ip_vs_dh_get(tbl, iph->daddr);
+	dest = ip_vs_dh_get(svc->af, tbl, &iph.daddr);
 	if (!dest
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
@@ -215,11 +225,10 @@
 		return NULL;
 	}
 
-	IP_VS_DBG(6, "DH: destination IP address %u.%u.%u.%u "
-		  "--> server %u.%u.%u.%u:%d\n",
-		  NIPQUAD(iph->daddr),
-		  NIPQUAD(dest->addr.ip),
-		  ntohs(dest->port));
+	IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n",
+		      IP_VS_DBG_ADDR(svc->af, &iph.daddr),
+		      IP_VS_DBG_ADDR(svc->af, &dest->addr),
+		      ntohs(dest->port));
 
 	return dest;
 }
@@ -234,9 +243,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_dh_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	0,
-#endif
 	.init_service =		ip_vs_dh_init_svc,
 	.done_service =		ip_vs_dh_done_svc,
 	.update_service =	ip_vs_dh_update_svc,
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 2e7dbd8..428edbf 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -178,10 +178,8 @@
 					   &start, &end) != 1)
 			return 1;
 
-		IP_VS_DBG(7, "PASV response (%u.%u.%u.%u:%d) -> "
-			  "%u.%u.%u.%u:%d detected\n",
-			  NIPQUAD(from.ip), ntohs(port),
-			  NIPQUAD(cp->caddr.ip), 0);
+		IP_VS_DBG(7, "PASV response (%pI4:%d) -> %pI4:%d detected\n",
+			  &from.ip, ntohs(port), &cp->caddr.ip, 0);
 
 		/*
 		 * Now update or create an connection entry for it
@@ -312,8 +310,7 @@
 				   &start, &end) != 1)
 		return 1;
 
-	IP_VS_DBG(7, "PORT %u.%u.%u.%u:%d detected\n",
-		  NIPQUAD(to.ip), ntohs(port));
+	IP_VS_DBG(7, "PORT %pI4:%d detected\n", &to.ip, ntohs(port));
 
 	/* Passive mode off */
 	cp->app_data = NULL;
@@ -321,9 +318,9 @@
 	/*
 	 * Now update or create a connection entry for it
 	 */
-	IP_VS_DBG(7, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n",
+	IP_VS_DBG(7, "protocol %s %pI4:%d %pI4:%d\n",
 		  ip_vs_proto_name(iph->protocol),
-		  NIPQUAD(to.ip), ntohs(port), NIPQUAD(cp->vaddr.ip), 0);
+		  &to.ip, ntohs(port), &cp->vaddr.ip, 0);
 
 	n_cp = ip_vs_conn_in_get(AF_INET, iph->protocol,
 				 &to, port,
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 6ecef35..9394f53 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -86,7 +86,8 @@
  */
 struct ip_vs_lblc_entry {
 	struct list_head        list;
-	__be32                  addr;           /* destination IP address */
+	int			af;		/* address family */
+	union nf_inet_addr      addr;           /* destination IP address */
 	struct ip_vs_dest       *dest;          /* real server (cache) */
 	unsigned long           lastuse;        /* last used time */
 };
@@ -115,7 +116,7 @@
 		.data		= &sysctl_ip_vs_lblc_expiration,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{ .ctl_name = 0 }
 };
@@ -137,9 +138,17 @@
 /*
  *	Returns hash value for IPVS LBLC entry
  */
-static inline unsigned ip_vs_lblc_hashkey(__be32 addr)
+static inline unsigned
+ip_vs_lblc_hashkey(int af, const union nf_inet_addr *addr)
 {
-	return (ntohl(addr)*2654435761UL) & IP_VS_LBLC_TAB_MASK;
+	__be32 addr_fold = addr->ip;
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6)
+		addr_fold = addr->ip6[0]^addr->ip6[1]^
+			    addr->ip6[2]^addr->ip6[3];
+#endif
+	return (ntohl(addr_fold)*2654435761UL) & IP_VS_LBLC_TAB_MASK;
 }
 
 
@@ -150,7 +159,7 @@
 static void
 ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en)
 {
-	unsigned hash = ip_vs_lblc_hashkey(en->addr);
+	unsigned hash = ip_vs_lblc_hashkey(en->af, &en->addr);
 
 	list_add(&en->list, &tbl->bucket[hash]);
 	atomic_inc(&tbl->entries);
@@ -162,13 +171,14 @@
  *  lock
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr)
+ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl,
+	       const union nf_inet_addr *addr)
 {
-	unsigned hash = ip_vs_lblc_hashkey(addr);
+	unsigned hash = ip_vs_lblc_hashkey(af, addr);
 	struct ip_vs_lblc_entry *en;
 
 	list_for_each_entry(en, &tbl->bucket[hash], list)
-		if (en->addr == addr)
+		if (ip_vs_addr_equal(af, &en->addr, addr))
 			return en;
 
 	return NULL;
@@ -180,12 +190,12 @@
  * address to a server. Called under write lock.
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, __be32 daddr,
+ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
 	       struct ip_vs_dest *dest)
 {
 	struct ip_vs_lblc_entry *en;
 
-	en = ip_vs_lblc_get(tbl, daddr);
+	en = ip_vs_lblc_get(dest->af, tbl, daddr);
 	if (!en) {
 		en = kmalloc(sizeof(*en), GFP_ATOMIC);
 		if (!en) {
@@ -193,7 +203,8 @@
 			return NULL;
 		}
 
-		en->addr = daddr;
+		en->af = dest->af;
+		ip_vs_addr_copy(dest->af, &en->addr, daddr);
 		en->lastuse = jiffies;
 
 		atomic_inc(&dest->refcnt);
@@ -369,7 +380,7 @@
 
 
 static inline struct ip_vs_dest *
-__ip_vs_lblc_schedule(struct ip_vs_service *svc, struct iphdr *iph)
+__ip_vs_lblc_schedule(struct ip_vs_service *svc)
 {
 	struct ip_vs_dest *dest, *least;
 	int loh, doh;
@@ -420,12 +431,13 @@
 		}
 	}
 
-	IP_VS_DBG(6, "LBLC: server %d.%d.%d.%d:%d "
-		  "activeconns %d refcnt %d weight %d overhead %d\n",
-		  NIPQUAD(least->addr.ip), ntohs(least->port),
-		  atomic_read(&least->activeconns),
-		  atomic_read(&least->refcnt),
-		  atomic_read(&least->weight), loh);
+	IP_VS_DBG_BUF(6, "LBLC: server %s:%d "
+		      "activeconns %d refcnt %d weight %d overhead %d\n",
+		      IP_VS_DBG_ADDR(least->af, &least->addr),
+		      ntohs(least->port),
+		      atomic_read(&least->activeconns),
+		      atomic_read(&least->refcnt),
+		      atomic_read(&least->weight), loh);
 
 	return least;
 }
@@ -459,15 +471,17 @@
 ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 {
 	struct ip_vs_lblc_table *tbl = svc->sched_data;
-	struct iphdr *iph = ip_hdr(skb);
+	struct ip_vs_iphdr iph;
 	struct ip_vs_dest *dest = NULL;
 	struct ip_vs_lblc_entry *en;
 
+	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+
 	IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n");
 
 	/* First look in our cache */
 	read_lock(&svc->sched_lock);
-	en = ip_vs_lblc_get(tbl, iph->daddr);
+	en = ip_vs_lblc_get(svc->af, tbl, &iph.daddr);
 	if (en) {
 		/* We only hold a read lock, but this is atomic */
 		en->lastuse = jiffies;
@@ -491,7 +505,7 @@
 		goto out;
 
 	/* No cache entry or it is invalid, time to schedule */
-	dest = __ip_vs_lblc_schedule(svc, iph);
+	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
 		IP_VS_DBG(1, "no destination available\n");
 		return NULL;
@@ -499,15 +513,13 @@
 
 	/* If we fail to create a cache entry, we'll just use the valid dest */
 	write_lock(&svc->sched_lock);
-	ip_vs_lblc_new(tbl, iph->daddr, dest);
+	ip_vs_lblc_new(tbl, &iph.daddr, dest);
 	write_unlock(&svc->sched_lock);
 
 out:
-	IP_VS_DBG(6, "LBLC: destination IP address %u.%u.%u.%u "
-		  "--> server %u.%u.%u.%u:%d\n",
-		  NIPQUAD(iph->daddr),
-		  NIPQUAD(dest->addr.ip),
-		  ntohs(dest->port));
+	IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n",
+		      IP_VS_DBG_ADDR(svc->af, &iph.daddr),
+		      IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port));
 
 	return dest;
 }
@@ -522,9 +534,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	0,
-#endif
 	.init_service =		ip_vs_lblc_init_svc,
 	.done_service =		ip_vs_lblc_done_svc,
 	.schedule =		ip_vs_lblc_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 1f75ea8..92dc76a 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -202,12 +202,13 @@
 		}
 	}
 
-	IP_VS_DBG(6, "ip_vs_dest_set_min: server %d.%d.%d.%d:%d "
-		  "activeconns %d refcnt %d weight %d overhead %d\n",
-		  NIPQUAD(least->addr.ip), ntohs(least->port),
-		  atomic_read(&least->activeconns),
-		  atomic_read(&least->refcnt),
-		  atomic_read(&least->weight), loh);
+	IP_VS_DBG_BUF(6, "ip_vs_dest_set_min: server %s:%d "
+		      "activeconns %d refcnt %d weight %d overhead %d\n",
+		      IP_VS_DBG_ADDR(least->af, &least->addr),
+		      ntohs(least->port),
+		      atomic_read(&least->activeconns),
+		      atomic_read(&least->refcnt),
+		      atomic_read(&least->weight), loh);
 	return least;
 }
 
@@ -248,12 +249,12 @@
 		}
 	}
 
-	IP_VS_DBG(6, "ip_vs_dest_set_max: server %d.%d.%d.%d:%d "
-		  "activeconns %d refcnt %d weight %d overhead %d\n",
-		  NIPQUAD(most->addr.ip), ntohs(most->port),
-		  atomic_read(&most->activeconns),
-		  atomic_read(&most->refcnt),
-		  atomic_read(&most->weight), moh);
+	IP_VS_DBG_BUF(6, "ip_vs_dest_set_max: server %s:%d "
+		      "activeconns %d refcnt %d weight %d overhead %d\n",
+		      IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port),
+		      atomic_read(&most->activeconns),
+		      atomic_read(&most->refcnt),
+		      atomic_read(&most->weight), moh);
 	return most;
 }
 
@@ -264,7 +265,8 @@
  */
 struct ip_vs_lblcr_entry {
 	struct list_head        list;
-	__be32                   addr;           /* destination IP address */
+	int			af;		/* address family */
+	union nf_inet_addr      addr;           /* destination IP address */
 	struct ip_vs_dest_set   set;            /* destination server set */
 	unsigned long           lastuse;        /* last used time */
 };
@@ -293,7 +295,7 @@
 		.data		= &sysctl_ip_vs_lblcr_expiration,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{ .ctl_name = 0 }
 };
@@ -311,9 +313,17 @@
 /*
  *	Returns hash value for IPVS LBLCR entry
  */
-static inline unsigned ip_vs_lblcr_hashkey(__be32 addr)
+static inline unsigned
+ip_vs_lblcr_hashkey(int af, const union nf_inet_addr *addr)
 {
-	return (ntohl(addr)*2654435761UL) & IP_VS_LBLCR_TAB_MASK;
+	__be32 addr_fold = addr->ip;
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6)
+		addr_fold = addr->ip6[0]^addr->ip6[1]^
+			    addr->ip6[2]^addr->ip6[3];
+#endif
+	return (ntohl(addr_fold)*2654435761UL) & IP_VS_LBLCR_TAB_MASK;
 }
 
 
@@ -324,7 +334,7 @@
 static void
 ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en)
 {
-	unsigned hash = ip_vs_lblcr_hashkey(en->addr);
+	unsigned hash = ip_vs_lblcr_hashkey(en->af, &en->addr);
 
 	list_add(&en->list, &tbl->bucket[hash]);
 	atomic_inc(&tbl->entries);
@@ -336,13 +346,14 @@
  *  read lock.
  */
 static inline struct ip_vs_lblcr_entry *
-ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr)
+ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl,
+		const union nf_inet_addr *addr)
 {
-	unsigned hash = ip_vs_lblcr_hashkey(addr);
+	unsigned hash = ip_vs_lblcr_hashkey(af, addr);
 	struct ip_vs_lblcr_entry *en;
 
 	list_for_each_entry(en, &tbl->bucket[hash], list)
-		if (en->addr == addr)
+		if (ip_vs_addr_equal(af, &en->addr, addr))
 			return en;
 
 	return NULL;
@@ -354,12 +365,12 @@
  * IP address to a server. Called under write lock.
  */
 static inline struct ip_vs_lblcr_entry *
-ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl,  __be32 daddr,
+ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
 		struct ip_vs_dest *dest)
 {
 	struct ip_vs_lblcr_entry *en;
 
-	en = ip_vs_lblcr_get(tbl, daddr);
+	en = ip_vs_lblcr_get(dest->af, tbl, daddr);
 	if (!en) {
 		en = kmalloc(sizeof(*en), GFP_ATOMIC);
 		if (!en) {
@@ -367,7 +378,8 @@
 			return NULL;
 		}
 
-		en->addr = daddr;
+		en->af = dest->af;
+		ip_vs_addr_copy(dest->af, &en->addr, daddr);
 		en->lastuse = jiffies;
 
 		/* initilize its dest set */
@@ -544,7 +556,7 @@
 
 
 static inline struct ip_vs_dest *
-__ip_vs_lblcr_schedule(struct ip_vs_service *svc, struct iphdr *iph)
+__ip_vs_lblcr_schedule(struct ip_vs_service *svc)
 {
 	struct ip_vs_dest *dest, *least;
 	int loh, doh;
@@ -596,12 +608,13 @@
 		}
 	}
 
-	IP_VS_DBG(6, "LBLCR: server %d.%d.%d.%d:%d "
-		  "activeconns %d refcnt %d weight %d overhead %d\n",
-		  NIPQUAD(least->addr.ip), ntohs(least->port),
-		  atomic_read(&least->activeconns),
-		  atomic_read(&least->refcnt),
-		  atomic_read(&least->weight), loh);
+	IP_VS_DBG_BUF(6, "LBLCR: server %s:%d "
+		      "activeconns %d refcnt %d weight %d overhead %d\n",
+		      IP_VS_DBG_ADDR(least->af, &least->addr),
+		      ntohs(least->port),
+		      atomic_read(&least->activeconns),
+		      atomic_read(&least->refcnt),
+		      atomic_read(&least->weight), loh);
 
 	return least;
 }
@@ -635,15 +648,17 @@
 ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 {
 	struct ip_vs_lblcr_table *tbl = svc->sched_data;
-	struct iphdr *iph = ip_hdr(skb);
+	struct ip_vs_iphdr iph;
 	struct ip_vs_dest *dest = NULL;
 	struct ip_vs_lblcr_entry *en;
 
+	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+
 	IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n");
 
 	/* First look in our cache */
 	read_lock(&svc->sched_lock);
-	en = ip_vs_lblcr_get(tbl, iph->daddr);
+	en = ip_vs_lblcr_get(svc->af, tbl, &iph.daddr);
 	if (en) {
 		/* We only hold a read lock, but this is atomic */
 		en->lastuse = jiffies;
@@ -673,7 +688,7 @@
 		}
 
 		/* The cache entry is invalid, time to schedule */
-		dest = __ip_vs_lblcr_schedule(svc, iph);
+		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
 			IP_VS_DBG(1, "no destination available\n");
 			read_unlock(&svc->sched_lock);
@@ -691,7 +706,7 @@
 		goto out;
 
 	/* No cache entry, time to schedule */
-	dest = __ip_vs_lblcr_schedule(svc, iph);
+	dest = __ip_vs_lblcr_schedule(svc);
 	if (!dest) {
 		IP_VS_DBG(1, "no destination available\n");
 		return NULL;
@@ -699,15 +714,13 @@
 
 	/* If we fail to create a cache entry, we'll just use the valid dest */
 	write_lock(&svc->sched_lock);
-	ip_vs_lblcr_new(tbl, iph->daddr, dest);
+	ip_vs_lblcr_new(tbl, &iph.daddr, dest);
 	write_unlock(&svc->sched_lock);
 
 out:
-	IP_VS_DBG(6, "LBLCR: destination IP address %u.%u.%u.%u "
-		  "--> server %u.%u.%u.%u:%d\n",
-		  NIPQUAD(iph->daddr),
-		  NIPQUAD(dest->addr.ip),
-		  ntohs(dest->port));
+	IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n",
+		      IP_VS_DBG_ADDR(svc->af, &iph.daddr),
+		      IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port));
 
 	return dest;
 }
@@ -722,9 +735,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	0,
-#endif
 	.init_service =		ip_vs_lblcr_init_svc,
 	.done_service =		ip_vs_lblcr_done_svc,
 	.schedule =		ip_vs_lblcr_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index b69f808..51912ca 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -81,9 +81,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.schedule =		ip_vs_lc_schedule,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index 9a2d803..6758ad2 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -116,9 +116,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.schedule =		ip_vs_nq_schedule,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 0791f9e..a01520e 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -164,26 +164,21 @@
 	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else if (ih->frag_off & htons(IP_OFFSET))
-		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-			pp->name, NIPQUAD(ih->saddr),
-			NIPQUAD(ih->daddr));
+		sprintf(buf, "%s %pI4->%pI4 frag",
+			pp->name, &ih->saddr, &ih->daddr);
 	else {
 		__be16 _ports[2], *pptr
 ;
 		pptr = skb_header_pointer(skb, offset + ih->ihl*4,
 					  sizeof(_ports), _ports);
 		if (pptr == NULL)
-			sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
-				pp->name,
-				NIPQUAD(ih->saddr),
-				NIPQUAD(ih->daddr));
+			sprintf(buf, "%s TRUNCATED %pI4->%pI4",
+				pp->name, &ih->saddr, &ih->daddr);
 		else
-			sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
+			sprintf(buf, "%s %pI4:%u->%pI4:%u",
 				pp->name,
-				NIPQUAD(ih->saddr),
-				ntohs(pptr[0]),
-				NIPQUAD(ih->daddr),
-				ntohs(pptr[1]));
+				&ih->saddr, ntohs(pptr[0]),
+				&ih->daddr, ntohs(pptr[1]));
 	}
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
@@ -203,26 +198,21 @@
 	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else if (ih->nexthdr == IPPROTO_FRAGMENT)
-		sprintf(buf, "%s " NIP6_FMT "->" NIP6_FMT " frag",
-			pp->name, NIP6(ih->saddr),
-			NIP6(ih->daddr));
+		sprintf(buf, "%s %pI6->%pI6 frag",
+			pp->name, &ih->saddr, &ih->daddr);
 	else {
 		__be16 _ports[2], *pptr;
 
 		pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
 					  sizeof(_ports), _ports);
 		if (pptr == NULL)
-			sprintf(buf, "%s TRUNCATED " NIP6_FMT "->" NIP6_FMT,
-				pp->name,
-				NIP6(ih->saddr),
-				NIP6(ih->daddr));
+			sprintf(buf, "%s TRUNCATED %pI6->%pI6",
+				pp->name, &ih->saddr, &ih->daddr);
 		else
-			sprintf(buf, "%s " NIP6_FMT ":%u->" NIP6_FMT ":%u",
+			sprintf(buf, "%s %pI6:%u->%pI6:%u",
 				pp->name,
-				NIP6(ih->saddr),
-				ntohs(pptr[0]),
-				NIP6(ih->daddr),
-				ntohs(pptr[1]));
+				&ih->saddr, ntohs(pptr[0]),
+				&ih->daddr, ntohs(pptr[1]));
 	}
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 80ab0c8..79f56c1 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -135,9 +135,8 @@
 	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
-		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name, NIPQUAD(ih->saddr),
-			NIPQUAD(ih->daddr));
+		sprintf(buf, "%s %pI4->%pI4",
+			pp->name, &ih->saddr, &ih->daddr);
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
@@ -154,9 +153,8 @@
 	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
-		sprintf(buf, "%s " NIP6_FMT "->" NIP6_FMT,
-			pp->name, NIP6(ih->saddr),
-			NIP6(ih->daddr));
+		sprintf(buf, "%s %pI6->%pI6",
+			pp->name, &ih->saddr, &ih->daddr);
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index dd4566e..8cba418 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -192,8 +192,8 @@
 	/* Adjust TCP checksums */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		tcp_partial_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
-					htonl(oldlen),
-					htonl(skb->len - tcphoff));
+					htons(oldlen),
+					htons(skb->len - tcphoff));
 	} else if (!cp->app) {
 		/* Only port and addr are changed, do fast csum update */
 		tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
@@ -267,8 +267,8 @@
 	 */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		tcp_partial_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
-					htonl(oldlen),
-					htonl(skb->len - tcphoff));
+					htons(oldlen),
+					htons(skb->len - tcphoff));
 	} else if (!cp->app) {
 		/* Only port and addr are changed, do fast csum update */
 		tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 6eb6039..d2930a7 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -203,8 +203,8 @@
 	 */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		udp_partial_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
-					htonl(oldlen),
-					htonl(skb->len - udphoff));
+					htons(oldlen),
+					htons(skb->len - udphoff));
 	} else if (!cp->app && (udph->check != 0)) {
 		/* Only port and addr are changed, do fast csum update */
 		udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
@@ -279,8 +279,8 @@
 	 */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		udp_partial_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
-					htonl(oldlen),
-					htonl(skb->len - udphoff));
+					htons(oldlen),
+					htons(skb->len - udphoff));
 	} else if (!cp->app && (udph->check != 0)) {
 		/* Only port and addr are changed, do fast csum update */
 		udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index a22195f..8fb51c1 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -89,9 +89,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.init_service =		ip_vs_rr_init_svc,
 	.update_service =	ip_vs_rr_update_svc,
 	.schedule =		ip_vs_rr_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index 7d2f22f..691a6a0 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -118,9 +118,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.schedule =		ip_vs_sed_schedule,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 1d96de2..0e53955 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -61,9 +61,16 @@
 /*
  *	Returns hash value for IPVS SH entry
  */
-static inline unsigned ip_vs_sh_hashkey(__be32 addr)
+static inline unsigned ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr)
 {
-	return (ntohl(addr)*2654435761UL) & IP_VS_SH_TAB_MASK;
+	__be32 addr_fold = addr->ip;
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6)
+		addr_fold = addr->ip6[0]^addr->ip6[1]^
+			    addr->ip6[2]^addr->ip6[3];
+#endif
+	return (ntohl(addr_fold)*2654435761UL) & IP_VS_SH_TAB_MASK;
 }
 
 
@@ -71,9 +78,10 @@
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_sh_get(struct ip_vs_sh_bucket *tbl, __be32 addr)
+ip_vs_sh_get(int af, struct ip_vs_sh_bucket *tbl,
+	     const union nf_inet_addr *addr)
 {
-	return (tbl[ip_vs_sh_hashkey(addr)]).dest;
+	return (tbl[ip_vs_sh_hashkey(af, addr)]).dest;
 }
 
 
@@ -199,12 +207,14 @@
 {
 	struct ip_vs_dest *dest;
 	struct ip_vs_sh_bucket *tbl;
-	struct iphdr *iph = ip_hdr(skb);
+	struct ip_vs_iphdr iph;
+
+	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
 
 	IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
 
 	tbl = (struct ip_vs_sh_bucket *)svc->sched_data;
-	dest = ip_vs_sh_get(tbl, iph->saddr);
+	dest = ip_vs_sh_get(svc->af, tbl, &iph.saddr);
 	if (!dest
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
@@ -212,11 +222,10 @@
 		return NULL;
 	}
 
-	IP_VS_DBG(6, "SH: source IP address %u.%u.%u.%u "
-		  "--> server %u.%u.%u.%u:%d\n",
-		  NIPQUAD(iph->saddr),
-		  NIPQUAD(dest->addr.ip),
-		  ntohs(dest->port));
+	IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
+		      IP_VS_DBG_ADDR(svc->af, &iph.saddr),
+		      IP_VS_DBG_ADDR(svc->af, &dest->addr),
+		      ntohs(dest->port));
 
 	return dest;
 }
@@ -231,9 +240,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list	 =		LIST_HEAD_INIT(ip_vs_sh_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	0,
-#endif
 	.init_service =		ip_vs_sh_init_svc,
 	.done_service =		ip_vs_sh_done_svc,
 	.update_service =	ip_vs_sh_update_svc,
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index de5e7e1..6be5d4e 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -580,8 +580,8 @@
 		IP_VS_ERR("You probably need to specify IP address on "
 			  "multicast interface.\n");
 
-	IP_VS_DBG(7, "binding socket with (%s) %u.%u.%u.%u\n",
-		  ifname, NIPQUAD(addr));
+	IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
+		  ifname, &addr);
 
 	/* Now bind the socket with the address of multicast interface */
 	sin.sin_family	     = AF_INET;
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index 8c596e7..57b452b 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -106,9 +106,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.schedule =		ip_vs_wlc_schedule,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index 7ea92fe..2f618dc 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -213,9 +213,6 @@
 	.refcnt =		ATOMIC_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_wrr_scheduler.n_list),
-#ifdef CONFIG_IP_VS_IPV6
-	.supports_ipv6 =	1,
-#endif
 	.init_service =		ip_vs_wrr_init_svc,
 	.done_service =		ip_vs_wrr_done_svc,
 	.update_service =	ip_vs_wrr_update_svc,
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index e90d52f..425ab144 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -82,14 +82,13 @@
 
 			if (ip_route_output_key(&init_net, &rt, &fl)) {
 				spin_unlock(&dest->dst_lock);
-				IP_VS_DBG_RL("ip_route_output error, "
-					     "dest: %u.%u.%u.%u\n",
-					     NIPQUAD(dest->addr.ip));
+				IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
+					     &dest->addr.ip);
 				return NULL;
 			}
 			__ip_vs_dst_set(dest, rtos, dst_clone(&rt->u.dst));
-			IP_VS_DBG(10, "new dst %u.%u.%u.%u, refcnt=%d, rtos=%X\n",
-				  NIPQUAD(dest->addr.ip),
+			IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n",
+				  &dest->addr.ip,
 				  atomic_read(&rt->u.dst.__refcnt), rtos);
 		}
 		spin_unlock(&dest->dst_lock);
@@ -104,8 +103,8 @@
 		};
 
 		if (ip_route_output_key(&init_net, &rt, &fl)) {
-			IP_VS_DBG_RL("ip_route_output error, dest: "
-				     "%u.%u.%u.%u\n", NIPQUAD(cp->daddr.ip));
+			IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
+				     &cp->daddr.ip);
 			return NULL;
 		}
 	}
@@ -141,14 +140,13 @@
 								 NULL, &fl);
 			if (!rt) {
 				spin_unlock(&dest->dst_lock);
-				IP_VS_DBG_RL("ip6_route_output error, "
-					     "dest: " NIP6_FMT "\n",
-					     NIP6(dest->addr.in6));
+				IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n",
+					     &dest->addr.in6);
 				return NULL;
 			}
 			__ip_vs_dst_set(dest, 0, dst_clone(&rt->u.dst));
-			IP_VS_DBG(10, "new dst " NIP6_FMT ", refcnt=%d\n",
-				  NIP6(dest->addr.in6),
+			IP_VS_DBG(10, "new dst %pI6, refcnt=%d\n",
+				  &dest->addr.in6,
 				  atomic_read(&rt->u.dst.__refcnt));
 		}
 		spin_unlock(&dest->dst_lock);
@@ -167,8 +165,8 @@
 
 		rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
 		if (!rt) {
-			IP_VS_DBG_RL("ip6_route_output error, dest: "
-				     NIP6_FMT "\n", NIP6(cp->daddr.in6));
+			IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n",
+				     &cp->daddr.in6);
 			return NULL;
 		}
 	}
@@ -237,8 +235,8 @@
 	EnterFunction(10);
 
 	if (ip_route_output_key(&init_net, &rt, &fl)) {
-		IP_VS_DBG_RL("ip_vs_bypass_xmit(): ip_route_output error, "
-			     "dest: %u.%u.%u.%u\n", NIPQUAD(iph->daddr));
+		IP_VS_DBG_RL("ip_vs_bypass_xmit(): ip_route_output error, dest: %pI4\n",
+			     &iph->daddr);
 		goto tx_error_icmp;
 	}
 
@@ -301,8 +299,8 @@
 
 	rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
 	if (!rt) {
-		IP_VS_DBG_RL("ip_vs_bypass_xmit_v6(): ip6_route_output error, "
-			     "dest: " NIP6_FMT "\n", NIP6(iph->daddr));
+		IP_VS_DBG_RL("ip_vs_bypass_xmit_v6(): ip6_route_output error, dest: %pI6\n",
+			     &iph->daddr);
 		goto tx_error_icmp;
 	}
 
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index b92df5c..9fe8982 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -35,7 +35,7 @@
 		.data		= &init_net.ct.sysctl_acct,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{}
 };
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 4f71071..6295009 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -462,16 +462,13 @@
 		   different IP address.  Simply don't record it for
 		   NAT. */
 		if (cmd.l3num == PF_INET) {
-			pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT
-				 " != " NIPQUAD_FMT "\n",
-				 NIPQUAD(cmd.u3.ip),
-				 NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
+			pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n",
+				 &cmd.u3.ip,
+				 &ct->tuplehash[dir].tuple.src.u3.ip);
 		} else {
-			pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT
-				 " != " NIP6_FMT "\n",
-				 NIP6(*((struct in6_addr *)cmd.u3.ip6)),
-				 NIP6(*((struct in6_addr *)
-					ct->tuplehash[dir].tuple.src.u3.ip6)));
+			pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n",
+				 cmd.u3.ip6,
+				 ct->tuplehash[dir].tuple.src.u3.ip6);
 		}
 
 		/* Thanks to Cristiano Lincoln Mattos
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index c1504f7..99bc803 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -850,10 +850,8 @@
 	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
-		pr_debug("nf_ct_q931: set destCallSignalAddress "
-			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
-			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
+		pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n",
+			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3,
 			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
 		ret = set_h225_addr(skb, data, dataoff,
 				    &setup->destCallSignalAddress,
@@ -868,10 +866,8 @@
 	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
-		pr_debug("nf_ct_q931: set sourceCallSignalAddress "
-			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
-			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
+		pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n",
+			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3,
 			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
 		ret = set_h225_addr(skb, data, dataoff,
 				    &setup->sourceCallSignalAddress,
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 20633fd..4d681a0 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -156,9 +156,9 @@
 		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
 		iph = ip_hdr(skb);
-		pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
-			 NIPQUAD(iph->saddr), ntohs(th->source),
-			 NIPQUAD(iph->daddr), ntohs(th->dest));
+		pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
+			 &iph->saddr, ntohs(th->source),
+			 &iph->daddr, ntohs(th->dest));
 
 		for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
 			if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -185,10 +185,9 @@
 			    tuple->dst.u3.ip != htonl(dcc_ip)) {
 				if (net_ratelimit())
 					printk(KERN_WARNING
-						"Forged DCC command from "
-						"%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
-						NIPQUAD(tuple->src.u3.ip),
-						HIPQUAD(dcc_ip), dcc_port);
+						"Forged DCC command from %pI4: %pI4:%u\n",
+						&tuple->src.u3.ip,
+						&dcc_ip, dcc_port);
 				continue;
 			}
 
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index dbe680a..4be80d7 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -67,7 +67,7 @@
 		.data		= &nf_ct_generic_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
@@ -80,7 +80,7 @@
 		.data		= &nf_ct_generic_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index ae8c260..c2bd457 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -548,49 +548,49 @@
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_cookie_wait",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_cookie_echoed",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_established",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_sent",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_recd",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_ack_sent",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name = 0
@@ -604,49 +604,49 @@
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_cookie_wait",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_cookie_echoed",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_established",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_sent",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_recd",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_ack_sent",
 		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name = 0
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index f947ec4..a1edb9c 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1192,70 +1192,70 @@
 		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_syn_recv",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_established",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_fin_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_close_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_last_ack",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_time_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_close",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_max_retrans",
 		.data		= &nf_ct_tcp_timeout_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_unacknowledged",
 		.data		= &nf_ct_tcp_timeout_unacknowledged,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_LOOSE,
@@ -1263,7 +1263,7 @@
 		.data		= &nf_ct_tcp_loose,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_BE_LIBERAL,
@@ -1271,7 +1271,7 @@
 		.data           = &nf_ct_tcp_be_liberal,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0644,
-		.proc_handler   = &proc_dointvec,
+		.proc_handler   = proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_MAX_RETRANS,
@@ -1279,7 +1279,7 @@
 		.data		= &nf_ct_tcp_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= 0
@@ -1293,63 +1293,63 @@
 		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_syn_recv",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_established",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_fin_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_close_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_last_ack",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_time_wait",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_close",
 		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_max_retrans",
 		.data		= &nf_ct_tcp_timeout_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
@@ -1357,7 +1357,7 @@
 		.data		= &nf_ct_tcp_loose,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
@@ -1365,7 +1365,7 @@
 		.data		= &nf_ct_tcp_be_liberal,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
@@ -1373,7 +1373,7 @@
 		.data		= &nf_ct_tcp_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= 0
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 7c2ca48..2b8b1f5 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -143,14 +143,14 @@
 		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_udp_timeout_stream",
 		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
@@ -163,14 +163,14 @@
 		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_udp_timeout_stream",
 		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index d22d839e..4579d8d 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -151,7 +151,7 @@
 		.data		= &nf_ct_udplite_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -159,7 +159,7 @@
 		.data		= &nf_ct_udplite_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_jiffies,
+		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.ctl_name	= 0
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 98106d4..f37b9b7 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -336,7 +336,7 @@
 		.data		= &nf_conntrack_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_COUNT,
@@ -344,7 +344,7 @@
 		.data		= &init_net.ct.count,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name       = NET_NF_CONNTRACK_BUCKETS,
@@ -352,7 +352,7 @@
 		.data           = &nf_conntrack_htable_size,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0444,
-		.proc_handler   = &proc_dointvec,
+		.proc_handler   = proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_CHECKSUM,
@@ -360,7 +360,7 @@
 		.data		= &init_net.ct.sysctl_checksum,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= NET_NF_CONNTRACK_LOG_INVALID,
@@ -368,8 +368,8 @@
 		.data		= &init_net.ct.sysctl_log_invalid,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
@@ -379,7 +379,7 @@
 		.data		= &nf_ct_expect_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{ .ctl_name = 0 }
 };
@@ -393,7 +393,7 @@
 		.data		= &nf_conntrack_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 6fc4292..f97fded 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -893,23 +893,21 @@
 
 	switch (family) {
 	case NFPROTO_IPV4:
-		return seq_printf(s, "%ld %u.%u.%u.%u:%u->"
-				     "%u.%u.%u.%u:%u %u %u %u\n",
+		return seq_printf(s, "%ld %pI4:%u->%pI4:%u %u %u %u\n",
 				 (long)(ent->expires - jiffies)/HZ,
-				 NIPQUAD(ent->dst.ip.src),
+				 &ent->dst.ip.src,
 				 ntohs(ent->dst.src_port),
-				 NIPQUAD(ent->dst.ip.dst),
+				 &ent->dst.ip.dst,
 				 ntohs(ent->dst.dst_port),
 				 ent->rateinfo.credit, ent->rateinfo.credit_cap,
 				 ent->rateinfo.cost);
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 	case NFPROTO_IPV6:
-		return seq_printf(s, "%ld " NIP6_FMT ":%u->"
-				     NIP6_FMT ":%u %u %u %u\n",
+		return seq_printf(s, "%ld %pI6:%u->%pI6:%u %u %u %u\n",
 				 (long)(ent->expires - jiffies)/HZ,
-				 NIP6(*(struct in6_addr *)&ent->dst.ip6.src),
+				 &ent->dst.ip6.src,
 				 ntohs(ent->dst.src_port),
-				 NIP6(*(struct in6_addr *)&ent->dst.ip6.dst),
+				 &ent->dst.ip6.dst,
 				 ntohs(ent->dst.dst_port),
 				 ent->rateinfo.credit, ent->rateinfo.credit_cap,
 				 ent->rateinfo.cost);
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c
index 7ac54ea..501f9b6 100644
--- a/net/netfilter/xt_iprange.c
+++ b/net/netfilter/xt_iprange.c
@@ -26,12 +26,11 @@
 		if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
 			  || ntohl(iph->saddr) > ntohl(info->src.max_ip))
 			 ^ !!(info->flags & IPRANGE_SRC_INV)) {
-			pr_debug("src IP %u.%u.%u.%u NOT in range %s"
-				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				 NIPQUAD(iph->saddr),
+			pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
+				 &iph->saddr,
 				 info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
-				 NIPQUAD(info->src.min_ip),
-				 NIPQUAD(info->src.max_ip));
+				 &info->src.min_ip,
+				 &info->src.max_ip);
 			return false;
 		}
 	}
@@ -39,12 +38,11 @@
 		if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
 			  || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
 			 ^ !!(info->flags & IPRANGE_DST_INV)) {
-			pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
-				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				 NIPQUAD(iph->daddr),
+			pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n",
+				 &iph->daddr,
 				 info->flags & IPRANGE_DST_INV ? "(INV) " : "",
-				 NIPQUAD(info->dst.min_ip),
-				 NIPQUAD(info->dst.max_ip));
+				 &info->dst.min_ip,
+				 &info->dst.max_ip);
 			return false;
 		}
 	}
@@ -63,12 +61,11 @@
 		m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
 		m ^= !!(info->flags & IPRANGE_SRC_INV);
 		if (m) {
-			pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
-			         NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
-			         NIPQUAD(iph->saddr),
+			pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
+			         &iph->saddr,
 			         (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
-			         NIPQUAD(info->src_max.ip),
-			         NIPQUAD(info->src_max.ip));
+			         &info->src_max.ip,
+			         &info->src_max.ip);
 			return false;
 		}
 	}
@@ -77,12 +74,11 @@
 		m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
 		m ^= !!(info->flags & IPRANGE_DST_INV);
 		if (m) {
-			pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
-			         NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
-			         NIPQUAD(iph->daddr),
+			pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n",
+			         &iph->daddr,
 			         (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
-			         NIPQUAD(info->dst_min.ip),
-			         NIPQUAD(info->dst_max.ip));
+			         &info->dst_min.ip,
+			         &info->dst_max.ip);
 			return false;
 		}
 	}
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 280c471..3c3dd22 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -422,13 +422,11 @@
 
 	i = (e->index - 1) % ip_pkt_list_tot;
 	if (e->family == NFPROTO_IPV4)
-		seq_printf(seq, "src=" NIPQUAD_FMT " ttl: %u last_seen: %lu "
-			   "oldest_pkt: %u", NIPQUAD(e->addr.ip), e->ttl,
-			   e->stamps[i], e->index);
+		seq_printf(seq, "src=%pI4 ttl: %u last_seen: %lu oldest_pkt: %u",
+			   &e->addr.ip, e->ttl, e->stamps[i], e->index);
 	else
-		seq_printf(seq, "src=" NIP6_FMT " ttl: %u last_seen: %lu "
-			   "oldest_pkt: %u", NIP6(e->addr.in6), e->ttl,
-			   e->stamps[i], e->index);
+		seq_printf(seq, "src=%pI6 ttl: %u last_seen: %lu oldest_pkt: %u",
+			   &e->addr.in6, e->ttl, e->stamps[i], e->index);
 	for (i = 0; i < e->nstamps; i++)
 		seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]);
 	seq_printf(seq, "\n");
diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c
index 249f6b9..834c6eb 100644
--- a/net/netlabel/netlabel_addrlist.c
+++ b/net/netlabel/netlabel_addrlist.c
@@ -337,7 +337,7 @@
 
 	if (dev != NULL)
 		audit_log_format(audit_buf, " netif=%s", dev);
-	audit_log_format(audit_buf, " %s=" NIPQUAD_FMT, dir, NIPQUAD(addr));
+	audit_log_format(audit_buf, " %s=%pI4", dir, &addr);
 	if (mask_val != 0xffffffff) {
 		u32 mask_len = 0;
 		while (mask_val > 0) {
@@ -371,7 +371,7 @@
 
 	if (dev != NULL)
 		audit_log_format(audit_buf, " netif=%s", dev);
-	audit_log_format(audit_buf, " %s=" NIP6_FMT, dir, NIP6(*addr));
+	audit_log_format(audit_buf, " %s=%pI6", dir, addr);
 	if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
 		u32 mask_len = 0;
 		u32 mask_val;
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index 2d106cf..c83fea7 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -233,7 +233,7 @@
  *
  * Returns the number of bytes copied.
  */
-int nla_memcpy(void *dest, struct nlattr *src, int count)
+int nla_memcpy(void *dest, const struct nlattr *src, int count)
 {
 	int minlen = min_t(int, count, nla_len(src));
 
diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c
index 34c96c9..7b49591 100644
--- a/net/netrom/sysctl_net_netrom.c
+++ b/net/netrom/sysctl_net_netrom.c
@@ -41,8 +41,8 @@
 		.data		= &sysctl_netrom_default_path_quality,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_quality,
 		.extra2		= &max_quality
 	},
@@ -52,8 +52,8 @@
 		.data		= &sysctl_netrom_obsolescence_count_initialiser,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_obs,
 		.extra2		= &max_obs
 	},
@@ -63,8 +63,8 @@
 		.data		= &sysctl_netrom_network_ttl_initialiser,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_ttl,
 		.extra2		= &max_ttl
 	},
@@ -74,8 +74,8 @@
 		.data		= &sysctl_netrom_transport_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t1,
 		.extra2		= &max_t1
 	},
@@ -85,8 +85,8 @@
 		.data		= &sysctl_netrom_transport_maximum_tries,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_n2,
 		.extra2		= &max_n2
 	},
@@ -96,8 +96,8 @@
 		.data		= &sysctl_netrom_transport_acknowledge_delay,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t2,
 		.extra2		= &max_t2
 	},
@@ -107,8 +107,8 @@
 		.data		= &sysctl_netrom_transport_busy_delay,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_t4,
 		.extra2		= &max_t4
 	},
@@ -118,8 +118,8 @@
 		.data		= &sysctl_netrom_transport_requested_window_size,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_window,
 		.extra2		= &max_window
 	},
@@ -129,8 +129,8 @@
 		.data		= &sysctl_netrom_transport_no_activity_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_idle,
 		.extra2		= &max_idle
 	},
@@ -140,8 +140,8 @@
 		.data		= &sysctl_netrom_routing_control,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_route,
 		.extra2		= &max_route
 	},
@@ -151,8 +151,8 @@
 		.data		= &sysctl_netrom_link_fails_count,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_fails,
 		.extra2		= &max_fails
 	},
@@ -162,8 +162,8 @@
 		.data		= &sysctl_netrom_reset_circuit,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_reset,
 		.extra2		= &max_reset
 	},
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index defeb7a..f400ff1 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -35,7 +35,11 @@
 
 static struct net_proto_family phonet_proto_family;
 static struct phonet_protocol *phonet_proto_get(int protocol);
-static inline void phonet_proto_put(struct phonet_protocol *pp);
+
+static inline void phonet_proto_put(struct phonet_protocol *pp)
+{
+	module_put(pp->prot->owner);
+}
 
 /* protocol family functions */
 
@@ -428,11 +432,6 @@
 	return pp;
 }
 
-static inline void phonet_proto_put(struct phonet_protocol *pp)
-{
-	module_put(pp->prot->owner);
-}
-
 /* Module registration */
 static int __init phonet_init(void)
 {
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 9978afb..e6e8e44 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -41,7 +41,6 @@
 	void			(*old_write_space)(struct sock *);
 
 	struct net_device	*net;
-	struct net_device_stats	stats;
 
 	struct sk_buff_head	tx_queue;
 	struct work_struct	tx_work;
@@ -49,14 +48,14 @@
 	unsigned		tx_max;
 };
 
-static int gprs_type_trans(struct sk_buff *skb)
+static __be16 gprs_type_trans(struct sk_buff *skb)
 {
 	const u8 *pvfc;
 	u8 buf;
 
 	pvfc = skb_header_pointer(skb, 0, 1, &buf);
 	if (!pvfc)
-		return 0;
+		return htons(0);
 	/* Look at IP version field */
 	switch (*pvfc >> 4) {
 	case 4:
@@ -64,7 +63,7 @@
 	case 6:
 		return htons(ETH_P_IPV6);
 	}
-	return 0;
+	return htons(0);
 }
 
 /*
@@ -83,8 +82,9 @@
 
 static int gprs_recv(struct gprs_dev *dev, struct sk_buff *skb)
 {
+	struct net_device *net = dev->net;
 	int err = 0;
-	u16 protocol = gprs_type_trans(skb);
+	__be16 protocol = gprs_type_trans(skb);
 
 	if (!protocol) {
 		err = -EINVAL;
@@ -99,7 +99,7 @@
 		 * so wrap the IP packet as a single fragment of an head-less
 		 * socket buffer. The network stack will pull what it needs,
 		 * but at least, the whole IP payload is not memcpy'd. */
-		rskb = netdev_alloc_skb(dev->net, 0);
+		rskb = netdev_alloc_skb(net, 0);
 		if (!rskb) {
 			err = -ENOBUFS;
 			goto drop;
@@ -123,11 +123,11 @@
 
 	skb->protocol = protocol;
 	skb_reset_mac_header(skb);
-	skb->dev = dev->net;
+	skb->dev = net;
 
-	if (likely(dev->net->flags & IFF_UP)) {
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
+	if (likely(net->flags & IFF_UP)) {
+		net->stats.rx_packets++;
+		net->stats.rx_bytes += skb->len;
 		netif_rx(skb);
 		skb = NULL;
 	} else
@@ -136,7 +136,7 @@
 drop:
 	if (skb) {
 		dev_kfree_skb(skb);
-		dev->stats.rx_dropped++;
+		net->stats.rx_dropped++;
 	}
 	return err;
 }
@@ -199,14 +199,15 @@
 static void gprs_tx(struct work_struct *work)
 {
 	struct gprs_dev *dev = container_of(work, struct gprs_dev, tx_work);
+	struct net_device *net = dev->net;
 	struct sock *sk = dev->sk;
 	struct sk_buff *skb;
 
 	while ((skb = skb_dequeue(&dev->tx_queue)) != NULL) {
 		int err;
 
-		dev->stats.tx_bytes += skb->len;
-		dev->stats.tx_packets++;
+		net->stats.tx_bytes += skb->len;
+		net->stats.tx_packets++;
 
 		skb_orphan(skb);
 		skb_set_owner_w(skb, sk);
@@ -215,9 +216,9 @@
 		err = pep_write(sk, skb);
 		if (err) {
 			LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
-					dev->net->name, err);
-			dev->stats.tx_aborted_errors++;
-			dev->stats.tx_errors++;
+					net->name, err);
+			net->stats.tx_aborted_errors++;
+			net->stats.tx_errors++;
 		}
 		release_sock(sk);
 	}
@@ -236,13 +237,6 @@
 	return 0;
 }
 
-static struct net_device_stats *gprs_get_stats(struct net_device *net)
-{
-	struct gprs_dev *dev = netdev_priv(net);
-
-	return &dev->stats;
-}
-
 static void gprs_setup(struct net_device *net)
 {
 	net->features		= NETIF_F_FRAGLIST;
@@ -256,7 +250,6 @@
 	net->destructor		= free_netdev;
 	net->hard_start_xmit	= gprs_xmit; /* mandatory */
 	net->change_mtu		= gprs_set_mtu;
-	net->get_stats		= gprs_get_stats;
 }
 
 /*
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c
index 600a430..0e3347b 100644
--- a/net/phonet/sysctl.c
+++ b/net/phonet/sysctl.c
@@ -89,7 +89,7 @@
 		.data		= &local_port_range,
 		.maxlen		= sizeof(local_port_range),
 		.mode		= 0644,
-		.proc_handler	= &proc_local_port_range,
+		.proc_handler	= proc_local_port_range,
 		.strategy	= NULL,
 	},
 	{ .ctl_name = 0 }
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index bfdade7..84efde9 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -24,138 +24,318 @@
 MODULE_DESCRIPTION("Input layer to RF switch connector");
 MODULE_LICENSE("GPL");
 
-struct rfkill_task {
-	struct work_struct work;
-	enum rfkill_type type;
-	struct mutex mutex; /* ensures that task is serialized */
-	spinlock_t lock; /* for accessing last and desired state */
-	unsigned long last; /* last schedule */
-	enum rfkill_state desired_state; /* on/off */
+enum rfkill_input_master_mode {
+	RFKILL_INPUT_MASTER_DONOTHING = 0,
+	RFKILL_INPUT_MASTER_RESTORE = 1,
+	RFKILL_INPUT_MASTER_UNBLOCKALL = 2,
+	RFKILL_INPUT_MASTER_MAX,	/* marker */
 };
 
+/* Delay (in ms) between consecutive switch ops */
+#define RFKILL_OPS_DELAY 200
+
+static enum rfkill_input_master_mode rfkill_master_switch_mode =
+					RFKILL_INPUT_MASTER_UNBLOCKALL;
+module_param_named(master_switch_mode, rfkill_master_switch_mode, uint, 0);
+MODULE_PARM_DESC(master_switch_mode,
+	"SW_RFKILL_ALL ON should: 0=do nothing; 1=restore; 2=unblock all");
+
+enum rfkill_global_sched_op {
+	RFKILL_GLOBAL_OP_EPO = 0,
+	RFKILL_GLOBAL_OP_RESTORE,
+	RFKILL_GLOBAL_OP_UNLOCK,
+	RFKILL_GLOBAL_OP_UNBLOCK,
+};
+
+/*
+ * Currently, the code marked with RFKILL_NEED_SWSET is inactive.
+ * If handling of EV_SW SW_WLAN/WWAN/BLUETOOTH/etc is needed in the
+ * future, when such events are added, that code will be necessary.
+ */
+
+struct rfkill_task {
+	struct delayed_work dwork;
+
+	/* ensures that task is serialized */
+	struct mutex mutex;
+
+	/* protects everything below */
+	spinlock_t lock;
+
+	/* pending regular switch operations (1=pending) */
+	unsigned long sw_pending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+#ifdef RFKILL_NEED_SWSET
+	/* set operation pending (1=pending) */
+	unsigned long sw_setpending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+	/* desired state for pending set operation (1=unblock) */
+	unsigned long sw_newstate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+#endif
+
+	/* should the state be complemented (1=yes) */
+	unsigned long sw_togglestate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+	bool global_op_pending;
+	enum rfkill_global_sched_op op;
+
+	/* last time it was scheduled */
+	unsigned long last_scheduled;
+};
+
+static void __rfkill_handle_global_op(enum rfkill_global_sched_op op)
+{
+	unsigned int i;
+
+	switch (op) {
+	case RFKILL_GLOBAL_OP_EPO:
+		rfkill_epo();
+		break;
+	case RFKILL_GLOBAL_OP_RESTORE:
+		rfkill_restore_states();
+		break;
+	case RFKILL_GLOBAL_OP_UNLOCK:
+		rfkill_remove_epo_lock();
+		break;
+	case RFKILL_GLOBAL_OP_UNBLOCK:
+		rfkill_remove_epo_lock();
+		for (i = 0; i < RFKILL_TYPE_MAX; i++)
+			rfkill_switch_all(i, RFKILL_STATE_UNBLOCKED);
+		break;
+	default:
+		/* memory corruption or bug, fail safely */
+		rfkill_epo();
+		WARN(1, "Unknown requested operation %d! "
+			"rfkill Emergency Power Off activated\n",
+			op);
+	}
+}
+
+#ifdef RFKILL_NEED_SWSET
+static void __rfkill_handle_normal_op(const enum rfkill_type type,
+			const bool sp, const bool s, const bool c)
+{
+	enum rfkill_state state;
+
+	if (sp)
+		state = (s) ? RFKILL_STATE_UNBLOCKED :
+			      RFKILL_STATE_SOFT_BLOCKED;
+	else
+		state = rfkill_get_global_state(type);
+
+	if (c)
+		state = rfkill_state_complement(state);
+
+	rfkill_switch_all(type, state);
+}
+#else
+static void __rfkill_handle_normal_op(const enum rfkill_type type,
+			const bool c)
+{
+	enum rfkill_state state;
+
+	state = rfkill_get_global_state(type);
+	if (c)
+		state = rfkill_state_complement(state);
+
+	rfkill_switch_all(type, state);
+}
+#endif
+
 static void rfkill_task_handler(struct work_struct *work)
 {
-	struct rfkill_task *task = container_of(work, struct rfkill_task, work);
+	struct rfkill_task *task = container_of(work,
+					struct rfkill_task, dwork.work);
+	bool doit = true;
 
 	mutex_lock(&task->mutex);
 
-	rfkill_switch_all(task->type, task->desired_state);
+	spin_lock_irq(&task->lock);
+	while (doit) {
+		if (task->global_op_pending) {
+			enum rfkill_global_sched_op op = task->op;
+			task->global_op_pending = false;
+			memset(task->sw_pending, 0, sizeof(task->sw_pending));
+			spin_unlock_irq(&task->lock);
+
+			__rfkill_handle_global_op(op);
+
+			/* make sure we do at least one pass with
+			 * !task->global_op_pending */
+			spin_lock_irq(&task->lock);
+			continue;
+		} else if (!rfkill_is_epo_lock_active()) {
+			unsigned int i = 0;
+
+			while (!task->global_op_pending &&
+						i < RFKILL_TYPE_MAX) {
+				if (test_and_clear_bit(i, task->sw_pending)) {
+					bool c;
+#ifdef RFKILL_NEED_SWSET
+					bool sp, s;
+					sp = test_and_clear_bit(i,
+							task->sw_setpending);
+					s = test_bit(i, task->sw_newstate);
+#endif
+					c = test_and_clear_bit(i,
+							task->sw_togglestate);
+					spin_unlock_irq(&task->lock);
+
+#ifdef RFKILL_NEED_SWSET
+					__rfkill_handle_normal_op(i, sp, s, c);
+#else
+					__rfkill_handle_normal_op(i, c);
+#endif
+
+					spin_lock_irq(&task->lock);
+				}
+				i++;
+			}
+		}
+		doit = task->global_op_pending;
+	}
+	spin_unlock_irq(&task->lock);
 
 	mutex_unlock(&task->mutex);
 }
 
-static void rfkill_task_epo_handler(struct work_struct *work)
+static struct rfkill_task rfkill_task = {
+	.dwork = __DELAYED_WORK_INITIALIZER(rfkill_task.dwork,
+				rfkill_task_handler),
+	.mutex = __MUTEX_INITIALIZER(rfkill_task.mutex),
+	.lock = __SPIN_LOCK_UNLOCKED(rfkill_task.lock),
+};
+
+static unsigned long rfkill_ratelimit(const unsigned long last)
 {
-	rfkill_epo();
+	const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY);
+	return (time_after(jiffies, last + delay)) ? 0 : delay;
 }
 
-static DECLARE_WORK(epo_work, rfkill_task_epo_handler);
-
-static void rfkill_schedule_epo(void)
+static void rfkill_schedule_ratelimited(void)
 {
-	schedule_work(&epo_work);
+	if (!delayed_work_pending(&rfkill_task.dwork)) {
+		schedule_delayed_work(&rfkill_task.dwork,
+				rfkill_ratelimit(rfkill_task.last_scheduled));
+		rfkill_task.last_scheduled = jiffies;
+	}
 }
 
-static void rfkill_schedule_set(struct rfkill_task *task,
+static void rfkill_schedule_global_op(enum rfkill_global_sched_op op)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	rfkill_task.op = op;
+	rfkill_task.global_op_pending = true;
+	if (op == RFKILL_GLOBAL_OP_EPO && !rfkill_is_epo_lock_active()) {
+		/* bypass the limiter for EPO */
+		cancel_delayed_work(&rfkill_task.dwork);
+		schedule_delayed_work(&rfkill_task.dwork, 0);
+		rfkill_task.last_scheduled = jiffies;
+	} else
+		rfkill_schedule_ratelimited();
+	spin_unlock_irqrestore(&rfkill_task.lock, flags);
+}
+
+#ifdef RFKILL_NEED_SWSET
+/* Use this if you need to add EV_SW SW_WLAN/WWAN/BLUETOOTH/etc handling */
+
+static void rfkill_schedule_set(enum rfkill_type type,
 				enum rfkill_state desired_state)
 {
 	unsigned long flags;
 
-	if (unlikely(work_pending(&epo_work)))
+	if (rfkill_is_epo_lock_active())
 		return;
 
-	spin_lock_irqsave(&task->lock, flags);
-
-	if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
-		task->desired_state = desired_state;
-		task->last = jiffies;
-		schedule_work(&task->work);
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	if (!rfkill_task.global_op_pending) {
+		set_bit(type, rfkill_task.sw_pending);
+		set_bit(type, rfkill_task.sw_setpending);
+		clear_bit(type, rfkill_task.sw_togglestate);
+		if (desired_state)
+			set_bit(type,  rfkill_task.sw_newstate);
+		else
+			clear_bit(type, rfkill_task.sw_newstate);
+		rfkill_schedule_ratelimited();
 	}
-
-	spin_unlock_irqrestore(&task->lock, flags);
+	spin_unlock_irqrestore(&rfkill_task.lock, flags);
 }
+#endif
 
-static void rfkill_schedule_toggle(struct rfkill_task *task)
+static void rfkill_schedule_toggle(enum rfkill_type type)
 {
 	unsigned long flags;
 
-	if (unlikely(work_pending(&epo_work)))
+	if (rfkill_is_epo_lock_active())
 		return;
 
-	spin_lock_irqsave(&task->lock, flags);
-
-	if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
-		task->desired_state =
-				rfkill_state_complement(task->desired_state);
-		task->last = jiffies;
-		schedule_work(&task->work);
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	if (!rfkill_task.global_op_pending) {
+		set_bit(type, rfkill_task.sw_pending);
+		change_bit(type, rfkill_task.sw_togglestate);
+		rfkill_schedule_ratelimited();
 	}
-
-	spin_unlock_irqrestore(&task->lock, flags);
+	spin_unlock_irqrestore(&rfkill_task.lock, flags);
 }
 
-#define DEFINE_RFKILL_TASK(n, t)				\
-	struct rfkill_task n = {				\
-		.work = __WORK_INITIALIZER(n.work,		\
-				rfkill_task_handler),		\
-		.type = t,					\
-		.mutex = __MUTEX_INITIALIZER(n.mutex),		\
-		.lock = __SPIN_LOCK_UNLOCKED(n.lock),		\
-		.desired_state = RFKILL_STATE_UNBLOCKED,	\
-	}
-
-static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
-static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
-static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
-static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
-static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
-
 static void rfkill_schedule_evsw_rfkillall(int state)
 {
-	/* EVERY radio type. state != 0 means radios ON */
-	/* handle EPO (emergency power off) through shortcut */
 	if (state) {
-		rfkill_schedule_set(&rfkill_wwan,
-				    RFKILL_STATE_UNBLOCKED);
-		rfkill_schedule_set(&rfkill_wimax,
-				    RFKILL_STATE_UNBLOCKED);
-		rfkill_schedule_set(&rfkill_uwb,
-				    RFKILL_STATE_UNBLOCKED);
-		rfkill_schedule_set(&rfkill_bt,
-				    RFKILL_STATE_UNBLOCKED);
-		rfkill_schedule_set(&rfkill_wlan,
-				    RFKILL_STATE_UNBLOCKED);
+		switch (rfkill_master_switch_mode) {
+		case RFKILL_INPUT_MASTER_UNBLOCKALL:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNBLOCK);
+			break;
+		case RFKILL_INPUT_MASTER_RESTORE:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_RESTORE);
+			break;
+		case RFKILL_INPUT_MASTER_DONOTHING:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNLOCK);
+			break;
+		default:
+			/* memory corruption or driver bug! fail safely */
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
+			WARN(1, "Unknown rfkill_master_switch_mode (%d), "
+				"driver bug or memory corruption detected!\n",
+				rfkill_master_switch_mode);
+			break;
+		}
 	} else
-		rfkill_schedule_epo();
+		rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
 }
 
 static void rfkill_event(struct input_handle *handle, unsigned int type,
 			unsigned int code, int data)
 {
 	if (type == EV_KEY && data == 1) {
+		enum rfkill_type t;
+
 		switch (code) {
 		case KEY_WLAN:
-			rfkill_schedule_toggle(&rfkill_wlan);
+			t = RFKILL_TYPE_WLAN;
 			break;
 		case KEY_BLUETOOTH:
-			rfkill_schedule_toggle(&rfkill_bt);
+			t = RFKILL_TYPE_BLUETOOTH;
 			break;
 		case KEY_UWB:
-			rfkill_schedule_toggle(&rfkill_uwb);
+			t = RFKILL_TYPE_UWB;
 			break;
 		case KEY_WIMAX:
-			rfkill_schedule_toggle(&rfkill_wimax);
+			t = RFKILL_TYPE_WIMAX;
 			break;
 		default:
-			break;
+			return;
 		}
+		rfkill_schedule_toggle(t);
+		return;
 	} else if (type == EV_SW) {
 		switch (code) {
 		case SW_RFKILL_ALL:
 			rfkill_schedule_evsw_rfkillall(data);
-			break;
+			return;
 		default:
-			break;
+			return;
 		}
 	}
 }
@@ -256,18 +436,23 @@
 
 static int __init rfkill_handler_init(void)
 {
-	unsigned long last_run = jiffies - msecs_to_jiffies(500);
-	rfkill_wlan.last = last_run;
-	rfkill_bt.last = last_run;
-	rfkill_uwb.last = last_run;
-	rfkill_wimax.last = last_run;
+	if (rfkill_master_switch_mode >= RFKILL_INPUT_MASTER_MAX)
+		return -EINVAL;
+
+	/*
+	 * The penalty to not doing this is a possible RFKILL_OPS_DELAY delay
+	 * at the first use.  Acceptable, but if we can avoid it, why not?
+	 */
+	rfkill_task.last_scheduled =
+			jiffies - msecs_to_jiffies(RFKILL_OPS_DELAY) - 1;
 	return input_register_handler(&rfkill_handler);
 }
 
 static void __exit rfkill_handler_exit(void)
 {
 	input_unregister_handler(&rfkill_handler);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&rfkill_task.dwork);
+	rfkill_remove_epo_lock();
 }
 
 module_init(rfkill_handler_init);
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h
index bbfa646..fe8df6b 100644
--- a/net/rfkill/rfkill-input.h
+++ b/net/rfkill/rfkill-input.h
@@ -14,5 +14,8 @@
 void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
 void rfkill_epo(void);
 void rfkill_restore_states(void);
+void rfkill_remove_epo_lock(void);
+bool rfkill_is_epo_lock_active(void);
+enum rfkill_state rfkill_get_global_state(const enum rfkill_type type);
 
 #endif /* __RFKILL_INPUT_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 25ba3bd..ec26eae 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -51,6 +51,7 @@
 
 static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX];
 static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+static bool rfkill_epo_lock_active;
 
 static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
 
@@ -264,11 +265,14 @@
  *
  * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state).
  * Please refer to __rfkill_switch_all() for details.
+ *
+ * Does nothing if the EPO lock is active.
  */
 void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
 {
 	mutex_lock(&rfkill_global_mutex);
-	__rfkill_switch_all(type, state);
+	if (!rfkill_epo_lock_active)
+		__rfkill_switch_all(type, state);
 	mutex_unlock(&rfkill_global_mutex);
 }
 EXPORT_SYMBOL(rfkill_switch_all);
@@ -289,6 +293,7 @@
 
 	mutex_lock(&rfkill_global_mutex);
 
+	rfkill_epo_lock_active = true;
 	list_for_each_entry(rfkill, &rfkill_list, node) {
 		mutex_lock(&rfkill->mutex);
 		rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
@@ -317,6 +322,7 @@
 
 	mutex_lock(&rfkill_global_mutex);
 
+	rfkill_epo_lock_active = false;
 	for (i = 0; i < RFKILL_TYPE_MAX; i++)
 		__rfkill_switch_all(i, rfkill_global_states[i].default_state);
 	mutex_unlock(&rfkill_global_mutex);
@@ -324,6 +330,48 @@
 EXPORT_SYMBOL_GPL(rfkill_restore_states);
 
 /**
+ * rfkill_remove_epo_lock - unlock state changes
+ *
+ * Used by rfkill-input manually unlock state changes, when
+ * the EPO switch is deactivated.
+ */
+void rfkill_remove_epo_lock(void)
+{
+	mutex_lock(&rfkill_global_mutex);
+	rfkill_epo_lock_active = false;
+	mutex_unlock(&rfkill_global_mutex);
+}
+EXPORT_SYMBOL_GPL(rfkill_remove_epo_lock);
+
+/**
+ * rfkill_is_epo_lock_active - returns true EPO is active
+ *
+ * Returns 0 (false) if there is NOT an active EPO contidion,
+ * and 1 (true) if there is an active EPO contition, which
+ * locks all radios in one of the BLOCKED states.
+ *
+ * Can be called in atomic context.
+ */
+bool rfkill_is_epo_lock_active(void)
+{
+	return rfkill_epo_lock_active;
+}
+EXPORT_SYMBOL_GPL(rfkill_is_epo_lock_active);
+
+/**
+ * rfkill_get_global_state - returns global state for a type
+ * @type: the type to get the global state of
+ *
+ * Returns the current global state for a given wireless
+ * device type.
+ */
+enum rfkill_state rfkill_get_global_state(const enum rfkill_type type)
+{
+	return rfkill_global_states[type].current_state;
+}
+EXPORT_SYMBOL_GPL(rfkill_get_global_state);
+
+/**
  * rfkill_force_state - Force the internal rfkill radio state
  * @rfkill: pointer to the rfkill class to modify.
  * @state: the current radio state the class should be forced to.
@@ -431,9 +479,15 @@
 	    state != RFKILL_STATE_SOFT_BLOCKED)
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&rfkill->mutex))
-		return -ERESTARTSYS;
-	error = rfkill_toggle_radio(rfkill, state, 0);
+	error = mutex_lock_killable(&rfkill->mutex);
+	if (error)
+		return error;
+
+	if (!rfkill_epo_lock_active)
+		error = rfkill_toggle_radio(rfkill, state, 0);
+	else
+		error = -EPERM;
+
 	mutex_unlock(&rfkill->mutex);
 
 	return error ? error : count;
@@ -472,12 +526,12 @@
 	 * Take the global lock to make sure the kernel is not in
 	 * the middle of rfkill_switch_all
 	 */
-	error = mutex_lock_interruptible(&rfkill_global_mutex);
+	error = mutex_lock_killable(&rfkill_global_mutex);
 	if (error)
 		return error;
 
 	if (rfkill->user_claim != claim) {
-		if (!claim) {
+		if (!claim && !rfkill_epo_lock_active) {
 			mutex_lock(&rfkill->mutex);
 			rfkill_toggle_radio(rfkill,
 					rfkill_global_states[rfkill->type].current_state,
@@ -527,8 +581,17 @@
 
 		dev->power.power_state.event = PM_EVENT_ON;
 
-		/* restore radio state AND notify everybody */
-		rfkill_toggle_radio(rfkill, rfkill->state, 1);
+		/*
+		 * If we are under EPO, kick transmitter offline,
+		 * otherwise restore to pre-suspend state.
+		 *
+		 * Issue a notification in any case
+		 */
+		rfkill_toggle_radio(rfkill,
+				rfkill_epo_lock_active ?
+					RFKILL_STATE_SOFT_BLOCKED :
+					rfkill->state,
+				1);
 
 		mutex_unlock(&rfkill->mutex);
 	}
@@ -711,7 +774,7 @@
 	int error;
 
 	if (!rfkill->led_trigger.name)
-		rfkill->led_trigger.name = rfkill->dev.bus_id;
+		rfkill->led_trigger.name = dev_name(&rfkill->dev);
 	if (!rfkill->led_trigger.activate)
 		rfkill->led_trigger.activate = rfkill_led_trigger_activate;
 	error = led_trigger_register(&rfkill->led_trigger);
@@ -752,8 +815,7 @@
 			"badly initialized rfkill struct\n"))
 		return -EINVAL;
 
-	snprintf(dev->bus_id, sizeof(dev->bus_id),
-		 "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
+	dev_set_name(dev, "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
 
 	rfkill_led_trigger_register(rfkill);
 
@@ -833,6 +895,7 @@
 
 	if (!test_and_set_bit(type, rfkill_states_lockdflt)) {
 		rfkill_global_states[type].default_state = state;
+		rfkill_global_states[type].current_state = state;
 		error = 0;
 	} else
 		error = -EPERM;
diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c
index 20be348..3bfe504 100644
--- a/net/rose/sysctl_net_rose.c
+++ b/net/rose/sysctl_net_rose.c
@@ -31,8 +31,8 @@
 		.data		= &sysctl_rose_restart_request_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
@@ -42,8 +42,8 @@
 		.data		= &sysctl_rose_call_request_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
@@ -53,8 +53,8 @@
 		.data		= &sysctl_rose_reset_request_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
@@ -64,8 +64,8 @@
 		.data		= &sysctl_rose_clear_request_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
@@ -75,8 +75,8 @@
 		.data		= &sysctl_rose_no_activity_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_idle,
 		.extra2		= &max_idle
 	},
@@ -86,8 +86,8 @@
 		.data		= &sysctl_rose_ack_hold_back_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
@@ -97,8 +97,8 @@
 		.data		= &sysctl_rose_routing_control,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_route,
 		.extra2		= &max_route
 	},
@@ -108,8 +108,8 @@
 		.data		= &sysctl_rose_link_fail_timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_ftimer,
 		.extra2		= &max_ftimer
 	},
@@ -119,8 +119,8 @@
 		.data		= &sysctl_rose_maximum_vcs,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_maxvcs,
 		.extra2		= &max_maxvcs
 	},
@@ -130,8 +130,8 @@
 		.data		= &sysctl_rose_window_size,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &min_window,
 		.extra2		= &max_window
 	},
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 32e4891..d7d2bed 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -96,9 +96,9 @@
 
 	switch (srx->transport.family) {
 	case AF_INET:
-		_debug("INET: %x @ %u.%u.%u.%u",
+		_debug("INET: %x @ %pI4",
 		       ntohs(srx->transport.sin.sin_port),
-		       NIPQUAD(srx->transport.sin.sin_addr));
+		       &srx->transport.sin.sin_addr);
 		if (srx->transport_len > 8)
 			memset((void *)&srx->transport + 8, 0,
 			       srx->transport_len - 8);
diff --git a/net/rxrpc/ar-error.c b/net/rxrpc/ar-error.c
index 6cb3e88..d4d1ae2 100644
--- a/net/rxrpc/ar-error.c
+++ b/net/rxrpc/ar-error.c
@@ -49,8 +49,7 @@
 	addr = *(__be32 *)(skb_network_header(skb) + serr->addr_offset);
 	port = serr->port;
 
-	_net("Rx UDP Error from "NIPQUAD_FMT":%hu",
-	     NIPQUAD(addr), ntohs(port));
+	_net("Rx UDP Error from %pI4:%hu", &addr, ntohs(port));
 	_debug("Msg l:%d d:%d", skb->len, skb->data_len);
 
 	peer = rxrpc_find_peer(local, addr, port);
diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c
index f3a2bd7..807535f 100644
--- a/net/rxrpc/ar-local.c
+++ b/net/rxrpc/ar-local.c
@@ -131,10 +131,10 @@
 	struct rxrpc_local *local;
 	int ret;
 
-	_enter("{%d,%u,%u.%u.%u.%u+%hu}",
+	_enter("{%d,%u,%pI4+%hu}",
 	       srx->transport_type,
 	       srx->transport.family,
-	       NIPQUAD(srx->transport.sin.sin_addr),
+	       &srx->transport.sin.sin_addr,
 	       ntohs(srx->transport.sin.sin_port));
 
 	down_write(&rxrpc_local_sem);
@@ -143,10 +143,10 @@
 	read_lock_bh(&rxrpc_local_lock);
 
 	list_for_each_entry(local, &rxrpc_locals, link) {
-		_debug("CMP {%d,%u,%u.%u.%u.%u+%hu}",
+		_debug("CMP {%d,%u,%pI4+%hu}",
 		       local->srx.transport_type,
 		       local->srx.transport.family,
-		       NIPQUAD(local->srx.transport.sin.sin_addr),
+		       &local->srx.transport.sin.sin_addr,
 		       ntohs(local->srx.transport.sin.sin_port));
 
 		if (local->srx.transport_type != srx->transport_type ||
@@ -188,11 +188,11 @@
 
 	up_write(&rxrpc_local_sem);
 
-	_net("LOCAL new %d {%d,%u,%u.%u.%u.%u+%hu}",
+	_net("LOCAL new %d {%d,%u,%pI4+%hu}",
 	     local->debug_id,
 	     local->srx.transport_type,
 	     local->srx.transport.family,
-	     NIPQUAD(local->srx.transport.sin.sin_addr),
+	     &local->srx.transport.sin.sin_addr,
 	     ntohs(local->srx.transport.sin.sin_port));
 
 	_leave(" = %p [new]", local);
@@ -203,11 +203,11 @@
 	read_unlock_bh(&rxrpc_local_lock);
 	up_write(&rxrpc_local_sem);
 
-	_net("LOCAL old %d {%d,%u,%u.%u.%u.%u+%hu}",
+	_net("LOCAL old %d {%d,%u,%pI4+%hu}",
 	     local->debug_id,
 	     local->srx.transport_type,
 	     local->srx.transport.family,
-	     NIPQUAD(local->srx.transport.sin.sin_addr),
+	     &local->srx.transport.sin.sin_addr,
 	     ntohs(local->srx.transport.sin.sin_port));
 
 	_leave(" = %p [reuse]", local);
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c
index 2abe208..edc026c 100644
--- a/net/rxrpc/ar-peer.c
+++ b/net/rxrpc/ar-peer.c
@@ -123,10 +123,10 @@
 	const char *new = "old";
 	int usage;
 
-	_enter("{%d,%d,%u.%u.%u.%u+%hu}",
+	_enter("{%d,%d,%pI4+%hu}",
 	       srx->transport_type,
 	       srx->transport_len,
-	       NIPQUAD(srx->transport.sin.sin_addr),
+	       &srx->transport.sin.sin_addr,
 	       ntohs(srx->transport.sin.sin_port));
 
 	/* search the peer list first */
@@ -177,12 +177,12 @@
 	new = "new";
 
 success:
-	_net("PEER %s %d {%d,%u,%u.%u.%u.%u+%hu}",
+	_net("PEER %s %d {%d,%u,%pI4+%hu}",
 	     new,
 	     peer->debug_id,
 	     peer->srx.transport_type,
 	     peer->srx.transport.family,
-	     NIPQUAD(peer->srx.transport.sin.sin_addr),
+	     &peer->srx.transport.sin.sin_addr,
 	     ntohs(peer->srx.transport.sin.sin_port));
 
 	_leave(" = %p {u=%d}", peer, atomic_read(&peer->usage));
diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
index 017322e..38047f7 100644
--- a/net/rxrpc/ar-proc.c
+++ b/net/rxrpc/ar-proc.c
@@ -61,12 +61,12 @@
 	call = list_entry(v, struct rxrpc_call, link);
 	trans = call->conn->trans;
 
-	sprintf(lbuff, NIPQUAD_FMT":%u",
-		NIPQUAD(trans->local->srx.transport.sin.sin_addr),
+	sprintf(lbuff, "%pI4:%u",
+		&trans->local->srx.transport.sin.sin_addr,
 		ntohs(trans->local->srx.transport.sin.sin_port));
 
-	sprintf(rbuff, NIPQUAD_FMT":%u",
-		NIPQUAD(trans->peer->srx.transport.sin.sin_addr),
+	sprintf(rbuff, "%pI4:%u",
+		&trans->peer->srx.transport.sin.sin_addr,
 		ntohs(trans->peer->srx.transport.sin.sin_port));
 
 	seq_printf(seq,
@@ -144,12 +144,12 @@
 	conn = list_entry(v, struct rxrpc_connection, link);
 	trans = conn->trans;
 
-	sprintf(lbuff, NIPQUAD_FMT":%u",
-		NIPQUAD(trans->local->srx.transport.sin.sin_addr),
+	sprintf(lbuff, "%pI4:%u",
+		&trans->local->srx.transport.sin.sin_addr,
 		ntohs(trans->local->srx.transport.sin.sin_port));
 
-	sprintf(rbuff, NIPQUAD_FMT":%u",
-		NIPQUAD(trans->peer->srx.transport.sin.sin_addr),
+	sprintf(rbuff, "%pI4:%u",
+		&trans->peer->srx.transport.sin.sin_addr,
 		ntohs(trans->peer->srx.transport.sin.sin_port));
 
 	seq_printf(seq,
diff --git a/net/rxrpc/ar-transport.c b/net/rxrpc/ar-transport.c
index 64069c8..0936e1a 100644
--- a/net/rxrpc/ar-transport.c
+++ b/net/rxrpc/ar-transport.c
@@ -78,10 +78,10 @@
 	const char *new = "old";
 	int usage;
 
-	_enter("{%u.%u.%u.%u+%hu},{%u.%u.%u.%u+%hu},",
-	       NIPQUAD(local->srx.transport.sin.sin_addr),
+	_enter("{%pI4+%hu},{%pI4+%hu},",
+	       &local->srx.transport.sin.sin_addr,
 	       ntohs(local->srx.transport.sin.sin_port),
-	       NIPQUAD(peer->srx.transport.sin.sin_addr),
+	       &peer->srx.transport.sin.sin_addr,
 	       ntohs(peer->srx.transport.sin.sin_port));
 
 	/* search the transport list first */
@@ -149,10 +149,10 @@
 {
 	struct rxrpc_transport *trans;
 
-	_enter("{%u.%u.%u.%u+%hu},{%u.%u.%u.%u+%hu},",
-	       NIPQUAD(local->srx.transport.sin.sin_addr),
+	_enter("{%pI4+%hu},{%pI4+%hu},",
+	       &local->srx.transport.sin.sin_addr,
 	       ntohs(local->srx.transport.sin.sin_port),
-	       NIPQUAD(peer->srx.transport.sin.sin_addr),
+	       &peer->srx.transport.sin.sin_addr,
 	       ntohs(peer->srx.transport.sin.sin_port));
 
 	/* search the transport list */
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index ba3f6e4..ef8f910 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -897,7 +897,7 @@
 	/* get the IPv4 address of the entity that requested the ticket */
 	memcpy(&addr, p, sizeof(addr));
 	p += 4;
-	_debug("KIV ADDR : "NIPQUAD_FMT, NIPQUAD(addr));
+	_debug("KIV ADDR : %pI4", &addr);
 
 	/* get the session key from the ticket */
 	memcpy(&key, p, sizeof(key));
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 6767e54..36543b6 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -316,6 +316,17 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_flow.
 
+config NET_CLS_CGROUP
+	bool "Control Group Classifier"
+	select NET_CLS
+	depends on CGROUPS
+	---help---
+	  Say Y here if you want to classify packets based on the control
+	  cgroup of their process.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called cls_cgroup.
+
 config NET_EMATCH
 	bool "Extended Matches"
 	select NET_CLS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index e60c992..70b35f8 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -38,6 +38,7 @@
 obj-$(CONFIG_NET_CLS_RSVP6)	+= cls_rsvp6.o
 obj-$(CONFIG_NET_CLS_BASIC)	+= cls_basic.o
 obj-$(CONFIG_NET_CLS_FLOW)	+= cls_flow.o
+obj-$(CONFIG_NET_CLS_CGROUP)	+= cls_cgroup.o
 obj-$(CONFIG_NET_EMATCH)	+= ematch.o
 obj-$(CONFIG_NET_EMATCH_CMP)	+= em_cmp.o
 obj-$(CONFIG_NET_EMATCH_NBYTE)	+= em_nbyte.o
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
new file mode 100644
index 0000000..53ada2c
--- /dev/null
+++ b/net/sched/cls_cgroup.c
@@ -0,0 +1,290 @@
+/*
+ * net/sched/cls_cgroup.c	Control Group Classifier
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/cgroup.h>
+#include <net/rtnetlink.h>
+#include <net/pkt_cls.h>
+
+struct cgroup_cls_state
+{
+	struct cgroup_subsys_state css;
+	u32 classid;
+};
+
+static inline struct cgroup_cls_state *net_cls_state(struct cgroup *cgrp)
+{
+	return (struct cgroup_cls_state *)
+		cgroup_subsys_state(cgrp, net_cls_subsys_id);
+}
+
+static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
+						 struct cgroup *cgrp)
+{
+	struct cgroup_cls_state *cs;
+
+	if (!(cs = kzalloc(sizeof(*cs), GFP_KERNEL)))
+		return ERR_PTR(-ENOMEM);
+
+	if (cgrp->parent)
+		cs->classid = net_cls_state(cgrp->parent)->classid;
+
+	return &cs->css;
+}
+
+static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp)
+{
+	kfree(ss);
+}
+
+static u64 read_classid(struct cgroup *cgrp, struct cftype *cft)
+{
+	return net_cls_state(cgrp)->classid;
+}
+
+static int write_classid(struct cgroup *cgrp, struct cftype *cft, u64 value)
+{
+	if (!cgroup_lock_live_group(cgrp))
+		return -ENODEV;
+
+	net_cls_state(cgrp)->classid = (u32) value;
+
+	cgroup_unlock();
+
+	return 0;
+}
+
+static struct cftype ss_files[] = {
+	{
+		.name = "classid",
+		.read_u64 = read_classid,
+		.write_u64 = write_classid,
+	},
+};
+
+static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
+{
+	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
+}
+
+struct cgroup_subsys net_cls_subsys = {
+	.name		= "net_cls",
+	.create		= cgrp_create,
+	.destroy	= cgrp_destroy,
+	.populate	= cgrp_populate,
+	.subsys_id	= net_cls_subsys_id,
+};
+
+struct cls_cgroup_head
+{
+	u32			handle;
+	struct tcf_exts		exts;
+	struct tcf_ematch_tree	ematches;
+};
+
+static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
+			       struct tcf_result *res)
+{
+	struct cls_cgroup_head *head = tp->root;
+	struct cgroup_cls_state *cs;
+	int ret = 0;
+
+	/*
+	 * Due to the nature of the classifier it is required to ignore all
+	 * packets originating from softirq context as accessing `current'
+	 * would lead to false results.
+	 *
+	 * This test assumes that all callers of dev_queue_xmit() explicitely
+	 * disable bh. Knowing this, it is possible to detect softirq based
+	 * calls by looking at the number of nested bh disable calls because
+	 * softirqs always disables bh.
+	 */
+	if (softirq_count() != SOFTIRQ_OFFSET)
+		return -1;
+
+	rcu_read_lock();
+	cs = (struct cgroup_cls_state *) task_subsys_state(current,
+							   net_cls_subsys_id);
+	if (cs->classid && tcf_em_tree_match(skb, &head->ematches, NULL)) {
+		res->classid = cs->classid;
+		res->class = 0;
+		ret = tcf_exts_exec(skb, &head->exts, res);
+	} else
+		ret = -1;
+
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static unsigned long cls_cgroup_get(struct tcf_proto *tp, u32 handle)
+{
+	return 0UL;
+}
+
+static void cls_cgroup_put(struct tcf_proto *tp, unsigned long f)
+{
+}
+
+static int cls_cgroup_init(struct tcf_proto *tp)
+{
+	return 0;
+}
+
+static const struct tcf_ext_map cgroup_ext_map = {
+	.action = TCA_CGROUP_ACT,
+	.police = TCA_CGROUP_POLICE,
+};
+
+static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = {
+	[TCA_CGROUP_EMATCHES]	= { .type = NLA_NESTED },
+};
+
+static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base,
+			     u32 handle, struct nlattr **tca,
+			     unsigned long *arg)
+{
+	struct nlattr *tb[TCA_CGROUP_MAX+1];
+	struct cls_cgroup_head *head = tp->root;
+	struct tcf_ematch_tree t;
+	struct tcf_exts e;
+	int err;
+
+	if (head == NULL) {
+		if (!handle)
+			return -EINVAL;
+
+		head = kzalloc(sizeof(*head), GFP_KERNEL);
+		if (head == NULL)
+			return -ENOBUFS;
+
+		head->handle = handle;
+
+		tcf_tree_lock(tp);
+		tp->root = head;
+		tcf_tree_unlock(tp);
+	}
+
+	if (handle != head->handle)
+		return -ENOENT;
+
+	err = nla_parse_nested(tb, TCA_CGROUP_MAX, tca[TCA_OPTIONS],
+			       cgroup_policy);
+	if (err < 0)
+		return err;
+
+	err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &cgroup_ext_map);
+	if (err < 0)
+		return err;
+
+	err = tcf_em_tree_validate(tp, tb[TCA_CGROUP_EMATCHES], &t);
+	if (err < 0)
+		return err;
+
+	tcf_exts_change(tp, &head->exts, &e);
+	tcf_em_tree_change(tp, &head->ematches, &t);
+
+	return 0;
+}
+
+static void cls_cgroup_destroy(struct tcf_proto *tp)
+{
+	struct cls_cgroup_head *head;
+
+	head = (struct cls_cgroup_head *)xchg(&tp->root, NULL);
+
+	if (head) {
+		tcf_exts_destroy(tp, &head->exts);
+		tcf_em_tree_destroy(tp, &head->ematches);
+		kfree(head);
+	}
+}
+
+static int cls_cgroup_delete(struct tcf_proto *tp, unsigned long arg)
+{
+	return -EOPNOTSUPP;
+}
+
+static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+	struct cls_cgroup_head *head = tp->root;
+
+	if (arg->count < arg->skip)
+		goto skip;
+
+	if (arg->fn(tp, (unsigned long) head, arg) < 0) {
+		arg->stop = 1;
+		return;
+	}
+skip:
+	arg->count++;
+}
+
+static int cls_cgroup_dump(struct tcf_proto *tp, unsigned long fh,
+			   struct sk_buff *skb, struct tcmsg *t)
+{
+	struct cls_cgroup_head *head = tp->root;
+	unsigned char *b = skb_tail_pointer(skb);
+	struct nlattr *nest;
+
+	t->tcm_handle = head->handle;
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
+
+	if (tcf_exts_dump(skb, &head->exts, &cgroup_ext_map) < 0 ||
+	    tcf_em_tree_dump(skb, &head->ematches, TCA_CGROUP_EMATCHES) < 0)
+		goto nla_put_failure;
+
+	nla_nest_end(skb, nest);
+
+	if (tcf_exts_dump_stats(skb, &head->exts, &cgroup_ext_map) < 0)
+		goto nla_put_failure;
+
+	return skb->len;
+
+nla_put_failure:
+	nlmsg_trim(skb, b);
+	return -1;
+}
+
+static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
+	.kind		=	"cgroup",
+	.init		=	cls_cgroup_init,
+	.change		=	cls_cgroup_change,
+	.classify	=	cls_cgroup_classify,
+	.destroy	=	cls_cgroup_destroy,
+	.get		=	cls_cgroup_get,
+	.put		=	cls_cgroup_put,
+	.delete		=	cls_cgroup_delete,
+	.walk		=	cls_cgroup_walk,
+	.dump		=	cls_cgroup_dump,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init init_cgroup_cls(void)
+{
+	return register_tcf_proto_ops(&cls_cgroup_ops);
+}
+
+static void __exit exit_cgroup_cls(void)
+{
+	unregister_tcf_proto_ops(&cls_cgroup_ops);
+}
+
+module_init(init_cgroup_cls);
+module_exit(exit_cgroup_cls);
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index b16ad29..e564661 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -102,6 +102,10 @@
    requeues once dequeued packet. It is used for non-standard or
    just buggy devices, which can defer output even if netif_queue_stopped()=0.
 
+   ---peek
+
+   like dequeue but without removing a packet from the queue
+
    ---reset
 
    returns qdisc to initial state: purge all buffers, clear all
@@ -149,6 +153,14 @@
 		qops->enqueue = noop_qdisc_ops.enqueue;
 	if (qops->requeue == NULL)
 		qops->requeue = noop_qdisc_ops.requeue;
+	if (qops->peek == NULL) {
+		if (qops->dequeue == NULL) {
+			qops->peek = noop_qdisc_ops.peek;
+		} else {
+			rc = -EINVAL;
+			goto out;
+		}
+	}
 	if (qops->dequeue == NULL)
 		qops->dequeue = noop_qdisc_ops.dequeue;
 
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 43d3725..6eb9a65 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -480,11 +480,14 @@
 		 * If traffic is properly shaped, this won't generate nasty
 		 * little bursts. Otherwise, it may ... (but that's okay)
 		 */
-		while ((skb = flow->q->dequeue(flow->q))) {
-			if (!atm_may_send(flow->vcc, skb->truesize)) {
-				(void)flow->q->ops->requeue(skb, flow->q);
+		while ((skb = flow->q->ops->peek(flow->q))) {
+			if (!atm_may_send(flow->vcc, skb->truesize))
 				break;
-			}
+
+			skb = qdisc_dequeue_peeked(flow->q);
+			if (unlikely(!skb))
+				break;
+
 			pr_debug("atm_tc_dequeue: sending on class %p\n", flow);
 			/* remove any LL header somebody else has attached */
 			skb_pull(skb, skb_network_offset(skb));
@@ -516,12 +519,21 @@
 
 	pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
 	tasklet_schedule(&p->task);
-	skb = p->link.q->dequeue(p->link.q);
+	skb = qdisc_dequeue_peeked(p->link.q);
 	if (skb)
 		sch->q.qlen--;
 	return skb;
 }
 
+static struct sk_buff *atm_tc_peek(struct Qdisc *sch)
+{
+	struct atm_qdisc_data *p = qdisc_priv(sch);
+
+	pr_debug("atm_tc_peek(sch %p,[qdisc %p])\n", sch, p);
+
+	return p->link.q->ops->peek(p->link.q);
+}
+
 static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = qdisc_priv(sch);
@@ -694,6 +706,7 @@
 	.priv_size	= sizeof(struct atm_qdisc_data),
 	.enqueue	= atm_tc_enqueue,
 	.dequeue	= atm_tc_dequeue,
+	.peek		= atm_tc_peek,
 	.requeue	= atm_tc_requeue,
 	.drop		= atm_tc_drop,
 	.init		= atm_tc_init,
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index 507fb48..094a874 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -33,6 +33,7 @@
 	.priv_size	= 0,
 	.enqueue	= blackhole_enqueue,
 	.dequeue	= blackhole_dequeue,
+	.peek		= blackhole_dequeue,
 	.owner		= THIS_MODULE,
 };
 
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 03e389e..63efa70 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -2066,6 +2066,7 @@
 	.priv_size	=	sizeof(struct cbq_sched_data),
 	.enqueue	=	cbq_enqueue,
 	.dequeue	=	cbq_dequeue,
+	.peek		=	qdisc_peek_dequeued,
 	.requeue	=	cbq_requeue,
 	.drop		=	cbq_drop,
 	.init		=	cbq_init,
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index ba43aab..3e49147 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -313,6 +313,15 @@
 	return skb;
 }
 
+static struct sk_buff *dsmark_peek(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = qdisc_priv(sch);
+
+	pr_debug("dsmark_peek(sch %p,[qdisc %p])\n", sch, p);
+
+	return p->q->ops->peek(p->q);
+}
+
 static int dsmark_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = qdisc_priv(sch);
@@ -496,6 +505,7 @@
 	.priv_size	=	sizeof(struct dsmark_qdisc_data),
 	.enqueue	=	dsmark_enqueue,
 	.dequeue	=	dsmark_dequeue,
+	.peek		=	dsmark_peek,
 	.requeue	=	dsmark_requeue,
 	.drop		=	dsmark_drop,
 	.init		=	dsmark_init,
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 23d258b..8825e88 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -83,6 +83,7 @@
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	pfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	qdisc_requeue,
 	.drop		=	qdisc_queue_drop,
 	.init		=	fifo_init,
@@ -98,6 +99,7 @@
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	bfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	qdisc_requeue,
 	.drop		=	qdisc_queue_drop,
 	.init		=	fifo_init,
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 93cd30c..1192da2 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -320,6 +320,7 @@
 	.priv_size	=	0,
 	.enqueue	=	noop_enqueue,
 	.dequeue	=	noop_dequeue,
+	.peek		=	noop_dequeue,
 	.requeue	=	noop_requeue,
 	.owner		=	THIS_MODULE,
 };
@@ -346,6 +347,7 @@
 	.priv_size	=	0,
 	.enqueue	=	noop_enqueue,
 	.dequeue	=	noop_dequeue,
+	.peek		=	noop_dequeue,
 	.requeue	=	noop_requeue,
 	.owner		=	THIS_MODULE,
 };
@@ -411,6 +413,19 @@
 	return NULL;
 }
 
+static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
+{
+	int prio;
+	struct sk_buff_head *list = qdisc_priv(qdisc);
+
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
+		if (!skb_queue_empty(list + prio))
+			return skb_peek(list + prio);
+	}
+
+	return NULL;
+}
+
 static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
 {
 	qdisc->q.qlen++;
@@ -457,6 +472,7 @@
 	.priv_size	=	PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
 	.enqueue	=	pfifo_fast_enqueue,
 	.dequeue	=	pfifo_fast_dequeue,
+	.peek		=	pfifo_fast_peek,
 	.requeue	=	pfifo_fast_requeue,
 	.init		=	pfifo_fast_init,
 	.reset		=	pfifo_fast_reset,
@@ -526,6 +542,9 @@
 
 	if (ops->reset)
 		ops->reset(qdisc);
+
+	kfree_skb(qdisc->gso_skb);
+	qdisc->gso_skb = NULL;
 }
 EXPORT_SYMBOL(qdisc_reset);
 
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index c1ad6b8..cb20ee3 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -602,6 +602,7 @@
 	.priv_size	=	sizeof(struct gred_sched),
 	.enqueue	=	gred_enqueue,
 	.dequeue	=	gred_dequeue,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	gred_requeue,
 	.drop		=	gred_drop,
 	.init		=	gred_init,
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index c1e77da..d90b165 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -880,28 +880,20 @@
 	 */
 }
 
-/*
- * hack to get length of first packet in queue.
- */
 static unsigned int
 qdisc_peek_len(struct Qdisc *sch)
 {
 	struct sk_buff *skb;
 	unsigned int len;
 
-	skb = sch->dequeue(sch);
+	skb = sch->ops->peek(sch);
 	if (skb == NULL) {
 		if (net_ratelimit())
 			printk("qdisc_peek_len: non work-conserving qdisc ?\n");
 		return 0;
 	}
 	len = qdisc_pkt_len(skb);
-	if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
-		if (net_ratelimit())
-			printk("qdisc_peek_len: failed to requeue\n");
-		qdisc_tree_decrease_qlen(sch, 1);
-		return 0;
-	}
+
 	return len;
 }
 
@@ -1642,7 +1634,7 @@
 		}
 	}
 
-	skb = cl->qdisc->dequeue(cl->qdisc);
+	skb = qdisc_dequeue_peeked(cl->qdisc);
 	if (skb == NULL) {
 		if (net_ratelimit())
 			printk("HFSC: Non-work-conserving qdisc ?\n");
@@ -1735,6 +1727,7 @@
 	.dump		= hfsc_dump_qdisc,
 	.enqueue	= hfsc_enqueue,
 	.dequeue	= hfsc_dequeue,
+	.peek		= qdisc_peek_dequeued,
 	.requeue	= hfsc_requeue,
 	.drop		= hfsc_drop,
 	.cl_ops		= &hfsc_class_ops,
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index d14f020..3fda819 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1565,6 +1565,7 @@
 	.priv_size	=	sizeof(struct htb_sched),
 	.enqueue	=	htb_enqueue,
 	.dequeue	=	htb_dequeue,
+	.peek		=	qdisc_peek_dequeued,
 	.requeue	=	htb_requeue,
 	.drop		=	htb_drop,
 	.init		=	htb_init,
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 915f314..155648d 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -155,6 +155,34 @@
 
 }
 
+static struct sk_buff *multiq_peek(struct Qdisc *sch)
+{
+	struct multiq_sched_data *q = qdisc_priv(sch);
+	unsigned int curband = q->curband;
+	struct Qdisc *qdisc;
+	struct sk_buff *skb;
+	int band;
+
+	for (band = 0; band < q->bands; band++) {
+		/* cycle through bands to ensure fairness */
+		curband++;
+		if (curband >= q->bands)
+			curband = 0;
+
+		/* Check that target subqueue is available before
+		 * pulling an skb to avoid excessive requeues
+		 */
+		if (!__netif_subqueue_stopped(qdisc_dev(sch), curband)) {
+			qdisc = q->queues[curband];
+			skb = qdisc->ops->peek(qdisc);
+			if (skb)
+				return skb;
+		}
+	}
+	return NULL;
+
+}
+
 static unsigned int multiq_drop(struct Qdisc *sch)
 {
 	struct multiq_sched_data *q = qdisc_priv(sch);
@@ -451,6 +479,7 @@
 	.priv_size	=	sizeof(struct multiq_sched_data),
 	.enqueue	=	multiq_enqueue,
 	.dequeue	=	multiq_dequeue,
+	.peek		=	multiq_peek,
 	.requeue	=	multiq_requeue,
 	.drop		=	multiq_drop,
 	.init		=	multiq_init,
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index a119599..f69698f 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -233,7 +233,11 @@
 		 */
 		cb->time_to_send = psched_get_time();
 		q->counter = 0;
-		ret = q->qdisc->ops->requeue(skb, q->qdisc);
+
+		__skb_queue_head(&q->qdisc->q, skb);
+		q->qdisc->qstats.backlog += qdisc_pkt_len(skb);
+		q->qdisc->qstats.requeues++;
+		ret = NET_XMIT_SUCCESS;
 	}
 
 	if (likely(ret == NET_XMIT_SUCCESS)) {
@@ -283,25 +287,22 @@
 	if (sch->flags & TCQ_F_THROTTLED)
 		return NULL;
 
-	skb = q->qdisc->dequeue(q->qdisc);
+	skb = q->qdisc->ops->peek(q->qdisc);
 	if (skb) {
 		const struct netem_skb_cb *cb = netem_skb_cb(skb);
 		psched_time_t now = psched_get_time();
 
 		/* if more time remaining? */
 		if (cb->time_to_send <= now) {
+			skb = qdisc_dequeue_peeked(q->qdisc);
+			if (unlikely(!skb))
+				return NULL;
+
 			pr_debug("netem_dequeue: return skb=%p\n", skb);
 			sch->q.qlen--;
 			return skb;
 		}
 
-		if (unlikely(q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS)) {
-			qdisc_tree_decrease_qlen(q->qdisc, 1);
-			sch->qstats.drops++;
-			printk(KERN_ERR "netem: %s could not requeue\n",
-			       q->qdisc->ops->id);
-		}
-
 		qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send);
 	}
 
@@ -351,7 +352,7 @@
 	return 0;
 }
 
-static int get_correlation(struct Qdisc *sch, const struct nlattr *attr)
+static void get_correlation(struct Qdisc *sch, const struct nlattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_corr *c = nla_data(attr);
@@ -359,27 +360,24 @@
 	init_crandom(&q->delay_cor, c->delay_corr);
 	init_crandom(&q->loss_cor, c->loss_corr);
 	init_crandom(&q->dup_cor, c->dup_corr);
-	return 0;
 }
 
-static int get_reorder(struct Qdisc *sch, const struct nlattr *attr)
+static void get_reorder(struct Qdisc *sch, const struct nlattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_reorder *r = nla_data(attr);
 
 	q->reorder = r->probability;
 	init_crandom(&q->reorder_cor, r->correlation);
-	return 0;
 }
 
-static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
+static void get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_corrupt *r = nla_data(attr);
 
 	q->corrupt = r->probability;
 	init_crandom(&q->corrupt_cor, r->correlation);
-	return 0;
 }
 
 static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
@@ -438,11 +436,8 @@
 	if (q->gap)
 		q->reorder = ~0;
 
-	if (tb[TCA_NETEM_CORR]) {
-		ret = get_correlation(sch, tb[TCA_NETEM_CORR]);
-		if (ret)
-			return ret;
-	}
+	if (tb[TCA_NETEM_CORR])
+		get_correlation(sch, tb[TCA_NETEM_CORR]);
 
 	if (tb[TCA_NETEM_DELAY_DIST]) {
 		ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
@@ -450,17 +445,11 @@
 			return ret;
 	}
 
-	if (tb[TCA_NETEM_REORDER]) {
-		ret = get_reorder(sch, tb[TCA_NETEM_REORDER]);
-		if (ret)
-			return ret;
-	}
+	if (tb[TCA_NETEM_REORDER])
+		get_reorder(sch, tb[TCA_NETEM_REORDER]);
 
-	if (tb[TCA_NETEM_CORRUPT]) {
-		ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
-		if (ret)
-			return ret;
-	}
+	if (tb[TCA_NETEM_CORRUPT])
+		get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
 
 	return 0;
 }
@@ -541,6 +530,7 @@
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	tfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	qdisc_requeue,
 	.drop		=	qdisc_queue_drop,
 	.init		=	tfifo_init,
@@ -624,98 +614,12 @@
 	return -1;
 }
 
-static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
-			  struct sk_buff *skb, struct tcmsg *tcm)
-{
-	struct netem_sched_data *q = qdisc_priv(sch);
-
-	if (cl != 1) 	/* only one class */
-		return -ENOENT;
-
-	tcm->tcm_handle |= TC_H_MIN(1);
-	tcm->tcm_info = q->qdisc->handle;
-
-	return 0;
-}
-
-static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
-		     struct Qdisc **old)
-{
-	struct netem_sched_data *q = qdisc_priv(sch);
-
-	if (new == NULL)
-		new = &noop_qdisc;
-
-	sch_tree_lock(sch);
-	*old = xchg(&q->qdisc, new);
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
-
-	return 0;
-}
-
-static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
-{
-	struct netem_sched_data *q = qdisc_priv(sch);
-	return q->qdisc;
-}
-
-static unsigned long netem_get(struct Qdisc *sch, u32 classid)
-{
-	return 1;
-}
-
-static void netem_put(struct Qdisc *sch, unsigned long arg)
-{
-}
-
-static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
-			    struct nlattr **tca, unsigned long *arg)
-{
-	return -ENOSYS;
-}
-
-static int netem_delete(struct Qdisc *sch, unsigned long arg)
-{
-	return -ENOSYS;
-}
-
-static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
-{
-	if (!walker->stop) {
-		if (walker->count >= walker->skip)
-			if (walker->fn(sch, 1, walker) < 0) {
-				walker->stop = 1;
-				return;
-			}
-		walker->count++;
-	}
-}
-
-static struct tcf_proto **netem_find_tcf(struct Qdisc *sch, unsigned long cl)
-{
-	return NULL;
-}
-
-static const struct Qdisc_class_ops netem_class_ops = {
-	.graft		=	netem_graft,
-	.leaf		=	netem_leaf,
-	.get		=	netem_get,
-	.put		=	netem_put,
-	.change		=	netem_change_class,
-	.delete		=	netem_delete,
-	.walk		=	netem_walk,
-	.tcf_chain	=	netem_find_tcf,
-	.dump		=	netem_dump_class,
-};
-
 static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
 	.id		=	"netem",
-	.cl_ops		=	&netem_class_ops,
 	.priv_size	=	sizeof(struct netem_sched_data),
 	.enqueue	=	netem_enqueue,
 	.dequeue	=	netem_dequeue,
+	.peek		=	qdisc_peek_dequeued,
 	.requeue	=	netem_requeue,
 	.drop		=	netem_drop,
 	.init		=	netem_init,
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 504a78c..3651da3 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -120,6 +120,19 @@
 	return ret;
 }
 
+static struct sk_buff *prio_peek(struct Qdisc *sch)
+{
+	struct prio_sched_data *q = qdisc_priv(sch);
+	int prio;
+
+	for (prio = 0; prio < q->bands; prio++) {
+		struct Qdisc *qdisc = q->queues[prio];
+		struct sk_buff *skb = qdisc->ops->peek(qdisc);
+		if (skb)
+			return skb;
+	}
+	return NULL;
+}
 
 static struct sk_buff *prio_dequeue(struct Qdisc* sch)
 {
@@ -421,6 +434,7 @@
 	.priv_size	=	sizeof(struct prio_sched_data),
 	.enqueue	=	prio_enqueue,
 	.dequeue	=	prio_dequeue,
+	.peek		=	prio_peek,
 	.requeue	=	prio_requeue,
 	.drop		=	prio_drop,
 	.init		=	prio_init,
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 5da0583..7abc514 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -140,6 +140,14 @@
 	return skb;
 }
 
+static struct sk_buff * red_peek(struct Qdisc* sch)
+{
+	struct red_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child = q->qdisc;
+
+	return child->ops->peek(child);
+}
+
 static unsigned int red_drop(struct Qdisc* sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
@@ -361,6 +369,7 @@
 	.cl_ops		=	&red_class_ops,
 	.enqueue	=	red_enqueue,
 	.dequeue	=	red_dequeue,
+	.peek		=	red_peek,
 	.requeue	=	red_requeue,
 	.drop		=	red_drop,
 	.init		=	red_init,
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index fe1508e..198b83d 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -391,8 +391,19 @@
 	return NET_XMIT_CN;
 }
 
+static struct sk_buff *
+sfq_peek(struct Qdisc *sch)
+{
+	struct sfq_sched_data *q = qdisc_priv(sch);
+	sfq_index a;
 
+	/* No active slots */
+	if (q->tail == SFQ_DEPTH)
+		return NULL;
 
+	a = q->next[q->tail];
+	return skb_peek(&q->qs[a]);
+}
 
 static struct sk_buff *
 sfq_dequeue(struct Qdisc *sch)
@@ -624,6 +635,7 @@
 	.priv_size	=	sizeof(struct sfq_sched_data),
 	.enqueue	=	sfq_enqueue,
 	.dequeue	=	sfq_dequeue,
+	.peek		=	sfq_peek,
 	.requeue	=	sfq_requeue,
 	.drop		=	sfq_drop,
 	.init		=	sfq_init,
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 94c6159..435076c 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -169,7 +169,7 @@
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
 
-	skb = q->qdisc->dequeue(q->qdisc);
+	skb = q->qdisc->ops->peek(q->qdisc);
 
 	if (skb) {
 		psched_time_t now;
@@ -192,6 +192,10 @@
 		toks -= L2T(q, len);
 
 		if ((toks|ptoks) >= 0) {
+			skb = qdisc_dequeue_peeked(q->qdisc);
+			if (unlikely(!skb))
+				return NULL;
+
 			q->t_c = now;
 			q->tokens = toks;
 			q->ptokens = ptoks;
@@ -214,12 +218,6 @@
 		   (cf. CSZ, HPFQ, HFSC)
 		 */
 
-		if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
-			/* When requeue fails skb is dropped */
-			qdisc_tree_decrease_qlen(q->qdisc, 1);
-			sch->qstats.drops++;
-		}
-
 		sch->qstats.overlimits++;
 	}
 	return NULL;
@@ -469,6 +467,7 @@
 	.priv_size	=	sizeof(struct tbf_sched_data),
 	.enqueue	=	tbf_enqueue,
 	.dequeue	=	tbf_dequeue,
+	.peek		=	qdisc_peek_dequeued,
 	.requeue	=	tbf_requeue,
 	.drop		=	tbf_drop,
 	.init		=	tbf_init,
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d35ef05..bf03e7f 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -123,6 +123,13 @@
 	return skb;
 }
 
+static struct sk_buff *
+teql_peek(struct Qdisc* sch)
+{
+	/* teql is meant to be used as root qdisc */
+	return NULL;
+}
+
 static __inline__ void
 teql_neigh_release(struct neighbour *n)
 {
@@ -433,6 +440,7 @@
 
 	ops->enqueue	=	teql_enqueue;
 	ops->dequeue	=	teql_dequeue;
+	ops->peek	=	teql_peek;
 	ops->requeue	=	teql_requeue;
 	ops->init	=	teql_qdisc_init;
 	ops->reset	=	teql_reset;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 4124bbb..ceaa4aa 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -223,10 +223,9 @@
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
 	}
 
-	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
-			  "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
+	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n",
 			  __func__, skb, skb->len,
-			  NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
+			  &fl.fl6_src, &fl.fl6_dst);
 
 	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
 
@@ -252,23 +251,19 @@
 		fl.oif = daddr->v6.sin6_scope_id;
 
 
-	SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
-			  __func__, NIP6(fl.fl6_dst));
+	SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl.fl6_dst);
 
 	if (saddr) {
 		ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
-		SCTP_DEBUG_PRINTK(
-			"SRC=" NIP6_FMT " - ",
-			NIP6(fl.fl6_src));
+		SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl.fl6_src);
 	}
 
 	dst = ip6_route_output(&init_net, NULL, &fl);
 	if (!dst->error) {
 		struct rt6_info *rt;
 		rt = (struct rt6_info *)dst;
-		SCTP_DEBUG_PRINTK(
-			"rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
-			NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
+		SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n",
+			&rt->rt6i_dst.addr, &rt->rt6i_src.addr);
 		return dst;
 	}
 	SCTP_DEBUG_PRINTK("NO ROUTE\n");
@@ -314,9 +309,8 @@
 	__u8 matchlen = 0;
 	__u8 bmatchlen;
 
-	SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
-			  "daddr:" NIP6_FMT " ",
-			  __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
+	SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ",
+			  __func__, asoc, dst, &daddr->v6.sin6_addr);
 
 	if (!asoc) {
 		ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)),
@@ -324,8 +318,8 @@
 				   &daddr->v6.sin6_addr,
 				   inet6_sk(&sk->inet.sk)->srcprefs,
 				   &saddr->v6.sin6_addr);
-		SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
-				  NIP6(saddr->v6.sin6_addr));
+		SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n",
+				  &saddr->v6.sin6_addr);
 		return;
 	}
 
@@ -353,12 +347,11 @@
 
 	if (baddr) {
 		memcpy(saddr, baddr, sizeof(union sctp_addr));
-		SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n",
-				  NIP6(saddr->v6.sin6_addr));
+		SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr);
 	} else {
 		printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
-		       "address for the dest:" NIP6_FMT "\n",
-		       __func__, asoc, NIP6(daddr->v6.sin6_addr));
+		       "address for the dest:%pI6\n",
+		       __func__, asoc, &daddr->v6.sin6_addr);
 	}
 
 	rcu_read_unlock();
@@ -727,7 +720,7 @@
 /* Dump the v6 addr to the seq file. */
 static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
 {
-	seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr));
+	seq_printf(seq, "%pI6 ", &addr->v6.sin6_addr);
 }
 
 static void sctp_v6_ecn_capable(struct sock *sk)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0b65354..a8ca743 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -482,9 +482,8 @@
 	if (saddr)
 		fl.fl4_src = saddr->v4.sin_addr.s_addr;
 
-	SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
-			  __func__, NIPQUAD(fl.fl4_dst),
-			  NIPQUAD(fl.fl4_src));
+	SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ",
+			  __func__, &fl.fl4_dst, &fl.fl4_src);
 
 	if (!ip_route_output_key(&init_net, &rt, &fl)) {
 		dst = &rt->u.dst;
@@ -540,8 +539,8 @@
 	rcu_read_unlock();
 out:
 	if (dst)
-		SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n",
-				  NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_src));
+		SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n",
+				  &rt->rt_dst, &rt->rt_src);
 	else
 		SCTP_DEBUG_PRINTK("NO ROUTE\n");
 
@@ -646,7 +645,7 @@
 /* Dump the v4 addr to the seq file. */
 static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
 {
-	seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr));
+	seq_printf(seq, "%pI4 ", &addr->v4.sin_addr);
 }
 
 static void sctp_v4_ecn_capable(struct sock *sk)
@@ -866,11 +865,10 @@
 {
 	struct inet_sock *inet = inet_sk(skb->sk);
 
-	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
-			  "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
+	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n",
 			  __func__, skb, skb->len,
-			  NIPQUAD(skb->rtable->rt_src),
-			  NIPQUAD(skb->rtable->rt_dst));
+			  &skb->rtable->rt_src,
+			  &skb->rtable->rt_dst);
 
 	inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
 			 IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a6a0ea7..9f2a3eb 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1123,19 +1123,17 @@
 		if (from_addr.sa.sa_family == AF_INET6) {
 			if (net_ratelimit())
 				printk(KERN_WARNING
-				    "%s association %p could not find address "
-				    NIP6_FMT "\n",
+				    "%s association %p could not find address %pI6\n",
 				    __func__,
 				    asoc,
-				    NIP6(from_addr.v6.sin6_addr));
+				    &from_addr.v6.sin6_addr);
 		} else {
 			if (net_ratelimit())
 				printk(KERN_WARNING
-				    "%s association %p could not find address "
-				    NIPQUAD_FMT "\n",
+				    "%s association %p could not find address %pI4\n",
 				    __func__,
 				    asoc,
-				    NIPQUAD(from_addr.v4.sin_addr.s_addr));
+				    &from_addr.v4.sin_addr.s_addr);
 		}
 		return SCTP_DISPOSITION_DISCARD;
 	}
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 5291069..f58e994 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -63,8 +63,8 @@
 		.data		= &sctp_rto_initial,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &one,
 		.extra2         = &timer_max
 	},
@@ -74,8 +74,8 @@
 		.data		= &sctp_rto_min,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &one,
 		.extra2         = &timer_max
 	},
@@ -85,8 +85,8 @@
 		.data		= &sctp_rto_max,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &one,
 		.extra2         = &timer_max
 	},
@@ -96,8 +96,8 @@
 		.data		= &sctp_valid_cookie_life,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &one,
 		.extra2         = &timer_max
 	},
@@ -107,8 +107,8 @@
 		.data		= &sctp_max_burst,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &zero,
 		.extra2		= &int_max
 	},
@@ -118,8 +118,8 @@
 		.data		= &sctp_max_retrans_association,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &one,
 		.extra2		= &int_max
 	},
@@ -129,8 +129,8 @@
 		.data		= &sctp_sndbuf_policy,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_RCVBUF_POLICY,
@@ -138,8 +138,8 @@
 		.data		= &sctp_rcvbuf_policy,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_PATH_MAX_RETRANS,
@@ -147,8 +147,8 @@
 		.data		= &sctp_max_retrans_path,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &one,
 		.extra2		= &int_max
 	},
@@ -158,8 +158,8 @@
 		.data		= &sctp_max_retrans_init,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1		= &one,
 		.extra2		= &int_max
 	},
@@ -169,8 +169,8 @@
 		.data		= &sctp_hb_interval,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &one,
 		.extra2         = &timer_max
 	},
@@ -180,8 +180,8 @@
 		.data		= &sctp_cookie_preserve_enable,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_ALPHA,
@@ -189,8 +189,8 @@
 		.data		= &sctp_rto_alpha,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_RTO_BETA,
@@ -198,8 +198,8 @@
 		.data		= &sctp_rto_beta,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_ADDIP_ENABLE,
@@ -207,8 +207,8 @@
 		.data		= &sctp_addip_enable,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_PRSCTP_ENABLE,
@@ -216,8 +216,8 @@
 		.data		= &sctp_prsctp_enable,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= NET_SCTP_SACK_TIMEOUT,
@@ -225,8 +225,8 @@
 		.data		= &sctp_sack_timeout,
 		.maxlen		= sizeof(long),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
+		.proc_handler	= proc_dointvec_minmax,
+		.strategy	= sysctl_intvec,
 		.extra1         = &sack_timer_min,
 		.extra2         = &sack_timer_max,
 	},
@@ -236,7 +236,7 @@
 		.data		= &sysctl_sctp_mem,
 		.maxlen		= sizeof(sysctl_sctp_mem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -244,7 +244,7 @@
 		.data		= &sysctl_sctp_rmem,
 		.maxlen		= sizeof(sysctl_sctp_rmem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -252,7 +252,7 @@
 		.data		= &sysctl_sctp_wmem,
 		.maxlen		= sizeof(sysctl_sctp_wmem),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -260,8 +260,8 @@
 		.data		= &sctp_auth_enable,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -269,8 +269,8 @@
 		.data		= &sctp_addip_noauth,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
+		.proc_handler	= proc_dointvec,
+		.strategy	= sysctl_intvec
 	},
 	{ .ctl_name = 0 }
 };
diff --git a/net/socket.c b/net/socket.c
index 57550c3..d7128b7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -69,7 +69,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
-#include <linux/thread_info.h>
 #include <linux/wanrouter.h>
 #include <linux/if_bridge.h>
 #include <linux/if_frad.h>
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4895c34..3ca5183 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -271,15 +271,15 @@
 		case AF_INET: {
 			struct sockaddr_in *sin =
 					(struct sockaddr_in *)args->address;
-			snprintf(servername, sizeof(servername), NIPQUAD_FMT,
-				 NIPQUAD(sin->sin_addr.s_addr));
+			snprintf(servername, sizeof(servername), "%pI4",
+				 &sin->sin_addr.s_addr);
 			break;
 		}
 		case AF_INET6: {
 			struct sockaddr_in6 *sin =
 					(struct sockaddr_in6 *)args->address;
-			snprintf(servername, sizeof(servername), NIP6_FMT,
-				 NIP6(sin->sin6_addr));
+			snprintf(servername, sizeof(servername), "%pI6",
+				 &sin->sin6_addr);
 			break;
 		}
 		default:
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 41013dd..03ae007 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -270,10 +270,9 @@
 	char buf[32];
 
 	/* Construct AF_INET universal address */
-	snprintf(buf, sizeof(buf),
-			NIPQUAD_FMT".%u.%u",
-			NIPQUAD(address_to_register->sin_addr.s_addr),
-			port >> 8, port & 0xff);
+	snprintf(buf, sizeof(buf), "%pI4.%u.%u",
+		 &address_to_register->sin_addr.s_addr,
+		 port >> 8, port & 0xff);
 	map->r_addr = buf;
 
 	dprintk("RPC:       %sregistering [%u, %u, %s, '%s'] with "
@@ -305,9 +304,9 @@
 		snprintf(buf, sizeof(buf), "::.%u.%u",
 				port >> 8, port & 0xff);
 	else
-		snprintf(buf, sizeof(buf), NIP6_FMT".%u.%u",
-				NIP6(address_to_register->sin6_addr),
-				port >> 8, port & 0xff);
+		snprintf(buf, sizeof(buf), "%pI6.%u.%u",
+			 &address_to_register->sin6_addr,
+			 port >> 8, port & 0xff);
 	map->r_addr = buf;
 
 	dprintk("RPC:       %sregistering [%u, %u, %s, '%s'] with "
@@ -422,8 +421,8 @@
 	struct rpc_clnt	*rpcb_clnt;
 	int status;
 
-	dprintk("RPC:       %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
-		__func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+	dprintk("RPC:       %s(%pI4, %u, %u, %d)\n",
+		__func__, &sin->sin_addr.s_addr, prog, vers, prot);
 
 	rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
 				sizeof(*sin), prot, RPCBVERS_2);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index f24800f..82240e6 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -162,13 +162,9 @@
 	struct ip_map *im = container_of(h, struct ip_map, h);
 
 	if (ipv6_addr_v4mapped(&(im->m_addr))) {
-		snprintf(text_addr, 20, NIPQUAD_FMT,
-				ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
-				ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
-				ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
-				ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
+		snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
 	} else {
-		snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+		snprintf(text_addr, 40, "%pI6", &im->m_addr);
 	}
 	qword_add(bpp, blen, im->m_class);
 	qword_add(bpp, blen, text_addr);
@@ -208,13 +204,13 @@
 	len = qword_get(&mesg, buf, mlen);
 	if (len <= 0) return -EINVAL;
 
-	if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) {
 		addr.s6_addr32[0] = 0;
 		addr.s6_addr32[1] = 0;
 		addr.s6_addr32[2] = htonl(0xffff);
 		addr.s6_addr32[3] =
 			htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-       } else if (sscanf(buf, NIP6_FMT "%c",
+       } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c",
 			&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
 		addr.s6_addr16[0] = htons(b1);
 		addr.s6_addr16[1] = htons(b2);
@@ -278,16 +274,10 @@
 		dom = im->m_client->h.name;
 
 	if (ipv6_addr_v4mapped(&addr)) {
-		seq_printf(m, "%s " NIPQUAD_FMT " %s\n",
-			im->m_class,
-			ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
-			ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
-			ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
-			ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
-			dom);
+		seq_printf(m, "%s %pI4 %s\n",
+			im->m_class, &addr.s6_addr32[3], dom);
 	} else {
-		seq_printf(m, "%s " NIP6_FMT " %s\n",
-			im->m_class, NIP6(addr), dom);
+		seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
 	}
 	return 0;
 }
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 95293f5..6f7d1f2 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -250,10 +250,10 @@
 
 	switch(svsk->sk_sk->sk_family) {
 	case AF_INET:
-		len = sprintf(buf, "ipv4 %s %u.%u.%u.%u %d\n",
-			      svsk->sk_sk->sk_protocol==IPPROTO_UDP?
+		len = sprintf(buf, "ipv4 %s %pI4 %d\n",
+			      svsk->sk_sk->sk_protocol == IPPROTO_UDP ?
 			      "udp" : "tcp",
-			      NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
+			      &inet_sk(svsk->sk_sk)->rcv_saddr,
 			      inet_sk(svsk->sk_sk)->num);
 		break;
 	default:
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 6fb493c..f8500f0 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -1048,21 +1048,21 @@
 
 	dprintk("svcrdma: new connection %p accepted with the following "
 		"attributes:\n"
-		"    local_ip        : %d.%d.%d.%d\n"
+		"    local_ip        : %pI4\n"
 		"    local_port	     : %d\n"
-		"    remote_ip       : %d.%d.%d.%d\n"
+		"    remote_ip       : %pI4\n"
 		"    remote_port     : %d\n"
 		"    max_sge         : %d\n"
 		"    sq_depth        : %d\n"
 		"    max_requests    : %d\n"
 		"    ord             : %d\n",
 		newxprt,
-		NIPQUAD(((struct sockaddr_in *)&newxprt->sc_cm_id->
-			 route.addr.src_addr)->sin_addr.s_addr),
+		&((struct sockaddr_in *)&newxprt->sc_cm_id->
+			 route.addr.src_addr)->sin_addr.s_addr,
 		ntohs(((struct sockaddr_in *)&newxprt->sc_cm_id->
 		       route.addr.src_addr)->sin_port),
-		NIPQUAD(((struct sockaddr_in *)&newxprt->sc_cm_id->
-			 route.addr.dst_addr)->sin_addr.s_addr),
+		&((struct sockaddr_in *)&newxprt->sc_cm_id->
+			 route.addr.dst_addr)->sin_addr.s_addr,
 		ntohs(((struct sockaddr_in *)&newxprt->sc_cm_id->
 		       route.addr.dst_addr)->sin_port),
 		newxprt->sc_max_sge,
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 9839c3d..1dd6123 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -174,7 +174,7 @@
 
 	buf = kzalloc(20, GFP_KERNEL);
 	if (buf)
-		snprintf(buf, 20, NIPQUAD_FMT, NIPQUAD(addr->sin_addr.s_addr));
+		snprintf(buf, 20, "%pI4", &addr->sin_addr.s_addr);
 	xprt->address_strings[RPC_DISPLAY_ADDR] = buf;
 
 	buf = kzalloc(8, GFP_KERNEL);
@@ -186,8 +186,8 @@
 
 	buf = kzalloc(48, GFP_KERNEL);
 	if (buf)
-		snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s",
-			NIPQUAD(addr->sin_addr.s_addr),
+		snprintf(buf, 48, "addr=%pI4 port=%u proto=%s",
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port), "rdma");
 	xprt->address_strings[RPC_DISPLAY_ALL] = buf;
 
@@ -204,8 +204,8 @@
 
 	buf = kzalloc(30, GFP_KERNEL);
 	if (buf)
-		snprintf(buf, 30, NIPQUAD_FMT".%u.%u",
-			NIPQUAD(addr->sin_addr.s_addr),
+		snprintf(buf, 30, "%pI4.%u.%u",
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port) >> 8,
 			ntohs(addr->sin_port) & 0xff);
 	xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf;
@@ -369,8 +369,8 @@
 	if (ntohs(sin->sin_port) != 0)
 		xprt_set_bound(xprt);
 
-	dprintk("RPC:       %s: %u.%u.%u.%u:%u\n", __func__,
-			NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
+	dprintk("RPC:       %s: %pI4:%u\n",
+		__func__, &sin->sin_addr.s_addr, ntohs(sin->sin_port));
 
 	/* Set max requests */
 	cdata.max_requests = xprt->max_reqs;
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index a5fef5e..78f7f72 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -323,12 +323,11 @@
 	case RDMA_CM_EVENT_DEVICE_REMOVAL:
 		connstate = -ENODEV;
 connected:
-		dprintk("RPC:       %s: %s: %u.%u.%u.%u:%u"
-			" (ep 0x%p event 0x%x)\n",
+		dprintk("RPC:       %s: %s: %pI4:%u (ep 0x%p event 0x%x)\n",
 			__func__,
 			(event->event <= 11) ? conn[event->event] :
 						"unknown connection error",
-			NIPQUAD(addr->sin_addr.s_addr),
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port),
 			ep, event->event);
 		atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1);
@@ -348,18 +347,17 @@
 	if (connstate == 1) {
 		int ird = attr.max_dest_rd_atomic;
 		int tird = ep->rep_remote_cma.responder_resources;
-		printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u "
+		printk(KERN_INFO "rpcrdma: connection to %pI4:%u "
 			"on %s, memreg %d slots %d ird %d%s\n",
-			NIPQUAD(addr->sin_addr.s_addr),
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port),
 			ia->ri_id->device->name,
 			ia->ri_memreg_strategy,
 			xprt->rx_buf.rb_max_requests,
 			ird, ird < 4 && ird < tird / 2 ? " (low!)" : "");
 	} else if (connstate < 0) {
-		printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u "
-			"closed (%d)\n",
-			NIPQUAD(addr->sin_addr.s_addr),
+		printk(KERN_INFO "rpcrdma: connection to %pI4:%u closed (%d)\n",
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port),
 			connstate);
 	}
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 0a50361..5cbb404 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -284,8 +284,7 @@
 
 	buf = kzalloc(20, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 20, NIPQUAD_FMT,
-				NIPQUAD(addr->sin_addr.s_addr));
+		snprintf(buf, 20, "%pI4", &addr->sin_addr.s_addr);
 	}
 	xprt->address_strings[RPC_DISPLAY_ADDR] = buf;
 
@@ -300,8 +299,8 @@
 
 	buf = kzalloc(48, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s",
-			NIPQUAD(addr->sin_addr.s_addr),
+		snprintf(buf, 48, "addr=%pI4 port=%u proto=%s",
+			&addr->sin_addr.s_addr,
 			ntohs(addr->sin_port),
 			protocol);
 	}
@@ -323,8 +322,8 @@
 
 	buf = kzalloc(30, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 30, NIPQUAD_FMT".%u.%u",
-				NIPQUAD(addr->sin_addr.s_addr),
+		snprintf(buf, 30, "%pI4.%u.%u",
+				&addr->sin_addr.s_addr,
 				ntohs(addr->sin_port) >> 8,
 				ntohs(addr->sin_port) & 0xff);
 	}
@@ -342,8 +341,7 @@
 
 	buf = kzalloc(40, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 40, NIP6_FMT,
-				NIP6(addr->sin6_addr));
+		snprintf(buf, 40, "%pI6",&addr->sin6_addr);
 	}
 	xprt->address_strings[RPC_DISPLAY_ADDR] = buf;
 
@@ -358,18 +356,17 @@
 
 	buf = kzalloc(64, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s",
-				NIP6(addr->sin6_addr),
+		snprintf(buf, 64, "addr=%pI6 port=%u proto=%s",
+				&addr->sin6_addr,
 				ntohs(addr->sin6_port),
 				protocol);
 	}
 	xprt->address_strings[RPC_DISPLAY_ALL] = buf;
 
 	buf = kzalloc(36, GFP_KERNEL);
-	if (buf) {
-		snprintf(buf, 36, NIP6_SEQFMT,
-				NIP6(addr->sin6_addr));
-	}
+	if (buf)
+		snprintf(buf, 36, "%pi6", &addr->sin6_addr);
+
 	xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf;
 
 	buf = kzalloc(8, GFP_KERNEL);
@@ -381,10 +378,10 @@
 
 	buf = kzalloc(50, GFP_KERNEL);
 	if (buf) {
-		snprintf(buf, 50, NIP6_FMT".%u.%u",
-				NIP6(addr->sin6_addr),
-				ntohs(addr->sin6_port) >> 8,
-				ntohs(addr->sin6_port) & 0xff);
+		snprintf(buf, 50, "%pI6.%u.%u",
+			 &addr->sin6_addr,
+			 ntohs(addr->sin6_port) >> 8,
+			 ntohs(addr->sin6_port) & 0xff);
 	}
 	xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf;
 
@@ -1415,8 +1412,8 @@
 		if (port > last)
 			nloop++;
 	} while (err == -EADDRINUSE && nloop != 2);
-	dprintk("RPC:       %s "NIPQUAD_FMT":%u: %s (%d)\n",
-			__func__, NIPQUAD(myaddr.sin_addr),
+	dprintk("RPC:       %s %pI4:%u: %s (%d)\n",
+			__func__, &myaddr.sin_addr,
 			port, err ? "failed" : "ok", err);
 	return err;
 }
@@ -1448,8 +1445,8 @@
 		if (port > last)
 			nloop++;
 	} while (err == -EADDRINUSE && nloop != 2);
-	dprintk("RPC:       xs_bind6 "NIP6_FMT":%u: %s (%d)\n",
-		NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err);
+	dprintk("RPC:       xs_bind6 %pI6:%u: %s (%d)\n",
+		&myaddr.sin6_addr, port, err ? "failed" : "ok", err);
 	return err;
 }
 
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index fe43ef7..f72ba77 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -243,12 +243,11 @@
 static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
 {
 	unchar *addr = (unchar *)&a->dev_addr;
-	DECLARE_MAC_BUF(mac);
 
 	if (str_size < 18)
 		*str_buf = '\0';
 	else
-		sprintf(str_buf, "%s", print_mac(mac, addr));
+		sprintf(str_buf, "%pM", addr);
 	return str_buf;
 }
 
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index cd72e22..acab41a 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -555,7 +555,7 @@
 	struct name_seq *ns;
 
 	dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n",
-	    type, ntohl(type), type, table.types, hash(type));
+	    type, htonl(type), type, table.types, hash(type));
 
 	seq_head = &table.types[hash(type)];
 	hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index eb90f77..4a39771 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -211,7 +211,7 @@
 		 * we are guaranteed that it is a valid memory location in our
 		 * kernel address buffer.
 		 */
-		((char *)sunaddr)[len]=0;
+		((char *)sunaddr)[len] = 0;
 		len = strlen(sunaddr->sun_path)+1+sizeof(short);
 		return len;
 	}
@@ -392,9 +392,9 @@
 
 	wake_up_interruptible_all(&u->peer_wait);
 
-	skpair=unix_peer(sk);
+	skpair = unix_peer(sk);
 
-	if (skpair!=NULL) {
+	if (skpair != NULL) {
 		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
 			unix_state_lock(skpair);
 			/* No more writes */
@@ -414,7 +414,7 @@
 	/* Try to flush out this socket. Throw out buffers at least */
 
 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-		if (state==TCP_LISTEN)
+		if (state == TCP_LISTEN)
 			unix_release_sock(skb->sk, 1);
 		/* passed fds are erased in the kfree_skb hook	      */
 		kfree_skb(skb);
@@ -630,7 +630,7 @@
 		 *	nothing uses it.
 		 */
 	case SOCK_RAW:
-		sock->type=SOCK_DGRAM;
+		sock->type = SOCK_DGRAM;
 	case SOCK_DGRAM:
 		sock->ops = &unix_dgram_ops;
 		break;
@@ -736,14 +736,14 @@
 
 		path_put(&path);
 
-		err=-EPROTOTYPE;
+		err = -EPROTOTYPE;
 		if (u->sk_type != type) {
 			sock_put(u);
 			goto fail;
 		}
 	} else {
 		err = -ECONNREFUSED;
-		u=unix_find_socket_byname(net, sunname, len, type, hash);
+		u = unix_find_socket_byname(net, sunname, len, type, hash);
 		if (u) {
 			struct dentry *dentry;
 			dentry = unix_sk(u)->dentry;
@@ -757,7 +757,7 @@
 put_fail:
 	path_put(&path);
 fail:
-	*error=err;
+	*error = err;
 	return NULL;
 }
 
@@ -767,7 +767,7 @@
 	struct sock *sk = sock->sk;
 	struct net *net = sock_net(sk);
 	struct unix_sock *u = unix_sk(sk);
-	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
 	struct dentry * dentry = NULL;
 	struct nameidata nd;
 	int err;
@@ -779,7 +779,7 @@
 	if (sunaddr->sun_family != AF_UNIX)
 		goto out;
 
-	if (addr_len==sizeof(short)) {
+	if (addr_len == sizeof(short)) {
 		err = unix_autobind(sock);
 		goto out;
 	}
@@ -875,8 +875,8 @@
 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
 	path_put(&nd.path);
 out_mknod_parent:
-	if (err==-EEXIST)
-		err=-EADDRINUSE;
+	if (err == -EEXIST)
+		err = -EADDRINUSE;
 	unix_release_addr(addr);
 	goto out_up;
 }
@@ -911,7 +911,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct net *net = sock_net(sk);
-	struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
+	struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
 	struct sock *other;
 	unsigned hash;
 	int err;
@@ -927,7 +927,7 @@
 			goto out;
 
 restart:
-		other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
+		other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
 		if (!other)
 			goto out;
 
@@ -961,14 +961,14 @@
 	 */
 	if (unix_peer(sk)) {
 		struct sock *old_peer = unix_peer(sk);
-		unix_peer(sk)=other;
+		unix_peer(sk) = other;
 		unix_state_double_unlock(sk, other);
 
 		if (other != old_peer)
 			unix_dgram_disconnected(sk, old_peer);
 		sock_put(old_peer);
 	} else {
-		unix_peer(sk)=other;
+		unix_peer(sk) = other;
 		unix_state_double_unlock(sk, other);
 	}
 	return 0;
@@ -1004,7 +1004,7 @@
 static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 			       int addr_len, int flags)
 {
-	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
 	struct sock *sk = sock->sk;
 	struct net *net = sock_net(sk);
 	struct unix_sock *u = unix_sk(sk), *newu, *otheru;
@@ -1179,13 +1179,13 @@
 
 static int unix_socketpair(struct socket *socka, struct socket *sockb)
 {
-	struct sock *ska=socka->sk, *skb = sockb->sk;
+	struct sock *ska = socka->sk, *skb = sockb->sk;
 
 	/* Join our sockets back to back */
 	sock_hold(ska);
 	sock_hold(skb);
-	unix_peer(ska)=skb;
-	unix_peer(skb)=ska;
+	unix_peer(ska) = skb;
+	unix_peer(skb) = ska;
 	ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
 	ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
 	ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
@@ -1246,7 +1246,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct unix_sock *u;
-	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
 	int err = 0;
 
 	if (peer) {
@@ -1332,7 +1332,7 @@
 	struct sock *sk = sock->sk;
 	struct net *net = sock_net(sk);
 	struct unix_sock *u = unix_sk(sk);
-	struct sockaddr_un *sunaddr=msg->msg_name;
+	struct sockaddr_un *sunaddr = msg->msg_name;
 	struct sock *other = NULL;
 	int namelen = 0; /* fake GCC */
 	int err;
@@ -1373,7 +1373,7 @@
 		goto out;
 
 	skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err);
-	if (skb==NULL)
+	if (skb == NULL)
 		goto out;
 
 	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
@@ -1399,7 +1399,7 @@
 
 		other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
 					hash, &err);
-		if (other==NULL)
+		if (other == NULL)
 			goto out_free;
 	}
 
@@ -1419,7 +1419,7 @@
 		err = 0;
 		unix_state_lock(sk);
 		if (unix_peer(sk) == other) {
-			unix_peer(sk)=NULL;
+			unix_peer(sk) = NULL;
 			unix_state_unlock(sk);
 
 			unix_dgram_disconnected(sk, other);
@@ -1485,10 +1485,10 @@
 	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct sock *other = NULL;
-	struct sockaddr_un *sunaddr=msg->msg_name;
+	struct sockaddr_un *sunaddr = msg->msg_name;
 	int err,size;
 	struct sk_buff *skb;
-	int sent=0;
+	int sent = 0;
 	struct scm_cookie tmp_scm;
 
 	if (NULL == siocb->scm)
@@ -1535,9 +1535,9 @@
 		 *	Grab a buffer
 		 */
 
-		skb=sock_alloc_send_skb(sk,size,msg->msg_flags&MSG_DONTWAIT, &err);
+		skb = sock_alloc_send_skb(sk,size,msg->msg_flags&MSG_DONTWAIT, &err);
 
-		if (skb==NULL)
+		if (skb == NULL)
 			goto out_err;
 
 		/*
@@ -1572,7 +1572,7 @@
 		skb_queue_tail(&other->sk_receive_queue, skb);
 		unix_state_unlock(other);
 		other->sk_data_ready(other, size);
-		sent+=size;
+		sent += size;
 	}
 
 	scm_destroy(siocb->scm);
@@ -1751,7 +1751,7 @@
 	struct scm_cookie tmp_scm;
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
-	struct sockaddr_un *sunaddr=msg->msg_name;
+	struct sockaddr_un *sunaddr = msg->msg_name;
 	int copied = 0;
 	int check_creds = 0;
 	int target;
@@ -1789,7 +1789,7 @@
 
 		unix_state_lock(sk);
 		skb = skb_dequeue(&sk->sk_receive_queue);
-		if (skb==NULL)
+		if (skb == NULL)
 		{
 			if (copied >= target)
 				goto unlock;
@@ -1901,7 +1901,7 @@
 	if (mode) {
 		unix_state_lock(sk);
 		sk->sk_shutdown |= mode;
-		other=unix_peer(sk);
+		other = unix_peer(sk);
 		if (other)
 			sock_hold(other);
 		unix_state_unlock(sk);
@@ -1936,7 +1936,7 @@
 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	long amount=0;
+	long amount = 0;
 	int err;
 
 	switch(cmd)
@@ -1962,7 +1962,7 @@
 			} else {
 				skb = skb_peek(&sk->sk_receive_queue);
 				if (skb)
-					amount=skb->len;
+					amount = skb->len;
 			}
 			spin_unlock(&sk->sk_receive_queue.lock);
 			err = put_user(amount, (int __user *)arg);
@@ -2094,6 +2094,7 @@
 	struct seq_net_private p;
 	int i;
 };
+
 static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos)
 {
 	struct unix_iter_state *iter = seq->private;
@@ -2110,7 +2111,6 @@
 	return NULL;
 }
 
-
 static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
 	__acquires(unix_table_lock)
 {
@@ -2190,7 +2190,6 @@
 	.show   = unix_seq_show,
 };
 
-
 static int unix_seq_open(struct inode *inode, struct file *file)
 {
 	return seq_open_net(inode, file, &unix_seq_ops,
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 6d4a9a8..5a0061d 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -104,8 +104,8 @@
 	 *	Socket ?
 	 */
 	if (S_ISSOCK(inode->i_mode)) {
-		struct socket * sock = SOCKET_I(inode);
-		struct sock * s = sock->sk;
+		struct socket *sock = SOCKET_I(inode);
+		struct sock *s = sock->sk;
 
 		/*
 		 *	PF_UNIX ?
@@ -124,7 +124,7 @@
 void unix_inflight(struct file *fp)
 {
 	struct sock *s = unix_get_socket(fp);
-	if(s) {
+	if (s) {
 		struct unix_sock *u = unix_sk(s);
 		spin_lock(&unix_gc_lock);
 		if (atomic_long_inc_return(&u->inflight) == 1) {
@@ -141,7 +141,7 @@
 void unix_notinflight(struct file *fp)
 {
 	struct sock *s = unix_get_socket(fp);
-	if(s) {
+	if (s) {
 		struct unix_sock *u = unix_sk(s);
 		spin_lock(&unix_gc_lock);
 		BUG_ON(list_empty(&u->link));
@@ -154,7 +154,7 @@
 
 static inline struct sk_buff *sock_queue_head(struct sock *sk)
 {
-	return (struct sk_buff *) &sk->sk_receive_queue;
+	return (struct sk_buff *)&sk->sk_receive_queue;
 }
 
 #define receive_queue_for_each_skb(sk, next, skb) \
@@ -364,7 +364,7 @@
 	 */
 	skb_queue_head_init(&hitlist);
 	list_for_each_entry(u, &gc_candidates, link)
-		scan_children(&u->sk, inc_inflight, &hitlist);
+	scan_children(&u->sk, inc_inflight, &hitlist);
 
 	spin_unlock(&unix_gc_lock);
 
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 77513d7..83c0930 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -21,7 +21,7 @@
 		.data		= &init_net.unx.sysctl_max_dgram_qlen,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
+		.proc_handler	= proc_dointvec
 	},
 	{ .ctl_name = 0 }
 };
@@ -61,4 +61,3 @@
 	unregister_sysctl_table(net->unx.ctl);
 	kfree(table);
 }
-
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 646c712..ae7f226 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -72,3 +72,13 @@
 
 	  Say Y if you have programs using it, like old versions of
 	  hal.
+
+config LIB80211
+	tristate "Common routines for IEEE802.11 drivers"
+	default n
+	help
+	  This options enables a library of common routines used
+	  by IEEE802.11 wireless LAN drivers.
+
+	  Drivers should select this themselves if needed.  Say Y if
+	  you want this built into your kernel.
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index b9f943c..d2d848d 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_WIRELESS_EXT) += wext.o
 obj-$(CONFIG_CFG80211) += cfg80211.o
+obj-$(CONFIG_LIB80211) += lib80211.o
 
 cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
 cfg80211-$(CONFIG_NL80211) += nl80211.o
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5031db7..39e3d10 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -236,8 +236,7 @@
 	mutex_unlock(&cfg80211_drv_mutex);
 
 	/* give it a proper name */
-	snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
-		 PHY_NAME "%d", drv->idx);
+	dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->idx);
 
 	mutex_init(&drv->mtx);
 	mutex_init(&drv->devlist_mtx);
@@ -301,13 +300,11 @@
 	/* check and set up bitrates */
 	ieee80211_set_bitrate_flags(wiphy);
 
-	/* set up regulatory info */
-	mutex_lock(&cfg80211_reg_mutex);
-	wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE);
-	mutex_unlock(&cfg80211_reg_mutex);
-
 	mutex_lock(&cfg80211_drv_mutex);
 
+	/* set up regulatory info */
+	wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE);
+
 	res = device_add(&drv->wiphy.dev);
 	if (res)
 		goto out_unlock;
diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c
new file mode 100644
index 0000000..e71f7d0
--- /dev/null
+++ b/net/wireless/lib80211.c
@@ -0,0 +1,65 @@
+/*
+ * lib80211 -- common bits for IEEE802.11 drivers
+ *
+ * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/ieee80211.h>
+
+#include <net/lib80211.h>
+
+#define DRV_NAME        "lib80211"
+
+#define DRV_DESCRIPTION	"common routines for IEEE802.11 drivers"
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
+MODULE_LICENSE("GPL");
+
+const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
+{
+	const char *s = ssid;
+	char *d = buf;
+
+	ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN);
+	while (ssid_len--) {
+		if (isprint(*s)) {
+			*d++ = *s++;
+			continue;
+		}
+
+		*d++ = '\\';
+		if (*s == '\0')
+			*d++ = '0';
+		else if (*s == '\n')
+			*d++ = 'n';
+		else if (*s == '\r')
+			*d++ = 'r';
+		else if (*s == '\t')
+			*d++ = 't';
+		else if (*s == '\\')
+			*d++ = '\\';
+		else
+			d += snprintf(d, 3, "%03o", *s);
+		s++;
+	}
+	*d = '\0';
+	return buf;
+}
+EXPORT_SYMBOL(print_ssid);
+
+static int __init ieee80211_init(void)
+{
+	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n");
+	return 0;
+}
+
+static void __exit ieee80211_exit(void)
+{
+}
+
+module_init(ieee80211_init);
+module_exit(ieee80211_exit);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 572793c..e3e1494 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -58,6 +58,7 @@
 	[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
 	[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
 				      .len = BUS_ID_SIZE-1 },
+	[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
 
 	[NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
 	[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -84,7 +85,7 @@
 					       .len = NL80211_MAX_SUPP_RATES },
 	[NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
 	[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
-	[NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
+	[NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
 	[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
 				.len = IEEE80211_MAX_MESH_ID_LEN },
 	[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
@@ -95,6 +96,10 @@
 	[NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
 	[NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
 	[NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
+	[NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
+					   .len = NL80211_MAX_SUPP_RATES },
+
+	[NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED },
 
 	[NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
 					 .len = NL80211_HT_CAPABILITY_LEN },
@@ -157,6 +162,19 @@
 		if (!nl_band)
 			goto nla_put_failure;
 
+		/* add HT info */
+		if (dev->wiphy.bands[band]->ht_cap.ht_supported) {
+			NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET,
+				sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
+				&dev->wiphy.bands[band]->ht_cap.mcs);
+			NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA,
+				dev->wiphy.bands[band]->ht_cap.cap);
+			NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
+				dev->wiphy.bands[band]->ht_cap.ampdu_factor);
+			NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+				dev->wiphy.bands[band]->ht_cap.ampdu_density);
+		}
+
 		/* add frequencies */
 		nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
 		if (!nl_freqs)
@@ -269,20 +287,76 @@
 	return -ENOBUFS;
 }
 
+static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
+	[NL80211_TXQ_ATTR_QUEUE]		= { .type = NLA_U8 },
+	[NL80211_TXQ_ATTR_TXOP]			= { .type = NLA_U16 },
+	[NL80211_TXQ_ATTR_CWMIN]		= { .type = NLA_U16 },
+	[NL80211_TXQ_ATTR_CWMAX]		= { .type = NLA_U16 },
+	[NL80211_TXQ_ATTR_AIFS]			= { .type = NLA_U8 },
+};
+
+static int parse_txq_params(struct nlattr *tb[],
+			    struct ieee80211_txq_params *txq_params)
+{
+	if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] ||
+	    !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
+	    !tb[NL80211_TXQ_ATTR_AIFS])
+		return -EINVAL;
+
+	txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]);
+	txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
+	txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
+	txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
+	txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
+
+	return 0;
+}
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev;
-	int result;
-
-	if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
-		return -EINVAL;
+	int result = 0, rem_txq_params = 0;
+	struct nlattr *nl_txq_params;
 
 	rdev = cfg80211_get_dev_from_info(info);
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
-	result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
+	if (info->attrs[NL80211_ATTR_WIPHY_NAME]) {
+		result = cfg80211_dev_rename(
+			rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
+		if (result)
+			goto bad_res;
+	}
 
+	if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
+		struct ieee80211_txq_params txq_params;
+		struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
+
+		if (!rdev->ops->set_txq_params) {
+			result = -EOPNOTSUPP;
+			goto bad_res;
+		}
+
+		nla_for_each_nested(nl_txq_params,
+				    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
+				    rem_txq_params) {
+			nla_parse(tb, NL80211_TXQ_ATTR_MAX,
+				  nla_data(nl_txq_params),
+				  nla_len(nl_txq_params),
+				  txq_params_policy);
+			result = parse_txq_params(tb, &txq_params);
+			if (result)
+				goto bad_res;
+
+			result = rdev->ops->set_txq_params(&rdev->wiphy,
+							   &txq_params);
+			if (result)
+				goto bad_res;
+		}
+	}
+
+bad_res:
 	cfg80211_put_dev(rdev);
 	return result;
 }
@@ -1598,6 +1672,12 @@
 	if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
 		params.use_short_slot_time =
 		    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
+	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
+		params.basic_rates =
+			nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+		params.basic_rates_len =
+			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+	}
 
 	err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
 	if (err)
@@ -1680,11 +1760,188 @@
 		return -EINVAL;
 #endif
 	mutex_lock(&cfg80211_drv_mutex);
-	r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL);
+	r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data);
 	mutex_unlock(&cfg80211_drv_mutex);
 	return r;
 }
 
+static int nl80211_get_mesh_params(struct sk_buff *skb,
+	struct genl_info *info)
+{
+	struct cfg80211_registered_device *drv;
+	struct mesh_config cur_params;
+	int err;
+	struct net_device *dev;
+	void *hdr;
+	struct nlattr *pinfoattr;
+	struct sk_buff *msg;
+
+	/* Look up our device */
+	err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+	if (err)
+		return err;
+
+	/* Get the mesh params */
+	rtnl_lock();
+	err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
+	rtnl_unlock();
+	if (err)
+		goto out;
+
+	/* Draw up a netlink message to send back */
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg) {
+		err = -ENOBUFS;
+		goto out;
+	}
+	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+			     NL80211_CMD_GET_MESH_PARAMS);
+	if (!hdr)
+		goto nla_put_failure;
+	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS);
+	if (!pinfoattr)
+		goto nla_put_failure;
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
+			cur_params.dot11MeshRetryTimeout);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
+			cur_params.dot11MeshConfirmTimeout);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
+			cur_params.dot11MeshHoldingTimeout);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
+			cur_params.dot11MeshMaxPeerLinks);
+	NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES,
+			cur_params.dot11MeshMaxRetries);
+	NLA_PUT_U8(msg, NL80211_MESHCONF_TTL,
+			cur_params.dot11MeshTTL);
+	NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+			cur_params.auto_open_plinks);
+	NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+			cur_params.dot11MeshHWMPmaxPREQretries);
+	NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
+			cur_params.path_refresh_time);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+			cur_params.min_discovery_timeout);
+	NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+			cur_params.dot11MeshHWMPactivePathTimeout);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+			cur_params.dot11MeshHWMPpreqMinInterval);
+	NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+			cur_params.dot11MeshHWMPnetDiameterTraversalTime);
+	nla_nest_end(msg, pinfoattr);
+	genlmsg_end(msg, hdr);
+	err = genlmsg_unicast(msg, info->snd_pid);
+	goto out;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	err = -EMSGSIZE;
+out:
+	/* Cleanup */
+	cfg80211_put_dev(drv);
+	dev_put(dev);
+	return err;
+}
+
+#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
+do {\
+	if (table[attr_num]) {\
+		cfg.param = nla_fn(table[attr_num]); \
+		mask |= (1 << (attr_num - 1)); \
+	} \
+} while (0);\
+
+static struct nla_policy
+nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
+	[NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
+	[NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
+	[NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
+
+	[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
+	[NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
+	[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
+	[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
+	[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
+};
+
+static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	u32 mask;
+	struct cfg80211_registered_device *drv;
+	struct net_device *dev;
+	struct mesh_config cfg;
+	struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
+	struct nlattr *parent_attr;
+
+	parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS];
+	if (!parent_attr)
+		return -EINVAL;
+	if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
+			parent_attr, nl80211_meshconf_params_policy))
+		return -EINVAL;
+
+	err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+	if (err)
+		return err;
+
+	/* This makes sure that there aren't more than 32 mesh config
+	 * parameters (otherwise our bitfield scheme would not work.) */
+	BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
+
+	/* Fill in the params struct */
+	mask = 0;
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout,
+			mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout,
+			mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout,
+			mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks,
+			mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries,
+			mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL,
+			mask, NL80211_MESHCONF_TTL, nla_get_u8);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks,
+			mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries,
+			mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+			nla_get_u8);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time,
+			mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout,
+			mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+			nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
+			mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+			nla_get_u32);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
+			mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+			nla_get_u16);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
+			dot11MeshHWMPnetDiameterTraversalTime,
+			mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+			nla_get_u16);
+
+	/* Apply changes */
+	rtnl_lock();
+	err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
+	rtnl_unlock();
+
+	/* cleanup */
+	cfg80211_put_dev(drv);
+	dev_put(dev);
+	return err;
+}
+
+#undef FILL_IN_MESH_PARAM_IF_SET
+
 static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 {
 	struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
@@ -1743,12 +2000,9 @@
 	mutex_lock(&cfg80211_drv_mutex);
 	r = set_regdom(rd);
 	mutex_unlock(&cfg80211_drv_mutex);
-	if (r)
-		goto bad_reg;
-
 	return r;
 
-bad_reg:
+ bad_reg:
 	kfree(rd);
 	return -EINVAL;
 }
@@ -1902,6 +2156,18 @@
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = NL80211_CMD_GET_MESH_PARAMS,
+		.doit = nl80211_get_mesh_params,
+		.policy = nl80211_policy,
+		/* can be retrieved by unprivileged users */
+	},
+	{
+		.cmd = NL80211_CMD_SET_MESH_PARAMS,
+		.doit = nl80211_set_mesh_params,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
 };
 
 /* multicast groups */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 626dbb6..4c7e39d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -42,17 +42,34 @@
 #include "core.h"
 #include "reg.h"
 
-/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */
+/**
+ * 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.
+ */
 struct regulatory_request {
-	struct list_head list;
 	struct wiphy *wiphy;
-	int granted;
 	enum reg_set_by initiator;
 	char alpha2[2];
+	bool intersect;
 };
 
-static LIST_HEAD(regulatory_requests);
-DEFINE_MUTEX(cfg80211_reg_mutex);
+/* Receipt of information from last regulatory request */
+static struct regulatory_request *last_request;
 
 /* To trigger userspace events */
 static struct platform_device *reg_pdev;
@@ -63,8 +80,6 @@
 	MHZ_TO_KHZ(20),
 };
 
-static struct list_head regulatory_requests;
-
 /* Central wireless core regulatory domains, we only need two,
  * the current one and a world regulatory domain in case we have no
  * information to give us an alpha2 */
@@ -204,7 +219,7 @@
  * core upon initialization */
 static void update_world_regdomain(const struct ieee80211_regdomain *rd)
 {
-	BUG_ON(list_empty(&regulatory_requests));
+	BUG_ON(!last_request);
 
 	reset_regdomains();
 
@@ -300,121 +315,13 @@
 	return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
 }
 
-/* This has the logic which determines when a new request
- * should be ignored. */
-static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
-	char *alpha2, struct ieee80211_regdomain *rd)
-{
-	struct regulatory_request *last_request = NULL;
-
-	/* All initial requests are respected */
-	if (list_empty(&regulatory_requests))
-		return 0;
-
-	last_request = list_first_entry(&regulatory_requests,
-		struct regulatory_request, list);
-
-	switch (set_by) {
-	case REGDOM_SET_BY_INIT:
-		return -EINVAL;
-	case REGDOM_SET_BY_CORE:
-		/* Always respect new wireless core hints, should only
-		 * come in for updating the world regulatory domain at init
-		 * anyway */
-		return 0;
-	case REGDOM_SET_BY_COUNTRY_IE:
-		if (last_request->initiator == set_by) {
-			if (last_request->wiphy != wiphy) {
-				/* Two cards with two APs claiming different
-				 * different Country IE alpha2s!
-				 * You're special!! */
-				if (!alpha2_equal(last_request->alpha2,
-						cfg80211_regdomain->alpha2)) {
-					/* XXX: Deal with conflict, consider
-					 * building a new one out of the
-					 * intersection */
-					WARN_ON(1);
-					return -EOPNOTSUPP;
-				}
-				return -EALREADY;
-			}
-			/* Two consecutive Country IE hints on the same wiphy */
-			if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
-				return 0;
-			return -EALREADY;
-		}
-		if (WARN_ON(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2)),
-				"Invalid Country IE regulatory hint passed "
-				"to the wireless core\n")
-			return -EINVAL;
-		/* We ignore Country IE hints for now, as we haven't yet
-		 * added the dot11MultiDomainCapabilityEnabled flag
-		 * for wiphys */
-		return 1;
-	case REGDOM_SET_BY_DRIVER:
-		BUG_ON(!wiphy);
-		if (last_request->initiator == set_by) {
-			/* Two separate drivers hinting different things,
-			 * this is possible if you have two devices present
-			 * on a system with different EEPROM regulatory
-			 * readings. XXX: Do intersection, we support only
-			 * the first regulatory hint for now */
-			if (last_request->wiphy != wiphy)
-				return -EALREADY;
-			if (rd)
-				return -EALREADY;
-			/* Driver should not be trying to hint different
-			 * regulatory domains! */
-			BUG_ON(!alpha2_equal(alpha2,
-					cfg80211_regdomain->alpha2));
-			return -EALREADY;
-		}
-		if (last_request->initiator == REGDOM_SET_BY_CORE)
-			return 0;
-		/* XXX: Handle intersection, and add the
-		 * dot11MultiDomainCapabilityEnabled flag to wiphy. For now
-		 * we assume the driver has this set to false, following the
-		 * 802.11d dot11MultiDomainCapabilityEnabled documentation */
-		if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
-			return 0;
-		return 0;
-	case REGDOM_SET_BY_USER:
-		if (last_request->initiator == set_by ||
-				last_request->initiator == REGDOM_SET_BY_CORE)
-			return 0;
-		/* Drivers can use their wiphy's reg_notifier()
-		 * to override any information */
-		if (last_request->initiator == REGDOM_SET_BY_DRIVER)
-			return 0;
-		/* XXX: Handle intersection */
-		if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
-			return -EOPNOTSUPP;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-static bool __reg_is_valid_request(const char *alpha2,
-	struct regulatory_request **request)
-{
-	struct regulatory_request *req;
-	if (list_empty(&regulatory_requests))
-		return false;
-	list_for_each_entry(req, &regulatory_requests, list) {
-		if (alpha2_equal(req->alpha2, alpha2)) {
-			*request = req;
-			return true;
-		}
-	}
-	return false;
-}
-
 /* Used by nl80211 before kmalloc'ing our regulatory domain */
 bool reg_is_valid_request(const char *alpha2)
 {
-	struct regulatory_request *request = NULL;
-	return  __reg_is_valid_request(alpha2, &request);
+	if (!last_request)
+		return false;
+
+	return alpha2_equal(last_request->alpha2, alpha2);
 }
 
 /* Sanity check on a regulatory rule */
@@ -431,7 +338,7 @@
 
 	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
 
-	if (freq_range->max_bandwidth_khz > freq_diff)
+	if (freq_diff <= 0 || freq_range->max_bandwidth_khz > freq_diff)
 		return false;
 
 	return true;
@@ -469,6 +376,143 @@
 	return 0;
 }
 
+/* Helper for regdom_intersect(), this does the real
+ * mathematical intersection fun */
+static int reg_rules_intersect(
+	const struct ieee80211_reg_rule *rule1,
+	const struct ieee80211_reg_rule *rule2,
+	struct ieee80211_reg_rule *intersected_rule)
+{
+	const struct ieee80211_freq_range *freq_range1, *freq_range2;
+	struct ieee80211_freq_range *freq_range;
+	const struct ieee80211_power_rule *power_rule1, *power_rule2;
+	struct ieee80211_power_rule *power_rule;
+	u32 freq_diff;
+
+	freq_range1 = &rule1->freq_range;
+	freq_range2 = &rule2->freq_range;
+	freq_range = &intersected_rule->freq_range;
+
+	power_rule1 = &rule1->power_rule;
+	power_rule2 = &rule2->power_rule;
+	power_rule = &intersected_rule->power_rule;
+
+	freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
+		freq_range2->start_freq_khz);
+	freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
+		freq_range2->end_freq_khz);
+	freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
+		freq_range2->max_bandwidth_khz);
+
+	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+	if (freq_range->max_bandwidth_khz > freq_diff)
+		freq_range->max_bandwidth_khz = freq_diff;
+
+	power_rule->max_eirp = min(power_rule1->max_eirp,
+		power_rule2->max_eirp);
+	power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
+		power_rule2->max_antenna_gain);
+
+	intersected_rule->flags = (rule1->flags | rule2->flags);
+
+	if (!is_valid_reg_rule(intersected_rule))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * regdom_intersect - do the intersection between two regulatory domains
+ * @rd1: first regulatory domain
+ * @rd2: second regulatory domain
+ *
+ * Use this function to get the intersection between two regulatory domains.
+ * Once completed we will mark the alpha2 for the rd as intersected, "98",
+ * as no one single alpha2 can represent this regulatory domain.
+ *
+ * Returns a pointer to the regulatory domain structure which will hold the
+ * resulting intersection of rules between rd1 and rd2. We will
+ * kzalloc() this structure for you.
+ */
+static struct ieee80211_regdomain *regdom_intersect(
+	const struct ieee80211_regdomain *rd1,
+	const struct ieee80211_regdomain *rd2)
+{
+	int r, size_of_regd;
+	unsigned int x, y;
+	unsigned int num_rules = 0, rule_idx = 0;
+	const struct ieee80211_reg_rule *rule1, *rule2;
+	struct ieee80211_reg_rule *intersected_rule;
+	struct ieee80211_regdomain *rd;
+	/* This is just a dummy holder to help us count */
+	struct ieee80211_reg_rule irule;
+
+	/* Uses the stack temporarily for counter arithmetic */
+	intersected_rule = &irule;
+
+	memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule));
+
+	if (!rd1 || !rd2)
+		return NULL;
+
+	/* First we get a count of the rules we'll need, then we actually
+	 * build them. This is to so we can malloc() and free() a
+	 * regdomain once. The reason we use reg_rules_intersect() here
+	 * is it will return -EINVAL if the rule computed makes no sense.
+	 * All rules that do check out OK are valid. */
+
+	for (x = 0; x < rd1->n_reg_rules; x++) {
+		rule1 = &rd1->reg_rules[x];
+		for (y = 0; y < rd2->n_reg_rules; y++) {
+			rule2 = &rd2->reg_rules[y];
+			if (!reg_rules_intersect(rule1, rule2,
+					intersected_rule))
+				num_rules++;
+			memset(intersected_rule, 0,
+					sizeof(struct ieee80211_reg_rule));
+		}
+	}
+
+	if (!num_rules)
+		return NULL;
+
+	size_of_regd = sizeof(struct ieee80211_regdomain) +
+		((num_rules + 1) * sizeof(struct ieee80211_reg_rule));
+
+	rd = kzalloc(size_of_regd, GFP_KERNEL);
+	if (!rd)
+		return NULL;
+
+	for (x = 0; x < rd1->n_reg_rules; x++) {
+		rule1 = &rd1->reg_rules[x];
+		for (y = 0; y < rd2->n_reg_rules; y++) {
+			rule2 = &rd2->reg_rules[y];
+			/* This time around instead of using the stack lets
+			 * write to the target rule directly saving ourselves
+			 * a memcpy() */
+			intersected_rule = &rd->reg_rules[rule_idx];
+			r = reg_rules_intersect(rule1, rule2,
+				intersected_rule);
+			/* No need to memset here the intersected rule here as
+			 * we're not using the stack anymore */
+			if (r)
+				continue;
+			rule_idx++;
+		}
+	}
+
+	if (rule_idx != num_rules) {
+		kfree(rd);
+		return NULL;
+	}
+
+	rd->n_reg_rules = num_rules;
+	rd->alpha2[0] = '9';
+	rd->alpha2[1] = '8';
+
+	return rd;
+}
+
 /* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
  * want to just have the channel structure use these */
 static u32 map_regdom_flags(u32 rd_flags)
@@ -578,22 +622,81 @@
 	}
 }
 
+/* Return value which can be used by ignore_request() to indicate
+ * it has been determined we should intersect two regulatory domains */
+#define REG_INTERSECT	1
+
+/* This has the logic which determines when a new request
+ * should be ignored. */
+static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
+			  const char *alpha2)
+{
+	/* All initial requests are respected */
+	if (!last_request)
+		return 0;
+
+	switch (set_by) {
+	case REGDOM_SET_BY_INIT:
+		return -EINVAL;
+	case REGDOM_SET_BY_CORE:
+		/*
+		 * Always respect new wireless core hints, should only happen
+		 * when updating the world regulatory domain at init.
+		 */
+		return 0;
+	case REGDOM_SET_BY_COUNTRY_IE:
+		if (unlikely(!is_an_alpha2(alpha2)))
+			return -EINVAL;
+		if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
+			if (last_request->wiphy != wiphy) {
+				/*
+				 * Two cards with two APs claiming different
+				 * different Country IE alpha2s. We could
+				 * intersect them, but that seems unlikely
+				 * to be correct. Reject second one for now.
+				 */
+				if (!alpha2_equal(alpha2,
+						  cfg80211_regdomain->alpha2))
+					return -EOPNOTSUPP;
+				return -EALREADY;
+			}
+			/* Two consecutive Country IE hints on the same wiphy */
+			if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
+				return 0;
+			return -EALREADY;
+		}
+		/*
+		 * Ignore Country IE hints for now, need to think about
+		 * what we need to do to support multi-domain operation.
+		 */
+		return -EOPNOTSUPP;
+	case REGDOM_SET_BY_DRIVER:
+		if (last_request->initiator == REGDOM_SET_BY_DRIVER)
+			return -EALREADY;
+		return 0;
+	case REGDOM_SET_BY_USER:
+		if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
+			return REG_INTERSECT;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 /* Caller must hold &cfg80211_drv_mutex */
 int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
-		      const char *alpha2, struct ieee80211_regdomain *rd)
+		      const char *alpha2)
 {
 	struct regulatory_request *request;
-	char *rd_alpha2;
+	bool intersect = false;
 	int r = 0;
 
-	r = ignore_request(wiphy, set_by, (char *) alpha2, rd);
-	if (r)
-		return r;
+	r = ignore_request(wiphy, set_by, alpha2);
 
-	if (rd)
-		rd_alpha2 = rd->alpha2;
-	else
-		rd_alpha2 = (char *) alpha2;
+	if (r == REG_INTERSECT)
+		intersect = true;
+	else if (r)
+		return r;
 
 	switch (set_by) {
 	case REGDOM_SET_BY_CORE:
@@ -601,18 +704,18 @@
 	case REGDOM_SET_BY_DRIVER:
 	case REGDOM_SET_BY_USER:
 		request = kzalloc(sizeof(struct regulatory_request),
-			GFP_KERNEL);
+				  GFP_KERNEL);
 		if (!request)
 			return -ENOMEM;
 
-		request->alpha2[0] = rd_alpha2[0];
-		request->alpha2[1] = rd_alpha2[1];
+		request->alpha2[0] = alpha2[0];
+		request->alpha2[1] = alpha2[1];
 		request->initiator = set_by;
 		request->wiphy = wiphy;
+		request->intersect = intersect;
 
-		list_add_tail(&request->list, &regulatory_requests);
-		if (rd)
-			break;
+		kfree(last_request);
+		last_request = request;
 		r = call_crda(alpha2);
 #ifndef CONFIG_WIRELESS_OLD_REGULATORY
 		if (r)
@@ -627,26 +730,13 @@
 	return r;
 }
 
-/* If rd is not NULL and if this call fails the caller must free it */
-int regulatory_hint(struct wiphy *wiphy, const char *alpha2,
-	struct ieee80211_regdomain *rd)
+void regulatory_hint(struct wiphy *wiphy, const char *alpha2)
 {
-	int r;
-	BUG_ON(!rd && !alpha2);
+	BUG_ON(!alpha2);
 
 	mutex_lock(&cfg80211_drv_mutex);
-
-	r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, rd);
-	if (r || !rd)
-		goto unlock_and_exit;
-
-	/* If the driver passed a regulatory domain we skipped asking
-	 * userspace for one so we can now go ahead and set it */
-	r = set_regdom(rd);
-
-unlock_and_exit:
+	__regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2);
 	mutex_unlock(&cfg80211_drv_mutex);
-	return r;
 }
 EXPORT_SYMBOL(regulatory_hint);
 
@@ -705,21 +795,21 @@
 	print_rd_rules(rd);
 }
 
-void print_regdomain_info(const struct ieee80211_regdomain *rd)
+static void print_regdomain_info(const struct ieee80211_regdomain *rd)
 {
 	printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n",
 		rd->alpha2[0], rd->alpha2[1]);
 	print_rd_rules(rd);
 }
 
+/* Takes ownership of rd only if it doesn't fail */
 static int __set_regdom(const struct ieee80211_regdomain *rd)
 {
-	struct regulatory_request *request = NULL;
-
+	const struct ieee80211_regdomain *intersected_rd = NULL;
 	/* Some basic sanity checks first */
 
 	if (is_world_regdom(rd->alpha2)) {
-		if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
+		if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
 			return -EINVAL;
 		update_world_regdomain(rd);
 		return 0;
@@ -729,7 +819,7 @@
 			!is_unknown_alpha2(rd->alpha2))
 		return -EINVAL;
 
-	if (list_empty(&regulatory_requests))
+	if (!last_request)
 		return -EINVAL;
 
 	/* allow overriding the static definitions if CRDA is present */
@@ -742,13 +832,13 @@
 	 * to review or adjust their own settings based on their own
 	 * internal EEPROM data */
 
-	if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
+	if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
 		return -EINVAL;
 
 	reset_regdomains();
 
 	/* Country IE parsing coming soon */
-	switch (request->initiator) {
+	switch (last_request->initiator) {
 	case REGDOM_SET_BY_CORE:
 	case REGDOM_SET_BY_DRIVER:
 	case REGDOM_SET_BY_USER:
@@ -765,9 +855,16 @@
 		return -EOPNOTSUPP;
 	}
 
+	if (unlikely(last_request->intersect)) {
+		intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
+		if (!intersected_rd)
+			return -EINVAL;
+		kfree(rd);
+		rd = intersected_rd;
+	}
+
 	/* Tada! */
 	cfg80211_regdomain = rd;
-	request->granted = 1;
 
 	return 0;
 }
@@ -775,46 +872,23 @@
 
 /* Use this call to set the current regulatory domain. Conflicts with
  * multiple drivers can be ironed out later. Caller must've already
- * kmalloc'd the rd structure. If this calls fails you should kfree()
- * the passed rd. Caller must hold cfg80211_drv_mutex */
+ * kmalloc'd the rd structure. Caller must hold cfg80211_drv_mutex */
 int set_regdom(const struct ieee80211_regdomain *rd)
 {
-	struct regulatory_request *this_request = NULL, *prev_request = NULL;
 	int r;
 
-	if (!list_empty(&regulatory_requests))
-		prev_request = list_first_entry(&regulatory_requests,
-			struct regulatory_request, list);
-
 	/* Note that this doesn't update the wiphys, this is done below */
 	r = __set_regdom(rd);
-	if (r)
+	if (r) {
+		kfree(rd);
 		return r;
-
-	BUG_ON((!__reg_is_valid_request(rd->alpha2, &this_request)));
-
-	/* The initial standard core update of the world regulatory domain, no
-	 * need to keep that request info around if it didn't fail. */
-	if (is_world_regdom(rd->alpha2) &&
-			this_request->initiator == REGDOM_SET_BY_CORE &&
-			this_request->granted) {
-		list_del(&this_request->list);
-		kfree(this_request);
-		this_request = NULL;
-	}
-
-	/* Remove old requests, we only leave behind the last one */
-	if (prev_request) {
-		list_del(&prev_request->list);
-		kfree(prev_request);
-		prev_request = NULL;
 	}
 
 	/* This would make this whole thing pointless */
 	BUG_ON(rd != cfg80211_regdomain);
 
 	/* update all wiphys now with the new established regulatory domain */
-	update_all_wiphy_regulatory(this_request->initiator);
+	update_all_wiphy_regulatory(last_request->initiator);
 
 	print_regdomain(rd);
 
@@ -838,13 +912,13 @@
 	 * you have CRDA you get it updated, otherwise you get
 	 * stuck with the static values. We ignore "EU" code as
 	 * that is not a valid ISO / IEC 3166 alpha2 */
-	if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U')
+	if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U')
 		err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
-					ieee80211_regdom, NULL);
+					ieee80211_regdom);
 #else
 	cfg80211_regdomain = cfg80211_world_regdom;
 
-	err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
+	err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00");
 	if (err)
 		printk(KERN_ERR "cfg80211: calling CRDA failed - "
 		       "unable to update world regulatory domain, "
@@ -856,16 +930,12 @@
 
 void regulatory_exit(void)
 {
-	struct regulatory_request *req, *req_tmp;
-
 	mutex_lock(&cfg80211_drv_mutex);
 
 	reset_regdomains();
 
-	list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) {
-		list_del(&req->list);
-		kfree(req);
-	}
+	kfree(last_request);
+
 	platform_device_unregister(reg_pdev);
 
 	mutex_unlock(&cfg80211_drv_mutex);
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index a333628..c9b6b63 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,7 +1,6 @@
 #ifndef __NET_WIRELESS_REG_H
 #define __NET_WIRELESS_REG_H
 
-extern struct mutex cfg80211_reg_mutex;
 bool is_world_regdom(const char *alpha2);
 bool reg_is_valid_request(const char *alpha2);
 
@@ -10,4 +9,23 @@
 
 int set_regdom(const struct ieee80211_regdomain *rd);
 
+/**
+ * __regulatory_hint - hint to the wireless core a regulatory domain
+ * @wiphy: if the hint comes from country information from an AP, this
+ *	is required to be set to the wiphy that received the information
+ * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain
+ *	should be in.
+ *
+ * The Wireless subsystem can use this function to hint to the wireless core
+ * what it believes should be the current regulatory domain by
+ * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
+ * domain should be in.
+ *
+ * Returns zero if all went fine, %-EALREADY if a regulatory domain had
+ * already been set or other standard error codes.
+ *
+ */
+extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
+			     const char *alpha2);
+
 #endif  /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f544246..e76cc28 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -7,6 +7,25 @@
 #include <asm/bitops.h>
 #include "core.h"
 
+struct ieee80211_rate *
+ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
+			    u64 basic_rates, int bitrate)
+{
+	struct ieee80211_rate *result = &sband->bitrates[0];
+	int i;
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if (!(basic_rates & BIT(i)))
+			continue;
+		if (sband->bitrates[i].bitrate > bitrate)
+			continue;
+		result = &sband->bitrates[i];
+	}
+
+	return result;
+}
+EXPORT_SYMBOL(ieee80211_get_response_rate);
+
 int ieee80211_channel_to_frequency(int chan)
 {
 	if (chan < 14)
diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c
index 6ebda25..a5d3416 100644
--- a/net/x25/sysctl_net_x25.c
+++ b/net/x25/sysctl_net_x25.c
@@ -24,8 +24,8 @@
 		.data =		&sysctl_x25_restart_request_timeout,
 		.maxlen =	sizeof(int),
 		.mode =		0644,
-		.proc_handler =	&proc_dointvec_minmax,
-		.strategy =	&sysctl_intvec,
+		.proc_handler =	proc_dointvec_minmax,
+		.strategy =	sysctl_intvec,
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
@@ -35,8 +35,8 @@
 		.data =		&sysctl_x25_call_request_timeout,
 		.maxlen =	sizeof(int),
 		.mode =		0644,
-		.proc_handler =	&proc_dointvec_minmax,
-		.strategy =	&sysctl_intvec,
+		.proc_handler =	proc_dointvec_minmax,
+		.strategy =	sysctl_intvec,
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
@@ -46,8 +46,8 @@
 		.data =		&sysctl_x25_reset_request_timeout,
 		.maxlen =	sizeof(int),
 		.mode =		0644,
-		.proc_handler =	&proc_dointvec_minmax,
-		.strategy =	&sysctl_intvec,
+		.proc_handler =	proc_dointvec_minmax,
+		.strategy =	sysctl_intvec,
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
@@ -57,8 +57,8 @@
 		.data =		&sysctl_x25_clear_request_timeout,
 		.maxlen =	sizeof(int),
 		.mode =		0644,
-		.proc_handler =	&proc_dointvec_minmax,
-		.strategy =	&sysctl_intvec,
+		.proc_handler =	proc_dointvec_minmax,
+		.strategy =	sysctl_intvec,
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
@@ -68,8 +68,8 @@
 		.data =		&sysctl_x25_ack_holdback_timeout,
 		.maxlen =	sizeof(int),
 		.mode =		0644,
-		.proc_handler =	&proc_dointvec_minmax,
-		.strategy =	&sysctl_intvec,
+		.proc_handler =	proc_dointvec_minmax,
+		.strategy =	sysctl_intvec,
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
@@ -79,7 +79,7 @@
 		.data = 	&sysctl_x25_forward,
 		.maxlen = 	sizeof(int),
 		.mode = 	0644,
-		.proc_handler = &proc_dointvec,
+		.proc_handler = proc_dointvec,
 	},
 	{ 0, },
 };
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 058f04f..c546cf6 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2381,9 +2381,7 @@
 }
 
 static struct notifier_block xfrm_dev_notifier = {
-	xfrm_dev_event,
-	NULL,
-	0
+	.notifier_call	= xfrm_dev_event,
 };
 
 #ifdef CONFIG_XFRM_STATISTICS
@@ -2457,25 +2455,21 @@
 
 	switch(sel->family) {
 	case AF_INET:
-		audit_log_format(audit_buf, " src=" NIPQUAD_FMT,
-				 NIPQUAD(sel->saddr.a4));
+		audit_log_format(audit_buf, " src=%pI4", &sel->saddr.a4);
 		if (sel->prefixlen_s != 32)
 			audit_log_format(audit_buf, " src_prefixlen=%d",
 					 sel->prefixlen_s);
-		audit_log_format(audit_buf, " dst=" NIPQUAD_FMT,
-				 NIPQUAD(sel->daddr.a4));
+		audit_log_format(audit_buf, " dst=%pI4", &sel->daddr.a4);
 		if (sel->prefixlen_d != 32)
 			audit_log_format(audit_buf, " dst_prefixlen=%d",
 					 sel->prefixlen_d);
 		break;
 	case AF_INET6:
-		audit_log_format(audit_buf, " src=" NIP6_FMT,
-				 NIP6(*(struct in6_addr *)sel->saddr.a6));
+		audit_log_format(audit_buf, " src=%pI6", sel->saddr.a6);
 		if (sel->prefixlen_s != 128)
 			audit_log_format(audit_buf, " src_prefixlen=%d",
 					 sel->prefixlen_s);
-		audit_log_format(audit_buf, " dst=" NIP6_FMT,
-				 NIP6(*(struct in6_addr *)sel->daddr.a6));
+		audit_log_format(audit_buf, " dst=%pI6", sel->daddr.a6);
 		if (sel->prefixlen_d != 128)
 			audit_log_format(audit_buf, " dst_prefixlen=%d",
 					 sel->prefixlen_d);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 508337f..cd9d917 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2109,16 +2109,12 @@
 
 	switch(x->props.family) {
 	case AF_INET:
-		audit_log_format(audit_buf,
-				 " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT,
-				 NIPQUAD(x->props.saddr.a4),
-				 NIPQUAD(x->id.daddr.a4));
+		audit_log_format(audit_buf, " src=%pI4 dst=%pI4",
+				 &x->props.saddr.a4, &x->id.daddr.a4);
 		break;
 	case AF_INET6:
-		audit_log_format(audit_buf,
-				 " src=" NIP6_FMT " dst=" NIP6_FMT,
-				 NIP6(*(struct in6_addr *)x->props.saddr.a6),
-				 NIP6(*(struct in6_addr *)x->id.daddr.a6));
+		audit_log_format(audit_buf, " src=%pI6 dst=%pI6",
+				 x->props.saddr.a6, x->id.daddr.a6);
 		break;
 	}
 
@@ -2134,18 +2130,14 @@
 	switch (family) {
 	case AF_INET:
 		iph4 = ip_hdr(skb);
-		audit_log_format(audit_buf,
-				 " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT,
-				 NIPQUAD(iph4->saddr),
-				 NIPQUAD(iph4->daddr));
+		audit_log_format(audit_buf, " src=%pI4 dst=%pI4",
+				 &iph4->saddr, &iph4->daddr);
 		break;
 	case AF_INET6:
 		iph6 = ipv6_hdr(skb);
 		audit_log_format(audit_buf,
-				 " src=" NIP6_FMT " dst=" NIP6_FMT
-				 " flowlbl=0x%x%02x%02x",
-				 NIP6(iph6->saddr),
-				 NIP6(iph6->daddr),
+				 " src=%pI6 dst=%pI6 flowlbl=0x%x%02x%02x",
+				 &iph6->saddr,&iph6->daddr,
 				 iph6->flow_lbl[0] & 0x0f,
 				 iph6->flow_lbl[1],
 				 iph6->flow_lbl[2]);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index a278a6f..ee15d5d 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2503,6 +2503,57 @@
 	return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
 }
 
+static inline size_t xfrm_mapping_msgsize(void)
+{
+	return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping));
+}
+
+static int build_mapping(struct sk_buff *skb, struct xfrm_state *x,
+			 xfrm_address_t *new_saddr, __be16 new_sport)
+{
+	struct xfrm_user_mapping *um;
+	struct nlmsghdr *nlh;
+
+	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0);
+	if (nlh == NULL)
+		return -EMSGSIZE;
+
+	um = nlmsg_data(nlh);
+
+	memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr));
+	um->id.spi = x->id.spi;
+	um->id.family = x->props.family;
+	um->id.proto = x->id.proto;
+	memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr));
+	memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr));
+	um->new_sport = new_sport;
+	um->old_sport = x->encap->encap_sport;
+	um->reqid = x->props.reqid;
+
+	return nlmsg_end(skb, nlh);
+}
+
+static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
+			     __be16 sport)
+{
+	struct sk_buff *skb;
+
+	if (x->id.proto != IPPROTO_ESP)
+		return -EINVAL;
+
+	if (!x->encap)
+		return -EINVAL;
+
+	skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (build_mapping(skb, x, ipaddr, sport) < 0)
+		BUG();
+
+	return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
+}
+
 static struct xfrm_mgr netlink_mgr = {
 	.id		= "netlink",
 	.notify		= xfrm_send_state_notify,
@@ -2511,6 +2562,7 @@
 	.notify_policy	= xfrm_send_policy_notify,
 	.report		= xfrm_send_report,
 	.migrate	= xfrm_send_migrate,
+	.new_mapping	= xfrm_send_mapping,
 };
 
 static int __init xfrm_user_init(void)
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index cb30c7e..d43bd6b 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -495,7 +495,7 @@
 				       char *name1, char *name2)
 {
 	if (!ipv6_addr_any(addr))
-		audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr));
+		audit_log_format(ab, " %s=%pI6", name1, addr);
 	if (port)
 		audit_log_format(ab, " %s=%d", name2, ntohs(port));
 }
@@ -504,7 +504,7 @@
 				       __be16 port, char *name1, char *name2)
 {
 	if (addr)
-		audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr));
+		audit_log_format(ab, " %s=%pI4", name1, &addr);
 	if (port)
 		audit_log_format(ab, " %s=%d", name2, ntohs(port));
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f85597a..f3c4bc1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4628,7 +4628,7 @@
 	 * as fast and as clean as possible. */
 	if (selinux_compat_net || !selinux_policycap_netpeer)
 		return selinux_ip_postroute_compat(skb, ifindex, family);
-
+#ifdef CONFIG_XFRM
 	/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
 	 * packet transformation so allow the packet to pass without any checks
 	 * since we'll have another chance to perform access control checks
@@ -4637,7 +4637,7 @@
 	 *       is NULL, in this case go ahead and apply access control. */
 	if (skb->dst != NULL && skb->dst->xfrm != NULL)
 		return NF_ACCEPT;
-
+#endif
 	secmark_active = selinux_secmark_enabled();
 	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
 	if (!secmark_active && !peerlbl_active)