Sfoglia il codice sorgente

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (173 commits)
  [NETNS]: Lookup in FIB semantic hashes taking into account the namespace.
  [NETNS]: Add a namespace mark to fib_info.
  [IPV4]: fib_sync_down rework.
  [NETNS]: Process interface address manipulation routines in the namespace.
  [IPV4]: Small style cleanup of the error path in rtm_to_ifaddr.
  [IPV4]: Fix memory leak on error path during FIB initialization.
  [NETFILTER]: Ipv6-related xt_hashlimit compilation fix.
  [NET_SCHED]: Add flow classifier
  [NET_SCHED]: sch_sfq: make internal queues visible as classes
  [NET_SCHED]: sch_sfq: add support for external classifiers
  [NET_SCHED]: Constify struct tcf_ext_map
  [BLUETOOTH]: Fix bugs in previous conn add/del workqueue changes.
  [TCP]: Unexport sysctl_tcp_tso_win_divisor
  [IPV4]: Make struct ipv4_devconf static.
  [TR] net/802/tr.c: sysctl_tr_rif_timeout static
  [XFRM]: Fix statistics.
  [XFRM]: Remove unused exports.
  [PKT_SCHED] sch_teql.c: Duplicate IFF_BROADCAST in FMASK, remove 2nd.
  [BNX2]: Fix ASYM PAUSE advertisement for remote PHY.
  [IPV4] route cache: Introduce rt_genid for smooth cache invalidation
  ...
Linus Torvalds 17 anni fa
parent
commit
cec03afcb6
100 ha cambiato i file con 5032 aggiunte e 1680 eliminazioni
  1. 0 5
      Documentation/filesystems/proc.txt
  2. 6 2
      Documentation/networking/xfrm_proc.txt
  3. 6 0
      MAINTAINERS
  4. 134 79
      drivers/net/bnx2.c
  5. 21 18
      drivers/net/bnx2.h
  6. 745 744
      drivers/net/bnx2_fw.h
  7. 232 232
      drivers/net/bnx2_fw2.h
  8. 1 1
      drivers/net/macvlan.c
  9. 1 2
      drivers/net/usb/asix.c
  10. 6 7
      drivers/net/usb/cdc_ether.c
  11. 1 2
      drivers/net/usb/cdc_subset.c
  12. 1 2
      drivers/net/usb/dm9601.c
  13. 1 2
      drivers/net/usb/gl620a.c
  14. 1 2
      drivers/net/usb/mcs7830.c
  15. 1 2
      drivers/net/usb/net1080.c
  16. 1 2
      drivers/net/usb/plusb.c
  17. 83 220
      drivers/net/usb/rndis_host.c
  18. 4 2
      drivers/net/usb/usbnet.c
  19. 1 2
      drivers/net/usb/zaurus.c
  20. 28 0
      drivers/net/wireless/Kconfig
  21. 2 0
      drivers/net/wireless/Makefile
  22. 5 5
      drivers/net/wireless/ath5k/base.c
  23. 103 21
      drivers/net/wireless/ath5k/debug.c
  24. 7 11
      drivers/net/wireless/ath5k/debug.h
  25. 26 4
      drivers/net/wireless/b43/dma.c
  26. 16 3
      drivers/net/wireless/b43/main.c
  27. 16 7
      drivers/net/wireless/b43/xmit.c
  28. 5 5
      drivers/net/wireless/b43/xmit.h
  29. 12 19
      drivers/net/wireless/b43legacy/b43legacy.h
  30. 88 45
      drivers/net/wireless/b43legacy/main.c
  31. 7 7
      drivers/net/wireless/b43legacy/phy.c
  32. 3 3
      drivers/net/wireless/b43legacy/pio.c
  33. 8 8
      drivers/net/wireless/b43legacy/radio.c
  34. 0 5
      drivers/net/wireless/hostap/hostap_80211.h
  35. 3 0
      drivers/net/wireless/hostap/hostap_cs.c
  36. 1 1
      drivers/net/wireless/iwlwifi/iwl-3945-hw.h
  37. 0 14
      drivers/net/wireless/iwlwifi/iwl-3945.c
  38. 0 2
      drivers/net/wireless/iwlwifi/iwl-3945.h
  39. 1 1
      drivers/net/wireless/iwlwifi/iwl-4965-hw.h
  40. 0 7
      drivers/net/wireless/iwlwifi/iwl-4965.c
  41. 0 1
      drivers/net/wireless/iwlwifi/iwl-4965.h
  42. 2 2
      drivers/net/wireless/iwlwifi/iwl-helpers.h
  43. 65 21
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  44. 61 23
      drivers/net/wireless/iwlwifi/iwl4965-base.c
  45. 4 2
      drivers/net/wireless/libertas/assoc.c
  46. 1 1
      drivers/net/wireless/libertas/dev.h
  47. 3 3
      drivers/net/wireless/libertas/if_cs.c
  48. 2757 0
      drivers/net/wireless/rndis_wlan.c
  49. 2 1
      drivers/net/wireless/rt2x00/rt61pci.c
  50. 1 0
      drivers/net/wireless/rtl8180_dev.c
  51. 2 0
      include/asm-alpha/socket.h
  52. 2 0
      include/asm-arm/socket.h
  53. 2 0
      include/asm-avr32/socket.h
  54. 3 0
      include/asm-blackfin/socket.h
  55. 2 0
      include/asm-cris/socket.h
  56. 2 0
      include/asm-frv/socket.h
  57. 2 0
      include/asm-h8300/socket.h
  58. 2 0
      include/asm-ia64/socket.h
  59. 2 0
      include/asm-m32r/socket.h
  60. 2 0
      include/asm-m68k/socket.h
  61. 2 0
      include/asm-mips/socket.h
  62. 2 0
      include/asm-parisc/socket.h
  63. 2 0
      include/asm-powerpc/socket.h
  64. 2 0
      include/asm-s390/socket.h
  65. 2 0
      include/asm-sh/socket.h
  66. 2 0
      include/asm-sparc/socket.h
  67. 1 0
      include/asm-sparc64/socket.h
  68. 2 0
      include/asm-v850/socket.h
  69. 2 0
      include/asm-x86/socket.h
  70. 2 0
      include/asm-xtensa/socket.h
  71. 0 2
      include/linux/inetdevice.h
  72. 2 0
      include/linux/input.h
  73. 10 2
      include/linux/ipv6.h
  74. 4 0
      include/linux/netdevice.h
  75. 1 1
      include/linux/netfilter/nf_conntrack_pptp.h
  76. 3 3
      include/linux/netfilter/nf_conntrack_sip.h
  77. 15 13
      include/linux/netfilter/x_tables.h
  78. 18 12
      include/linux/netfilter/xt_conntrack.h
  79. 32 5
      include/linux/netfilter/xt_hashlimit.h
  80. 2 2
      include/linux/netfilter/xt_owner.h
  81. 3 2
      include/linux/netfilter_arp/arp_tables.h
  82. 3 2
      include/linux/netfilter_ipv4/ip_tables.h
  83. 3 2
      include/linux/netfilter_ipv6/ip6_tables.h
  84. 1 1
      include/linux/netlink.h
  85. 6 0
      include/linux/pfkeyv2.h
  86. 50 0
      include/linux/pkt_cls.h
  87. 5 0
      include/linux/pkt_sched.h
  88. 2 0
      include/linux/rfkill.h
  89. 0 3
      include/linux/skbuff.h
  90. 2 1
      include/linux/snmp.h
  91. 2 2
      include/linux/sysctl.h
  92. 1 1
      include/linux/types.h
  93. 274 0
      include/linux/usb/rndis_host.h
  94. 12 0
      include/linux/usb/usbnet.h
  95. 8 0
      include/linux/xfrm.h
  96. 5 3
      include/net/arp.h
  97. 8 46
      include/net/esp.h
  98. 10 7
      include/net/inet6_hashtables.h
  99. 34 21
      include/net/inet_hashtables.h
  100. 3 1
      include/net/ip_fib.h

+ 0 - 5
Documentation/filesystems/proc.txt

@@ -1919,11 +1919,6 @@ max_size
 Maximum size  of  the routing cache. Old entries will be purged once the cache
 reached has this size.
 
-max_delay, min_delay
---------------------
-
-Delays for flushing the routing cache.
-
 redirect_load, redirect_number
 ------------------------------
 

+ 6 - 2
Documentation/networking/xfrm_proc.txt

@@ -26,8 +26,9 @@ XfrmInStateProtoError:
 	e.g. SA key is wrong
 XfrmInStateModeError:
 	Transformation mode specific error
-XfrmInSeqOutOfWindow:
-	Sequence out of window
+XfrmInStateSeqError:
+	Sequence error
+	i.e. Sequence number is out of window
 XfrmInStateExpired:
 	State is expired
 XfrmInStateMismatch:
@@ -60,6 +61,9 @@ XfrmOutStateProtoError:
 	Transformation protocol specific error
 XfrmOutStateModeError:
 	Transformation mode specific error
+XfrmOutStateSeqError:
+	Sequence error
+	i.e. Sequence number overflow
 XfrmOutStateExpired:
 	State is expired
 XfrmOutPolBlock:

+ 6 - 0
MAINTAINERS

@@ -4085,6 +4085,12 @@ L:	video4linux-list@redhat.com
 W:	http://www.linux-projects.org
 S:	Maintained
 
+USB WIRELESS RNDIS DRIVER (rndis_wlan)
+P:	Jussi Kivilinna
+M:	jussi.kivilinna@mbnet.fi
+L:	linux-wireless@vger.kernel.org
+S:	Maintained
+
 USB ZC0301 DRIVER
 P:	Luca Risolia
 M:	luca.risolia@studio.unibo.it

+ 134 - 79
drivers/net/bnx2.c

@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.7.2"
-#define DRV_MODULE_RELDATE	"January 21, 2008"
+#define DRV_MODULE_VERSION	"1.7.3"
+#define DRV_MODULE_RELDATE	"January 29, 2008"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -265,6 +265,18 @@ bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
 	spin_unlock_bh(&bp->indirect_lock);
 }
 
+static void
+bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val)
+{
+	bnx2_reg_wr_ind(bp, bp->shmem_base + offset, val);
+}
+
+static u32
+bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
+{
+	return (bnx2_reg_rd_ind(bp, bp->shmem_base + offset));
+}
+
 static void
 bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
 {
@@ -685,7 +697,7 @@ bnx2_report_fw_link(struct bnx2 *bp)
 	else
 		fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
 
-	REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
+	bnx2_shmem_wr(bp, BNX2_LINK_STATUS, fw_link_status);
 }
 
 static char *
@@ -980,6 +992,42 @@ bnx2_copper_linkup(struct bnx2 *bp)
 	return 0;
 }
 
+static void
+bnx2_init_rx_context0(struct bnx2 *bp)
+{
+	u32 val, rx_cid_addr = GET_CID_ADDR(RX_CID);
+
+	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
+	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
+	val |= 0x02 << 8;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		u32 lo_water, hi_water;
+
+		if (bp->flow_ctrl & FLOW_CTRL_TX)
+			lo_water = BNX2_L2CTX_LO_WATER_MARK_DEFAULT;
+		else
+			lo_water = BNX2_L2CTX_LO_WATER_MARK_DIS;
+		if (lo_water >= bp->rx_ring_size)
+			lo_water = 0;
+
+		hi_water = bp->rx_ring_size / 4;
+
+		if (hi_water <= lo_water)
+			lo_water = 0;
+
+		hi_water /= BNX2_L2CTX_HI_WATER_MARK_SCALE;
+		lo_water /= BNX2_L2CTX_LO_WATER_MARK_SCALE;
+
+		if (hi_water > 0xf)
+			hi_water = 0xf;
+		else if (hi_water == 0)
+			lo_water = 0;
+		val |= lo_water | (hi_water << BNX2_L2CTX_HI_WATER_MARK_SHIFT);
+	}
+	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
+}
+
 static int
 bnx2_set_mac_link(struct bnx2 *bp)
 {
@@ -1044,6 +1092,9 @@ bnx2_set_mac_link(struct bnx2 *bp)
 	/* Acknowledge the interrupt. */
 	REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
 
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_init_rx_context0(bp);
+
 	return 0;
 }
 
@@ -1378,14 +1429,14 @@ bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
 
 	if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
 		speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
-	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM))
+	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_PAUSE_ASYM))
 		speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
 
 	if (port == PORT_TP)
 		speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
 			     BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
 
-	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg);
+	bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg);
 
 	spin_unlock_bh(&bp->phy_lock);
 	bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0);
@@ -1530,9 +1581,9 @@ bnx2_set_default_remote_link(struct bnx2 *bp)
 	u32 link;
 
 	if (bp->phy_port == PORT_TP)
-		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK);
+		link = bnx2_shmem_rd(bp, BNX2_RPHY_COPPER_LINK);
 	else
-		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK);
+		link = bnx2_shmem_rd(bp, BNX2_RPHY_SERDES_LINK);
 
 	if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
 		bp->req_line_speed = 0;
@@ -1584,7 +1635,7 @@ bnx2_set_default_link(struct bnx2 *bp)
 
 		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
 
-		reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+		reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG);
 		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
 		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
 			bp->autoneg = 0;
@@ -1616,7 +1667,7 @@ bnx2_remote_phy_event(struct bnx2 *bp)
 	u8 link_up = bp->link_up;
 	u8 old_port;
 
-	msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+	msg = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
 
 	if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
 		bnx2_send_heart_beat(bp);
@@ -1693,7 +1744,7 @@ bnx2_set_remote_link(struct bnx2 *bp)
 {
 	u32 evt_code;
 
-	evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB);
+	evt_code = bnx2_shmem_rd(bp, BNX2_FW_EVT_CODE_MB);
 	switch (evt_code) {
 		case BNX2_FW_EVT_CODE_LINK_EVENT:
 			bnx2_remote_phy_event(bp);
@@ -1905,14 +1956,13 @@ bnx2_init_5708s_phy(struct bnx2 *bp)
 		bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
 	}
 
-	val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) &
+	val = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG) &
 	      BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
 
 	if (val) {
 		u32 is_backplane;
 
-		is_backplane = REG_RD_IND(bp, bp->shmem_base +
-					  BNX2_SHARED_HW_CFG_CONFIG);
+		is_backplane = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
 		if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
 			bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
 				       BCM5708S_BLK_ADDR_TX_MISC);
@@ -2111,13 +2161,13 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
 	bp->fw_wr_seq++;
 	msg_data |= bp->fw_wr_seq;
 
-	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+	bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
 
 	/* wait for an acknowledgement. */
 	for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
 		msleep(10);
 
-		val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
+		val = bnx2_shmem_rd(bp, BNX2_FW_MB);
 
 		if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
 			break;
@@ -2134,7 +2184,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
 		msg_data &= ~BNX2_DRV_MSG_CODE;
 		msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
 
-		REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+		bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
 
 		return -EBUSY;
 	}
@@ -2226,7 +2276,7 @@ bnx2_init_context(struct bnx2 *bp)
 
 			/* Zero out the context. */
 			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
-				CTX_WR(bp, vcid_addr, offset, 0);
+				bnx2_ctx_wr(bp, vcid_addr, offset, 0);
 		}
 	}
 }
@@ -2251,11 +2301,12 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
 	good_mbuf_cnt = 0;
 
 	/* Allocate a bunch of mbufs and save the good ones in an array. */
-	val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+	val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
 	while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
-		REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ);
+		bnx2_reg_wr_ind(bp, BNX2_RBUF_COMMAND,
+				BNX2_RBUF_COMMAND_ALLOC_REQ);
 
-		val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC);
+		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_FW_BUF_ALLOC);
 
 		val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
 
@@ -2265,7 +2316,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
 			good_mbuf_cnt++;
 		}
 
-		val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
 	}
 
 	/* Free the good ones back to the mbuf pool thus discarding
@@ -2276,7 +2327,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
 		val = good_mbuf[good_mbuf_cnt];
 		val = (val << 9) | val | 1;
 
-		REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val);
+		bnx2_reg_wr_ind(bp, BNX2_RBUF_FW_BUF_FREE, val);
 	}
 	kfree(good_mbuf);
 	return 0;
@@ -3151,10 +3202,10 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 	int rc;
 
 	/* Halt the CPU. */
-	val = REG_RD_IND(bp, cpu_reg->mode);
+	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
 	val |= cpu_reg->mode_value_halt;
-	REG_WR_IND(bp, cpu_reg->mode, val);
-	REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
+	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
 
 	/* Load the Text area. */
 	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
@@ -3167,7 +3218,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 			return rc;
 
 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, le32_to_cpu(fw->text[j]));
+			bnx2_reg_wr_ind(bp, offset, le32_to_cpu(fw->text[j]));
 	        }
 	}
 
@@ -3177,7 +3228,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 		int j;
 
 		for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, fw->data[j]);
+			bnx2_reg_wr_ind(bp, offset, fw->data[j]);
 		}
 	}
 
@@ -3187,7 +3238,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 		int j;
 
 		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, 0);
+			bnx2_reg_wr_ind(bp, offset, 0);
 		}
 	}
 
@@ -3197,7 +3248,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 		int j;
 
 		for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, 0);
+			bnx2_reg_wr_ind(bp, offset, 0);
 		}
 	}
 
@@ -3208,19 +3259,19 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 		int j;
 
 		for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, fw->rodata[j]);
+			bnx2_reg_wr_ind(bp, offset, fw->rodata[j]);
 		}
 	}
 
 	/* Clear the pre-fetch instruction. */
-	REG_WR_IND(bp, cpu_reg->inst, 0);
-	REG_WR_IND(bp, cpu_reg->pc, fw->start_addr);
+	bnx2_reg_wr_ind(bp, cpu_reg->inst, 0);
+	bnx2_reg_wr_ind(bp, cpu_reg->pc, fw->start_addr);
 
 	/* Start the CPU. */
-	val = REG_RD_IND(bp, cpu_reg->mode);
+	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
 	val &= ~cpu_reg->mode_value_halt;
-	REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
-	REG_WR_IND(bp, cpu_reg->mode, val);
+	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
+	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
 
 	return 0;
 }
@@ -3833,7 +3884,7 @@ bnx2_init_nvram(struct bnx2 *bp)
 	}
 
 get_flash_size:
-	val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
+	val = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG2);
 	val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
 	if (val)
 		bp->flash_size = val;
@@ -4142,14 +4193,14 @@ bnx2_init_remote_phy(struct bnx2 *bp)
 	if (!(bp->phy_flags & BNX2_PHY_FLAG_SERDES))
 		return;
 
-	val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB);
+	val = bnx2_shmem_rd(bp, BNX2_FW_CAP_MB);
 	if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
 		return;
 
 	if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
 		bp->phy_flags |= BNX2_PHY_FLAG_REMOTE_PHY_CAP;
 
-		val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+		val = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
 		if (val & BNX2_LINK_STATUS_SERDES_LINK)
 			bp->phy_port = PORT_FIBRE;
 		else
@@ -4167,8 +4218,7 @@ bnx2_init_remote_phy(struct bnx2 *bp)
 			}
 			sig = BNX2_DRV_ACK_CAP_SIGNATURE |
 			      BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
-			REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
-				   sig);
+			bnx2_shmem_wr(bp, BNX2_DRV_ACK_CAP_MB, sig);
 		}
 	}
 }
@@ -4204,8 +4254,8 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 
 	/* Deposit a driver reset signature so the firmware knows that
 	 * this is a soft reset. */
-	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
-		   BNX2_DRV_RESET_SIGNATURE_MAGIC);
+	bnx2_shmem_wr(bp, BNX2_DRV_RESET_SIGNATURE,
+		      BNX2_DRV_RESET_SIGNATURE_MAGIC);
 
 	/* Do a dummy read to force the chip to complete all current transaction
 	 * before we issue a reset. */
@@ -4438,18 +4488,21 @@ bnx2_init_chip(struct bnx2 *bp)
 	}
 
 	if (bp->flags & BNX2_FLAG_USING_MSIX) {
+		u32 base = ((BNX2_TX_VEC - 1) * BNX2_HC_SB_CONFIG_SIZE) +
+			   BNX2_HC_SB_CONFIG_1;
+
 		REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
 		       BNX2_HC_MSIX_BIT_VECTOR_VAL);
 
-		REG_WR(bp, BNX2_HC_SB_CONFIG_1,
+		REG_WR(bp, base,
 			BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
 			BNX2_HC_SB_CONFIG_1_ONE_SHOT);
 
-		REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP_1,
+		REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
 			(bp->tx_quick_cons_trip_int << 16) |
 			 bp->tx_quick_cons_trip);
 
-		REG_WR(bp, BNX2_HC_TX_TICKS_1,
+		REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
 			(bp->tx_ticks_int << 16) | bp->tx_ticks);
 
 		val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
@@ -4509,6 +4562,7 @@ static void
 bnx2_init_tx_context(struct bnx2 *bp, u32 cid)
 {
 	u32 val, offset0, offset1, offset2, offset3;
+	u32 cid_addr = GET_CID_ADDR(cid);
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
 		offset0 = BNX2_L2CTX_TYPE_XI;
@@ -4522,16 +4576,16 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid)
 		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
 	}
 	val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
-	CTX_WR(bp, GET_CID_ADDR(cid), offset0, val);
+	bnx2_ctx_wr(bp, cid_addr, offset0, val);
 
 	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
-	CTX_WR(bp, GET_CID_ADDR(cid), offset1, val);
+	bnx2_ctx_wr(bp, cid_addr, offset1, val);
 
 	val = (u64) bp->tx_desc_mapping >> 32;
-	CTX_WR(bp, GET_CID_ADDR(cid), offset2, val);
+	bnx2_ctx_wr(bp, cid_addr, offset2, val);
 
 	val = (u64) bp->tx_desc_mapping & 0xffffffff;
-	CTX_WR(bp, GET_CID_ADDR(cid), offset3, val);
+	bnx2_ctx_wr(bp, cid_addr, offset3, val);
 }
 
 static void
@@ -4601,36 +4655,38 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping,
 			     bp->rx_buf_use_size, bp->rx_max_ring);
 
-	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
+	bnx2_init_rx_context0(bp);
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
+		REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
+	}
+
+	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
 	if (bp->rx_pg_ring_size) {
 		bnx2_init_rxbd_rings(bp->rx_pg_desc_ring,
 				     bp->rx_pg_desc_mapping,
 				     PAGE_SIZE, bp->rx_max_pg_ring);
 		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
-		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
-		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
+		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
+		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
 		       BNX2_L2CTX_RBDC_JUMBO_KEY);
 
 		val = (u64) bp->rx_pg_desc_mapping[0] >> 32;
-		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
+		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
 
 		val = (u64) bp->rx_pg_desc_mapping[0] & 0xffffffff;
-		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
+		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
 
 		if (CHIP_NUM(bp) == CHIP_NUM_5709)
 			REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
 	}
 
-	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
-	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
-	val |= 0x02 << 8;
-	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
-
 	val = (u64) bp->rx_desc_mapping[0] >> 32;
-	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
+	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
 
 	val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
-	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
+	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
 
 	ring_prod = prod = bnapi->rx_pg_prod;
 	for (i = 0; i < bp->rx_pg_ring_size; i++) {
@@ -5003,9 +5059,9 @@ bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
 
 		for (offset = 0; offset < size; offset += 4) {
 
-			REG_WR_IND(bp, start + offset, test_pattern[i]);
+			bnx2_reg_wr_ind(bp, start + offset, test_pattern[i]);
 
-			if (REG_RD_IND(bp, start + offset) !=
+			if (bnx2_reg_rd_ind(bp, start + offset) !=
 				test_pattern[i]) {
 				return -ENODEV;
 			}
@@ -5315,7 +5371,7 @@ bnx2_5706_serdes_has_link(struct bnx2 *bp)
 	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
 	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
 
-	if (an_dbg & MISC_SHDW_AN_DBG_NOSYNC)
+	if (an_dbg & (MISC_SHDW_AN_DBG_NOSYNC | MISC_SHDW_AN_DBG_RUDI_INVALID))
 		return 0;
 
 	bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_REG1);
@@ -5440,7 +5496,8 @@ bnx2_timer(unsigned long data)
 
 	bnx2_send_heart_beat(bp);
 
-	bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+	bp->stats_blk->stat_FwRxDrop =
+		bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT);
 
 	/* workaround occasional corrupted counters */
 	if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
@@ -7155,20 +7212,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
 	bnx2_init_nvram(bp);
 
-	reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
+	reg = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_SIGNATURE);
 
 	if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
 	    BNX2_SHM_HDR_SIGNATURE_SIG) {
 		u32 off = PCI_FUNC(pdev->devfn) << 2;
 
-		bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0 + off);
+		bp->shmem_base = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_ADDR_0 + off);
 	} else
 		bp->shmem_base = HOST_VIEW_SHMEM_BASE;
 
 	/* Get the permanent MAC address.  First we need to make sure the
 	 * firmware is actually running.
 	 */
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE);
+	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE);
 
 	if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
 	    BNX2_DEV_INFO_SIGNATURE_MAGIC) {
@@ -7177,7 +7234,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 		goto err_out_unmap;
 	}
 
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV);
 	for (i = 0, j = 0; i < 3; i++) {
 		u8 num, k, skip0;
 
@@ -7191,7 +7248,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 		if (i != 2)
 			bp->fw_version[j++] = '.';
 	}
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE);
+	reg = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE);
 	if (reg & BNX2_PORT_FEATURE_WOL_ENABLED)
 		bp->wol = 1;
 
@@ -7199,34 +7256,33 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 		bp->flags |= BNX2_FLAG_ASF_ENABLE;
 
 		for (i = 0; i < 30; i++) {
-			reg = REG_RD_IND(bp, bp->shmem_base +
-					     BNX2_BC_STATE_CONDITION);
+			reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
 			if (reg & BNX2_CONDITION_MFW_RUN_MASK)
 				break;
 			msleep(10);
 		}
 	}
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION);
+	reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
 	reg &= BNX2_CONDITION_MFW_RUN_MASK;
 	if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
 	    reg != BNX2_CONDITION_MFW_RUN_NONE) {
 		int i;
-		u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR);
+		u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR);
 
 		bp->fw_version[j++] = ' ';
 		for (i = 0; i < 3; i++) {
-			reg = REG_RD_IND(bp, addr + i * 4);
+			reg = bnx2_reg_rd_ind(bp, addr + i * 4);
 			reg = swab32(reg);
 			memcpy(&bp->fw_version[j], &reg, 4);
 			j += 4;
 		}
 	}
 
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
+	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_UPPER);
 	bp->mac_addr[0] = (u8) (reg >> 8);
 	bp->mac_addr[1] = (u8) reg;
 
-	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER);
+	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_LOWER);
 	bp->mac_addr[2] = (u8) (reg >> 24);
 	bp->mac_addr[3] = (u8) (reg >> 16);
 	bp->mac_addr[4] = (u8) (reg >> 8);
@@ -7265,8 +7321,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 	bp->phy_port = PORT_TP;
 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
 		bp->phy_port = PORT_FIBRE;
-		reg = REG_RD_IND(bp, bp->shmem_base +
-				     BNX2_SHARED_HW_CFG_CONFIG);
+		reg = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
 		if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) {
 			bp->flags |= BNX2_FLAG_NO_WOL;
 			bp->wol = 0;

+ 21 - 18
drivers/net/bnx2.h

@@ -348,6 +348,12 @@ struct l2_fhdr {
 #define BNX2_L2CTX_BD_PRE_READ				0x00000000
 #define BNX2_L2CTX_CTX_SIZE				0x00000000
 #define BNX2_L2CTX_CTX_TYPE				0x00000000
+#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT		 32
+#define BNX2_L2CTX_LO_WATER_MARK_SCALE			 4
+#define BNX2_L2CTX_LO_WATER_MARK_DIS			 0
+#define BNX2_L2CTX_HI_WATER_MARK_SHIFT			 4
+#define BNX2_L2CTX_HI_WATER_MARK_SCALE			 16
+#define BNX2_L2CTX_WATER_MARKS_MSK			 0x000000ff
 #define BNX2_L2CTX_CTX_TYPE_SIZE_L2			 ((0x20/20)<<16)
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE		 (0xf<<28)
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED	 (0<<28)
@@ -4494,6 +4500,9 @@ struct l2_fhdr {
 #define BNX2_MQ_MAP_L2_3_ENA				 (0x1L<<31)
 #define BNX2_MQ_MAP_L2_3_DEFAULT			 0x82004646
 
+#define BNX2_MQ_MAP_L2_5				0x00003d34
+#define BNX2_MQ_MAP_L2_5_ARM				 (0x3L<<26)
+
 /*
  *  tsch_reg definition
  *  offset: 0x4c00
@@ -5510,6 +5519,15 @@ struct l2_fhdr {
 #define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS	 (0xffffL<<0)
 #define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
 
+#define BNX2_HC_SB_CONFIG_SIZE	(BNX2_HC_SB_CONFIG_2 - BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_COMP_PROD_TRIP_OFF	(BNX2_HC_COMP_PROD_TRIP_1 -	\
+					 BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_COM_TICKS_OFF	(BNX2_HC_COM_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_CMD_TICKS_OFF	(BNX2_HC_CMD_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_OFF	(BNX2_HC_TX_QUICK_CONS_TRIP_1 -	\
+					 BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_TX_TICKS_OFF	(BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+
 
 /*
  *  txp_reg definition
@@ -6346,11 +6364,12 @@ struct l2_fhdr {
 #define MII_BNX2_DSP_EXPAND_REG			 0x0f00
 #define MII_EXPAND_REG1				  (MII_BNX2_DSP_EXPAND_REG | 1)
 #define MII_EXPAND_REG1_RUDI_C			   0x20
-#define MII_EXPAND_SERDES_CTL			  (MII_BNX2_DSP_EXPAND_REG | 2)
+#define MII_EXPAND_SERDES_CTL			  (MII_BNX2_DSP_EXPAND_REG | 3)
 
 #define MII_BNX2_MISC_SHADOW			0x1c
 #define MISC_SHDW_AN_DBG			 0x6800
 #define MISC_SHDW_AN_DBG_NOSYNC			  0x0002
+#define MISC_SHDW_AN_DBG_RUDI_INVALID		  0x0100
 #define MISC_SHDW_MODE_CTL			 0x7c00
 #define MISC_SHDW_MODE_CTL_SIG_DET		  0x0010
 
@@ -6395,7 +6414,7 @@ struct l2_fhdr {
 
 #define RX_COPY_THRESH			128
 
-#define BNX2_MISC_ENABLE_DEFAULT	0x7ffffff
+#define BNX2_MISC_ENABLE_DEFAULT	0x17ffffff
 
 #define DMA_READ_CHANS	5
 #define DMA_WRITE_CHANS	3
@@ -6795,9 +6814,6 @@ struct bnx2 {
 	int			irq_nvecs;
 };
 
-static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
-static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val);
-
 #define REG_RD(bp, offset)					\
 	readl(bp->regview + offset)
 
@@ -6807,19 +6823,6 @@ static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val);
 #define REG_WR16(bp, offset, val)				\
 	writew(val, bp->regview + offset)
 
-#define REG_RD_IND(bp, offset)					\
-	bnx2_reg_rd_ind(bp, offset)
-
-#define REG_WR_IND(bp, offset, val)				\
-	bnx2_reg_wr_ind(bp, offset, val)
-
-/* Indirect context access.  Unlike the MBQ_WR, these macros will not
- * trigger a chip event. */
-static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val);
-
-#define CTX_WR(bp, cid_addr, offset, val)			\
-	bnx2_ctx_wr(bp, cid_addr, offset, val)
-
 struct cpu_reg {
 	u32 mode;
 	u32 mode_value_halt;

File diff suppressed because it is too large
+ 745 - 744
drivers/net/bnx2_fw.h


+ 232 - 232
drivers/net/bnx2_fw2.h

@@ -3173,250 +3173,250 @@ static struct fw_info bnx2_rxp_fw_09 = {
 };
 
 static u8 bnx2_xi_rv2p_proc1[] = {
-	/* Date:        12/07/2007 16:21 */
-	0xc5, 0x56, 0xcd, 0x6b, 0x13, 0x51, 0x10, 0x9f, 0xdd, 0xa4, 0xd9, 0x34,
-	0xd9, 0x64, 0x97, 0xaa, 0x25, 0xb4, 0x91, 0xa6, 0x55, 0x0f, 0x69, 0x23,
-	0xb6, 0xea, 0xc1, 0x43, 0xc1, 0xda, 0x8b, 0xa0, 0x9e, 0x7a, 0x10, 0xf1,
-	0xdb, 0x20, 0x05, 0xf1, 0x8f, 0x70, 0x51, 0xab, 0x20, 0x78, 0x28, 0x6a,
-	0xb0, 0x0a, 0xea, 0x49, 0x45, 0x3c, 0x34, 0x07, 0x41, 0x50, 0x14, 0x14,
-	0x3c, 0xe9, 0x4d, 0xf0, 0xe3, 0x50, 0x15, 0x3f, 0x0e, 0x7a, 0x13, 0x8f,
-	0xda, 0xf8, 0xde, 0xcc, 0xef, 0xd9, 0xdd, 0x4d, 0xd3, 0x14, 0x0f, 0xba,
-	0xd0, 0xfc, 0xfa, 0xde, 0x9b, 0x37, 0x6f, 0xe6, 0x37, 0xf3, 0x66, 0x9e,
-	0x4f, 0x44, 0x36, 0x05, 0xf5, 0x3e, 0x85, 0x94, 0xb5, 0x12, 0x69, 0x05,
-	0x16, 0xd1, 0x5d, 0x97, 0x31, 0xd8, 0x40, 0xf2, 0x0d, 0x09, 0x04, 0x43,
-	0xbe, 0xfa, 0xfd, 0x4e, 0x5b, 0x4b, 0x1a, 0x13, 0xb4, 0xb5, 0x5f, 0xe3,
-	0x36, 0x7a, 0x5c, 0x2a, 0x28, 0xfc, 0xd5, 0xa0, 0x40, 0x8f, 0xd7, 0xcc,
-	0xde, 0xaf, 0x67, 0x59, 0xef, 0x3b, 0xec, 0x7f, 0x9d, 0x10, 0xdc, 0x52,
-	0x49, 0x8b, 0x1e, 0x20, 0xad, 0xf7, 0x19, 0x5e, 0x4e, 0xeb, 0x71, 0xd1,
-	0x0a, 0xd6, 0xe3, 0x7c, 0x5b, 0xe6, 0xe7, 0xa6, 0x3d, 0x3d, 0x4f, 0xef,
-	0xc7, 0xf5, 0xd8, 0xcb, 0x9c, 0xae, 0xa7, 0x59, 0xaf, 0xac, 0x77, 0x65,
-	0x4e, 0xf3, 0x3e, 0xd7, 0x12, 0x7d, 0xea, 0x8f, 0xf7, 0x6f, 0x56, 0x7a,
-	0x60, 0x37, 0x89, 0x9e, 0x43, 0x25, 0x3d, 0x3f, 0x06, 0xb9, 0x51, 0xc8,
-	0x15, 0x9b, 0xe4, 0xe6, 0xa6, 0x35, 0x3a, 0x54, 0xad, 0x68, 0x7f, 0xfa,
-	0x95, 0xa1, 0xae, 0xf0, 0xd3, 0x27, 0xfe, 0x4e, 0xc2, 0xec, 0x77, 0x83,
-	0xfa, 0x1f, 0x65, 0xdb, 0xa0, 0x96, 0x9b, 0x53, 0x7e, 0x1b, 0x7f, 0x8d,
-	0xbc, 0xc8, 0x39, 0xac, 0xe7, 0xad, 0x5a, 0x37, 0x7e, 0x85, 0xfd, 0xc9,
-	0x86, 0xfc, 0x89, 0xf9, 0xd9, 0xe4, 0x57, 0x98, 0xa7, 0xf4, 0x22, 0x76,
-	0xeb, 0x73, 0x94, 0x0d, 0x7c, 0x4e, 0x0a, 0xfc, 0xa6, 0x62, 0xfb, 0x52,
-	0x2d, 0xf6, 0x7d, 0x6a, 0x2c, 0xf8, 0x69, 0xd6, 0xf5, 0xfc, 0xd3, 0x85,
-	0xf9, 0x72, 0x74, 0x5d, 0xfc, 0xef, 0x80, 0xff, 0x8f, 0xe0, 0xdf, 0x0e,
-	0x5a, 0x6b, 0x17, 0x78, 0x3d, 0xc9, 0xfb, 0x7b, 0x95, 0x3d, 0x1a, 0x57,
-	0x03, 0xfb, 0x81, 0x07, 0x81, 0x07, 0x80, 0xab, 0x80, 0x2b, 0x81, 0x2b,
-	0x80, 0x5d, 0xc0, 0xcb, 0x40, 0x1f, 0xe8, 0x01, 0xf3, 0xc0, 0x8b, 0x40,
-	0x17, 0x98, 0x05, 0xd6, 0x80, 0x57, 0x81, 0x69, 0xe0, 0x31, 0xe0, 0x23,
-	0xe0, 0x13, 0xe0, 0x37, 0xe0, 0x39, 0xa3, 0xcf, 0xc2, 0xb9, 0x40, 0x42,
-	0x3e, 0x58, 0x31, 0x9e, 0xae, 0x21, 0xef, 0x35, 0xcf, 0x58, 0x2f, 0x1b,
-	0x39, 0xc4, 0x97, 0x79, 0x9a, 0x81, 0x5c, 0xd7, 0xec, 0x8d, 0xd8, 0xfd,
-	0x28, 0xb5, 0xbd, 0x17, 0xf1, 0xb8, 0x79, 0xec, 0xcf, 0xe1, 0xed, 0x1e,
-	0x9f, 0x93, 0x4f, 0xc9, 0xbc, 0x31, 0x6b, 0x8f, 0x27, 0x78, 0x34, 0x23,
-	0xf8, 0x39, 0xd3, 0xa9, 0x7e, 0x1b, 0x8d, 0xc9, 0xac, 0x8c, 0x8f, 0xe4,
-	0x0c, 0xcf, 0x46, 0x8f, 0xb1, 0xa7, 0x9d, 0x1d, 0xad, 0xce, 0x33, 0x76,
-	0xb5, 0x3b, 0x57, 0xb0, 0x6a, 0x47, 0xfd, 0xbf, 0x32, 0x2c, 0x98, 0x1c,
-	0x61, 0xa8, 0xb8, 0xa9, 0xa4, 0xc6, 0xcd, 0xee, 0x33, 0x73, 0x8e, 0x46,
-	0xb7, 0x50, 0xe3, 0xfb, 0x92, 0xa4, 0x5a, 0x4a, 0xeb, 0xfd, 0xd9, 0x38,
-	0x2f, 0x72, 0x3d, 0x47, 0x5e, 0x30, 0x16, 0xae, 0x3c, 0x17, 0xf9, 0x57,
-	0x25, 0x97, 0x71, 0xf7, 0x10, 0xc5, 0x3e, 0xb3, 0x2e, 0xf7, 0x31, 0x60,
-	0xbb, 0x7f, 0x58, 0x41, 0xdd, 0x9c, 0x83, 0x7d, 0xc7, 0x4d, 0x1c, 0x7d,
-	0xb6, 0x73, 0x80, 0x64, 0x3c, 0x51, 0x96, 0xf5, 0x89, 0x32, 0xee, 0xf3,
-	0x40, 0x34, 0x1f, 0xe4, 0x5e, 0x24, 0x10, 0xef, 0x7d, 0xb8, 0x17, 0xf1,
-	0x7b, 0x9c, 0x9e, 0xbd, 0x31, 0x1d, 0xce, 0x97, 0x02, 0x55, 0x47, 0x60,
-	0x4f, 0x53, 0x9c, 0x4d, 0x3d, 0x36, 0xf9, 0xce, 0xd3, 0xb3, 0x41, 0x22,
-	0xc2, 0xdf, 0x18, 0x55, 0xc2, 0x71, 0xb2, 0x16, 0xc9, 0x97, 0x76, 0xe7,
-	0x44, 0xf4, 0xe5, 0x55, 0x04, 0xa8, 0x39, 0x8f, 0x1d, 0xf8, 0x35, 0x86,
-	0x3c, 0xee, 0x6d, 0xca, 0x63, 0x53, 0xe7, 0x25, 0x9f, 0x5b, 0xd5, 0xaf,
-	0xbf, 0xaf, 0xcf, 0x22, 0x17, 0x84, 0xf2, 0xd3, 0xd4, 0x43, 0xf0, 0xe4,
-	0xb0, 0x5c, 0x71, 0xee, 0x9e, 0xc4, 0x4d, 0xea, 0xb8, 0x4a, 0xc6, 0x20,
-	0x6a, 0xa7, 0x63, 0xfc, 0xeb, 0x0b, 0xd7, 0xc1, 0x75, 0x2d, 0xe2, 0x15,
-	0xae, 0xbb, 0x71, 0x5e, 0xa2, 0x79, 0x2f, 0xf1, 0xcf, 0x80, 0xa7, 0xde,
-	0x36, 0x75, 0xa1, 0x13, 0x72, 0xdd, 0x4b, 0xc8, 0x89, 0xde, 0xf1, 0x72,
-	0xb8, 0x8e, 0xf8, 0x0d, 0xd4, 0xc1, 0x3f, 0x71, 0x78, 0xd8, 0x22, 0x0e,
-	0xa3, 0xff, 0x37, 0x0e, 0xe8, 0xa7, 0xed, 0xe2, 0x40, 0xb1, 0x38, 0xfc,
-	0x98, 0x5f, 0x5e, 0x1c, 0x08, 0x3c, 0x51, 0x8b, 0x38, 0xa4, 0xc0, 0xd7,
-	0xd7, 0xf9, 0xa5, 0xe3, 0x90, 0x85, 0xdc, 0xe7, 0x90, 0x1c, 0xdb, 0x3d,
-	0x2a, 0xf7, 0xd4, 0xa9, 0x7e, 0x89, 0xf1, 0x3b, 0x52, 0xd1, 0xf5, 0xe7,
-	0x04, 0xd5, 0xe1, 0xff, 0x9b, 0x08, 0x0f, 0x39, 0x65, 0x9f, 0xbc, 0x23,
-	0x6e, 0xd7, 0x0d, 0x5f, 0xb2, 0x5c, 0xaa, 0x08, 0xde, 0x62, 0x79, 0x3f,
-	0xc4, 0x5b, 0x94, 0x5f, 0xe1, 0xcd, 0xa7, 0x9b, 0x7f, 0xea, 0x92, 0xc7,
-	0xfa, 0x86, 0x51, 0xd7, 0x0f, 0xa3, 0xbe, 0x7e, 0xc8, 0x48, 0xfd, 0xae,
-	0xee, 0xe4, 0x3a, 0x4b, 0xdd, 0xa8, 0xb3, 0xd5, 0x9c, 0x8c, 0x7b, 0x72,
-	0xf2, 0x6e, 0x19, 0x76, 0x5c, 0x96, 0xeb, 0xc9, 0x09, 0x76, 0x67, 0xf5,
-	0xbe, 0x02, 0x7d, 0xdc, 0xc5, 0xe2, 0x95, 0x19, 0x57, 0xea, 0xed, 0xcc,
-	0x73, 0xd4, 0x7f, 0xcf, 0xf0, 0x04, 0x7f, 0x37, 0xe9, 0xf9, 0x6e, 0x55,
-	0xef, 0xc2, 0xfc, 0x2a, 0x99, 0x41, 0xb1, 0xef, 0x3a, 0xac, 0x2f, 0x99,
-	0x7d, 0x7d, 0x9a, 0xcf, 0x07, 0xf3, 0xa6, 0xbf, 0x0c, 0x6c, 0xd7, 0xf6,
-	0x78, 0x94, 0x77, 0x24, 0x9e, 0x82, 0x4a, 0xce, 0x76, 0xf4, 0xb6, 0xe2,
-	0x94, 0x2d, 0xe3, 0xa9, 0x93, 0xac, 0x66, 0xd7, 0x94, 0x99, 0x1f, 0xe7,
-	0x44, 0x9e, 0xb8, 0xf3, 0x94, 0xe7, 0xf3, 0xf5, 0x84, 0xcc, 0x3b, 0x3b,
-	0x0d, 0x1f, 0x1e, 0xfb, 0x57, 0x13, 0x3e, 0xf6, 0x5f, 0x12, 0xdc, 0xab,
-	0x9e, 0x22, 0xfa, 0xcb, 0xd4, 0x5c, 0xe9, 0x3f, 0x33, 0x6e, 0x9a, 0x91,
-	0x98, 0x0f, 0x7b, 0xa3, 0xf4, 0x91, 0x0e, 0xd4, 0xff, 0xce, 0x50, 0x9c,
-	0xe2, 0x7d, 0x79, 0xb9, 0xf1, 0x0a, 0xf7, 0x0b, 0xd3, 0x47, 0xe2, 0x7d,
-	0x21, 0x87, 0x3c, 0xbb, 0xdc, 0x26, 0x1f, 0x4d, 0x9d, 0xbd, 0x80, 0x7b,
-	0xb0, 0x58, 0x3f, 0xd6, 0x98, 0x6f, 0xf1, 0x8e, 0x28, 0x22, 0xff, 0x4c,
-	0xdf, 0x5c, 0xec, 0xbd, 0x20, 0xf2, 0xcb, 0x7b, 0x27, 0xf8, 0x2d, 0xde,
-	0x09, 0xff, 0xec, 0x3d, 0x50, 0x58, 0x88, 0xa3, 0xc9, 0xd3, 0x70, 0x1c,
-	0xc3, 0xf9, 0x1a, 0xef, 0xd7, 0x4b, 0xf5, 0xe9, 0x3c, 0x78, 0x9e, 0x04,
-	0xcf, 0x49, 0xea, 0x48, 0x30, 0x31, 0x6e, 0xf2, 0x14, 0xeb, 0xb5, 0xa7,
-	0x6c, 0x16, 0x77, 0x3b, 0xce, 0x58, 0x1a, 0xf3, 0xee, 0x19, 0x91, 0x4b,
-	0xca, 0x7c, 0xc1, 0xe0, 0xd9, 0x53, 0xf2, 0x3e, 0xb4, 0xe9, 0x37, 0xf9,
-	0x0f, 0x65, 0x7b, 0x50, 0x0d, 0x00, 0x00, 0x00 };
+	/* Date:        01/14/2008 15:44 */
+	0xc5, 0x56, 0xcd, 0x6b, 0x13, 0x51, 0x10, 0x9f, 0xdd, 0x7c, 0x6c, 0x9a,
+	0x6c, 0xb2, 0xa1, 0x6a, 0x09, 0x35, 0xd2, 0x58, 0x7a, 0x30, 0x6d, 0xc4,
+	0x56, 0x3d, 0x78, 0x28, 0x54, 0x7a, 0x11, 0xac, 0xa7, 0x1e, 0x44, 0xc4,
+	0xcf, 0x20, 0x05, 0xf5, 0x8f, 0x70, 0x51, 0xab, 0x20, 0x78, 0x28, 0x68,
+	0xb4, 0x7e, 0xa0, 0x27, 0x15, 0xf1, 0x90, 0x1c, 0x04, 0x05, 0x45, 0x50,
+	0xf0, 0xa4, 0x37, 0x41, 0xbd, 0x54, 0xc5, 0x0f, 0xf0, 0xe2, 0x45, 0x8f,
+	0xda, 0xf8, 0xde, 0xcc, 0xef, 0xd9, 0xdd, 0x4d, 0xd2, 0x14, 0x0f, 0x1a,
+	0x68, 0x7f, 0xec, 0xdb, 0xdf, 0x9b, 0x37, 0xf3, 0x9b, 0x79, 0x33, 0x9b,
+	0x27, 0x22, 0x9b, 0xfc, 0xc6, 0x80, 0x42, 0x72, 0xad, 0x58, 0x4a, 0x81,
+	0x45, 0x74, 0xcf, 0x65, 0xf4, 0x37, 0x91, 0xfc, 0x46, 0x04, 0xfc, 0x91,
+	0xbc, 0xfa, 0xff, 0x9d, 0x26, 0x4a, 0x1a, 0x63, 0x34, 0xb1, 0x5e, 0xe3,
+	0x24, 0x3d, 0x29, 0x15, 0x14, 0xfe, 0x6a, 0x92, 0xaf, 0x9f, 0x87, 0xea,
+	0x0f, 0x1a, 0x19, 0xb6, 0xfb, 0x0e, 0xfb, 0xdf, 0xc4, 0x04, 0xb7, 0x55,
+	0x52, 0x62, 0x07, 0x48, 0x1b, 0xf3, 0x0c, 0xaf, 0xe6, 0xf4, 0x73, 0xd1,
+	0xf2, 0x37, 0xe2, 0x7c, 0x5b, 0xd6, 0x17, 0xe6, 0x3c, 0xbd, 0x4e, 0xef,
+	0x27, 0xf5, 0xb3, 0x97, 0x3e, 0xdd, 0x48, 0xb1, 0x5d, 0x79, 0xdf, 0x9b,
+	0x3e, 0xcd, 0xfb, 0x5c, 0x4b, 0xec, 0xa9, 0x3f, 0xde, 0xbf, 0x55, 0xd9,
+	0x81, 0xdf, 0x24, 0x76, 0x0e, 0x96, 0xf4, 0xfa, 0x76, 0xf0, 0xc6, 0xc1,
+	0x2b, 0xb6, 0xf0, 0x16, 0xe6, 0x34, 0x3a, 0x54, 0xad, 0xe8, 0x78, 0x06,
+	0x49, 0xe2, 0x49, 0xd0, 0x4c, 0xca, 0x15, 0x9d, 0x06, 0x84, 0xfd, 0x6e,
+	0x58, 0xef, 0x57, 0xbe, 0x0d, 0x6b, 0xde, 0x82, 0x8a, 0xdb, 0xc4, 0x1b,
+	0xe6, 0x39, 0x15, 0x63, 0x57, 0xf3, 0xde, 0x2a, 0x9e, 0x89, 0x2f, 0x18,
+	0x57, 0x26, 0x10, 0x57, 0x24, 0xde, 0x96, 0xf8, 0x82, 0x7a, 0xa5, 0xda,
+	0xf8, 0xaf, 0xcf, 0x51, 0xbe, 0xf0, 0x39, 0x49, 0xe8, 0x9c, 0x8c, 0xec,
+	0x4b, 0x76, 0x88, 0xfb, 0x93, 0x35, 0xb3, 0x21, 0xec, 0x3f, 0x91, 0xb6,
+	0xf7, 0x54, 0xf9, 0x8d, 0xf5, 0x72, 0x3b, 0x1d, 0x12, 0xd0, 0xe1, 0x31,
+	0xe2, 0x9b, 0xa2, 0x21, 0xbb, 0xc0, 0xef, 0xe3, 0xbc, 0x7f, 0xad, 0xf2,
+	0x47, 0xe3, 0x3a, 0xe0, 0x7a, 0xe0, 0x01, 0xe0, 0x7e, 0xe0, 0x1a, 0xe0,
+	0x6a, 0xe0, 0x2a, 0x60, 0x2f, 0xf0, 0x32, 0x30, 0x0f, 0xf4, 0x80, 0x39,
+	0xe0, 0x05, 0xa0, 0x0b, 0xcc, 0x00, 0x6b, 0xc0, 0xab, 0xc0, 0x14, 0xf0,
+	0x28, 0xf0, 0x21, 0xf0, 0x31, 0xf0, 0x0b, 0xf0, 0x1c, 0xd0, 0xb1, 0x60,
+	0x0f, 0xa8, 0x7e, 0x3e, 0xee, 0x47, 0x48, 0xa7, 0xeb, 0xa8, 0x7f, 0xad,
+	0x33, 0xde, 0x97, 0x0d, 0x0f, 0xf9, 0x65, 0x9d, 0x2e, 0x83, 0xd7, 0x5b,
+	0xbf, 0x19, 0xb9, 0x27, 0xa5, 0xae, 0xf7, 0x23, 0x9a, 0x37, 0x8f, 0xe3,
+	0x39, 0xb4, 0xc3, 0xe3, 0x73, 0x72, 0x49, 0x59, 0x37, 0x6e, 0xed, 0xf1,
+	0x04, 0x8f, 0xa4, 0x05, 0x3f, 0xa7, 0x7b, 0xd4, 0xff, 0x66, 0x73, 0x26,
+	0x23, 0xcf, 0x87, 0xb3, 0x46, 0x67, 0x63, 0xc7, 0xf8, 0xd3, 0xcd, 0x8f,
+	0x4e, 0xe7, 0x19, 0xbf, 0xba, 0x9d, 0x2b, 0x58, 0xb5, 0xc3, 0xf1, 0x5f,
+	0x19, 0x15, 0x8c, 0x8f, 0x31, 0x54, 0xdc, 0x64, 0x5c, 0xe3, 0x56, 0xf7,
+	0xb9, 0x39, 0x47, 0xa3, 0x5b, 0xa8, 0xf1, 0x7d, 0x89, 0x53, 0x2d, 0xa9,
+	0xed, 0xfe, 0x6c, 0x9e, 0x17, 0x5e, 0xff, 0xe1, 0x97, 0x8c, 0x85, 0x2b,
+	0x2f, 0x84, 0xff, 0xba, 0xe4, 0x32, 0xee, 0x1e, 0xa1, 0xc8, 0xcf, 0xbc,
+	0x97, 0xfb, 0xe8, 0xb3, 0xdf, 0x3f, 0x2c, 0xbf, 0x61, 0xce, 0xc1, 0xbe,
+	0xe3, 0x26, 0x8f, 0x79, 0xf6, 0x73, 0x90, 0xe4, 0x79, 0xba, 0x2c, 0xef,
+	0xa7, 0xcb, 0xb8, 0xcf, 0x83, 0xe1, 0x7a, 0x90, 0x7b, 0x11, 0x43, 0xbe,
+	0xf7, 0xe2, 0x5e, 0x44, 0xef, 0x71, 0xaa, 0x7e, 0x73, 0x2e, 0x58, 0x2f,
+	0x05, 0xaa, 0x8e, 0xc1, 0x9f, 0x96, 0x3c, 0x9b, 0xbe, 0x6c, 0xea, 0x9d,
+	0x97, 0xeb, 0x7e, 0x2c, 0xa4, 0xdf, 0x76, 0xaa, 0x04, 0xf3, 0x64, 0xb5,
+	0xa9, 0x97, 0x6e, 0xe7, 0x84, 0xec, 0xe5, 0x54, 0x06, 0xa8, 0xb5, 0x8e,
+	0x1d, 0xc4, 0x35, 0x81, 0x3a, 0x5e, 0xdb, 0x52, 0xc7, 0xa6, 0xdf, 0x4b,
+	0x3d, 0x77, 0xea, 0x5f, 0x7f, 0xdf, 0xa7, 0x85, 0xe7, 0x07, 0xea, 0xd3,
+	0xf4, 0x43, 0xe8, 0xe4, 0x30, 0xaf, 0xb8, 0x70, 0x5f, 0xf2, 0x26, 0xfd,
+	0x5c, 0x15, 0xa3, 0x1f, 0xf6, 0xd3, 0x31, 0xf1, 0x0d, 0x04, 0xfb, 0xe7,
+	0x50, 0x87, 0x7c, 0x05, 0xfb, 0x6e, 0x54, 0x97, 0x70, 0xdd, 0x4b, 0xfe,
+	0xd3, 0xd0, 0xa9, 0xbf, 0x4b, 0x5f, 0xe8, 0x01, 0x6f, 0xcd, 0x32, 0x3c,
+	0xb1, 0x3b, 0x59, 0x0e, 0xf6, 0x11, 0xaf, 0x89, 0xfe, 0x87, 0x7d, 0x7d,
+	0xf5, 0x47, 0x1d, 0xf2, 0x30, 0xfe, 0x7f, 0xf3, 0x80, 0xf9, 0x52, 0xb4,
+	0x24, 0x0f, 0x09, 0x5a, 0x99, 0xbe, 0x84, 0xf8, 0xa9, 0x83, 0xbe, 0x49,
+	0xe8, 0xf0, 0x6d, 0x71, 0x79, 0x7d, 0x33, 0xe0, 0x7d, 0x0d, 0xf0, 0xb8,
+	0x2e, 0xc6, 0xe5, 0xfe, 0x39, 0xd5, 0x2f, 0x11, 0xdd, 0xc6, 0x2a, 0xba,
+	0xaf, 0x9c, 0xa0, 0x06, 0xe2, 0x7a, 0x1b, 0x8a, 0x2f, 0xab, 0xfc, 0x93,
+	0xef, 0x84, 0x3b, 0x0d, 0xa3, 0x83, 0xbc, 0x2e, 0x55, 0x04, 0x6f, 0x33,
+	0x3f, 0x1f, 0xd0, 0x23, 0xac, 0x9b, 0xe8, 0x91, 0xa7, 0x5b, 0x7f, 0xfa,
+	0x8d, 0xc7, 0xf6, 0x46, 0xd1, 0xaf, 0x0f, 0xa1, 0x6f, 0x7e, 0x48, 0x4b,
+	0x5f, 0xae, 0x4e, 0x71, 0xff, 0xa4, 0x3e, 0xf4, 0xcf, 0x6a, 0x56, 0x9e,
+	0xfb, 0xb3, 0xf2, 0x1d, 0x36, 0xea, 0xb8, 0xcc, 0xeb, 0xcf, 0x0a, 0xf6,
+	0x65, 0xf4, 0xbe, 0x02, 0x7d, 0xdc, 0xc5, 0xf4, 0xca, 0xbc, 0x2b, 0x7d,
+	0x74, 0xfe, 0x05, 0xfa, 0xba, 0x67, 0x74, 0x42, 0xbc, 0x5b, 0xf4, 0x7a,
+	0x1f, 0x7f, 0xf2, 0x2c, 0xe9, 0xab, 0x38, 0xc3, 0xe2, 0xdf, 0x0d, 0x78,
+	0x5f, 0x32, 0xfb, 0x06, 0xb4, 0x9e, 0x4f, 0x16, 0xcd, 0xdc, 0x18, 0xdc,
+	0xa1, 0xfd, 0xf1, 0x28, 0xe7, 0x48, 0x3e, 0x05, 0x15, 0xcf, 0x76, 0xf4,
+	0xb6, 0xe2, 0xac, 0x2d, 0xcf, 0xb3, 0x27, 0xd9, 0xcc, 0xae, 0x59, 0xb3,
+	0x3e, 0xc9, 0x05, 0x3a, 0x7d, 0xf7, 0x19, 0xaf, 0xe7, 0x1a, 0x31, 0x59,
+	0x77, 0xa6, 0x8c, 0x1e, 0x1e, 0xc7, 0x57, 0x13, 0x3d, 0xf6, 0x5d, 0x14,
+	0xdc, 0x4b, 0x3b, 0x19, 0xd3, 0x35, 0x57, 0xe6, 0xca, 0xbc, 0x9b, 0x62,
+	0x24, 0xd6, 0xc3, 0xde, 0x2c, 0xf3, 0x21, 0x81, 0xbe, 0xde, 0x13, 0xc8,
+	0x53, 0x74, 0xde, 0xae, 0x34, 0x5f, 0xc1, 0x39, 0x60, 0xe6, 0x43, 0xb4,
+	0xdf, 0x67, 0x51, 0x67, 0xd7, 0xba, 0xd4, 0xa3, 0xe9, 0x9f, 0x97, 0x16,
+	0xe5, 0x1e, 0xb4, 0x9b, 0xb3, 0x1a, 0x73, 0x1d, 0xbe, 0x0f, 0x8a, 0xa8,
+	0x3f, 0x33, 0x0f, 0xdb, 0x7d, 0x07, 0x08, 0x7f, 0x65, 0xf3, 0x3f, 0xdf,
+	0x61, 0xfe, 0xff, 0xb3, 0x39, 0x5f, 0x58, 0xca, 0xa3, 0xa9, 0xd3, 0x60,
+	0x1e, 0x83, 0xf5, 0x1a, 0x9d, 0xc3, 0xcb, 0xcd, 0xdf, 0x1c, 0x74, 0x3e,
+	0x06, 0x9d, 0xe3, 0x94, 0x88, 0xb1, 0x30, 0x6e, 0xfc, 0x14, 0xdb, 0xb5,
+	0x67, 0x6d, 0xa6, 0xbb, 0x89, 0x33, 0x96, 0xc6, 0x9c, 0x7b, 0x46, 0x78,
+	0x71, 0x59, 0x2f, 0x18, 0x3c, 0x7b, 0x4a, 0xbe, 0xfb, 0x6c, 0xfa, 0x0d,
+	0x6d, 0x29, 0x98, 0xe1, 0x30, 0x0d, 0x00, 0x00, 0x00 };
 
 static u8 bnx2_xi_rv2p_proc2[] = {
-	/* Date:        12/07/2007 16:21 */
-	0xad, 0x58, 0x5d, 0x6c, 0xd3, 0x55, 0x14, 0xbf, 0xfd, 0x58, 0xdb, 0xb5,
+	/* Date:        01/14/2008 15:44 */
+	0xad, 0x58, 0x5d, 0x6c, 0xd3, 0x55, 0x14, 0xbf, 0xfd, 0x58, 0xdb, 0x75,
 	0xff, 0xb6, 0x63, 0x9b, 0xdd, 0xa7, 0x6e, 0x6e, 0x61, 0x6c, 0xd8, 0xcd,
 	0xd1, 0x8d, 0x4f, 0x4d, 0x5c, 0x86, 0x19, 0x20, 0x26, 0x8c, 0x61, 0xd4,
-	0x37, 0xd8, 0x90, 0xb2, 0xb1, 0x8d, 0x2c, 0x8c, 0xf0, 0xc0, 0x8b, 0x0d,
+	0x37, 0xd8, 0x90, 0xb2, 0xb2, 0x8d, 0x2c, 0x8c, 0xf0, 0xc0, 0x8b, 0x0d,
 	0xd3, 0xf1, 0xd2, 0x07, 0x47, 0xb2, 0x0d, 0x8d, 0xc1, 0x45, 0x7d, 0x40,
-	0x9f, 0xec, 0x83, 0x32, 0x30, 0xc6, 0xc4, 0xe8, 0x42, 0xf0, 0x01, 0x48,
+	0x9f, 0xec, 0x83, 0x52, 0x30, 0xc6, 0xc4, 0xe8, 0x42, 0xf0, 0x01, 0x48,
 	0x30, 0xc6, 0x68, 0x48, 0x08, 0xea, 0x32, 0x10, 0x75, 0x0c, 0xfb, 0x64,
-	0x98, 0xf7, 0x9e, 0xdf, 0xb9, 0xff, 0xfe, 0xff, 0x6d, 0x27, 0x18, 0xec,
+	0x98, 0xf7, 0x9e, 0xdf, 0xb9, 0xff, 0xfe, 0xff, 0x5d, 0x27, 0x18, 0xec,
 	0x43, 0x4f, 0xef, 0xbd, 0xe7, 0x9e, 0x7b, 0x3e, 0x7e, 0xe7, 0x9c, 0x7b,
-	0x5b, 0x24, 0x84, 0x70, 0x8a, 0x44, 0xaa, 0x46, 0x52, 0x11, 0x70, 0xb8,
-	0x04, 0x3e, 0x6b, 0x8b, 0x88, 0x5c, 0x4b, 0xf9, 0xe4, 0x77, 0x81, 0x78,
-	0xc9, 0x59, 0x4e, 0x63, 0xb7, 0x50, 0x34, 0x2c, 0x44, 0xc2, 0x4a, 0x4b,
-	0x98, 0x5e, 0x65, 0xfa, 0x3b, 0xd3, 0xc7, 0x1d, 0xa0, 0x57, 0x78, 0xbc,
-	0x85, 0xc7, 0xd7, 0x78, 0xfc, 0x23, 0xd3, 0x8d, 0x3c, 0xbf, 0x99, 0x69,
-	0x92, 0xe9, 0x76, 0x5e, 0x9f, 0x65, 0x2a, 0x3f, 0x09, 0x43, 0x7e, 0xc9,
-	0xe5, 0x26, 0xad, 0xa7, 0x81, 0xe9, 0x26, 0xe8, 0xbb, 0xa7, 0x56, 0xf1,
-	0x2d, 0x2c, 0x67, 0xf8, 0x30, 0x7f, 0x7d, 0x02, 0xb4, 0x06, 0xbb, 0x3e,
-	0x4e, 0x3c, 0xad, 0xf7, 0x83, 0xf4, 0x06, 0x41, 0xfb, 0xd8, 0xfe, 0x8e,
-	0x28, 0x91, 0xe4, 0x7e, 0x27, 0xc6, 0x5d, 0x0d, 0xca, 0x0f, 0xc5, 0xc2,
-	0xed, 0x54, 0x72, 0x5a, 0x7c, 0x9e, 0xf3, 0x98, 0x7f, 0x35, 0x0c, 0xfa,
-	0x9a, 0x1f, 0xf4, 0x17, 0x7f, 0xa1, 0xfc, 0x5e, 0x5e, 0x8e, 0x07, 0x58,
-	0xbe, 0xc1, 0x6a, 0x07, 0xb0, 0x7f, 0xce, 0x80, 0x1e, 0x2f, 0xd7, 0x42,
+	0x5b, 0x2c, 0x84, 0x70, 0x8a, 0x44, 0xaa, 0x56, 0x52, 0x61, 0x38, 0x5c,
+	0x02, 0x9f, 0xb5, 0xc5, 0x44, 0xae, 0xa5, 0x7c, 0xf2, 0xbb, 0x40, 0xbc,
+	0xe4, 0xac, 0xa0, 0xb1, 0x5b, 0x28, 0x1a, 0x12, 0x22, 0x61, 0xa5, 0xa5,
+	0x4c, 0xaf, 0x32, 0xfd, 0x9d, 0xe9, 0xe3, 0x0e, 0xd0, 0x2b, 0x3c, 0xde,
+	0xc2, 0xe3, 0x6b, 0x3c, 0xfe, 0x91, 0xe9, 0x46, 0x9e, 0xdf, 0xcc, 0x34,
+	0xc9, 0x74, 0x3b, 0xaf, 0xa7, 0x99, 0xca, 0x4f, 0xc2, 0x90, 0x5f, 0x72,
+	0xb9, 0x59, 0xeb, 0x69, 0x60, 0xba, 0x19, 0xfa, 0xee, 0xa9, 0x53, 0x7c,
+	0xf3, 0x4b, 0x59, 0x3e, 0xcc, 0x5f, 0x9f, 0x00, 0xad, 0xc5, 0xae, 0x8f,
+	0x13, 0x4f, 0xeb, 0xfd, 0x20, 0x7d, 0x01, 0xd0, 0x7e, 0xb6, 0xbf, 0x33,
+	0x42, 0x24, 0xb9, 0xdf, 0x89, 0x71, 0x77, 0xa3, 0xf2, 0x43, 0x89, 0x70,
+	0x3b, 0x95, 0x9c, 0x56, 0x9f, 0xe7, 0x3c, 0xe6, 0x5f, 0x0d, 0x81, 0xbe,
+	0xe6, 0x07, 0xfd, 0xc5, 0x5f, 0x28, 0xbf, 0x97, 0x96, 0x62, 0x45, 0x2c,
+	0xdf, 0x60, 0xb5, 0x8b, 0xb0, 0x7f, 0xd6, 0x80, 0x1e, 0x2f, 0xd7, 0x41,
 	0xbf, 0xef, 0x9f, 0x52, 0xf3, 0x2e, 0x91, 0x60, 0x39, 0x42, 0x68, 0x3d,
-	0x79, 0x7d, 0x10, 0xfb, 0x56, 0xad, 0xc1, 0xea, 0x5b, 0x71, 0x8c, 0xab,
-	0x3e, 0x28, 0xa2, 0xb8, 0x9c, 0x4e, 0x69, 0xfe, 0x7c, 0x72, 0xdd, 0x52,
-	0x2e, 0xe4, 0x8b, 0x3a, 0x1f, 0x29, 0x93, 0x88, 0x82, 0x8a, 0xe6, 0xec,
-	0x73, 0x20, 0x7f, 0x6a, 0xb5, 0x9a, 0x77, 0x8a, 0x1e, 0x97, 0x9a, 0xf7,
-	0x88, 0x9e, 0x01, 0xed, 0x5f, 0xac, 0xc7, 0x3d, 0x44, 0xca, 0x7b, 0xc7,
-	0x95, 0x9d, 0x61, 0xb1, 0xcf, 0x19, 0x26, 0x7e, 0xf8, 0xc5, 0xe5, 0x33,
-	0x3e, 0x03, 0xff, 0x97, 0x35, 0x06, 0xd9, 0x12, 0x6f, 0xc3, 0xbe, 0xd2,
-	0x18, 0xe8, 0x64, 0xac, 0x40, 0x91, 0x68, 0x7c, 0x94, 0x86, 0x2d, 0x37,
-	0xd7, 0xf9, 0x88, 0x2f, 0xd1, 0xac, 0xe3, 0xa7, 0xe3, 0xa5, 0xe2, 0xf8,
-	0x89, 0x8c, 0x23, 0xbb, 0xa5, 0x1e, 0x7e, 0xfd, 0x75, 0xb5, 0xe2, 0x97,
-	0xce, 0xad, 0xc3, 0x39, 0x19, 0xfd, 0xac, 0xf1, 0xff, 0xe8, 0x3f, 0xc4,
-	0x5f, 0xc9, 0xeb, 0x60, 0xbf, 0xd4, 0x4a, 0xbf, 0x28, 0x5a, 0xed, 0x48,
-	0x34, 0xdb, 0xe3, 0x71, 0x7d, 0x22, 0x4c, 0xbf, 0x6f, 0x75, 0x16, 0x91,
-	0x5f, 0x77, 0x61, 0xfe, 0x54, 0xd7, 0x39, 0xc4, 0x63, 0x07, 0xd9, 0x2f,
-	0xfc, 0x6f, 0x7c, 0x8a, 0x5d, 0xbd, 0x41, 0x35, 0x7e, 0xa5, 0x3d, 0x7e,
-	0x01, 0xeb, 0x05, 0x63, 0xf0, 0xeb, 0x2e, 0x96, 0xba, 0xc3, 0xe5, 0x50,
-	0x24, 0xe9, 0x19, 0xa3, 0xa1, 0x31, 0x47, 0xeb, 0x86, 0x38, 0x99, 0xc2,
-	0xfa, 0xe1, 0x80, 0x1a, 0xef, 0x8a, 0x2e, 0x60, 0x1c, 0x1d, 0x18, 0xe7,
-	0x8d, 0x4e, 0xf8, 0xe1, 0x96, 0x13, 0xf2, 0x18, 0x5e, 0x7e, 0x37, 0xc5,
-	0xc1, 0x21, 0x8c, 0x2e, 0xd0, 0x37, 0x69, 0xfd, 0x6f, 0x47, 0x92, 0xec,
-	0xee, 0x0a, 0xb9, 0xcf, 0x81, 0x91, 0x71, 0x6d, 0xe2, 0x56, 0xe3, 0xfe,
-	0x61, 0xf1, 0x3b, 0x6e, 0x68, 0xbc, 0xb2, 0xff, 0xd9, 0xbf, 0xef, 0x89,
-	0x6c, 0x9c, 0x82, 0x76, 0x35, 0x80, 0x7a, 0xea, 0xb3, 0xf1, 0xaa, 0xf1,
-	0x69, 0xf7, 0x33, 0xc7, 0xc7, 0x82, 0x17, 0x22, 0x12, 0x27, 0x36, 0xdc,
-	0x30, 0x4e, 0x2b, 0xa4, 0xbf, 0x74, 0xfc, 0x95, 0x20, 0xaf, 0x18, 0x64,
-	0x79, 0x03, 0x6c, 0xd7, 0x10, 0xdb, 0x75, 0xc7, 0xaf, 0xfd, 0xaa, 0xed,
-	0x01, 0x3d, 0x69, 0xb3, 0xc7, 0x21, 0xf1, 0x64, 0xc7, 0x21, 0xeb, 0x93,
-	0xfc, 0xa6, 0x0e, 0x3f, 0xaa, 0xea, 0x41, 0x4d, 0x3b, 0x1b, 0x14, 0x9f,
-	0x27, 0x36, 0x9d, 0xb2, 0xe3, 0x50, 0xe7, 0xe3, 0x9e, 0x5a, 0x2d, 0x5f,
-	0xe1, 0x32, 0x2d, 0x71, 0x89, 0xb8, 0x9d, 0x4e, 0x59, 0xf3, 0xb3, 0x32,
-	0x4f, 0x7e, 0xda, 0xf3, 0x42, 0xfb, 0xe5, 0x70, 0x90, 0x0a, 0x54, 0xfb,
-	0xe5, 0x79, 0xfb, 0x79, 0xc0, 0xb7, 0xd7, 0xc4, 0x4f, 0xe9, 0x06, 0xf6,
-	0x1f, 0xd3, 0xc8, 0x46, 0x25, 0xaf, 0x9b, 0xe5, 0xb7, 0xb2, 0x7c, 0xc3,
-	0x92, 0x77, 0x4a, 0xbf, 0x4e, 0x33, 0xdf, 0x74, 0xdc, 0x32, 0x79, 0xa7,
-	0xfd, 0x47, 0xe7, 0x47, 0x2f, 0xcf, 0xab, 0xfd, 0x55, 0x0f, 0xc8, 0xc3,
-	0x4d, 0xa6, 0xbc, 0xef, 0xcc, 0x7c, 0x53, 0xeb, 0x01, 0xf1, 0x1c, 0x0f,
-	0xed, 0xf5, 0xe4, 0x4f, 0x59, 0x4f, 0xc8, 0x0e, 0x9f, 0x71, 0x8e, 0xeb,
-	0xc7, 0xa8, 0x3a, 0xa7, 0x9c, 0xf5, 0x2e, 0x67, 0xbd, 0x65, 0xbf, 0x6a,
-	0xe6, 0x3a, 0xb3, 0xd7, 0x5a, 0x2f, 0xd6, 0x5a, 0xf2, 0x5e, 0x8d, 0x1b,
-	0x97, 0x73, 0xfb, 0x85, 0xcd, 0x9f, 0x09, 0x41, 0xfe, 0xf7, 0x72, 0x7c,
+	0x79, 0x7d, 0x10, 0xfb, 0x56, 0xad, 0xc1, 0xea, 0x5b, 0x31, 0x8c, 0xab,
+	0x3f, 0x28, 0xa6, 0xb8, 0x9c, 0x4e, 0x69, 0xfe, 0x7c, 0x72, 0xdd, 0x52,
+	0x2e, 0xe4, 0x8b, 0x7a, 0x1f, 0x29, 0x93, 0x88, 0x80, 0x8a, 0x96, 0xdc,
+	0x73, 0x20, 0x7f, 0x6a, 0xb5, 0x9a, 0x77, 0x8a, 0x5e, 0x97, 0x9a, 0xf7,
+	0x88, 0xde, 0xb8, 0xf6, 0x2f, 0xd6, 0x63, 0x1e, 0x22, 0x15, 0x7d, 0xe3,
+	0xca, 0xce, 0x90, 0xd8, 0xe7, 0x0c, 0x11, 0x3f, 0xfc, 0xe2, 0xf2, 0x19,
+	0x9f, 0x81, 0xff, 0xcb, 0x5a, 0x83, 0x6c, 0x89, 0xb5, 0x63, 0x5f, 0x59,
+	0x14, 0x74, 0x32, 0x5a, 0xa0, 0x48, 0x24, 0x36, 0x4a, 0xc3, 0xd6, 0x9b,
+	0xeb, 0x7c, 0xc4, 0x97, 0x68, 0xd1, 0xf1, 0xd3, 0xf1, 0x52, 0x71, 0xfc,
+	0x44, 0xc6, 0x91, 0xdd, 0xd2, 0x00, 0xbf, 0xfe, 0xba, 0x5a, 0xf1, 0x4b,
+	0xe7, 0xd6, 0xe3, 0x9c, 0xac, 0x7e, 0xd6, 0xf8, 0x7f, 0xf4, 0x1f, 0xe2,
+	0xaf, 0xe4, 0x75, 0xb2, 0x5f, 0xea, 0xa4, 0x5f, 0x14, 0xad, 0x71, 0x24,
+	0x5a, 0xec, 0xf1, 0xb8, 0x3e, 0x11, 0xa2, 0xdf, 0xb7, 0xba, 0x8a, 0xc9,
+	0xaf, 0xbb, 0x30, 0x7f, 0xaa, 0xfb, 0x1c, 0xe2, 0xb1, 0x83, 0xec, 0x17,
+	0xfe, 0x37, 0x3e, 0xc5, 0xae, 0xbe, 0x80, 0x1a, 0xbf, 0xd2, 0x11, 0xbb,
+	0x80, 0xf5, 0x82, 0x31, 0xf8, 0x75, 0x17, 0x4b, 0xdd, 0xe1, 0x72, 0x28,
+	0x92, 0xf4, 0x8c, 0xd1, 0xd0, 0x98, 0xa5, 0x75, 0x43, 0x9c, 0x4c, 0x61,
+	0xfd, 0x70, 0x91, 0x1a, 0xef, 0x8a, 0xcc, 0x63, 0x1c, 0x89, 0x8f, 0xf3,
+	0x46, 0x27, 0xfc, 0x70, 0xcb, 0x09, 0x79, 0x0c, 0x2f, 0xbf, 0x9b, 0xe2,
+	0xe0, 0x10, 0x46, 0x37, 0xe8, 0x9b, 0xb4, 0xfe, 0xb7, 0x23, 0x49, 0x76,
+	0x77, 0x07, 0xdd, 0xe7, 0xc0, 0xc8, 0xb8, 0x36, 0x71, 0xab, 0x71, 0xff,
+	0xb0, 0xf8, 0x1d, 0x37, 0x34, 0x5e, 0xd9, 0xff, 0xec, 0xdf, 0xf7, 0x44,
+	0x2e, 0x4e, 0x41, 0xbb, 0x1b, 0x41, 0x3d, 0x0d, 0xb9, 0x78, 0xd5, 0xf8,
+	0xb4, 0xfb, 0x99, 0xe3, 0x63, 0xc1, 0x0b, 0x11, 0x89, 0x13, 0x1b, 0x6e,
+	0x18, 0xa7, 0x95, 0xd2, 0x5f, 0x3a, 0xfe, 0x4a, 0x90, 0x57, 0x0c, 0xb2,
+	0xbc, 0x38, 0xdb, 0x35, 0xc4, 0x76, 0xdd, 0xf1, 0x6b, 0xbf, 0x6a, 0x7b,
+	0x40, 0x4f, 0xda, 0xec, 0x71, 0x48, 0x3c, 0xd9, 0x71, 0xc8, 0xfa, 0x24,
+	0xbf, 0xa9, 0xc7, 0x8f, 0xea, 0x06, 0x50, 0xd3, 0xce, 0x46, 0xc5, 0xe7,
+	0x89, 0x4e, 0xa7, 0xec, 0x38, 0xd4, 0xf9, 0xb8, 0xa7, 0x4e, 0xcb, 0x57,
+	0xb8, 0xcc, 0x48, 0x5c, 0x22, 0x6e, 0xa7, 0x53, 0xd6, 0xfc, 0xac, 0xca,
+	0x93, 0x9f, 0xf6, 0xbc, 0xd0, 0x7e, 0x39, 0x1c, 0xa0, 0x02, 0xd5, 0x71,
+	0x79, 0xce, 0x7e, 0x1e, 0xf0, 0xed, 0x35, 0xf1, 0x53, 0xb6, 0x81, 0xfd,
+	0xc7, 0x34, 0xbc, 0x51, 0xc9, 0xeb, 0x61, 0xf9, 0x6d, 0x2c, 0xdf, 0xb0,
+	0xe4, 0x9d, 0xd2, 0xaf, 0xcb, 0xcc, 0x37, 0x1d, 0xb7, 0x6c, 0xde, 0x69,
+	0xff, 0xd1, 0xf9, 0x91, 0xcb, 0x73, 0x6a, 0x7f, 0xf5, 0x03, 0xf2, 0x70,
+	0x93, 0x29, 0xef, 0x3b, 0x33, 0xdf, 0xd4, 0x7a, 0x91, 0x78, 0x8e, 0x87,
+	0xf6, 0x7a, 0xf2, 0xa7, 0xac, 0x27, 0x64, 0x87, 0xcf, 0x38, 0xc7, 0xf5,
+	0x63, 0x54, 0x9d, 0x53, 0xc1, 0x7a, 0x57, 0xb0, 0xde, 0xb2, 0x5f, 0xb5,
+	0x70, 0x9d, 0xd9, 0x6b, 0xad, 0x17, 0x6b, 0x2d, 0x79, 0xaf, 0xc6, 0x4d,
+	0x4b, 0xcb, 0xfb, 0x85, 0xcd, 0x9f, 0x09, 0x41, 0xfe, 0xf7, 0x72, 0x7c,
 	0x3c, 0x79, 0xfa, 0x8b, 0xe6, 0x07, 0xbe, 0xb6, 0x11, 0xbf, 0xcf, 0xc4,
-	0xbf, 0xdd, 0xde, 0xca, 0x3c, 0x75, 0x27, 0xdb, 0x7e, 0xf8, 0xb3, 0xd7,
-	0x19, 0x24, 0xbe, 0x1b, 0x23, 0x6a, 0xdf, 0x49, 0x87, 0xf6, 0x53, 0x07,
-	0xea, 0x90, 0x03, 0xf6, 0x56, 0xb3, 0xbd, 0x72, 0xb9, 0x99, 0xf0, 0xef,
+	0xbf, 0xdd, 0xde, 0xaa, 0x3c, 0x75, 0x27, 0xd7, 0x7e, 0xf8, 0xb3, 0xcf,
+	0x19, 0x20, 0xbe, 0x1b, 0x23, 0x6a, 0xdf, 0x49, 0x87, 0xf6, 0x53, 0x27,
+	0xea, 0x90, 0x03, 0xf6, 0xd6, 0xb0, 0xbd, 0x72, 0xb9, 0x85, 0xf0, 0xef,
 	0xbb, 0x31, 0x62, 0xb5, 0xd7, 0xf8, 0x97, 0xf3, 0xec, 0xb8, 0x19, 0xe1,
-	0x3e, 0xd6, 0x87, 0xbc, 0xf0, 0xed, 0xff, 0x5c, 0xeb, 0xc3, 0xe7, 0x86,
-	0xf5, 0xf9, 0x4a, 0x5e, 0x95, 0x98, 0x1f, 0x55, 0xfb, 0x1f, 0x13, 0x0c,
-	0x33, 0x31, 0xdc, 0x88, 0xfa, 0x77, 0xe7, 0x00, 0xf4, 0x1f, 0x6e, 0xd0,
+	0x3e, 0xd6, 0x8f, 0xbc, 0xf0, 0xed, 0xff, 0x5c, 0xeb, 0xc3, 0xe7, 0x86,
+	0xf4, 0xf9, 0x4a, 0x5e, 0xb5, 0x98, 0x1b, 0x55, 0xfb, 0x1f, 0x13, 0x0c,
+	0x33, 0x31, 0xdc, 0x84, 0xfa, 0x77, 0xe7, 0x00, 0xf4, 0x1f, 0x6e, 0xd4,
 	0x7d, 0x1c, 0x38, 0x16, 0x5c, 0xff, 0xbf, 0x9e, 0xc8, 0xe7, 0x97, 0x41,
-	0x07, 0xf8, 0x4a, 0xd9, 0xae, 0x22, 0xb6, 0x2b, 0x2a, 0xb2, 0xeb, 0xec,
-	0x5e, 0xca, 0x97, 0x0e, 0xe6, 0x7b, 0x56, 0xd7, 0xe3, 0x1c, 0x3e, 0xd8,
-	0x5f, 0xc0, 0xe7, 0xe7, 0xf3, 0x57, 0x3e, 0xb9, 0xb3, 0x8c, 0xa3, 0x7e,
-	0xe6, 0x73, 0xe7, 0xa9, 0xf3, 0x18, 0xa5, 0xd7, 0x50, 0x9d, 0x3f, 0x73,
-	0x7c, 0x56, 0xf1, 0x05, 0x4d, 0x9c, 0xdb, 0xed, 0xfa, 0xe9, 0xfe, 0xa3,
-	0xfb, 0x5f, 0xf1, 0x45, 0xc4, 0xc1, 0xd0, 0x4a, 0x7e, 0x76, 0xab, 0xe9,
-	0x99, 0xc5, 0x59, 0x1d, 0x27, 0x83, 0xec, 0x9c, 0x1f, 0x55, 0xe7, 0x7f,
-	0x98, 0xe5, 0x7f, 0xa7, 0xc5, 0xff, 0xe0, 0x7f, 0x22, 0xfa, 0xa8, 0x7e,
-	0xcf, 0xd7, 0x97, 0xbf, 0xb8, 0x9f, 0x9b, 0x27, 0x6a, 0xfe, 0xc2, 0x43,
-	0xfb, 0x63, 0x77, 0x9b, 0xd5, 0xfe, 0x7a, 0x31, 0x97, 0x42, 0x7e, 0x75,
-	0x33, 0x0e, 0xf7, 0x71, 0xbd, 0xbe, 0xe1, 0x57, 0x13, 0x3e, 0xd1, 0xb7,
-	0x93, 0xfc, 0x21, 0x22, 0x01, 0xf8, 0xa7, 0xef, 0x45, 0xed, 0x4f, 0xcc,
-	0x57, 0x52, 0xbf, 0x75, 0x89, 0x6e, 0xaf, 0x41, 0xfc, 0x95, 0x41, 0xd0,
-	0x08, 0xd7, 0xf9, 0x39, 0xb3, 0x8f, 0x81, 0x9e, 0xf6, 0xe8, 0xba, 0x8c,
-	0x7e, 0xfe, 0x95, 0x47, 0x31, 0xc8, 0x20, 0x35, 0xa1, 0x3e, 0x77, 0x36,
-	0x18, 0xb4, 0xde, 0xd3, 0x04, 0x3c, 0x89, 0x3a, 0xdd, 0xe7, 0xf0, 0xe1,
-	0x3e, 0x50, 0x99, 0xe9, 0x77, 0xd6, 0x7e, 0x58, 0x68, 0xe9, 0x07, 0xfa,
+	0x07, 0xf8, 0xca, 0xd8, 0xae, 0x62, 0xb6, 0x2b, 0x22, 0x72, 0xeb, 0xec,
+	0x5e, 0xca, 0x97, 0x4e, 0xe6, 0x7b, 0x56, 0xd7, 0xe3, 0x65, 0x7c, 0xb0,
+	0xbf, 0x80, 0xcf, 0xcf, 0xe7, 0xaf, 0x7c, 0x72, 0xd3, 0x8c, 0xa3, 0x01,
+	0xe6, 0x73, 0xe7, 0xa9, 0xf3, 0x18, 0x65, 0xd6, 0x50, 0x9d, 0x3f, 0x73,
+	0x3c, 0xad, 0xf8, 0x02, 0x26, 0xce, 0xed, 0x76, 0xfd, 0x74, 0xff, 0xd1,
+	0xfd, 0xaf, 0xf8, 0xc2, 0xe2, 0x60, 0x70, 0x25, 0x3f, 0xbb, 0xd5, 0xf4,
+	0xcc, 0x42, 0x5a, 0xc7, 0xc9, 0x20, 0x3b, 0xe7, 0x46, 0xd5, 0xf9, 0x1f,
+	0xe6, 0xf8, 0xdf, 0x69, 0xf1, 0x3f, 0xf8, 0x9f, 0x88, 0x3c, 0xaa, 0xdf,
+	0xf3, 0xf5, 0xe5, 0x2f, 0xee, 0x2f, 0xcf, 0x13, 0x35, 0x7f, 0xe1, 0xa1,
+	0xfd, 0xb1, 0xbb, 0xdd, 0x6a, 0x7f, 0x83, 0x98, 0x4d, 0x21, 0xbf, 0x7a,
+	0x18, 0x87, 0xfb, 0xb8, 0x5e, 0xdf, 0xf0, 0xab, 0x09, 0x9f, 0xe8, 0xdf,
+	0x49, 0xfe, 0x10, 0xe1, 0x22, 0xf8, 0xa7, 0xff, 0x45, 0xed, 0x4f, 0xcc,
+	0x57, 0x51, 0xbf, 0x75, 0x89, 0x1e, 0xaf, 0x41, 0xfc, 0x55, 0x01, 0xd0,
+	0x30, 0xd7, 0xf9, 0x59, 0xb3, 0x8f, 0x81, 0x9e, 0xf6, 0xe8, 0xba, 0x8c,
+	0x7e, 0xfe, 0x95, 0x47, 0x31, 0xc8, 0x20, 0x35, 0xa3, 0x3e, 0x77, 0x35,
+	0x1a, 0xb4, 0xde, 0xdb, 0x0c, 0x3c, 0x89, 0x7a, 0xdd, 0xe7, 0xf0, 0xe1,
+	0x3e, 0x50, 0x95, 0xed, 0x77, 0xd6, 0x7e, 0x58, 0x68, 0xe9, 0x07, 0xfa,
 	0x3c, 0xed, 0x47, 0x2d, 0x97, 0x86, 0xb2, 0xaf, 0x58, 0xfb, 0xa1, 0xee,
-	0x13, 0x4b, 0xdc, 0x27, 0x4a, 0xc4, 0xc5, 0x14, 0xec, 0x9a, 0x4b, 0x65,
-	0xe3, 0x4f, 0x9f, 0xa7, 0xe5, 0x41, 0x6f, 0x6d, 0x47, 0x46, 0x3e, 0xce,
-	0x3f, 0xc0, 0x7a, 0xfe, 0x4c, 0xf7, 0xd8, 0x08, 0xdb, 0xa3, 0xe4, 0x62,
-	0x7e, 0x3b, 0xf7, 0xe7, 0x84, 0x39, 0xb6, 0xf7, 0xd5, 0x6e, 0xd2, 0xab,
-	0x98, 0xf1, 0x16, 0xb1, 0xe4, 0x03, 0xf8, 0x4b, 0x5b, 0x41, 0x27, 0x5b,
-	0x75, 0x1c, 0x74, 0xbc, 0x74, 0x7c, 0x10, 0xc7, 0xc8, 0x3a, 0x62, 0x6b,
-	0xef, 0x5b, 0x47, 0x7d, 0xa4, 0xb5, 0x6f, 0x51, 0xe3, 0x0f, 0xfb, 0x77,
-	0x47, 0x15, 0xff, 0xeb, 0xe2, 0x2a, 0xe1, 0x50, 0x88, 0x1f, 0x98, 0x66,
-	0xfa, 0x15, 0x07, 0xc0, 0xcc, 0x57, 0x8e, 0x5f, 0x01, 0x4f, 0xb7, 0xe9,
-	0x7a, 0xae, 0xe3, 0x65, 0xcd, 0xd7, 0x78, 0x0e, 0x6e, 0x33, 0x75, 0x59,
-	0xdb, 0xa9, 0xf8, 0xa3, 0x8c, 0x47, 0x9f, 0xe8, 0xdc, 0x86, 0x7b, 0x6e,
-	0xc8, 0x8b, 0xba, 0x1f, 0xf2, 0x5a, 0xe3, 0x25, 0x71, 0x51, 0xe8, 0x55,
-	0xc3, 0xea, 0xe2, 0x42, 0xb2, 0xe7, 0xd4, 0xa5, 0x6f, 0x69, 0xf9, 0xfd,
-	0xe9, 0x00, 0xe6, 0xcb, 0x76, 0x86, 0xc9, 0x1f, 0x53, 0xc0, 0xf3, 0xbb,
-	0x93, 0xa0, 0xef, 0x88, 0x17, 0xb0, 0xbf, 0xf8, 0x04, 0xdd, 0x03, 0x7d,
-	0x65, 0x8c, 0xcf, 0x72, 0xd4, 0x89, 0xe4, 0x34, 0xdd, 0x4b, 0x96, 0x97,
-	0x45, 0x50, 0x51, 0x8f, 0xd9, 0x6f, 0x80, 0x4f, 0xb7, 0x25, 0xce, 0x0f,
-	0xc2, 0x2b, 0xdd, 0x2b, 0x25, 0x1e, 0xb1, 0x9d, 0x71, 0xeb, 0xcb, 0xc6,
-	0xad, 0xf6, 0x47, 0xb9, 0x33, 0x2f, 0x4e, 0x37, 0xd8, 0x71, 0xea, 0x61,
-	0x9c, 0xde, 0x33, 0xfb, 0x7b, 0xae, 0x5c, 0xf4, 0xf9, 0x8b, 0xff, 0x1b,
-	0x6e, 0x41, 0xb7, 0xd7, 0xab, 0xf3, 0xcb, 0x72, 0xea, 0x71, 0x8d, 0x2d,
-	0xce, 0x4d, 0xf7, 0xb5, 0x5e, 0x27, 0x3c, 0xd6, 0xf5, 0x66, 0xb3, 0x9f,
-	0x1d, 0xe1, 0x77, 0x5e, 0xda, 0xa0, 0x1f, 0xb1, 0x3b, 0x49, 0x1a, 0x1a,
-	0x15, 0x67, 0x15, 0x5f, 0x63, 0xec, 0x08, 0xd7, 0xdb, 0x4b, 0x2e, 0xd4,
-	0x9b, 0xfe, 0x03, 0x18, 0x5f, 0xe6, 0xfa, 0x71, 0x77, 0x0d, 0xd5, 0xe5,
-	0xd8, 0x91, 0xf3, 0x5a, 0x1e, 0xc9, 0x31, 0xd2, 0x5c, 0xd7, 0x9f, 0x77,
-	0x71, 0xbd, 0x25, 0xbf, 0xb9, 0x63, 0x7f, 0xd0, 0x7d, 0xc6, 0x2d, 0x3a,
-	0x9f, 0x54, 0xb4, 0x42, 0xd6, 0x6f, 0x3e, 0xff, 0x19, 0xd0, 0x1e, 0x2f,
-	0xa8, 0x68, 0xb2, 0xc7, 0x43, 0x98, 0x76, 0x61, 0xe4, 0xa9, 0x63, 0x39,
-	0xbd, 0x18, 0x7b, 0xf9, 0x5e, 0x36, 0xcd, 0x7e, 0x0a, 0x91, 0x3f, 0x8a,
-	0xa4, 0x9d, 0x8a, 0x86, 0x63, 0xa3, 0xb3, 0xd0, 0x7f, 0x68, 0x2b, 0xec,
-	0x5b, 0x62, 0xbb, 0x99, 0x86, 0xde, 0x1e, 0x23, 0xfc, 0x85, 0xc6, 0xf1,
-	0x0e, 0x09, 0x79, 0xc6, 0x60, 0xc7, 0x50, 0x1a, 0xe3, 0xa5, 0xcd, 0xa0,
-	0x7f, 0x6d, 0xc1, 0xbe, 0xa3, 0xc7, 0xd9, 0x1f, 0x5b, 0xf3, 0xef, 0xeb,
-	0xbf, 0x07, 0xbe, 0xe1, 0x46, 0x75, 0xfe, 0xe0, 0x0c, 0xbf, 0x5f, 0xc4,
-	0x80, 0x4b, 0x8d, 0x07, 0x8c, 0x34, 0x8f, 0x0f, 0x71, 0x7d, 0xbf, 0xcd,
-	0xef, 0x8d, 0xa1, 0xac, 0xf7, 0xc6, 0x02, 0xee, 0x99, 0x33, 0xe9, 0x24,
-	0x70, 0x91, 0x28, 0xcc, 0x7e, 0xaf, 0xaa, 0x71, 0x75, 0xac, 0x8c, 0xe3,
-	0x54, 0xba, 0x1e, 0x74, 0x72, 0x3d, 0xde, 0x09, 0x43, 0xc7, 0xd8, 0x2f,
-	0xed, 0x14, 0xa7, 0x96, 0xc5, 0xd9, 0x95, 0xde, 0xc9, 0xe0, 0x9b, 0xe2,
-	0x73, 0x23, 0xdc, 0x4f, 0x22, 0xc8, 0x3f, 0x51, 0x9e, 0xe4, 0x77, 0xcb,
-	0x04, 0xee, 0x9d, 0x53, 0x06, 0x68, 0x24, 0xa8, 0xf5, 0x45, 0x3e, 0x26,
-	0x52, 0xc8, 0x3b, 0xac, 0x3b, 0x2c, 0xeb, 0x7c, 0x1f, 0xc9, 0x79, 0xe7,
-	0x28, 0xba, 0xe4, 0x28, 0x71, 0x68, 0x3b, 0xb1, 0xda, 0x17, 0x54, 0xf8,
-	0xbd, 0x69, 0xe6, 0xd5, 0x02, 0xf9, 0xad, 0x6a, 0x26, 0x4d, 0xfa, 0x57,
-	0x8a, 0x12, 0xea, 0xc3, 0x15, 0xa1, 0x45, 0xf8, 0x31, 0x36, 0xcd, 0xfe,
-	0x1f, 0xd9, 0x04, 0x7a, 0x8c, 0xf1, 0xa7, 0x71, 0x75, 0x65, 0xa3, 0x41,
-	0xfb, 0xe6, 0x47, 0x71, 0x8e, 0xbe, 0x47, 0x64, 0xbf, 0xc7, 0x35, 0x1e,
-	0x2b, 0xda, 0x50, 0x48, 0xfb, 0x8f, 0xaa, 0x73, 0x82, 0x12, 0x47, 0x4a,
-	0x7f, 0xe9, 0x13, 0xce, 0x47, 0x3b, 0x4e, 0x15, 0x8e, 0x75, 0x7e, 0x58,
-	0xf1, 0x9d, 0x9d, 0xef, 0x19, 0xbc, 0x86, 0xe8, 0x5e, 0x2e, 0x8b, 0x5c,
-	0x82, 0xdf, 0x4d, 0x7c, 0x3f, 0x58, 0x29, 0x7e, 0x6f, 0x23, 0x7e, 0x31,
-	0xd6, 0xdb, 0x18, 0x18, 0x43, 0x5f, 0x1c, 0x67, 0x1c, 0x2d, 0x34, 0xf2,
-	0xfd, 0x87, 0xf5, 0xfb, 0x8d, 0xdf, 0x67, 0xc0, 0x9b, 0xd7, 0x88, 0xcf,
-	0x32, 0xbe, 0x18, 0xf7, 0x87, 0xd8, 0xee, 0xdb, 0xb0, 0xdb, 0xd0, 0x76,
-	0x0f, 0x98, 0x76, 0xeb, 0xfb, 0x95, 0x55, 0x4e, 0xb1, 0xc4, 0xad, 0xa2,
-	0xab, 0x8c, 0x2b, 0x54, 0xcf, 0x0a, 0xd8, 0x4e, 0xc9, 0xd7, 0xa6, 0xec,
-	0x09, 0xb1, 0x3d, 0x41, 0x71, 0xb0, 0xc5, 0xba, 0x2f, 0xc0, 0xfb, 0xfc,
-	0x72, 0x1f, 0xe6, 0x51, 0x17, 0x8c, 0x15, 0xfc, 0xa9, 0xfc, 0xa6, 0xe5,
-	0x66, 0xe7, 0xbd, 0xd5, 0x7f, 0x74, 0x23, 0xa5, 0x0f, 0xea, 0x9b, 0x8c,
-	0x53, 0x33, 0xfe, 0x3f, 0xd0, 0xf5, 0xed, 0x2e, 0xdd, 0x5f, 0xfd, 0x67,
-	0x86, 0x51, 0x9f, 0xce, 0x0c, 0x9f, 0xe5, 0x77, 0x07, 0xfb, 0xa5, 0x9b,
-	0xfe, 0xb7, 0x90, 0xb1, 0xab, 0xb3, 0xd7, 0x37, 0xbb, 0x1e, 0x55, 0x16,
-	0x3d, 0xf4, 0xb9, 0xff, 0x00, 0x0e, 0x4b, 0x7c, 0x26, 0x30, 0x14, 0x00,
+	0x13, 0x8b, 0xdc, 0x27, 0x4a, 0xc5, 0xc5, 0x14, 0xec, 0x9a, 0x4d, 0xe5,
+	0xe2, 0x4f, 0x9f, 0xa7, 0xe5, 0x41, 0x6f, 0x6d, 0x47, 0x56, 0x3e, 0xce,
+	0x3f, 0xc0, 0x7a, 0xfe, 0x4c, 0xf7, 0xd8, 0x30, 0xdb, 0xa3, 0xe4, 0x62,
+	0x7e, 0x3b, 0xf7, 0xe7, 0x84, 0x39, 0xb6, 0xf7, 0xd5, 0x1e, 0xd2, 0xab,
+	0x84, 0xf1, 0x16, 0xb6, 0xe4, 0x03, 0xf8, 0xcb, 0xda, 0x40, 0x27, 0xdb,
+	0x74, 0x1c, 0x74, 0xbc, 0x74, 0x7c, 0x10, 0xc7, 0xf0, 0x3a, 0x62, 0xeb,
+	0xe8, 0x5f, 0x47, 0x7d, 0xa4, 0xad, 0x7f, 0x41, 0xe3, 0x0f, 0xfb, 0x77,
+	0x47, 0x14, 0xff, 0xeb, 0xe2, 0x2a, 0xe1, 0x50, 0x88, 0x1f, 0x98, 0x66,
+	0xfb, 0x15, 0x07, 0xc0, 0xcc, 0x57, 0x8e, 0x5f, 0x01, 0x4f, 0xb7, 0xeb,
+	0x7a, 0xae, 0xe3, 0x65, 0xcd, 0xd7, 0xd8, 0x32, 0xdc, 0x66, 0xeb, 0xb2,
+	0xb6, 0x53, 0xf1, 0x47, 0x18, 0x8f, 0x3e, 0xd1, 0xb5, 0x0d, 0xf7, 0xdc,
+	0xa0, 0x17, 0x75, 0x3f, 0xe8, 0xb5, 0xc6, 0x4b, 0xe2, 0xa2, 0xd0, 0xab,
+	0x86, 0x35, 0x25, 0x85, 0x64, 0xcf, 0xa9, 0x4b, 0xdf, 0xd2, 0xf2, 0xfb,
+	0xd3, 0x45, 0x98, 0x2f, 0xdf, 0x19, 0x22, 0x7f, 0x4c, 0x01, 0xcf, 0xef,
+	0x4e, 0x82, 0xbe, 0x23, 0x5e, 0xc0, 0xfe, 0x92, 0x13, 0x74, 0x0f, 0xf4,
+	0x95, 0x33, 0x3e, 0x2b, 0x50, 0x27, 0x92, 0xd3, 0x74, 0x2f, 0x59, 0x5a,
+	0x12, 0x01, 0x45, 0x3d, 0x66, 0xbf, 0x01, 0x3e, 0xdd, 0x96, 0x38, 0x3f,
+	0x08, 0xaf, 0x74, 0xaf, 0x94, 0x78, 0xc4, 0x76, 0xc6, 0xad, 0x2f, 0x17,
+	0xb7, 0xda, 0x1f, 0x15, 0xce, 0xbc, 0x38, 0xdd, 0x60, 0xc7, 0xa9, 0x87,
+	0x71, 0x7a, 0xcf, 0xec, 0xef, 0xcb, 0xe5, 0xa2, 0xcf, 0x5f, 0xfc, 0xdf,
+	0x70, 0x0b, 0xba, 0xbd, 0x41, 0x9d, 0x5f, 0xbe, 0xac, 0x1e, 0xd7, 0xda,
+	0xe2, 0xdc, 0x7c, 0x5f, 0xeb, 0x75, 0xc2, 0x63, 0x5d, 0x6f, 0x31, 0xfb,
+	0xd9, 0x11, 0x7e, 0xe7, 0x65, 0x0c, 0xfa, 0x11, 0xbd, 0x93, 0xa4, 0xa1,
+	0x51, 0x79, 0x56, 0xf1, 0x35, 0x45, 0x8f, 0x70, 0xbd, 0xbd, 0xe4, 0x42,
+	0xbd, 0x19, 0x38, 0x80, 0xf1, 0x65, 0xae, 0x1f, 0x77, 0xd7, 0x50, 0x5d,
+	0x8e, 0x1e, 0x39, 0xaf, 0xe5, 0x91, 0x1c, 0x23, 0xc3, 0x75, 0xfd, 0x79,
+	0x17, 0xd7, 0x5b, 0xf2, 0x9b, 0x3b, 0xfa, 0x07, 0xdd, 0x67, 0xdc, 0xa2,
+	0xeb, 0x49, 0x45, 0x2b, 0x65, 0xfd, 0xe6, 0xf3, 0x9f, 0x01, 0xed, 0xf5,
+	0x82, 0x8a, 0x66, 0x7b, 0x3c, 0x84, 0x69, 0x17, 0x46, 0x9e, 0x7a, 0x96,
+	0xd3, 0x87, 0xb1, 0x97, 0xef, 0x65, 0xd3, 0xec, 0xa7, 0x20, 0xf9, 0xa3,
+	0x58, 0xda, 0xa9, 0x68, 0x28, 0x3a, 0x9a, 0x86, 0xfe, 0x43, 0x5b, 0x61,
+	0xdf, 0x22, 0xdb, 0xcd, 0x34, 0xf8, 0xf6, 0x18, 0xe1, 0x2f, 0x38, 0x8e,
+	0x77, 0x48, 0xd0, 0x33, 0x06, 0x3b, 0x86, 0x32, 0x18, 0x2f, 0x6e, 0x06,
+	0xfd, 0x6b, 0x0b, 0xf6, 0x1d, 0x3d, 0xce, 0xfe, 0xd8, 0x9a, 0x7f, 0xdf,
+	0xc0, 0x3d, 0xf0, 0x0d, 0x37, 0xa9, 0xf3, 0x07, 0x67, 0xf8, 0xfd, 0x22,
+	0xe2, 0x2e, 0x35, 0x8e, 0x1b, 0x19, 0x1e, 0x1f, 0xe2, 0xfa, 0x7e, 0x9b,
+	0xdf, 0x1b, 0x43, 0x39, 0xef, 0x8d, 0x79, 0xdc, 0x33, 0x67, 0x32, 0x49,
+	0xe0, 0x22, 0x51, 0x98, 0xfb, 0x5e, 0x55, 0xe3, 0x9a, 0x68, 0x39, 0xc7,
+	0xa9, 0x6c, 0x3d, 0xe8, 0xe4, 0x7a, 0xbc, 0x13, 0x86, 0x8e, 0xb1, 0x5f,
+	0x3a, 0x28, 0x4e, 0xad, 0x0b, 0xe9, 0x95, 0xde, 0xc9, 0xe0, 0x9b, 0xe2,
+	0x73, 0xc3, 0xdc, 0x4f, 0xc2, 0xc8, 0x3f, 0x51, 0x91, 0xe4, 0x77, 0xcb,
+	0x04, 0xee, 0x9d, 0x53, 0x06, 0x68, 0x38, 0xa0, 0xf5, 0x45, 0x3e, 0x26,
+	0x52, 0xc8, 0x3b, 0xac, 0x3b, 0x2c, 0xeb, 0x7c, 0x1f, 0x59, 0xf6, 0xce,
+	0x51, 0x74, 0xd1, 0x51, 0xea, 0xd0, 0x76, 0x62, 0xb5, 0x3f, 0xa0, 0xf0,
+	0x7b, 0xd3, 0xcc, 0xab, 0x79, 0xf2, 0x5b, 0xf5, 0x4c, 0x86, 0xf4, 0xaf,
+	0x12, 0xa5, 0xd4, 0x87, 0x2b, 0x83, 0x0b, 0xf0, 0x63, 0x74, 0x9a, 0xfd,
+	0x3f, 0xb2, 0x09, 0xf4, 0x18, 0xe3, 0x4f, 0xe3, 0xea, 0xca, 0x46, 0x83,
+	0xf6, 0xcd, 0x8d, 0xe2, 0x1c, 0x7d, 0x8f, 0xc8, 0x7d, 0x8f, 0x6b, 0x3c,
+	0x56, 0xb6, 0xa3, 0x90, 0x0e, 0x1c, 0x55, 0xe7, 0x04, 0x24, 0x8e, 0x94,
+	0xfe, 0xd2, 0x27, 0x9c, 0x8f, 0x76, 0x9c, 0x2a, 0x1c, 0xeb, 0xfc, 0xb0,
+	0xe2, 0x3b, 0x37, 0xdf, 0xb3, 0x78, 0x0d, 0xd2, 0xbd, 0x5c, 0x16, 0xb9,
+	0x04, 0xbf, 0x9b, 0xf8, 0x7e, 0xb0, 0x52, 0xfc, 0xde, 0x46, 0xfc, 0xa2,
+	0xac, 0xb7, 0x11, 0x1f, 0x43, 0x5f, 0x1c, 0x67, 0x1c, 0xcd, 0x37, 0xf1,
+	0xfd, 0x87, 0xf5, 0xfb, 0x8d, 0xdf, 0x67, 0xc0, 0x9b, 0xd7, 0x88, 0xa5,
+	0x19, 0x5f, 0x8c, 0xfb, 0x43, 0x6c, 0xf7, 0x6d, 0xd8, 0x6d, 0x68, 0xbb,
+	0xe3, 0xa6, 0xdd, 0xfa, 0x7e, 0x65, 0x95, 0x53, 0x22, 0x71, 0xab, 0xe8,
+	0x2a, 0xe3, 0x0a, 0xd5, 0xb3, 0x02, 0xb6, 0x53, 0xf2, 0xb5, 0x2b, 0x7b,
+	0x82, 0x6c, 0x4f, 0x40, 0x1c, 0x6c, 0xb5, 0xee, 0x2b, 0xe2, 0x7d, 0x7e,
+	0xb9, 0x0f, 0xf3, 0xa8, 0x0b, 0xc6, 0x0a, 0xfe, 0x54, 0x7e, 0xd3, 0x72,
+	0x73, 0xf3, 0xde, 0xea, 0x3f, 0xba, 0x91, 0xd2, 0x07, 0xf5, 0x4d, 0xc6,
+	0xa9, 0x05, 0xff, 0x1f, 0xe8, 0xfa, 0x76, 0x97, 0xee, 0xaf, 0xfe, 0x33,
+	0xc3, 0xa8, 0x4f, 0x67, 0x86, 0xcf, 0xf2, 0xbb, 0x83, 0xfd, 0xd2, 0x43,
+	0xff, 0x5b, 0xc8, 0xd8, 0xd5, 0xdb, 0xeb, 0x9b, 0x5d, 0x8f, 0x6a, 0x8b,
+	0x1e, 0xfa, 0xdc, 0x7f, 0x00, 0x5a, 0x33, 0xe6, 0xc0, 0x30, 0x14, 0x00,
 	0x00, 0x00 };
 
 static u8 bnx2_TPAT_b09FwText[] = {

+ 1 - 1
drivers/net/macvlan.c

@@ -508,7 +508,7 @@ static int __init macvlan_init_module(void)
 		goto err1;
 	return 0;
 err1:
-	macvlan_handle_frame_hook = macvlan_handle_frame;
+	macvlan_handle_frame_hook = NULL;
 	unregister_netdevice_notifier(&macvlan_notifier_block);
 	return err;
 }

+ 1 - 2
drivers/net/usb/asix.c

@@ -33,8 +33,7 @@
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 #define DRIVER_VERSION "14-Jun-2006"
 static const char driver_name [] = "asix";

+ 6 - 7
drivers/net/usb/cdc_ether.c

@@ -31,8 +31,7 @@
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 
 #if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
@@ -228,15 +227,16 @@ next_desc:
 		buf += buf [0];
 	}
 
-	/* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors,
-	 * so we'll hard-wire the interfaces and not check for descriptors.
+	/* Microsoft ActiveSync based and some regular RNDIS devices lack the
+	 * CDC descriptors, so we'll hard-wire the interfaces and not check
+	 * for descriptors.
 	 */
-	if (is_activesync(&intf->cur_altsetting->desc) && !info->u) {
+	if (rndis && !info->u) {
 		info->control = usb_ifnum_to_if(dev->udev, 0);
 		info->data = usb_ifnum_to_if(dev->udev, 1);
 		if (!info->control || !info->data) {
 			dev_dbg(&intf->dev,
-				"activesync: master #0/%p slave #1/%p\n",
+				"rndis: master #0/%p slave #1/%p\n",
 				info->control,
 				info->data);
 			goto bad_desc;
@@ -316,7 +316,6 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
 
-
 /*-------------------------------------------------------------------------
  *
  * Communications Device Class, Ethernet Control model

+ 1 - 2
drivers/net/usb/cdc_subset.c

@@ -26,8 +26,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 
 /*

+ 1 - 2
drivers/net/usb/dm9601.c

@@ -20,8 +20,7 @@
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 /* datasheet:
  http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf

+ 1 - 2
drivers/net/usb/gl620a.c

@@ -29,8 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 
 /*

+ 1 - 2
drivers/net/usb/mcs7830.c

@@ -31,8 +31,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/usb.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 /* requests */
 #define MCS7830_RD_BMREQ	(USB_DIR_IN  | USB_TYPE_VENDOR | \

+ 1 - 2
drivers/net/usb/net1080.c

@@ -28,11 +28,10 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/usb/usbnet.h>
 
 #include <asm/unaligned.h>
 
-#include "usbnet.h"
-
 
 /*
  * Netchip 1080 driver ... http://www.netchip.com

+ 1 - 2
drivers/net/usb/plusb.c

@@ -28,8 +28,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 
 /*

+ 83 - 220
drivers/net/usb/rndis_host.c

@@ -29,8 +29,8 @@
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
+#include <linux/usb/rndis_host.h>
 
 
 /*
@@ -55,218 +55,18 @@
  * currently rare) "Ethernet Emulation Model" (EEM).
  */
 
-/*
- * CONTROL uses CDC "encapsulated commands" with funky notifications.
- *  - control-out:  SEND_ENCAPSULATED
- *  - interrupt-in:  RESPONSE_AVAILABLE
- *  - control-in:  GET_ENCAPSULATED
- *
- * We'll try to ignore the RESPONSE_AVAILABLE notifications.
- *
- * REVISIT some RNDIS implementations seem to have curious issues still
- * to be resolved.
- */
-struct rndis_msg_hdr {
-	__le32	msg_type;			/* RNDIS_MSG_* */
-	__le32	msg_len;
-	// followed by data that varies between messages
-	__le32	request_id;
-	__le32	status;
-	// ... and more
-} __attribute__ ((packed));
-
-/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */
-#define	CONTROL_BUFFER_SIZE		1025
-
-/* RNDIS defines an (absurdly huge) 10 second control timeout,
- * but ActiveSync seems to use a more usual 5 second timeout
- * (which matches the USB 2.0 spec).
- */
-#define	RNDIS_CONTROL_TIMEOUT_MS	(5 * 1000)
-
-
-#define ccpu2 __constant_cpu_to_le32
-
-#define RNDIS_MSG_COMPLETION	ccpu2(0x80000000)
-
-/* codes for "msg_type" field of rndis messages;
- * only the data channel uses packet messages (maybe batched);
- * everything else goes on the control channel.
- */
-#define RNDIS_MSG_PACKET	ccpu2(0x00000001)	/* 1-N packets */
-#define RNDIS_MSG_INIT		ccpu2(0x00000002)
-#define RNDIS_MSG_INIT_C	(RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
-#define RNDIS_MSG_HALT		ccpu2(0x00000003)
-#define RNDIS_MSG_QUERY		ccpu2(0x00000004)
-#define RNDIS_MSG_QUERY_C	(RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
-#define RNDIS_MSG_SET		ccpu2(0x00000005)
-#define RNDIS_MSG_SET_C		(RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
-#define RNDIS_MSG_RESET		ccpu2(0x00000006)
-#define RNDIS_MSG_RESET_C	(RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
-#define RNDIS_MSG_INDICATE	ccpu2(0x00000007)
-#define RNDIS_MSG_KEEPALIVE	ccpu2(0x00000008)
-#define RNDIS_MSG_KEEPALIVE_C	(RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
-
-/* codes for "status" field of completion messages */
-#define	RNDIS_STATUS_SUCCESS		ccpu2(0x00000000)
-#define	RNDIS_STATUS_FAILURE		ccpu2(0xc0000001)
-#define	RNDIS_STATUS_INVALID_DATA	ccpu2(0xc0010015)
-#define	RNDIS_STATUS_NOT_SUPPORTED	ccpu2(0xc00000bb)
-#define	RNDIS_STATUS_MEDIA_CONNECT	ccpu2(0x4001000b)
-#define	RNDIS_STATUS_MEDIA_DISCONNECT	ccpu2(0x4001000c)
-
-
-struct rndis_data_hdr {
-	__le32	msg_type;		/* RNDIS_MSG_PACKET */
-	__le32	msg_len;		// rndis_data_hdr + data_len + pad
-	__le32	data_offset;		// 36 -- right after header
-	__le32	data_len;		// ... real packet size
-
-	__le32	oob_data_offset;	// zero
-	__le32	oob_data_len;		// zero
-	__le32	num_oob;		// zero
-	__le32	packet_data_offset;	// zero
-
-	__le32	packet_data_len;	// zero
-	__le32	vc_handle;		// zero
-	__le32	reserved;		// zero
-} __attribute__ ((packed));
-
-struct rndis_init {		/* OUT */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_INIT */
-	__le32	msg_len;			// 24
-	__le32	request_id;
-	__le32	major_version;			// of rndis (1.0)
-	__le32	minor_version;
-	__le32	max_transfer_size;
-} __attribute__ ((packed));
-
-struct rndis_init_c {		/* IN */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_INIT_C */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	status;
-	__le32	major_version;			// of rndis (1.0)
-	__le32	minor_version;
-	__le32	device_flags;
-	__le32	medium;				// zero == 802.3
-	__le32	max_packets_per_message;
-	__le32	max_transfer_size;
-	__le32	packet_alignment;		// max 7; (1<<n) bytes
-	__le32	af_list_offset;			// zero
-	__le32	af_list_size;			// zero
-} __attribute__ ((packed));
-
-struct rndis_halt {		/* OUT (no reply) */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_HALT */
-	__le32	msg_len;
-	__le32	request_id;
-} __attribute__ ((packed));
-
-struct rndis_query {		/* OUT */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_QUERY */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	oid;
-	__le32	len;
-	__le32	offset;
-/*?*/	__le32	handle;				// zero
-} __attribute__ ((packed));
-
-struct rndis_query_c {		/* IN */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_QUERY_C */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	status;
-	__le32	len;
-	__le32	offset;
-} __attribute__ ((packed));
-
-struct rndis_set {		/* OUT */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_SET */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	oid;
-	__le32	len;
-	__le32	offset;
-/*?*/	__le32	handle;				// zero
-} __attribute__ ((packed));
-
-struct rndis_set_c {		/* IN */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_SET_C */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	status;
-} __attribute__ ((packed));
-
-struct rndis_reset {		/* IN */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_RESET */
-	__le32	msg_len;
-	__le32	reserved;
-} __attribute__ ((packed));
-
-struct rndis_reset_c {		/* OUT */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_RESET_C */
-	__le32	msg_len;
-	__le32	status;
-	__le32	addressing_lost;
-} __attribute__ ((packed));
-
-struct rndis_indicate {		/* IN (unrequested) */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_INDICATE */
-	__le32	msg_len;
-	__le32	status;
-	__le32	length;
-	__le32	offset;
-/**/	__le32	diag_status;
-	__le32	error_offset;
-/**/	__le32	message;
-} __attribute__ ((packed));
-
-struct rndis_keepalive {	/* OUT (optionally IN) */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE */
-	__le32	msg_len;
-	__le32	request_id;
-} __attribute__ ((packed));
-
-struct rndis_keepalive_c {	/* IN (optionally OUT) */
-	// header and:
-	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE_C */
-	__le32	msg_len;
-	__le32	request_id;
-	__le32	status;
-} __attribute__ ((packed));
-
-/* NOTE:  about 30 OIDs are "mandatory" for peripherals to support ... and
- * there are gobs more that may optionally be supported.  We'll avoid as much
- * of that mess as possible.
- */
-#define OID_802_3_PERMANENT_ADDRESS	ccpu2(0x01010101)
-#define OID_GEN_MAXIMUM_FRAME_SIZE	ccpu2(0x00010106)
-#define OID_GEN_CURRENT_PACKET_FILTER	ccpu2(0x0001010e)
-
 /*
  * RNDIS notifications from device: command completion; "reverse"
  * keepalives; etc
  */
-static void rndis_status(struct usbnet *dev, struct urb *urb)
+void rndis_status(struct usbnet *dev, struct urb *urb)
 {
 	devdbg(dev, "rndis status urb, len %d stat %d",
 		urb->actual_length, urb->status);
 	// FIXME for keepalives, respond immediately (asynchronously)
 	// if not an RNDIS status, do like cdc_status(dev,urb) does
 }
+EXPORT_SYMBOL_GPL(rndis_status);
 
 /*
  * RPC done RNDIS-style.  Caller guarantees:
@@ -278,7 +78,7 @@ static void rndis_status(struct usbnet *dev, struct urb *urb)
  * Call context is likely probe(), before interface name is known,
  * which is why we won't try to use it in the diagnostics.
  */
-static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
+int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
 {
 	struct cdc_state	*info = (void *) &dev->data;
 	int			master_ifnum;
@@ -347,10 +147,26 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
 					request_id, xid);
 				/* then likely retry */
 			} else switch (buf->msg_type) {
-			case RNDIS_MSG_INDICATE: {	/* fault */
-				// struct rndis_indicate *msg = (void *)buf;
-				dev_info(&info->control->dev,
-					"rndis fault indication\n");
+			case RNDIS_MSG_INDICATE: {	/* fault/event */
+				struct rndis_indicate *msg = (void *)buf;
+				int state = 0;
+
+				switch (msg->status) {
+				case RNDIS_STATUS_MEDIA_CONNECT:
+					state = 1;
+				case RNDIS_STATUS_MEDIA_DISCONNECT:
+					dev_info(&info->control->dev,
+						"rndis media %sconnect\n",
+						!state?"dis":"");
+					if (dev->driver_info->link_change)
+						dev->driver_info->link_change(
+							dev, state);
+					break;
+				default:
+					dev_info(&info->control->dev,
+						"rndis indication: 0x%08x\n",
+						le32_to_cpu(msg->status));
+				}
 				}
 				break;
 			case RNDIS_MSG_KEEPALIVE: {	/* ping */
@@ -387,6 +203,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
 	dev_dbg(&info->control->dev, "rndis response timeout\n");
 	return -ETIMEDOUT;
 }
+EXPORT_SYMBOL_GPL(rndis_command);
 
 /*
  * rndis_query:
@@ -453,7 +270,8 @@ response_error:
 	return -EDOM;
 }
 
-static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
+int
+generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
 {
 	int			retval;
 	struct net_device	*net = dev->net;
@@ -467,8 +285,9 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 		struct rndis_query_c	*get_c;
 		struct rndis_set	*set;
 		struct rndis_set_c	*set_c;
+		struct rndis_halt	*halt;
 	} u;
-	u32			tmp;
+	u32			tmp, *phym;
 	int			reply_len;
 	unsigned char		*bp;
 
@@ -517,7 +336,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 				"dev can't take %u byte packets (max %u)\n",
 				dev->hard_mtu, tmp);
 			retval = -EINVAL;
-			goto fail_and_release;
+			goto halt_fail_and_release;
 		}
 		dev->hard_mtu = tmp;
 		net->mtu = dev->hard_mtu - net->hard_header_len;
@@ -533,13 +352,43 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 		dev->hard_mtu, tmp, dev->rx_urb_size,
 		1 << le32_to_cpu(u.init_c->packet_alignment));
 
+	/* module has some device initialization code needs to be done right
+	 * after RNDIS_INIT */
+	if (dev->driver_info->early_init &&
+			dev->driver_info->early_init(dev) != 0)
+		goto halt_fail_and_release;
+
+	/* Check physical medium */
+	reply_len = sizeof *phym;
+	retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM,
+			0, (void **) &phym, &reply_len);
+	if (retval != 0)
+		/* OID is optional so don't fail here. */
+		*phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
+	if ((flags & FLAG_RNDIS_PHYM_WIRELESS) &&
+			*phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
+		if (netif_msg_probe(dev))
+			dev_dbg(&intf->dev, "driver requires wireless "
+				"physical medium, but device is not.\n");
+		retval = -ENODEV;
+		goto halt_fail_and_release;
+	}
+	if ((flags & FLAG_RNDIS_PHYM_NOT_WIRELESS) &&
+			*phym == RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
+		if (netif_msg_probe(dev))
+			dev_dbg(&intf->dev, "driver requires non-wireless "
+				"physical medium, but device is wireless.\n");
+		retval = -ENODEV;
+		goto halt_fail_and_release;
+	}
+
 	/* Get designated host ethernet address */
 	reply_len = ETH_ALEN;
 	retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS,
 			48, (void **) &bp, &reply_len);
 	if (unlikely(retval< 0)) {
 		dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
-		goto fail_and_release;
+		goto halt_fail_and_release;
 	}
 	memcpy(net->dev_addr, bp, ETH_ALEN);
 
@@ -550,12 +399,12 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 	u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
 	u.set->len = ccpu2(4);
 	u.set->offset = ccpu2((sizeof *u.set) - 8);
-	*(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER);
+	*(__le32 *)(u.buf + sizeof *u.set) = RNDIS_DEFAULT_FILTER;
 
 	retval = rndis_command(dev, u.header);
 	if (unlikely(retval < 0)) {
 		dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
-		goto fail_and_release;
+		goto halt_fail_and_release;
 	}
 
 	retval = 0;
@@ -563,6 +412,11 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
 	kfree(u.buf);
 	return retval;
 
+halt_fail_and_release:
+	memset(u.halt, 0, sizeof *u.halt);
+	u.halt->msg_type = RNDIS_MSG_HALT;
+	u.halt->msg_len = ccpu2(sizeof *u.halt);
+	(void) rndis_command(dev, (void *)u.halt);
 fail_and_release:
 	usb_set_intfdata(info->data, NULL);
 	usb_driver_release_interface(driver_of(intf), info->data);
@@ -571,13 +425,19 @@ fail:
 	kfree(u.buf);
 	return retval;
 }
+EXPORT_SYMBOL_GPL(generic_rndis_bind);
+
+static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	return generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_NOT_WIRELESS);
+}
 
-static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
+void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct rndis_halt	*halt;
 
 	/* try to clear any rndis state/activity (no i/o from stack!) */
-	halt = kzalloc(sizeof *halt, GFP_KERNEL);
+	halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
 	if (halt) {
 		halt->msg_type = RNDIS_MSG_HALT;
 		halt->msg_len = ccpu2(sizeof *halt);
@@ -585,13 +445,14 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
 		kfree(halt);
 	}
 
-	return usbnet_cdc_unbind(dev, intf);
+	usbnet_cdc_unbind(dev, intf);
 }
+EXPORT_SYMBOL_GPL(rndis_unbind);
 
 /*
  * DATA -- host must not write zlps
  */
-static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	/* peripheral may have batched packets to us... */
 	while (likely(skb->len)) {
@@ -633,8 +494,9 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 	/* caller will usbnet_skb_return the remaining packet */
 	return 1;
 }
+EXPORT_SYMBOL_GPL(rndis_rx_fixup);
 
-static struct sk_buff *
+struct sk_buff *
 rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
 	struct rndis_data_hdr	*hdr;
@@ -679,6 +541,7 @@ fill:
 	/* FIXME make the last packet always be short ... */
 	return skb;
 }
+EXPORT_SYMBOL_GPL(rndis_tx_fixup);
 
 
 static const struct driver_info	rndis_info = {

+ 4 - 2
drivers/net/usb/usbnet.c

@@ -41,8 +41,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 #define DRIVER_VERSION		"22-Aug-2005"
 
@@ -1204,6 +1203,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 		if ((dev->driver_info->flags & FLAG_ETHER) != 0
 				&& (net->dev_addr [0] & 0x02) == 0)
 			strcpy (net->name, "eth%d");
+		/* WLAN devices should always be named "wlan%d" */
+		if ((dev->driver_info->flags & FLAG_WLAN) != 0)
+			strcpy(net->name, "wlan%d");
 
 		/* maybe the remote can't receive an Ethernet MTU */
 		if (net->mtu > (dev->hard_mtu - net->hard_header_len))

+ 1 - 2
drivers/net/usb/zaurus.c

@@ -29,8 +29,7 @@
 #include <linux/crc32.h>
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
-
-#include "usbnet.h"
+#include <linux/usb/usbnet.h>
 
 
 /*

+ 28 - 0
drivers/net/wireless/Kconfig

@@ -545,6 +545,34 @@ config USB_ZD1201
 	  To compile this driver as a module, choose M here: the
 	  module will be called zd1201.
 
+config USB_NET_RNDIS_WLAN
+	tristate "Wireless RNDIS USB support"
+	depends on USB && WLAN_80211 && EXPERIMENTAL
+	select USB_USBNET
+	select USB_NET_CDCETHER
+	select USB_NET_RNDIS_HOST
+	select WIRELESS_EXT
+	---help---
+	  This is a driver for wireless RNDIS devices.
+	  These are USB based adapters found in devices such as:
+
+	  Buffalo WLI-U2-KG125S
+	  U.S. Robotics USR5421
+	  Belkin F5D7051
+	  Linksys WUSB54GSv2
+	  Linksys WUSB54GSC
+	  Asus WL169gE
+	  Eminent EM4045
+	  BT Voyager 1055
+	  Linksys WUSB54GSv1
+	  U.S. Robotics USR5420
+	  BUFFALO WLI-USB-G54
+
+	  All of these devices are based on Broadcom 4320 chip which is the
+	  only wireless RNDIS chip known to date.
+
+	  If you choose to build a module, it'll be called rndis_wlan.
+
 config RTL8180
 	tristate "Realtek 8180/8185 PCI support"
 	depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL

+ 2 - 0
drivers/net/wireless/Makefile

@@ -44,6 +44,8 @@ obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
 obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
 
+obj-$(CONFIG_USB_NET_RNDIS_WLAN)	+= rndis_wlan.o
+
 obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 obj-$(CONFIG_LIBERTAS)		+= libertas/
 

+ 5 - 5
drivers/net/wireless/ath5k/base.c

@@ -1980,7 +1980,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	struct ath5k_buf *bf = sc->bbuf;
 	struct ath5k_hw *ah = sc->ah;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n");
+	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
 	if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
 			sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
@@ -1996,10 +1996,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	 */
 	if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
 		sc->bmisscount++;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 			"missed %u consecutive beacons\n", sc->bmisscount);
 		if (sc->bmisscount > 3) {		/* NB: 3 is a guess */
-			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 				"stuck beacon time (%u missed)\n",
 				sc->bmisscount);
 			tasklet_schedule(&sc->restq);
@@ -2007,7 +2007,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 		return;
 	}
 	if (unlikely(sc->bmisscount != 0)) {
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 			"resume beacon xmit after %u misses\n",
 			sc->bmisscount);
 		sc->bmisscount = 0;
@@ -2027,7 +2027,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 
 	ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
 	ath5k_hw_tx_start(ah, sc->bhalq);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n",
+	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
 		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
 
 	sc->bsent++;

+ 103 - 21
drivers/net/wireless/ath5k/debug.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
+ * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
  *
  *  This file is free software: you may copy, redistribute and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -200,7 +200,7 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
 {
 	struct ath5k_softc *sc = file->private_data;
 	char buf[100];
-	snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
+	snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
 	return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
 }
 
@@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file,
 				 size_t count, loff_t *ppos)
 {
 	struct ath5k_softc *sc = file->private_data;
-	if (strncmp(userbuf, "reset", 5) == 0) {
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	if (strncmp(buf, "reset", 5) == 0) {
 		ath5k_hw_reset_tsf(sc->ah);
 		printk(KERN_INFO "debugfs reset TSF\n");
 	}
@@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
 {
 	struct ath5k_softc *sc = file->private_data;
 	struct ath5k_hw *ah = sc->ah;
-	char buf[1000];
-	int len = 0;
+	char buf[500];
+	unsigned int len = 0;
 	unsigned int v;
 	u64 tsf;
 
@@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file,
 {
 	struct ath5k_softc *sc = file->private_data;
 	struct ath5k_hw *ah = sc->ah;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
 
-	if (strncmp(userbuf, "disable", 7) == 0) {
+	if (strncmp(buf, "disable", 7) == 0) {
 		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
 		printk(KERN_INFO "debugfs disable beacons\n");
-	} else if (strncmp(userbuf, "enable", 6) == 0) {
+	} else if (strncmp(buf, "enable", 6) == 0) {
 		AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
 		printk(KERN_INFO "debugfs enable beacons\n");
 	}
@@ -314,6 +323,82 @@ static const struct file_operations fops_reset = {
 };
 
 
+/* debugfs: debug level */
+
+static struct {
+	enum ath5k_debug_level level;
+	const char *name;
+	const char *desc;
+} dbg_info[] = {
+	{ ATH5K_DEBUG_RESET,	"reset",	"reset and initialization" },
+	{ ATH5K_DEBUG_INTR,	"intr",		"interrupt handling" },
+	{ ATH5K_DEBUG_MODE,	"mode",		"mode init/setup" },
+	{ ATH5K_DEBUG_XMIT,	"xmit",		"basic xmit operation" },
+	{ ATH5K_DEBUG_BEACON,	"beacon",	"beacon handling" },
+	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
+	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
+	{ ATH5K_DEBUG_LED,	"led",		"LED mamagement" },
+	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
+	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
+	{ ATH5K_DEBUG_DUMPMODES, "dumpmodes",	"dump modes" },
+	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
+	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
+};
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+	unsigned int i;
+
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
+		len += snprintf(buf+len, sizeof(buf)-len,
+			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+			sc->debug.level & dbg_info[i].level ? '+' : ' ',
+			dbg_info[i].level, dbg_info[i].desc);
+	}
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+		sc->debug.level == dbg_info[i].level ? '+' : ' ',
+		dbg_info[i].level, dbg_info[i].desc);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	unsigned int i;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
+		if (strncmp(buf, dbg_info[i].name,
+					strlen(dbg_info[i].name)) == 0) {
+			sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+			break;
+		}
+	}
+	return count;
+}
+
+static const struct file_operations fops_debug = {
+	.read = read_file_debug,
+	.write = write_file_debug,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
 /* init */
 
 void
@@ -326,26 +411,24 @@ void
 ath5k_debug_init_device(struct ath5k_softc *sc)
 {
 	sc->debug.level = ath5k_debug;
+
 	sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-			ath5k_global_debugfs);
-	sc->debug.debugfs_debug = debugfs_create_u32("debug",
-			0666, sc->debug.debugfs_phydir, &sc->debug.level);
+				ath5k_global_debugfs);
+
+	sc->debug.debugfs_debug = debugfs_create_file("debug", 0666,
+				sc->debug.debugfs_phydir, sc, &fops_debug);
 
 	sc->debug.debugfs_registers = debugfs_create_file("registers", 0444,
-				sc->debug.debugfs_phydir,
-				sc, &fops_registers);
+				sc->debug.debugfs_phydir, sc, &fops_registers);
 
 	sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666,
-				sc->debug.debugfs_phydir,
-				sc, &fops_tsf);
+				sc->debug.debugfs_phydir, sc, &fops_tsf);
 
 	sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666,
-				sc->debug.debugfs_phydir,
-				sc, &fops_beacon);
+				sc->debug.debugfs_phydir, sc, &fops_beacon);
 
 	sc->debug.debugfs_reset = debugfs_create_file("reset", 0222,
-				sc->debug.debugfs_phydir,
-				sc, &fops_reset);
+				sc->debug.debugfs_phydir, sc, &fops_reset);
 }
 
 void
@@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 	struct ath5k_buf *bf;
 	int status;
 
-	if (likely(!(sc->debug.level &
-	    (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL))))
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
 		return;
 
 	printk(KERN_DEBUG "rx queue %x, link %p\n",
@@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 	list_for_each_entry(bf, &sc->rxbuf, list) {
 		ds = bf->desc;
 		status = ah->ah_proc_rx_desc(ah, ds);
-		if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL))
+		if (!status)
 			ath5k_debug_printrxbuf(bf, status == 0);
 	}
 	spin_unlock_bh(&sc->rxbuflock);

+ 7 - 11
drivers/net/wireless/ath5k/debug.h

@@ -91,7 +91,6 @@ struct ath5k_dbg_info {
  * @ATH5K_DEBUG_MODE: mode init/setup
  * @ATH5K_DEBUG_XMIT: basic xmit operation
  * @ATH5K_DEBUG_BEACON: beacon handling
- * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc
  * @ATH5K_DEBUG_CALIBRATE: periodic calibration
  * @ATH5K_DEBUG_TXPOWER: transmit power setting
  * @ATH5K_DEBUG_LED: led management
@@ -99,7 +98,6 @@ struct ath5k_dbg_info {
  * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
  * @ATH5K_DEBUG_DUMPMODES: dump modes
  * @ATH5K_DEBUG_TRACE: trace function calls
- * @ATH5K_DEBUG_FATAL: fatal errors
  * @ATH5K_DEBUG_ANY: show at any debug level
  *
  * The debug level is used to control the amount and type of debugging output
@@ -115,15 +113,13 @@ enum ath5k_debug_level {
 	ATH5K_DEBUG_MODE	= 0x00000004,
 	ATH5K_DEBUG_XMIT	= 0x00000008,
 	ATH5K_DEBUG_BEACON	= 0x00000010,
-	ATH5K_DEBUG_BEACON_PROC	= 0x00000020,
-	ATH5K_DEBUG_CALIBRATE	= 0x00000100,
-	ATH5K_DEBUG_TXPOWER	= 0x00000200,
-	ATH5K_DEBUG_LED		= 0x00000400,
-	ATH5K_DEBUG_DUMP_RX	= 0x00001000,
-	ATH5K_DEBUG_DUMP_TX	= 0x00002000,
-	ATH5K_DEBUG_DUMPMODES	= 0x00004000,
-	ATH5K_DEBUG_TRACE	= 0x00010000,
-	ATH5K_DEBUG_FATAL	= 0x80000000,
+	ATH5K_DEBUG_CALIBRATE	= 0x00000020,
+	ATH5K_DEBUG_TXPOWER	= 0x00000040,
+	ATH5K_DEBUG_LED		= 0x00000080,
+	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
+	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
+	ATH5K_DEBUG_DUMPMODES	= 0x00000400,
+	ATH5K_DEBUG_TRACE	= 0x00001000,
 	ATH5K_DEBUG_ANY		= 0xffffffff
 };
 

+ 26 - 4
drivers/net/wireless/b43/dma.c

@@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 {
 	const struct b43_dma_ops *ops = ring->ops;
 	u8 *header;
-	int slot;
+	int slot, old_top_slot, old_used_slots;
 	int err;
 	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_meta *meta;
@@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 #define SLOTS_PER_PACKET  2
 	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
+	old_top_slot = ring->current_slot;
+	old_used_slots = ring->used_slots;
+
 	/* Get a slot for the header. */
 	slot = request_slot(ring);
 	desc = ops->idx2desc(ring, slot, &meta_hdr);
@@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 
 	header = &(ring->txhdr_cache[slot * hdrsize]);
 	cookie = generate_cookie(ring, slot);
-	b43_generate_txhdr(ring->dev, header,
-			   skb->data, skb->len, ctl, cookie);
+	err = b43_generate_txhdr(ring->dev, header,
+				 skb->data, skb->len, ctl, cookie);
+	if (unlikely(err)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return err;
+	}
 
 	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
 					   hdrsize, 1);
-	if (dma_mapping_error(meta_hdr->dmaaddr))
+	if (dma_mapping_error(meta_hdr->dmaaddr)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
 		return -EIO;
+	}
 	ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
 			     hdrsize, 1, 0, 0);
 
@@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 	if (dma_mapping_error(meta->dmaaddr)) {
 		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -ENOMEM;
 			goto out_unmap_hdr;
 		}
@@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 		meta->skb = skb;
 		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 		if (dma_mapping_error(meta->dmaaddr)) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -EIO;
 			goto out_free_bounce;
 		}
@@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev,
 	B43_WARN_ON(ring->stopped);
 
 	err = dma_tx_fragment(ring, skb, ctl);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		dev_kfree_skb_any(skb);
+		err = 0;
+		goto out_unlock;
+	}
 	if (unlikely(err)) {
 		b43err(dev->wl, "DMA tx mapping failure\n");
 		goto out_unlock;

+ 16 - 3
drivers/net/wireless/b43/main.c

@@ -3532,8 +3532,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	b43_bluetooth_coext_enable(dev);
 
 	ssb_bus_powerup(bus, 1);	/* Enable dynamic PCTL */
-	memset(wl->bssid, 0, ETH_ALEN);
-	memset(wl->mac_addr, 0, ETH_ALEN);
 	b43_upload_card_macaddress(dev);
 	b43_security_init(dev);
 	b43_rng_init(wl);
@@ -3630,6 +3628,15 @@ static int b43_op_start(struct ieee80211_hw *hw)
 	struct b43_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
+	bool do_rfkill_exit = 0;
+
+	/* Kill all old instance specific information to make sure
+	 * the card won't use it in the short timeframe between start
+	 * and mac80211 reconfiguring it. */
+	memset(wl->bssid, 0, ETH_ALEN);
+	memset(wl->mac_addr, 0, ETH_ALEN);
+	wl->filter_flags = 0;
+	wl->radiotap_enabled = 0;
 
 	/* First register RFkill.
 	 * LEDs that are registered later depend on it. */
@@ -3639,8 +3646,10 @@ static int b43_op_start(struct ieee80211_hw *hw)
 
 	if (b43_status(dev) < B43_STAT_INITIALIZED) {
 		err = b43_wireless_core_init(dev);
-		if (err)
+		if (err) {
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
+		}
 		did_init = 1;
 	}
 
@@ -3649,6 +3658,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
 		if (err) {
 			if (did_init)
 				b43_wireless_core_exit(dev);
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
@@ -3656,6 +3666,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
  out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
+	if (do_rfkill_exit)
+		b43_rfkill_exit(dev);
+
 	return err;
 }
 

+ 16 - 7
drivers/net/wireless/b43/xmit.c

@@ -178,12 +178,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
 }
 
 /* Generate a TX data header. */
-void b43_generate_txhdr(struct b43_wldev *dev,
-			u8 *_txhdr,
-			const unsigned char *fragment_data,
-			unsigned int fragment_len,
-			const struct ieee80211_tx_control *txctl,
-			u16 cookie)
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 *_txhdr,
+		       const unsigned char *fragment_data,
+		       unsigned int fragment_len,
+		       const struct ieee80211_tx_control *txctl,
+		       u16 cookie)
 {
 	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
 	const struct b43_phy *phy = &dev->phy;
@@ -237,7 +237,15 @@ void b43_generate_txhdr(struct b43_wldev *dev,
 
 		B43_WARN_ON(key_idx >= dev->max_nr_keys);
 		key = &(dev->key[key_idx]);
-		B43_WARN_ON(!key->keyconf);
+
+		if (unlikely(!key->keyconf)) {
+			/* This key is invalid. This might only happen
+			 * in a short timeframe after machine resume before
+			 * we were able to reconfigure keys.
+			 * Drop this packet completely. Do not transmit it
+			 * unencrypted to avoid leaking information. */
+			return -ENOKEY;
+		}
 
 		/* Hardware appends ICV. */
 		plcp_fragment_len += txctl->icv_len;
@@ -408,6 +416,7 @@ void b43_generate_txhdr(struct b43_wldev *dev,
 	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
 	txhdr->extra_ft = extra_ft;
 
+	return 0;
 }
 
 static s8 b43_rssi_postprocess(struct b43_wldev *dev,

+ 5 - 5
drivers/net/wireless/b43/xmit.h

@@ -174,11 +174,11 @@ size_t b43_txhdr_size(struct b43_wldev *dev)
 }
 
 
-void b43_generate_txhdr(struct b43_wldev *dev,
-			u8 * txhdr,
-			const unsigned char *fragment_data,
-			unsigned int fragment_len,
-			const struct ieee80211_tx_control *txctl, u16 cookie);
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 * txhdr,
+		       const unsigned char *fragment_data,
+		       unsigned int fragment_len,
+		       const struct ieee80211_tx_control *txctl, u16 cookie);
 
 /* Transmit Status */
 struct b43_txstatus {

+ 12 - 19
drivers/net/wireless/b43legacy/b43legacy.h

@@ -23,7 +23,7 @@
 #include "phy.h"
 
 
-#define B43legacy_IRQWAIT_MAX_RETRIES	100
+#define B43legacy_IRQWAIT_MAX_RETRIES	20
 
 #define B43legacy_RX_MAX_SSI		60 /* best guess at max ssi */
 
@@ -40,9 +40,8 @@
 #define B43legacy_MMIO_DMA4_IRQ_MASK	0x44
 #define B43legacy_MMIO_DMA5_REASON	0x48
 #define B43legacy_MMIO_DMA5_IRQ_MASK	0x4C
-#define B43legacy_MMIO_MACCTL		0x120
-#define B43legacy_MMIO_STATUS_BITFIELD	0x120
-#define B43legacy_MMIO_STATUS2_BITFIELD	0x124
+#define B43legacy_MMIO_MACCTL		0x120	/* MAC control */
+#define B43legacy_MMIO_MACCMD		0x124	/* MAC command */
 #define B43legacy_MMIO_GEN_IRQ_REASON	0x128
 #define B43legacy_MMIO_GEN_IRQ_MASK	0x12C
 #define B43legacy_MMIO_RAM_CONTROL	0x130
@@ -177,31 +176,25 @@
 #define B43legacy_RADIOCTL_ID		0x01
 
 /* MAC Control bitfield */
+#define B43legacy_MACCTL_ENABLED	0x00000001 /* MAC Enabled */
+#define B43legacy_MACCTL_PSM_RUN	0x00000002 /* Run Microcode */
+#define B43legacy_MACCTL_PSM_JMP0	0x00000004 /* Microcode jump to 0 */
+#define B43legacy_MACCTL_SHM_ENABLED	0x00000100 /* SHM Enabled */
 #define B43legacy_MACCTL_IHR_ENABLED	0x00000400 /* IHR Region Enabled */
+#define B43legacy_MACCTL_BE		0x00010000 /* Big Endian mode */
 #define B43legacy_MACCTL_INFRA		0x00020000 /* Infrastructure mode */
 #define B43legacy_MACCTL_AP		0x00040000 /* AccessPoint mode */
+#define B43legacy_MACCTL_RADIOLOCK	0x00080000 /* Radio lock */
 #define B43legacy_MACCTL_BEACPROMISC	0x00100000 /* Beacon Promiscuous */
 #define B43legacy_MACCTL_KEEP_BADPLCP	0x00200000 /* Keep bad PLCP frames */
 #define B43legacy_MACCTL_KEEP_CTL	0x00400000 /* Keep control frames */
 #define B43legacy_MACCTL_KEEP_BAD	0x00800000 /* Keep bad frames (FCS) */
 #define B43legacy_MACCTL_PROMISC	0x01000000 /* Promiscuous mode */
+#define B43legacy_MACCTL_HWPS		0x02000000 /* Hardware Power Saving */
+#define B43legacy_MACCTL_AWAKE		0x04000000 /* Device is awake */
+#define B43legacy_MACCTL_TBTTHOLD	0x10000000 /* TBTT Hold */
 #define B43legacy_MACCTL_GMODE		0x80000000 /* G Mode */
 
-/* StatusBitField */
-#define B43legacy_SBF_MAC_ENABLED	0x00000001
-#define B43legacy_SBF_CORE_READY	0x00000004
-#define B43legacy_SBF_400		0x00000400 /*FIXME: fix name*/
-#define B43legacy_SBF_XFER_REG_BYTESWAP	0x00010000
-#define B43legacy_SBF_MODE_NOTADHOC	0x00020000
-#define B43legacy_SBF_MODE_AP		0x00040000
-#define B43legacy_SBF_RADIOREG_LOCK	0x00080000
-#define B43legacy_SBF_MODE_MONITOR	0x00400000
-#define B43legacy_SBF_MODE_PROMISC	0x01000000
-#define B43legacy_SBF_PS1		0x02000000
-#define B43legacy_SBF_PS2		0x04000000
-#define B43legacy_SBF_NO_SSID_BCAST	0x08000000
-#define B43legacy_SBF_TIME_UPDATE	0x10000000
-
 /* 802.11 core specific TM State Low flags */
 #define B43legacy_TMSLOW_GMODE		0x20000000 /* G Mode Enable */
 #define B43legacy_TMSLOW_PLLREFSEL	0x00200000 /* PLL Freq Ref Select */

+ 88 - 45
drivers/net/wireless/b43legacy/main.c

@@ -225,8 +225,8 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset,
 
 	B43legacy_WARN_ON(offset % 4 != 0);
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	if (status & B43legacy_SBF_XFER_REG_BYTESWAP)
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	if (status & B43legacy_MACCTL_BE)
 		val = swab32(val);
 
 	b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset);
@@ -434,9 +434,9 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	status |= B43legacy_SBF_TIME_UPDATE;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status |= B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 }
 
@@ -444,9 +444,9 @@ static void b43legacy_time_unlock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	status &= ~B43legacy_SBF_TIME_UPDATE;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status &= ~B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 }
 
 static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)
@@ -647,7 +647,7 @@ void b43legacy_dummy_transmission(struct b43legacy_wldev *dev)
 		b43legacy_ram_write(dev, i * 4, buffer[i]);
 
 	/* dummy read follows */
-	b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 
 	b43legacy_write16(dev, 0x0568, 0x0000);
 	b43legacy_write16(dev, 0x07C0, 0x0000);
@@ -794,9 +794,9 @@ static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi)
 static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
 {
 	b43legacy_jssi_write(dev, 0x7F7F7F7F);
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 			  b43legacy_read32(dev,
-			  B43legacy_MMIO_STATUS2_BITFIELD)
+			  B43legacy_MMIO_MACCMD)
 			  | (1 << 4));
 	B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
 			    dev->phy.channel);
@@ -895,8 +895,8 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
 {
 	if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
 		return;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
-			  b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD)
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+			  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
 			  | 0x4);
 }
 
@@ -1106,9 +1106,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev)
 	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
 					    B43legacy_CCK_RATE_11MB);
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 	status |= 0x03;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status);
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
 }
 
 static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
@@ -1166,7 +1166,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
 		return;
 
 	dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 
 	if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
 		/* ACK beacon IRQ. */
@@ -1182,14 +1182,14 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
 		b43legacy_write_beacon_template(dev, 0x68, 0x18,
 						B43legacy_CCK_RATE_1MB);
 		status |= 0x1;
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 				  status);
 	}
 	if (!(status & 0x2)) {
 		b43legacy_write_beacon_template(dev, 0x468, 0x1A,
 						B43legacy_CCK_RATE_1MB);
 		status |= 0x2;
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 				  status);
 	}
 }
@@ -1548,9 +1548,20 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 	u16 fwpatch;
 	u16 fwdate;
 	u16 fwtime;
-	u32 tmp;
+	u32 tmp, macctl;
 	int err = 0;
 
+	/* Jump the microcode PSM to offset 0 */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN);
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+	/* Zero out all microcode PSM registers and shared memory. */
+	for (i = 0; i < 64; i++)
+		b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0);
+	for (i = 0; i < 4096; i += 2)
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0);
+
 	/* Upload Microcode. */
 	data = (__be32 *) (dev->fw.ucode->data + hdr_len);
 	len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
@@ -1581,7 +1592,12 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 
 	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
 			  B43legacy_IRQ_ALL);
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402);
+
+	/* Start the microcode PSM */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_JMP0;
+	macctl |= B43legacy_MACCTL_PSM_RUN;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
 	/* Wait for the microcode to load and respond */
 	i = 0;
@@ -1594,9 +1610,13 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 			b43legacyerr(dev->wl, "Microcode not responding\n");
 			b43legacy_print_fw_helptext(dev->wl);
 			err = -ENODEV;
-			goto out;
+			goto error;
+		}
+		msleep_interruptible(50);
+		if (signal_pending(current)) {
+			err = -EINTR;
+			goto error;
 		}
-		udelay(10);
 	}
 	/* dummy read follows */
 	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
@@ -1617,9 +1637,8 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 			     " is supported. You must change your firmware"
 			     " files.\n");
 		b43legacy_print_fw_helptext(dev->wl);
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0);
 		err = -EOPNOTSUPP;
-		goto out;
+		goto error;
 	}
 	b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u "
 	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
@@ -1629,7 +1648,14 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
 
-out:
+	return 0;
+
+error:
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
 	return err;
 }
 
@@ -1736,9 +1762,9 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
 	u32 mask;
 	u32 set;
 
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 			  b43legacy_read32(dev,
-			  B43legacy_MMIO_STATUS_BITFIELD)
+			  B43legacy_MMIO_MACCTL)
 			  & 0xFFFF3FFF);
 
 	b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
@@ -1798,14 +1824,14 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
 	B43legacy_WARN_ON(dev->mac_suspended < 0);
 	B43legacy_WARN_ON(irqs_disabled());
 	if (dev->mac_suspended == 0) {
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 				  b43legacy_read32(dev,
-				  B43legacy_MMIO_STATUS_BITFIELD)
-				  | B43legacy_SBF_MAC_ENABLED);
+				  B43legacy_MMIO_MACCTL)
+				  | B43legacy_MACCTL_ENABLED);
 		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
 				  B43legacy_IRQ_MAC_SUSPENDED);
 		/* the next two are dummy reads */
-		b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+		b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 		b43legacy_power_saving_ctl_bits(dev, -1, -1);
 
@@ -1836,10 +1862,10 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
 		dev->irq_savedstate = tmp;
 
 		b43legacy_power_saving_ctl_bits(dev, -1, 1);
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 				  b43legacy_read32(dev,
-				  B43legacy_MMIO_STATUS_BITFIELD)
-				  & ~B43legacy_SBF_MAC_ENABLED);
+				  B43legacy_MMIO_MACCTL)
+				  & ~B43legacy_MACCTL_ENABLED);
 		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 		for (i = 40; i; i--) {
 			tmp = b43legacy_read32(dev,
@@ -2007,12 +2033,15 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
 	struct b43legacy_phy *phy = &dev->phy;
 	int err;
 	int tmp;
-	u32 value32;
+	u32 value32, macctl;
 	u16 value16;
 
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
-			  B43legacy_SBF_CORE_READY
-			  | B43legacy_SBF_400);
+	/* Initialize the MAC control */
+	macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED;
+	if (dev->phy.gmode)
+		macctl |= B43legacy_MACCTL_GMODE;
+	macctl |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
 	err = b43legacy_request_firmware(dev);
 	if (err)
@@ -2052,12 +2081,12 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
 	if (dev->dev->id.revision < 5)
 		b43legacy_write32(dev, 0x010C, 0x01000000);
 
-	value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value32 &= ~B43legacy_SBF_MODE_NOTADHOC;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
-	value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value32 |= B43legacy_SBF_MODE_NOTADHOC;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 &= ~B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
 
 	if (b43legacy_using_pio(dev)) {
 		b43legacy_write32(dev, 0x0210, 0x00000100);
@@ -2951,12 +2980,19 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
 {
 	struct b43legacy_wl *wl = dev->wl;
 	struct b43legacy_phy *phy = &dev->phy;
+	u32 macctl;
 
 	B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED);
 	if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED)
 		return;
 	b43legacy_set_status(dev, B43legacy_STAT_UNINIT);
 
+	/* Stop the microcode PSM. */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
 	mutex_unlock(&wl->mutex);
 	/* Must unlock as it would otherwise deadlock. No races here.
 	 * Cancel possibly pending workqueues. */
@@ -3221,6 +3257,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 	struct b43legacy_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
+	bool do_rfkill_exit = 0;
 
 	/* First register RFkill.
 	 * LEDs that are registered later depend on it. */
@@ -3230,8 +3267,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 
 	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
 		err = b43legacy_wireless_core_init(dev);
-		if (err)
+		if (err) {
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
+		}
 		did_init = 1;
 	}
 
@@ -3240,6 +3279,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 		if (err) {
 			if (did_init)
 				b43legacy_wireless_core_exit(dev);
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
@@ -3247,6 +3287,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
+	if (do_rfkill_exit)
+		b43legacy_rfkill_exit(dev);
+
 	return err;
 }
 

+ 7 - 7
drivers/net/wireless/b43legacy/phy.c

@@ -140,7 +140,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev)
 {
 	struct b43legacy_phy *phy = &dev->phy;
 
-	b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); /* Dummy read. */
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */
 	if (phy->calibrated)
 		return;
 	if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) {
@@ -2231,16 +2231,16 @@ bit26 = 1;
 		 *	or the latest PS-Poll packet sent was successful,
 		 *	set bit26  */
 	}
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 	if (bit25)
-		status |= B43legacy_SBF_PS1;
+		status |= B43legacy_MACCTL_HWPS;
 	else
-		status &= ~B43legacy_SBF_PS1;
+		status &= ~B43legacy_MACCTL_HWPS;
 	if (bit26)
-		status |= B43legacy_SBF_PS2;
+		status |= B43legacy_MACCTL_AWAKE;
 	else
-		status &= ~B43legacy_SBF_PS2;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+		status &= ~B43legacy_MACCTL_AWAKE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	if (bit26 && dev->dev->id.revision >= 5) {
 		for (i = 0; i < 100; i++) {
 			if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,

+ 3 - 3
drivers/net/wireless/b43legacy/pio.c

@@ -334,9 +334,9 @@ struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev,
 	tasklet_init(&queue->txtask, tx_tasklet,
 		     (unsigned long)queue);
 
-	value = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value &= ~B43legacy_SBF_XFER_REG_BYTESWAP;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value);
+	value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value &= ~B43legacy_MACCTL_BE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value);
 
 	qsize = b43legacy_read16(dev, queue->mmio_base
 				 + B43legacy_PIO_TXQBUFSIZE);

+ 8 - 8
drivers/net/wireless/b43legacy/radio.c

@@ -91,10 +91,10 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK);
-	status |= B43legacy_SBF_RADIOREG_LOCK;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK);
+	status |= B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 	udelay(10);
 }
@@ -104,10 +104,10 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
 	u32 status;
 
 	b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK));
-	status &= ~B43legacy_SBF_RADIOREG_LOCK;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK));
+	status &= ~B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 }
 

+ 0 - 5
drivers/net/wireless/hostap/hostap_80211.h

@@ -71,11 +71,6 @@ struct hostap_80211_rx_status {
 	u16 rate; /* in 100 kbps */
 };
 
-
-void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
-		     struct hostap_80211_rx_status *rx_stats);
-
-
 /* prism2_rx_80211 'type' argument */
 enum {
 	PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC,

+ 3 - 0
drivers/net/wireless/hostap/hostap_cs.c

@@ -891,6 +891,9 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID123(
 		"The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
 		0xa5f472c2, 0x9c05598d, 0xc9049a39),
+	PCMCIA_DEVICE_PROD_ID123(
+		"Wireless LAN" , "11Mbps PC Card", "Version 01.02",
+		0x4b8870ff, 0x70e946d1, 0x4b74baa0),
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-3945-hw.h

@@ -373,7 +373,7 @@ struct iwl3945_eeprom {
 #define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
 #define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
 #define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
 #define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
 #define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
 #define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */

+ 0 - 14
drivers/net/wireless/iwlwifi/iwl-3945.c

@@ -2369,18 +2369,4 @@ struct pci_device_id iwl3945_hw_card_ids[] = {
 	{0}
 };
 
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
-{
-	_iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-	return 0;
-}
-
 MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);

+ 0 - 2
drivers/net/wireless/iwlwifi/iwl-3945.h

@@ -671,7 +671,6 @@ extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel);
 /*
  * Forward declare iwl-3945.c functions for iwl-base.c
  */
-extern int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv);
 extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv);
 extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv);
 extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv);
@@ -791,7 +790,6 @@ struct iwl3945_priv {
 	u16 active_rate_basic;
 
 	u8 call_post_assoc_from_beacon;
-	u8 assoc_station_added;
 	/* Rate scaling data */
 	s8 data_retry_limit;
 	u8 retry_rate;

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-4965-hw.h

@@ -465,7 +465,7 @@ struct iwl4965_eeprom {
 #define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
 #define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
 #define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
 #define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
 #define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
 #define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */

+ 0 - 7
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -4961,11 +4961,4 @@ int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
 	return rc;
 }
 
-inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
-{
-	iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-}
-
-
 MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);

+ 0 - 1
drivers/net/wireless/iwlwifi/iwl-4965.h

@@ -750,7 +750,6 @@ struct iwl4965_priv;
  * Forward declare iwl-4965.c functions for iwl-base.c
  */
 extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
-extern void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv);
 
 extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
 					  struct iwl4965_tx_queue *txq,

+ 2 - 2
drivers/net/wireless/iwlwifi/iwl-helpers.h

@@ -246,10 +246,10 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask)
 static inline unsigned long elapsed_jiffies(unsigned long start,
 					    unsigned long end)
 {
-	if (end > start)
+	if (end >= start)
 		return end - start;
 
-	return end + (MAX_JIFFY_OFFSET - start);
+	return end + (MAX_JIFFY_OFFSET - start) + 1;
 }
 
 static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)

+ 65 - 21
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -1557,6 +1557,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
 	memcpy(mac, priv->eeprom.mac_address, 6);
 }
 
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
+{
+	_iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+	return 0;
+}
+
 /**
  * iwl3945_eeprom_init - read EEPROM contents
  *
@@ -2792,7 +2806,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
 #endif
 
 	/* drop all data frame if we are not associated */
-	if (!iwl3945_is_associated(priv) && !priv->assoc_id &&
+	if ((!iwl3945_is_associated(priv) || !priv->assoc_id) &&
 	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
 		IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
 		goto drop_unlock;
@@ -4745,8 +4759,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 #ifdef CONFIG_IWL3945_DEBUG
 	if (iwl3945_debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
-			IWL_DEBUG_ISR("Microcode started or stopped.\n");
+		if (inta & CSR_INT_BIT_SCD)
+			IWL_DEBUG_ISR("Scheduler finished to transmit "
+				      "the frame/frames.\n");
 
 		/* Alive notification via Rx interrupt will do the real work */
 		if (inta & CSR_INT_BIT_ALIVE)
@@ -4754,7 +4769,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
 	/* HW RF KILL switch toggled (4965 only) */
 	if (inta & CSR_INT_BIT_RF_KILL) {
@@ -4890,8 +4905,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
 	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
 		      inta, inta_mask, inta_fh);
 
+	inta &= ~CSR_INT_BIT_SCD;
+
 	/* iwl3945_irq_tasklet() will service interrupts and re-enable them */
-	tasklet_schedule(&priv->irq_tasklet);
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
 unplugged:
 	spin_unlock(&priv->lock);
 
@@ -5146,6 +5164,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map
+ */
+static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
@@ -5471,6 +5498,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl3945_free_geos - undo allocations in iwl3945_init_geos
+ */
+static void iwl3945_free_geos(struct iwl3945_priv *priv)
+{
+	kfree(priv->modes);
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+
 /******************************************************************************
  *
  * uCode download functions
@@ -6130,15 +6168,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 	/* Clear out the uCode error bit if it is set */
 	clear_bit(STATUS_FW_ERROR, &priv->status);
 
-	rc = iwl3945_init_channel_map(priv);
-	if (rc) {
-		IWL_ERROR("initializing regulatory failed: %d\n", rc);
-		return;
-	}
-
-	iwl3945_init_geos(priv);
-	iwl3945_reset_channel_flag(priv);
-
 	if (iwl3945_is_rfkill(priv))
 		return;
 
@@ -6599,7 +6628,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 	 * that based on the direct_mask added to each channel entry */
 	scan->tx_cmd.len = cpu_to_le16(
 		iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
+			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
 	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;
@@ -7120,7 +7149,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
 {
 	int rc = 0;
 
-	if (priv->status & STATUS_EXIT_PENDING)
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* The following should be done only at AP bring up */
@@ -8614,11 +8643,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+	err = iwl3945_init_channel_map(priv);
+	if (err) {
+		IWL_ERROR("initializing regulatory failed: %d\n", err);
+		goto out_remove_sysfs;
+	}
+
+	err = iwl3945_init_geos(priv);
+	if (err) {
+		IWL_ERROR("initializing geos failed: %d\n", err);
+		goto out_free_channel_map;
+	}
+	iwl3945_reset_channel_flag(priv);
+
 	iwl3945_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
 	if (err) {
 		IWL_ERROR("Failed to register network device (error %d)\n", err);
-		goto out_remove_sysfs;
+		goto out_free_geos;
 	}
 
 	priv->hw->conf.beacon_int = 100;
@@ -8628,6 +8670,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 	return 0;
 
+ out_free_geos:
+	iwl3945_free_geos(priv);
+ out_free_channel_map:
+	iwl3945_free_channel_map(priv);
  out_remove_sysfs:
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
@@ -8702,10 +8748,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
-	kfree(priv->channel_info);
-
-	kfree(priv->ieee_channels);
-	kfree(priv->ieee_rates);
+	iwl3945_free_channel_map(priv);
+	iwl3945_free_geos(priv);
 
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);

+ 61 - 23
drivers/net/wireless/iwlwifi/iwl4965-base.c

@@ -1639,6 +1639,12 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
 	memcpy(mac, priv->eeprom.mac_address, 6);
 }
 
+static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
+{
+	iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+}
+
 /**
  * iwl4965_eeprom_init - read EEPROM contents
  *
@@ -2927,8 +2933,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
 #endif
 
 	/* drop all data frame if we are not associated */
-	if (!iwl4965_is_associated(priv) && !priv->assoc_id &&
-	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+	   (!iwl4965_is_associated(priv) ||
+	    !priv->assoc_id ||
+	    !priv->assoc_station_added)) {
 		IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
 		goto drop_unlock;
 	}
@@ -5131,8 +5139,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
 #ifdef CONFIG_IWL4965_DEBUG
 	if (iwl4965_debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
-			IWL_DEBUG_ISR("Microcode started or stopped.\n");
+		if (inta & CSR_INT_BIT_SCD)
+			IWL_DEBUG_ISR("Scheduler finished to transmit "
+				      "the frame/frames.\n");
 
 		/* Alive notification via Rx interrupt will do the real work */
 		if (inta & CSR_INT_BIT_ALIVE)
@@ -5140,7 +5149,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
 	/* HW RF KILL switch toggled */
 	if (inta & CSR_INT_BIT_RF_KILL) {
@@ -5269,8 +5278,11 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
 	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
 		      inta, inta_mask, inta_fh);
 
+	inta &= ~CSR_INT_BIT_SCD;
+
 	/* iwl4965_irq_tasklet() will service interrupts and re-enable them */
-	tasklet_schedule(&priv->irq_tasklet);
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
 
  unplugged:
 	spin_unlock(&priv->lock);
@@ -5576,6 +5588,15 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
+ */
+static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
@@ -5909,6 +5930,17 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl4965_free_geos - undo allocations in iwl4965_init_geos
+ */
+static void iwl4965_free_geos(struct iwl4965_priv *priv)
+{
+	kfree(priv->modes);
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+
 /******************************************************************************
  *
  * uCode download functions
@@ -6560,15 +6592,6 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
 	/* Clear out the uCode error bit if it is set */
 	clear_bit(STATUS_FW_ERROR, &priv->status);
 
-	rc = iwl4965_init_channel_map(priv);
-	if (rc) {
-		IWL_ERROR("initializing regulatory failed: %d\n", rc);
-		return;
-	}
-
-	iwl4965_init_geos(priv);
-	iwl4965_reset_channel_flag(priv);
-
 	if (iwl4965_is_rfkill(priv))
 		return;
 
@@ -7023,7 +7046,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
 	 * that based on the direct_mask added to each channel entry */
 	scan->tx_cmd.len = cpu_to_le16(
 		iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
+			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
 	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;
@@ -7448,7 +7471,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
 
 	if (priv->vif) {
 		IWL_DEBUG_MAC80211("leave - vif != NULL\n");
-		return 0;
+		return -EOPNOTSUPP;
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -7580,7 +7603,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
 {
 	int rc = 0;
 
-	if (priv->status & STATUS_EXIT_PENDING)
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* The following should be done only at AP bring up */
@@ -9198,11 +9221,24 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+	err = iwl4965_init_channel_map(priv);
+	if (err) {
+		IWL_ERROR("initializing regulatory failed: %d\n", err);
+		goto out_remove_sysfs;
+	}
+
+	err = iwl4965_init_geos(priv);
+	if (err) {
+		IWL_ERROR("initializing geos failed: %d\n", err);
+		goto out_free_channel_map;
+	}
+	iwl4965_reset_channel_flag(priv);
+
 	iwl4965_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
 	if (err) {
 		IWL_ERROR("Failed to register network device (error %d)\n", err);
-		goto out_remove_sysfs;
+		goto out_free_geos;
 	}
 
 	priv->hw->conf.beacon_int = 100;
@@ -9212,6 +9248,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 	return 0;
 
+ out_free_geos:
+	iwl4965_free_geos(priv);
+ out_free_channel_map:
+	iwl4965_free_channel_map(priv);
  out_remove_sysfs:
 	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
 
@@ -9286,10 +9326,8 @@ static void iwl4965_pci_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
-	kfree(priv->channel_info);
-
-	kfree(priv->ieee_channels);
-	kfree(priv->ieee_rates);
+	iwl4965_free_channel_map(priv);
+	iwl4965_free_geos(priv);
 
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);

+ 4 - 2
drivers/net/wireless/libertas/assoc.c

@@ -12,8 +12,10 @@
 #include "cmd.h"
 
 
-static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 bssid_any[ETH_ALEN]  __attribute__ ((aligned (2))) =
+	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 
 static int assoc_helper_essid(struct lbs_private *priv,

+ 1 - 1
drivers/net/wireless/libertas/dev.h

@@ -349,7 +349,7 @@ struct assoc_request {
 	u8 channel;
 	u8 band;
 	u8 mode;
-	u8 bssid[ETH_ALEN];
+	u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
 
 	/** WEP keys */
 	struct enc_key wep_keys[4];

+ 3 - 3
drivers/net/wireless/libertas/if_cs.c

@@ -249,14 +249,14 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
 	lbs_deb_enter(LBS_DEB_CS);
 
 	int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
-	if(int_cause == 0x0) {
+	if (int_cause == 0x0) {
 		/* Not for us */
 		return IRQ_NONE;
 
 	} else if (int_cause == 0xffff) {
 		/* Read in junk, the card has probably been removed */
 		card->priv->surpriseremoved = 1;
-
+		return IRQ_HANDLED;
 	} else {
 		if (int_cause & IF_CS_H_IC_TX_OVER)
 			lbs_host_to_card_done(card->priv);
@@ -717,8 +717,8 @@ static void if_cs_release(struct pcmcia_device *p_dev)
 
 	lbs_deb_enter(LBS_DEB_CS);
 
-	pcmcia_disable_device(p_dev);
 	free_irq(p_dev->irq.AssignedIRQ, card);
+	pcmcia_disable_device(p_dev);
 	if (card->iobase)
 		ioport_unmap(card->iobase);
 

+ 2757 - 0
drivers/net/wireless/rndis_wlan.c

@@ -0,0 +1,2757 @@
+/*
+ * Driver for RNDIS based wireless USB devices.
+ *
+ * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
+ * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * 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
+ *
+ *  Portions of this file are based on NDISwrapper project,
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *  http://ndiswrapper.sourceforge.net/
+ */
+
+// #define	DEBUG			// error path messages, extra info
+// #define	VERBOSE			// more; success messages
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/wireless.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>
+
+
+/* NOTE: All these are settings for Broadcom chipset */
+static char modparam_country[4] = "EU";
+module_param_string(country, modparam_country, 4, 0444);
+MODULE_PARM_DESC(country, "Country code (ISO 3166-1 alpha-2), default: EU");
+
+static int modparam_frameburst = 1;
+module_param_named(frameburst, modparam_frameburst, int, 0444);
+MODULE_PARM_DESC(frameburst, "enable frame bursting (default: on)");
+
+static int modparam_afterburner = 0;
+module_param_named(afterburner, modparam_afterburner, int, 0444);
+MODULE_PARM_DESC(afterburner,
+	"enable afterburner aka '125 High Speed Mode' (default: off)");
+
+static int modparam_power_save = 0;
+module_param_named(power_save, modparam_power_save, int, 0444);
+MODULE_PARM_DESC(power_save,
+	"set power save mode: 0=off, 1=on, 2=fast (default: off)");
+
+static int modparam_power_output = 3;
+module_param_named(power_output, modparam_power_output, int, 0444);
+MODULE_PARM_DESC(power_output,
+	"set power output: 0=25%, 1=50%, 2=75%, 3=100% (default: 100%)");
+
+static int modparam_roamtrigger = -70;
+module_param_named(roamtrigger, modparam_roamtrigger, int, 0444);
+MODULE_PARM_DESC(roamtrigger,
+	"set roaming dBm trigger: -80=optimize for distance, "
+				"-60=bandwidth (default: -70)");
+
+static int modparam_roamdelta = 1;
+module_param_named(roamdelta, modparam_roamdelta, int, 0444);
+MODULE_PARM_DESC(roamdelta,
+	"set roaming tendency: 0=aggressive, 1=moderate, "
+				"2=conservative (default: moderate)");
+
+static int modparam_workaround_interval = 500;
+module_param_named(workaround_interval, modparam_workaround_interval,
+							int, 0444);
+MODULE_PARM_DESC(workaround_interval,
+	"set stall workaround interval in msecs (default: 500)");
+
+
+/* various RNDIS OID defs */
+#define OID_GEN_LINK_SPEED			ccpu2(0x00010107)
+#define OID_GEN_RNDIS_CONFIG_PARAMETER		ccpu2(0x0001021b)
+
+#define OID_GEN_XMIT_OK				ccpu2(0x00020101)
+#define OID_GEN_RCV_OK				ccpu2(0x00020102)
+#define OID_GEN_XMIT_ERROR			ccpu2(0x00020103)
+#define OID_GEN_RCV_ERROR			ccpu2(0x00020104)
+#define OID_GEN_RCV_NO_BUFFER			ccpu2(0x00020105)
+
+#define OID_802_3_PERMANENT_ADDRESS		ccpu2(0x01010101)
+#define OID_802_3_CURRENT_ADDRESS		ccpu2(0x01010102)
+#define OID_802_3_MULTICAST_LIST		ccpu2(0x01010103)
+#define OID_802_3_MAXIMUM_LIST_SIZE		ccpu2(0x01010104)
+
+#define OID_802_11_BSSID			ccpu2(0x0d010101)
+#define OID_802_11_SSID				ccpu2(0x0d010102)
+#define OID_802_11_INFRASTRUCTURE_MODE		ccpu2(0x0d010108)
+#define OID_802_11_ADD_WEP			ccpu2(0x0d010113)
+#define OID_802_11_REMOVE_WEP			ccpu2(0x0d010114)
+#define OID_802_11_DISASSOCIATE			ccpu2(0x0d010115)
+#define OID_802_11_AUTHENTICATION_MODE		ccpu2(0x0d010118)
+#define OID_802_11_PRIVACY_FILTER		ccpu2(0x0d010119)
+#define OID_802_11_BSSID_LIST_SCAN		ccpu2(0x0d01011a)
+#define OID_802_11_ENCRYPTION_STATUS		ccpu2(0x0d01011b)
+#define OID_802_11_ADD_KEY			ccpu2(0x0d01011d)
+#define OID_802_11_REMOVE_KEY			ccpu2(0x0d01011e)
+#define OID_802_11_PMKID			ccpu2(0x0d010123)
+#define OID_802_11_NETWORK_TYPES_SUPPORTED	ccpu2(0x0d010203)
+#define OID_802_11_NETWORK_TYPE_IN_USE		ccpu2(0x0d010204)
+#define OID_802_11_TX_POWER_LEVEL		ccpu2(0x0d010205)
+#define OID_802_11_RSSI				ccpu2(0x0d010206)
+#define OID_802_11_RSSI_TRIGGER			ccpu2(0x0d010207)
+#define OID_802_11_FRAGMENTATION_THRESHOLD	ccpu2(0x0d010209)
+#define OID_802_11_RTS_THRESHOLD		ccpu2(0x0d01020a)
+#define OID_802_11_SUPPORTED_RATES		ccpu2(0x0d01020e)
+#define OID_802_11_CONFIGURATION		ccpu2(0x0d010211)
+#define OID_802_11_BSSID_LIST			ccpu2(0x0d010217)
+
+
+/* Typical noise/maximum signal level values taken from ndiswrapper iw_ndis.h */
+#define	WL_NOISE	-96	/* typical noise level in dBm */
+#define	WL_SIGMAX	-32	/* typical maximum signal level in dBm */
+
+
+/* Assume that Broadcom 4320 (only chipset at time of writing known to be
+ * based on wireless rndis) has default txpower of 13dBm.
+ * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications.
+ *   13dBm == 19.9mW
+ */
+#define BCM4320_DEFAULT_TXPOWER 20
+
+
+/* codes for "status" field of completion messages */
+#define RNDIS_STATUS_ADAPTER_NOT_READY		ccpu2(0xc0010011)
+#define RNDIS_STATUS_ADAPTER_NOT_OPEN		ccpu2(0xc0010012)
+
+
+/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c
+ * slightly modified for datatype endianess, etc
+ */
+#define NDIS_802_11_LENGTH_SSID 32
+#define NDIS_802_11_LENGTH_RATES 8
+#define NDIS_802_11_LENGTH_RATES_EX 16
+
+struct NDIS_802_11_SSID {
+	__le32 SsidLength;
+	u8 Ssid[NDIS_802_11_LENGTH_SSID];
+} __attribute__((packed));
+
+enum NDIS_802_11_NETWORK_TYPE {
+	Ndis802_11FH,
+	Ndis802_11DS,
+	Ndis802_11OFDM5,
+	Ndis802_11OFDM24,
+	Ndis802_11NetworkTypeMax
+};
+
+struct NDIS_802_11_CONFIGURATION_FH {
+	__le32 Length;
+	__le32 HopPattern;
+	__le32 HopSet;
+	__le32 DwellTime;
+} __attribute__((packed));
+
+struct NDIS_802_11_CONFIGURATION {
+	__le32 Length;
+	__le32 BeaconPeriod;
+	__le32 ATIMWindow;
+	__le32 DSConfig;
+	struct NDIS_802_11_CONFIGURATION_FH FHConfig;
+} __attribute__((packed));
+
+enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
+	Ndis802_11IBSS,
+	Ndis802_11Infrastructure,
+	Ndis802_11AutoUnknown,
+	Ndis802_11InfrastructureMax
+};
+
+enum NDIS_802_11_AUTHENTICATION_MODE {
+	Ndis802_11AuthModeOpen,
+	Ndis802_11AuthModeShared,
+	Ndis802_11AuthModeAutoSwitch,
+	Ndis802_11AuthModeWPA,
+	Ndis802_11AuthModeWPAPSK,
+	Ndis802_11AuthModeWPANone,
+	Ndis802_11AuthModeWPA2,
+	Ndis802_11AuthModeWPA2PSK,
+	Ndis802_11AuthModeMax
+};
+
+enum NDIS_802_11_ENCRYPTION_STATUS {
+	Ndis802_11WEPEnabled,
+	Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+	Ndis802_11WEPDisabled,
+	Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+	Ndis802_11WEPKeyAbsent,
+	Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+	Ndis802_11WEPNotSupported,
+	Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+	Ndis802_11Encryption2Enabled,
+	Ndis802_11Encryption2KeyAbsent,
+	Ndis802_11Encryption3Enabled,
+	Ndis802_11Encryption3KeyAbsent
+};
+
+enum NDIS_802_11_PRIVACY_FILTER {
+	Ndis802_11PrivFilterAcceptAll,
+	Ndis802_11PrivFilter8021xWEP
+};
+
+struct NDIS_WLAN_BSSID_EX {
+	__le32 Length;
+	u8 MacAddress[6];
+	u8 Padding[2];
+	struct NDIS_802_11_SSID Ssid;
+	__le32 Privacy;
+	__le32 Rssi;
+	enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
+	struct NDIS_802_11_CONFIGURATION Configuration;
+	enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
+	u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
+	__le32 IELength;
+	u8 IEs[0];
+} __attribute__((packed));
+
+struct NDIS_802_11_BSSID_LIST_EX {
+	__le32 NumberOfItems;
+	struct NDIS_WLAN_BSSID_EX Bssid[0];
+} __attribute__((packed));
+
+struct NDIS_802_11_FIXED_IEs {
+	u8 Timestamp[8];
+	__le16 BeaconInterval;
+	__le16 Capabilities;
+} __attribute__((packed));
+
+struct NDIS_802_11_WEP {
+	__le32 Length;
+	__le32 KeyIndex;
+	__le32 KeyLength;
+	u8 KeyMaterial[32];
+} __attribute__((packed));
+
+struct NDIS_802_11_KEY {
+	__le32 Length;
+	__le32 KeyIndex;
+	__le32 KeyLength;
+	u8 Bssid[6];
+	u8 Padding[6];
+	__le64 KeyRSC;
+	u8 KeyMaterial[32];
+} __attribute__((packed));
+
+struct NDIS_802_11_REMOVE_KEY {
+	__le32 Length;
+	__le32 KeyIndex;
+	u8 Bssid[6];
+} __attribute__((packed));
+
+struct RNDIS_CONFIG_PARAMETER_INFOBUFFER {
+	__le32 ParameterNameOffset;
+	__le32 ParameterNameLength;
+	__le32 ParameterType;
+	__le32 ParameterValueOffset;
+	__le32 ParameterValueLength;
+} __attribute__((packed));
+
+/* these have to match what is in wpa_supplicant */
+enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
+enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 }
+	wpa_cipher;
+enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA,
+	KEY_MGMT_WPA_NONE } wpa_key_mgmt;
+
+/*
+ *  private data
+ */
+#define NET_TYPE_11FB	0
+
+#define CAP_MODE_80211A		1
+#define CAP_MODE_80211B		2
+#define CAP_MODE_80211G		4
+#define CAP_MODE_MASK		7
+#define CAP_SUPPORT_TXPOWER	8
+
+#define WORK_CONNECTION_EVENT	(1<<0)
+#define WORK_SET_MULTICAST_LIST	(1<<1)
+
+/* RNDIS device private data */
+struct rndis_wext_private {
+	char name[32];
+
+	struct usbnet *usbdev;
+
+	struct workqueue_struct *workqueue;
+	struct delayed_work stats_work;
+	struct work_struct work;
+	struct mutex command_lock;
+	spinlock_t stats_lock;
+	unsigned long work_pending;
+
+	struct iw_statistics iwstats;
+	struct iw_statistics privstats;
+
+	int  nick_len;
+	char nick[32];
+
+	int caps;
+	int multicast_size;
+
+	/* module parameters */
+	char param_country[4];
+	int  param_frameburst;
+	int  param_afterburner;
+	int  param_power_save;
+	int  param_power_output;
+	int  param_roamtrigger;
+	int  param_roamdelta;
+	u32  param_workaround_interval;
+
+	/* hardware state */
+	int radio_on;
+	int infra_mode;
+	struct NDIS_802_11_SSID essid;
+
+	/* encryption stuff */
+	int  encr_tx_key_index;
+	char encr_keys[4][32];
+	int  encr_key_len[4];
+	int  wpa_version;
+	int  wpa_keymgmt;
+	int  wpa_authalg;
+	int  wpa_ie_len;
+	u8  *wpa_ie;
+	int  wpa_cipher_pair;
+	int  wpa_cipher_group;
+};
+
+
+static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+
+static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
+
+static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
+
+static const unsigned char zero_bssid[ETH_ALEN] = {0,};
+static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff,
+							0xff, 0xff, 0xff };
+
+
+static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev)
+{
+	return (struct rndis_wext_private *)dev->driver_priv;
+}
+
+
+static u32 get_bcm4320_power(struct rndis_wext_private *priv)
+{
+	return BCM4320_DEFAULT_TXPOWER *
+		bcm4320_power_output[priv->param_power_output] / 100;
+}
+
+
+/* translate error code */
+static int rndis_error_status(__le32 rndis_status)
+{
+	int ret = -EINVAL;
+	switch (rndis_status) {
+	case RNDIS_STATUS_SUCCESS:
+		ret = 0;
+		break;
+	case RNDIS_STATUS_FAILURE:
+	case RNDIS_STATUS_INVALID_DATA:
+		ret = -EINVAL;
+		break;
+	case RNDIS_STATUS_NOT_SUPPORTED:
+		ret = -EOPNOTSUPP;
+		break;
+	case RNDIS_STATUS_ADAPTER_NOT_READY:
+	case RNDIS_STATUS_ADAPTER_NOT_OPEN:
+		ret = -EBUSY;
+		break;
+	}
+	return ret;
+}
+
+
+static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	union {
+		void			*buf;
+		struct rndis_msg_hdr	*header;
+		struct rndis_query	*get;
+		struct rndis_query_c	*get_c;
+	} u;
+	int ret, buflen;
+
+	buflen = *len + sizeof(*u.get);
+	if (buflen < CONTROL_BUFFER_SIZE)
+		buflen = CONTROL_BUFFER_SIZE;
+	u.buf = kmalloc(buflen, GFP_KERNEL);
+	if (!u.buf)
+		return -ENOMEM;
+	memset(u.get, 0, sizeof *u.get);
+	u.get->msg_type = RNDIS_MSG_QUERY;
+	u.get->msg_len = ccpu2(sizeof *u.get);
+	u.get->oid = oid;
+
+	mutex_lock(&priv->command_lock);
+	ret = rndis_command(dev, u.header);
+	mutex_unlock(&priv->command_lock);
+
+	if (ret == 0) {
+		ret = le32_to_cpu(u.get_c->len);
+		*len = (*len > ret) ? ret : *len;
+		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
+		ret = rndis_error_status(u.get_c->status);
+	}
+
+	kfree(u.buf);
+	return ret;
+}
+
+
+static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	union {
+		void			*buf;
+		struct rndis_msg_hdr	*header;
+		struct rndis_set	*set;
+		struct rndis_set_c	*set_c;
+	} u;
+	int ret, buflen;
+
+	buflen = len + sizeof(*u.set);
+	if (buflen < CONTROL_BUFFER_SIZE)
+		buflen = CONTROL_BUFFER_SIZE;
+	u.buf = kmalloc(buflen, GFP_KERNEL);
+	if (!u.buf)
+		return -ENOMEM;
+
+	memset(u.set, 0, sizeof *u.set);
+	u.set->msg_type = RNDIS_MSG_SET;
+	u.set->msg_len = cpu_to_le32(sizeof(*u.set) + len);
+	u.set->oid = oid;
+	u.set->len = cpu_to_le32(len);
+	u.set->offset = ccpu2(sizeof(*u.set) - 8);
+	u.set->handle = ccpu2(0);
+	memcpy(u.buf + sizeof(*u.set), data, len);
+
+	mutex_lock(&priv->command_lock);
+	ret = rndis_command(dev, u.header);
+	mutex_unlock(&priv->command_lock);
+
+	if (ret == 0)
+		ret = rndis_error_status(u.set_c->status);
+
+	kfree(u.buf);
+	return ret;
+}
+
+
+/*
+ * Specs say that we can only set config parameters only soon after device
+ * initialization.
+ *   value_type: 0 = u32, 2 = unicode string
+ */
+static int rndis_set_config_parameter(struct usbnet *dev, char *param,
+						int value_type, void *value)
+{
+	struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf;
+	int value_len, info_len, param_len, ret, i;
+	__le16 *unibuf;
+	__le32 *dst_value;
+
+	if (value_type == 0)
+		value_len = sizeof(__le32);
+	else if (value_type == 2)
+		value_len = strlen(value) * sizeof(__le16);
+	else
+		return -EINVAL;
+
+	param_len = strlen(param) * sizeof(__le16);
+	info_len = sizeof(*infobuf) + param_len + value_len;
+
+#ifdef DEBUG
+	info_len += 12;
+#endif
+	infobuf = kmalloc(info_len, GFP_KERNEL);
+	if (!infobuf)
+		return -ENOMEM;
+
+#ifdef DEBUG
+	info_len -= 12;
+	/* extra 12 bytes are for padding (debug output) */
+	memset(infobuf, 0xCC, info_len + 12);
+#endif
+
+	if (value_type == 2)
+		devdbg(dev, "setting config parameter: %s, value: %s",
+						param, (u8 *)value);
+	else
+		devdbg(dev, "setting config parameter: %s, value: %d",
+						param, *(u32 *)value);
+
+	infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf));
+	infobuf->ParameterNameLength = cpu_to_le32(param_len);
+	infobuf->ParameterType = cpu_to_le32(value_type);
+	infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) +
+								param_len);
+	infobuf->ParameterValueLength = cpu_to_le32(value_len);
+
+	/* simple string to unicode string conversion */
+	unibuf = (void *)infobuf + sizeof(*infobuf);
+	for (i = 0; i < param_len / sizeof(__le16); i++)
+		unibuf[i] = cpu_to_le16(param[i]);
+
+	if (value_type == 2) {
+		unibuf = (void *)infobuf + sizeof(*infobuf) + param_len;
+		for (i = 0; i < value_len / sizeof(__le16); i++)
+			unibuf[i] = cpu_to_le16(((u8 *)value)[i]);
+	} else {
+		dst_value = (void *)infobuf + sizeof(*infobuf) + param_len;
+		*dst_value = cpu_to_le32(*(u32 *)value);
+	}
+
+#ifdef DEBUG
+	devdbg(dev, "info buffer (len: %d):", info_len);
+	for (i = 0; i < info_len; i += 12) {
+		u32 *tmp = (u32 *)((u8 *)infobuf + i);
+		devdbg(dev, "%08X:%08X:%08X",
+			cpu_to_be32(tmp[0]),
+			cpu_to_be32(tmp[1]),
+			cpu_to_be32(tmp[2]));
+	}
+#endif
+
+	ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER,
+							infobuf, info_len);
+	if (ret != 0)
+		devdbg(dev, "setting rndis config paramater failed, %d.", ret);
+
+	kfree(infobuf);
+	return ret;
+}
+
+static int rndis_set_config_parameter_str(struct usbnet *dev,
+						char *param, char *value)
+{
+	return(rndis_set_config_parameter(dev, param, 2, value));
+}
+
+/*static int rndis_set_config_parameter_u32(struct usbnet *dev,
+						char *param, u32 value)
+{
+	return(rndis_set_config_parameter(dev, param, 0, &value));
+}*/
+
+
+/*
+ * data conversion functions
+ */
+static int level_to_qual(int level)
+{
+	int qual = 100 * (level - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
+	return qual >= 0 ? (qual <= 100 ? qual : 100) : 0;
+}
+
+
+static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
+{
+	freq->e = 0;
+	freq->i = 0;
+	freq->flags = 0;
+
+	/* see comment in wireless.h above the "struct iw_freq"
+	 * definition for an explanation of this if
+	 * NOTE: 1000000 is due to the kHz
+	 */
+	if (dsconfig > 1000000) {
+		freq->m = dsconfig / 10;
+		freq->e = 1;
+	} else
+		freq->m = dsconfig;
+
+	/* convert from kHz to Hz */
+	freq->e += 3;
+}
+
+
+static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
+{
+	if (freq->m < 1000 && freq->e == 0) {
+		if (freq->m >= 1 &&
+			freq->m <= (sizeof(freq_chan) / sizeof(freq_chan[0])))
+			*dsconfig = freq_chan[freq->m - 1] * 1000;
+		else
+			return -1;
+	} else {
+		int i;
+		*dsconfig = freq->m;
+		for (i = freq->e; i > 0; i--)
+			*dsconfig *= 10;
+		*dsconfig /= 1000;
+	}
+
+	return 0;
+}
+
+
+/*
+ * common functions
+ */
+static int
+add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
+
+static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+{
+	int ret, len;
+
+	len = sizeof(*ssid);
+	ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
+
+	if (ret != 0)
+		ssid->SsidLength = 0;
+
+#ifdef DEBUG
+	{
+		unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
+
+		memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength));
+		tmp[le32_to_cpu(ssid->SsidLength)] = 0;
+		devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
+	}
+#endif
+	return ret;
+}
+
+
+static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	int ret;
+
+	ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid));
+	if (ret == 0) {
+		memcpy(&priv->essid, ssid, sizeof(priv->essid));
+		priv->radio_on = 1;
+		devdbg(usbdev, "set_essid: radio_on = 1");
+	}
+
+	return ret;
+}
+
+
+static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
+{
+	int ret, len;
+
+	len = ETH_ALEN;
+	ret = rndis_query_oid(usbdev, OID_802_11_BSSID, bssid, &len);
+
+	if (ret != 0)
+		memset(bssid, 0, ETH_ALEN);
+
+	return ret;
+}
+
+
+static int is_associated(struct usbnet *usbdev)
+{
+	u8 bssid[ETH_ALEN];
+	int ret;
+
+	ret = get_bssid(usbdev, bssid);
+
+	return(ret == 0 && memcmp(bssid, zero_bssid, ETH_ALEN) != 0);
+}
+
+
+static int disassociate(struct usbnet *usbdev, int reset_ssid)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct NDIS_802_11_SSID ssid;
+	int i, ret = 0;
+
+	if (priv->radio_on) {
+		ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0);
+		if (ret == 0) {
+			priv->radio_on = 0;
+			devdbg(usbdev, "disassociate: radio_on = 0");
+
+			if (reset_ssid)
+				msleep(100);
+		}
+	}
+
+	/* disassociate causes radio to be turned off; if reset_ssid
+	 * is given, set random ssid to enable radio */
+	if (reset_ssid) {
+		ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid));
+		get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2);
+		ssid.Ssid[0] = 0x1;
+		ssid.Ssid[1] = 0xff;
+		for (i = 2; i < sizeof(ssid.Ssid); i++)
+			ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff);
+		ret = set_essid(usbdev, &ssid);
+	}
+	return ret;
+}
+
+
+static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tmp;
+	int auth_mode, ret;
+
+	devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x "
+		"keymgmt=0x%x", wpa_version, authalg, priv->wpa_keymgmt);
+
+	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
+		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+			auth_mode = Ndis802_11AuthModeWPA2;
+		else
+			auth_mode = Ndis802_11AuthModeWPA2PSK;
+	} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
+		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+			auth_mode = Ndis802_11AuthModeWPA;
+		else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
+			auth_mode = Ndis802_11AuthModeWPAPSK;
+		else
+			auth_mode = Ndis802_11AuthModeWPANone;
+	} else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
+		if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
+			auth_mode = Ndis802_11AuthModeAutoSwitch;
+		else
+			auth_mode = Ndis802_11AuthModeShared;
+	} else
+		auth_mode = Ndis802_11AuthModeOpen;
+
+	tmp = cpu_to_le32(auth_mode);
+	ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
+								sizeof(tmp));
+	if (ret != 0) {
+		devwarn(usbdev, "setting auth mode failed (%08X)", ret);
+		return ret;
+	}
+
+	priv->wpa_version = wpa_version;
+	priv->wpa_authalg = authalg;
+	return 0;
+}
+
+
+static int set_priv_filter(struct usbnet *usbdev)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tmp;
+
+	devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version);
+
+	if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
+	    priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
+		tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP);
+	else
+		tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll);
+
+	return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
+								sizeof(tmp));
+}
+
+
+static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tmp;
+	int encr_mode, ret;
+
+	devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x",
+		pairwise,
+		groupwise);
+
+	if (pairwise & IW_AUTH_CIPHER_CCMP)
+		encr_mode = Ndis802_11Encryption3Enabled;
+	else if (pairwise & IW_AUTH_CIPHER_TKIP)
+		encr_mode = Ndis802_11Encryption2Enabled;
+	else if (pairwise &
+		 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+		encr_mode = Ndis802_11Encryption1Enabled;
+	else if (groupwise & IW_AUTH_CIPHER_CCMP)
+		encr_mode = Ndis802_11Encryption3Enabled;
+	else if (groupwise & IW_AUTH_CIPHER_TKIP)
+		encr_mode = Ndis802_11Encryption2Enabled;
+	else
+		encr_mode = Ndis802_11EncryptionDisabled;
+
+	tmp = cpu_to_le32(encr_mode);
+	ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
+								sizeof(tmp));
+	if (ret != 0) {
+		devwarn(usbdev, "setting encr mode failed (%08X)", ret);
+		return ret;
+	}
+
+	priv->wpa_cipher_pair = pairwise;
+	priv->wpa_cipher_group = groupwise;
+	return 0;
+}
+
+
+static int set_assoc_params(struct usbnet *usbdev)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg);
+	set_priv_filter(usbdev);
+	set_encr_mode(usbdev, priv->wpa_cipher_pair, priv->wpa_cipher_group);
+
+	return 0;
+}
+
+
+static int set_infra_mode(struct usbnet *usbdev, int mode)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tmp;
+	int ret, i;
+
+	devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode);
+
+	tmp = cpu_to_le32(mode);
+	ret = rndis_set_oid(usbdev, OID_802_11_INFRASTRUCTURE_MODE, &tmp,
+								sizeof(tmp));
+	if (ret != 0) {
+		devwarn(usbdev, "setting infra mode failed (%08X)", ret);
+		return ret;
+	}
+
+	/* NDIS drivers clear keys when infrastructure mode is
+	 * changed. But Linux tools assume otherwise. So set the
+	 * keys */
+	if (priv->wpa_keymgmt == 0 ||
+		priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
+		for (i = 0; i < 4; i++) {
+			if (priv->encr_key_len[i] > 0)
+				add_wep_key(usbdev, priv->encr_keys[i],
+						priv->encr_key_len[i], i);
+		}
+	}
+
+	priv->infra_mode = mode;
+	return 0;
+}
+
+
+static void set_default_iw_params(struct usbnet *usbdev)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	priv->wpa_keymgmt = 0;
+	priv->wpa_version = 0;
+
+	set_infra_mode(usbdev, Ndis802_11Infrastructure);
+	set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
+				IW_AUTH_ALG_OPEN_SYSTEM);
+	set_priv_filter(usbdev);
+	set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
+}
+
+
+static int deauthenticate(struct usbnet *usbdev)
+{
+	int ret;
+
+	ret = disassociate(usbdev, 1);
+	set_default_iw_params(usbdev);
+	return ret;
+}
+
+
+/* index must be 0 - N, as per NDIS  */
+static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct NDIS_802_11_WEP ndis_key;
+	int ret;
+
+	if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
+		return -EINVAL;
+
+	memset(&ndis_key, 0, sizeof(ndis_key));
+
+	ndis_key.Length = cpu_to_le32(sizeof(ndis_key));
+	ndis_key.KeyLength = cpu_to_le32(key_len);
+	ndis_key.KeyIndex = cpu_to_le32(index);
+	memcpy(&ndis_key.KeyMaterial, key, key_len);
+
+	if (index == priv->encr_tx_key_index) {
+		ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
+		ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
+						IW_AUTH_CIPHER_NONE);
+		if (ret)
+			devwarn(usbdev, "encryption couldn't be enabled (%08X)",
+									ret);
+	}
+
+	ret = rndis_set_oid(usbdev, OID_802_11_ADD_WEP, &ndis_key,
+							sizeof(ndis_key));
+	if (ret != 0) {
+		devwarn(usbdev, "adding encryption key %d failed (%08X)",
+							index+1, ret);
+		return ret;
+	}
+
+	priv->encr_key_len[index] = key_len;
+	memcpy(&priv->encr_keys[index], key, key_len);
+
+	return 0;
+}
+
+
+/* remove_key is for both wep and wpa */
+static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct NDIS_802_11_REMOVE_KEY remove_key;
+	__le32 keyindex;
+	int ret;
+
+	if (priv->encr_key_len[index] == 0)
+		return 0;
+
+	priv->encr_key_len[index] = 0;
+	memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
+
+	if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
+	    priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
+	    priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
+	    priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
+		remove_key.Length = cpu_to_le32(sizeof(remove_key));
+		remove_key.KeyIndex = cpu_to_le32(index);
+		if (bssid) {
+			/* pairwise key */
+			if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
+				remove_key.KeyIndex |= cpu_to_le32(1 << 30);
+			memcpy(remove_key.Bssid, bssid,
+					sizeof(remove_key.Bssid));
+		} else
+			memset(remove_key.Bssid, 0xff,
+						sizeof(remove_key.Bssid));
+
+		ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key,
+							sizeof(remove_key));
+		if (ret != 0)
+			return ret;
+	} else {
+		keyindex = cpu_to_le32(index);
+		ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_WEP, &keyindex,
+							sizeof(keyindex));
+		if (ret != 0) {
+			devwarn(usbdev,
+				"removing encryption key %d failed (%08X)",
+				index, ret);
+			return ret;
+		}
+	}
+
+	/* if it is transmit key, disable encryption */
+	if (index == priv->encr_tx_key_index)
+		set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
+
+	return 0;
+}
+
+
+static void set_multicast_list(struct usbnet *usbdev)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct dev_mc_list *mclist;
+	__le32 filter;
+	int ret, i, size;
+	char *buf;
+
+	filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
+
+	if (usbdev->net->flags & IFF_PROMISC) {
+		filter |= RNDIS_PACKET_TYPE_PROMISCUOUS |
+			RNDIS_PACKET_TYPE_ALL_LOCAL;
+	} else if (usbdev->net->flags & IFF_ALLMULTI ||
+		   usbdev->net->mc_count > priv->multicast_size) {
+		filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
+	} else if (usbdev->net->mc_count > 0) {
+		size = min(priv->multicast_size, usbdev->net->mc_count);
+		buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);
+		if (!buf) {
+			devwarn(usbdev,
+				"couldn't alloc %d bytes of memory",
+				size * ETH_ALEN);
+			return;
+		}
+
+		mclist = usbdev->net->mc_list;
+		for (i = 0; i < size && mclist; mclist = mclist->next) {
+			if (mclist->dmi_addrlen != ETH_ALEN)
+				continue;
+
+			memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);
+			i++;
+		}
+
+		ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf,
+								i * ETH_ALEN);
+		if (ret == 0 && i > 0)
+			filter |= RNDIS_PACKET_TYPE_MULTICAST;
+		else
+			filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
+
+		devdbg(usbdev, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d",
+						i, priv->multicast_size, ret);
+
+		kfree(buf);
+	}
+
+	ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter,
+							sizeof(filter));
+	if (ret < 0) {
+		devwarn(usbdev, "couldn't set packet filter: %08x",
+							le32_to_cpu(filter));
+	}
+
+	devdbg(usbdev, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d",
+						le32_to_cpu(filter), ret);
+}
+
+
+/*
+ * wireless extension handlers
+ */
+
+static int rndis_iw_commit(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	/* dummy op */
+	return 0;
+}
+
+
+static int rndis_iw_get_range(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	int len, ret, i, j, num, has_80211g_rates;
+	u8 rates[8];
+	__le32 tx_power;
+
+	devdbg(usbdev, "SIOCGIWRANGE");
+
+	/* clear iw_range struct */
+	memset(range, 0, sizeof(*range));
+	wrqu->data.length = sizeof(*range);
+
+	range->txpower_capa = IW_TXPOW_MWATT;
+	range->num_txpower = 1;
+	if (priv->caps & CAP_SUPPORT_TXPOWER) {
+		len = sizeof(tx_power);
+		ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
+						&tx_power, &len);
+		if (ret == 0 && le32_to_cpu(tx_power) != 0xFF)
+			range->txpower[0] = le32_to_cpu(tx_power);
+		else
+			range->txpower[0] = get_bcm4320_power(priv);
+	} else
+		range->txpower[0] = get_bcm4320_power(priv);
+
+	len = sizeof(rates);
+	ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates,
+								&len);
+	has_80211g_rates = 0;
+	if (ret == 0) {
+		j = 0;
+		for (i = 0; i < len; i++) {
+			if (rates[i] == 0)
+				break;
+			range->bitrate[j] = (rates[i] & 0x7f) * 500000;
+			/* check for non 802.11b rates */
+			if (range->bitrate[j] == 6000000 ||
+				range->bitrate[j] == 9000000 ||
+				(range->bitrate[j] >= 12000000 &&
+				range->bitrate[j] != 22000000))
+				has_80211g_rates = 1;
+			j++;
+		}
+		range->num_bitrates = j;
+	} else
+		range->num_bitrates = 0;
+
+	/* fill in 802.11g rates */
+	if (has_80211g_rates) {
+		num = range->num_bitrates;
+		for (i = 0; i < sizeof(rates_80211g); i++) {
+			for (j = 0; j < num; j++) {
+				if (range->bitrate[j] ==
+					rates_80211g[i] * 1000000)
+					break;
+			}
+			if (j == num)
+				range->bitrate[range->num_bitrates++] =
+					rates_80211g[i] * 1000000;
+			if (range->num_bitrates == IW_MAX_BITRATES)
+				break;
+		}
+
+		/* estimated max real througput in bps */
+		range->throughput = 54 * 1000 * 1000 / 2;
+
+		/* ~35%	more with afterburner */
+		if (priv->param_afterburner)
+			range->throughput = range->throughput / 100 * 135;
+	} else {
+		/* estimated max real througput in bps */
+		range->throughput = 11 * 1000 * 1000 / 2;
+	}
+
+	range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0]));
+
+	for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
+			i < IW_MAX_FREQUENCIES; i++) {
+		range->freq[i].i = i + 1;
+		range->freq[i].m = freq_chan[i] * 100000;
+		range->freq[i].e = 1;
+	}
+	range->num_frequency = i;
+
+	range->min_rts = 0;
+	range->max_rts = 2347;
+	range->min_frag = 256;
+	range->max_frag = 2346;
+
+	range->max_qual.qual = 100;
+	range->max_qual.level = 154;
+	range->max_qual.updated = IW_QUAL_QUAL_UPDATED
+				| IW_QUAL_LEVEL_UPDATED
+				| IW_QUAL_NOISE_INVALID;
+
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = WIRELESS_EXT;
+
+	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+			IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+	return 0;
+}
+
+
+static int rndis_iw_get_name(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	strcpy(wrqu->name, priv->name);
+	return 0;
+}
+
+
+static int rndis_iw_set_essid(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+{
+	struct NDIS_802_11_SSID ssid;
+	int length = wrqu->essid.length;
+	struct usbnet *usbdev = dev->priv;
+
+	devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'",
+		wrqu->essid.flags, wrqu->essid.length, essid);
+
+	if (length > NDIS_802_11_LENGTH_SSID)
+		length = NDIS_802_11_LENGTH_SSID;
+
+	ssid.SsidLength = cpu_to_le32(length);
+	if (length > 0)
+		memcpy(ssid.Ssid, essid, length);
+	else
+		memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID);
+
+	set_assoc_params(usbdev);
+
+	if (!wrqu->essid.flags || length == 0)
+		return disassociate(usbdev, 1);
+	else
+		return set_essid(usbdev, &ssid);
+}
+
+
+static int rndis_iw_get_essid(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+{
+	struct NDIS_802_11_SSID ssid;
+	struct usbnet *usbdev = dev->priv;
+	int ret;
+
+	ret = get_essid(usbdev, &ssid);
+
+	if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) {
+		wrqu->essid.flags = 1;
+		wrqu->essid.length = le32_to_cpu(ssid.SsidLength);
+		memcpy(essid, ssid.Ssid, wrqu->essid.length);
+		essid[wrqu->essid.length] = 0;
+	} else {
+		memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
+		wrqu->essid.flags = 0;
+		wrqu->essid.length = 0;
+	}
+	devdbg(usbdev, "SIOCGIWESSID: %s", essid);
+	return ret;
+}
+
+
+static int rndis_iw_get_bssid(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	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));
+	else
+		devdbg(usbdev, "SIOCGIWAP: <not associated>");
+
+	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+	memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
+
+	return ret;
+}
+
+
+static int rndis_iw_set_bssid(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
+	DECLARE_MAC_BUF(mac);
+	int ret;
+
+	devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid));
+
+	ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
+
+	/* user apps may set ap's mac address, which is not required;
+	 * they may fail to work if this function fails, so return
+	 * success */
+	if (ret)
+		devwarn(usbdev, "setting AP mac address failed (%08X)", ret);
+
+	return 0;
+}
+
+
+static int rndis_iw_set_auth(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct iw_param *p = &wrqu->param;
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	int ret = -ENOTSUPP;
+
+	switch (p->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+		devdbg(usbdev, "SIOCSIWAUTH: WPA_VERSION, %08x", p->value);
+		priv->wpa_version = p->value;
+		ret = 0;
+		break;
+
+	case IW_AUTH_CIPHER_PAIRWISE:
+		devdbg(usbdev, "SIOCSIWAUTH: CIPHER_PAIRWISE, %08x", p->value);
+		priv->wpa_cipher_pair = p->value;
+		ret = 0;
+		break;
+
+	case IW_AUTH_CIPHER_GROUP:
+		devdbg(usbdev, "SIOCSIWAUTH: CIPHER_GROUP, %08x", p->value);
+		priv->wpa_cipher_group = p->value;
+		ret = 0;
+		break;
+
+	case IW_AUTH_KEY_MGMT:
+		devdbg(usbdev, "SIOCSIWAUTH: KEY_MGMT, %08x", p->value);
+		priv->wpa_keymgmt = p->value;
+		ret = 0;
+		break;
+
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+		devdbg(usbdev, "SIOCSIWAUTH: TKIP_COUNTERMEASURES, %08x",
+								p->value);
+		ret = 0;
+		break;
+
+	case IW_AUTH_DROP_UNENCRYPTED:
+		devdbg(usbdev, "SIOCSIWAUTH: DROP_UNENCRYPTED, %08x", p->value);
+		ret = 0;
+		break;
+
+	case IW_AUTH_80211_AUTH_ALG:
+		devdbg(usbdev, "SIOCSIWAUTH: 80211_AUTH_ALG, %08x", p->value);
+		priv->wpa_authalg = p->value;
+		ret = 0;
+		break;
+
+	case IW_AUTH_WPA_ENABLED:
+		devdbg(usbdev, "SIOCSIWAUTH: WPA_ENABLED, %08x", p->value);
+		if (wrqu->param.value)
+			deauthenticate(usbdev);
+		ret = 0;
+		break;
+
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+		devdbg(usbdev, "SIOCSIWAUTH: RX_UNENCRYPTED_EAPOL, %08x",
+								p->value);
+		ret = 0;
+		break;
+
+	case IW_AUTH_ROAMING_CONTROL:
+		devdbg(usbdev, "SIOCSIWAUTH: ROAMING_CONTROL, %08x", p->value);
+		ret = 0;
+		break;
+
+	case IW_AUTH_PRIVACY_INVOKED:
+		devdbg(usbdev, "SIOCSIWAUTH: invalid cmd %d",
+				wrqu->param.flags & IW_AUTH_INDEX);
+		return -EOPNOTSUPP;
+
+	default:
+		devdbg(usbdev, "SIOCSIWAUTH: UNKNOWN  %08x, %08x",
+			p->flags & IW_AUTH_INDEX, p->value);
+	}
+	return ret;
+}
+
+
+static int rndis_iw_get_auth(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct iw_param *p = &wrqu->param;
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	switch (p->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+		p->value = priv->wpa_version;
+		break;
+	case IW_AUTH_CIPHER_PAIRWISE:
+		p->value = priv->wpa_cipher_pair;
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		p->value = priv->wpa_cipher_group;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		p->value = priv->wpa_keymgmt;
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		p->value = priv->wpa_authalg;
+		break;
+	default:
+		devdbg(usbdev, "SIOCGIWAUTH: invalid cmd %d",
+				wrqu->param.flags & IW_AUTH_INDEX);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+
+static int rndis_iw_get_mode(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	switch (priv->infra_mode) {
+	case Ndis802_11IBSS:
+		wrqu->mode = IW_MODE_ADHOC;
+		break;
+	case Ndis802_11Infrastructure:
+		wrqu->mode = IW_MODE_INFRA;
+		break;
+	/*case Ndis802_11AutoUnknown:*/
+	default:
+		wrqu->mode = IW_MODE_AUTO;
+		break;
+	}
+	devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode);
+	return 0;
+}
+
+
+static int rndis_iw_set_mode(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	int mode;
+
+	devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode);
+
+	switch (wrqu->mode) {
+	case IW_MODE_ADHOC:
+		mode = Ndis802_11IBSS;
+		break;
+	case IW_MODE_INFRA:
+		mode = Ndis802_11Infrastructure;
+		break;
+	/*case IW_MODE_AUTO:*/
+	default:
+		mode = Ndis802_11AutoUnknown;
+		break;
+	}
+
+	return set_infra_mode(usbdev, mode);
+}
+
+
+static int rndis_iw_set_encode(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	int ret, index, key_len;
+	u8 *key;
+
+	index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
+
+	/* iwconfig gives index as 1 - N */
+	if (index > 0)
+		index--;
+	else
+		index = priv->encr_tx_key_index;
+
+	if (index < 0 || index >= 4) {
+		devwarn(usbdev, "encryption index out of range (%u)", index);
+		return -EINVAL;
+	}
+
+	/* remove key if disabled */
+	if (wrqu->data.flags & IW_ENCODE_DISABLED) {
+		if (remove_key(usbdev, index, NULL))
+			return -EINVAL;
+		else
+			return 0;
+	}
+
+	/* global encryption state (for all keys) */
+	if (wrqu->data.flags & IW_ENCODE_OPEN)
+		ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
+						IW_AUTH_ALG_OPEN_SYSTEM);
+	else /*if (wrqu->data.flags & IW_ENCODE_RESTRICTED)*/
+		ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
+						IW_AUTH_ALG_SHARED_KEY);
+	if (ret != 0)
+		return ret;
+
+	if (wrqu->data.length > 0) {
+		key_len = wrqu->data.length;
+		key = extra;
+	} else {
+		/* must be set as tx key */
+		if (priv->encr_key_len[index] == 0)
+			return -EINVAL;
+		key_len = priv->encr_key_len[index];
+		key = priv->encr_keys[index];
+		priv->encr_tx_key_index = index;
+	}
+
+	if (add_wep_key(usbdev, key, key_len, index) != 0)
+		return -EINVAL;
+
+	if (index == priv->encr_tx_key_index)
+		/* ndis drivers want essid to be set after setting encr */
+		set_essid(usbdev, &priv->essid);
+
+	return 0;
+}
+
+
+static int rndis_iw_set_encode_ext(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct NDIS_802_11_KEY ndis_key;
+	int i, keyidx, ret;
+	u8 *addr;
+
+	keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
+
+	/* iwconfig gives index as 1 - N */
+	if (keyidx)
+		keyidx--;
+	else
+		keyidx = priv->encr_tx_key_index;
+
+	if (keyidx < 0 || keyidx >= 4)
+		return -EINVAL;
+
+	if (ext->alg == WPA_ALG_WEP) {
+		if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+			priv->encr_tx_key_index = keyidx;
+		return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
+	}
+
+	if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
+	    ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
+		return remove_key(usbdev, keyidx, NULL);
+
+	if (ext->key_len > sizeof(ndis_key.KeyMaterial))
+		return -1;
+
+	memset(&ndis_key, 0, sizeof(ndis_key));
+
+	ndis_key.Length = cpu_to_le32(sizeof(ndis_key) -
+				sizeof(ndis_key.KeyMaterial) + ext->key_len);
+	ndis_key.KeyLength = cpu_to_le32(ext->key_len);
+	ndis_key.KeyIndex = cpu_to_le32(keyidx);
+
+	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+		for (i = 0; i < 6; i++)
+			ndis_key.KeyRSC |=
+				cpu_to_le64(ext->rx_seq[i] << (i * 8));
+		ndis_key.KeyIndex |= cpu_to_le32(1 << 29);
+	}
+
+	addr = ext->addr.sa_data;
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+		/* group key */
+		if (priv->infra_mode == Ndis802_11IBSS)
+			memset(ndis_key.Bssid, 0xff, ETH_ALEN);
+		else
+			get_bssid(usbdev, ndis_key.Bssid);
+	} else {
+		/* pairwise key */
+		ndis_key.KeyIndex |= cpu_to_le32(1 << 30);
+		memcpy(ndis_key.Bssid, addr, ETH_ALEN);
+	}
+
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
+
+	if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
+		/* wpa_supplicant gives us the Michael MIC RX/TX keys in
+		 * different order than NDIS spec, so swap the order here. */
+		memcpy(ndis_key.KeyMaterial, ext->key, 16);
+		memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8);
+		memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8);
+	} else
+		memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len);
+
+	ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
+					le32_to_cpu(ndis_key.Length));
+	devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
+	if (ret != 0)
+		return ret;
+
+	priv->encr_key_len[keyidx] = ext->key_len;
+	memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len);
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		priv->encr_tx_key_index = keyidx;
+
+	return 0;
+}
+
+
+static int rndis_iw_set_scan(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct iw_param *param = &wrqu->param;
+	struct usbnet *usbdev = dev->priv;
+	union iwreq_data evt;
+	int ret = -EINVAL;
+	__le32 tmp;
+
+	devdbg(usbdev, "SIOCSIWSCAN");
+
+	if (param->flags == 0) {
+		tmp = ccpu2(1);
+		ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
+								sizeof(tmp));
+		evt.data.flags = 0;
+		evt.data.length = 0;
+		wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL);
+	}
+	return ret;
+}
+
+
+static char *rndis_translate_scan(struct net_device *dev,
+    char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid)
+{
+#ifdef DEBUG
+	struct usbnet *usbdev = dev->priv;
+#endif
+	struct ieee80211_info_element *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->MacAddress));
+	iwe.cmd = SIOCGIWAP;
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN);
+	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+	devdbg(usbdev, "SSID(%d) %s",
+		le32_to_cpu(bssid->Ssid.SsidLength),
+		bssid->Ssid.Ssid);
+	iwe.cmd = SIOCGIWESSID;
+	iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength);
+	iwe.u.essid.flags = 1;
+	cev = iwe_stream_add_point(cev, end_buf, &iwe,
+						bssid->Ssid.Ssid);
+
+	devdbg(usbdev, "MODE %d",
+			le32_to_cpu(bssid->InfrastructureMode));
+	iwe.cmd = SIOCGIWMODE;
+	switch (le32_to_cpu(bssid->InfrastructureMode)) {
+	case Ndis802_11IBSS:
+		iwe.u.mode = IW_MODE_ADHOC;
+		break;
+	case Ndis802_11Infrastructure:
+		iwe.u.mode = IW_MODE_INFRA;
+		break;
+	/*case Ndis802_11AutoUnknown:*/
+	default:
+		iwe.u.mode = IW_MODE_AUTO;
+		break;
+	}
+	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+
+	devdbg(usbdev, "FREQ %d kHz",
+		le32_to_cpu(bssid->Configuration.DSConfig));
+	iwe.cmd = SIOCGIWFREQ;
+	dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig),
+								&iwe.u.freq);
+	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+	devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi));
+	iwe.cmd = IWEVQUAL;
+	iwe.u.qual.qual  = level_to_qual(le32_to_cpu(bssid->Rssi));
+	iwe.u.qual.level = le32_to_cpu(bssid->Rssi);
+	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+			| IW_QUAL_LEVEL_UPDATED
+			| IW_QUAL_NOISE_INVALID;
+	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+	devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy));
+	iwe.cmd = SIOCGIWENCODE;
+	iwe.u.data.length = 0;
+	if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll)
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	else
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+
+	cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+
+	devdbg(usbdev, "RATES:");
+	current_val = cev + IW_EV_LCP_LEN;
+	iwe.cmd = SIOCGIWRATE;
+	for (i = 0; i < sizeof(bssid->SupportedRates); i++) {
+		if (bssid->SupportedRates[i] & 0x7f) {
+			iwe.u.bitrate.value =
+				((bssid->SupportedRates[i] & 0x7f) *
+				500000);
+			devdbg(usbdev, " %d", iwe.u.bitrate.value);
+			current_val = iwe_stream_add_value(cev,
+				current_val, end_buf, &iwe,
+				IW_EV_PARAM_LEN);
+		}
+	}
+
+	if ((current_val - cev) > IW_EV_LCP_LEN)
+		cev = current_val;
+
+	beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod);
+	devdbg(usbdev, "BCN_INT %d", beacon);
+	iwe.cmd = IWEVCUSTOM;
+	snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
+	iwe.u.data.length = strlen(sbuf);
+	cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+
+	atim = le32_to_cpu(bssid->Configuration.ATIMWindow);
+	devdbg(usbdev, "ATIM %d", atim);
+	iwe.cmd = IWEVCUSTOM;
+	snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
+	iwe.u.data.length = strlen(sbuf);
+	cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+
+	ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs));
+	ie_len = min(bssid_len - (int)sizeof(*bssid),
+					(int)le32_to_cpu(bssid->IELength));
+	ie_len -= sizeof(struct NDIS_802_11_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) {
+			devdbg(usbdev, "IE: WPA%d",
+					(ie->id == MFIE_TYPE_RSN) ? 2 : 1);
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN);
+			cev = iwe_stream_add_point(cev, end_buf, &iwe,
+								(u8 *)ie);
+		}
+
+		ie_len -= sizeof(*ie) + ie->len;
+		ie = (struct ieee80211_info_element *)&ie->data[ie->len];
+	}
+
+	return cev;
+}
+
+
+static int rndis_iw_get_scan(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	void *buf = NULL;
+	char *cev = extra;
+	struct NDIS_802_11_BSSID_LIST_EX *bssid_list;
+	struct NDIS_WLAN_BSSID_EX *bssid;
+	int ret = -EINVAL, len, count, bssid_len;
+
+	devdbg(usbdev, "SIOCGIWSCAN");
+
+	len = CONTROL_BUFFER_SIZE;
+	buf = kmalloc(len, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
+
+	if (ret != 0)
+		goto out;
+
+	bssid_list = buf;
+	bssid = bssid_list->Bssid;
+	bssid_len = le32_to_cpu(bssid->Length);
+	count = le32_to_cpu(bssid_list->NumberOfItems);
+	devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
+
+	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
+		cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
+									bssid);
+		bssid = (void *)bssid + bssid_len;
+		bssid_len = le32_to_cpu(bssid->Length);
+		count--;
+	}
+
+out:
+	wrqu->data.length = cev - extra;
+	wrqu->data.flags = 0;
+	kfree(buf);
+	return ret;
+}
+
+
+static int rndis_iw_set_genie(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	int ret = 0;
+
+#ifdef DEBUG
+	int j;
+	u8 *gie = extra;
+	for (j = 0; j < wrqu->data.length; j += 8)
+		devdbg(usbdev,
+			"SIOCSIWGENIE %04x - "
+			"%02x %02x %02x %02x %02x %02x %02x %02x", j,
+			gie[j + 0], gie[j + 1], gie[j + 2], gie[j + 3],
+			gie[j + 4], gie[j + 5], gie[j + 6], gie[j + 7]);
+#endif
+	/* clear existing IEs */
+	if (priv->wpa_ie_len) {
+		kfree(priv->wpa_ie);
+		priv->wpa_ie_len = 0;
+	}
+
+	/* set new IEs */
+	priv->wpa_ie = kmalloc(wrqu->data.length, GFP_KERNEL);
+	if (priv->wpa_ie) {
+		priv->wpa_ie_len = wrqu->data.length;
+		memcpy(priv->wpa_ie, extra, priv->wpa_ie_len);
+	} else
+		ret = -ENOMEM;
+	return ret;
+}
+
+
+static int rndis_iw_get_genie(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	devdbg(usbdev, "SIOCGIWGENIE");
+
+	if (priv->wpa_ie_len == 0 || priv->wpa_ie == NULL) {
+		wrqu->data.length = 0;
+		return 0;
+	}
+
+	if (wrqu->data.length < priv->wpa_ie_len)
+		return -E2BIG;
+
+	wrqu->data.length = priv->wpa_ie_len;
+	memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
+
+	return 0;
+}
+
+
+static int rndis_iw_set_rts(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	__le32 tmp;
+	devdbg(usbdev, "SIOCSIWRTS");
+
+	tmp = cpu_to_le32(wrqu->rts.value);
+	return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp,
+								sizeof(tmp));
+}
+
+
+static int rndis_iw_get_rts(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	__le32 tmp;
+	int len, ret;
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, &len);
+	if (ret == 0) {
+		wrqu->rts.value = le32_to_cpu(tmp);
+		wrqu->rts.flags = 1;
+		wrqu->rts.disabled = 0;
+	}
+
+	devdbg(usbdev, "SIOCGIWRTS: %d", wrqu->rts.value);
+
+	return ret;
+}
+
+
+static int rndis_iw_set_frag(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	__le32 tmp;
+
+	devdbg(usbdev, "SIOCSIWFRAG");
+
+	tmp = cpu_to_le32(wrqu->frag.value);
+	return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
+								sizeof(tmp));
+}
+
+
+static int rndis_iw_get_frag(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	__le32 tmp;
+	int len, ret;
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
+									&len);
+	if (ret == 0) {
+		wrqu->frag.value = le32_to_cpu(tmp);
+		wrqu->frag.flags = 1;
+		wrqu->frag.disabled = 0;
+	}
+	devdbg(usbdev, "SIOCGIWFRAG: %d", wrqu->frag.value);
+	return ret;
+}
+
+
+static int rndis_iw_set_nick(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	devdbg(usbdev, "SIOCSIWNICK");
+
+	priv->nick_len = wrqu->data.length;
+	if (priv->nick_len > 32)
+		priv->nick_len = 32;
+
+	memcpy(priv->nick, extra, priv->nick_len);
+	return 0;
+}
+
+
+static int rndis_iw_get_nick(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	wrqu->data.flags = 1;
+	wrqu->data.length = priv->nick_len;
+	memcpy(extra, priv->nick, priv->nick_len);
+
+	devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick);
+
+	return 0;
+}
+
+
+static int rndis_iw_set_freq(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct NDIS_802_11_CONFIGURATION config;
+	unsigned int dsconfig;
+	int len, ret;
+
+	/* this OID is valid only when not associated */
+	if (is_associated(usbdev))
+		return 0;
+
+	dsconfig = 0;
+	if (freq_to_dsconfig(&wrqu->freq, &dsconfig))
+		return -EINVAL;
+
+	len = sizeof(config);
+	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+	if (ret != 0) {
+		devdbg(usbdev, "SIOCSIWFREQ: querying configuration failed");
+		return 0;
+	}
+
+	config.DSConfig = cpu_to_le32(dsconfig);
+
+	devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
+	return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
+								sizeof(config));
+}
+
+
+static int rndis_iw_get_freq(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct NDIS_802_11_CONFIGURATION config;
+	int len, ret;
+
+	len = sizeof(config);
+	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+	if (ret == 0)
+		dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq);
+
+	devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
+	return ret;
+}
+
+
+static int rndis_iw_get_txpower(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tx_power;
+	int ret = 0, len;
+
+	if (priv->radio_on) {
+		if (priv->caps & CAP_SUPPORT_TXPOWER) {
+			len = sizeof(tx_power);
+			ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
+							&tx_power, &len);
+			if (ret != 0)
+				return ret;
+		} else
+			/* fake incase not supported */
+			tx_power = cpu_to_le32(get_bcm4320_power(priv));
+
+		wrqu->txpower.flags = IW_TXPOW_MWATT;
+		wrqu->txpower.value = le32_to_cpu(tx_power);
+		wrqu->txpower.disabled = 0;
+	} else {
+		wrqu->txpower.flags = IW_TXPOW_MWATT;
+		wrqu->txpower.value = 0;
+		wrqu->txpower.disabled = 1;
+	}
+
+	devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
+
+	return ret;
+}
+
+
+static int rndis_iw_set_txpower(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	__le32 tx_power = 0;
+	int ret = 0;
+
+	if (!wrqu->txpower.disabled) {
+		if (wrqu->txpower.flags == IW_TXPOW_MWATT)
+			tx_power = cpu_to_le32(wrqu->txpower.value);
+		else { /* wrqu->txpower.flags == IW_TXPOW_DBM */
+			if (wrqu->txpower.value > 20)
+				tx_power = cpu_to_le32(128);
+			else if (wrqu->txpower.value < -43)
+				tx_power = cpu_to_le32(127);
+			else {
+				signed char tmp;
+				tmp = wrqu->txpower.value;
+				tmp = -12 - tmp;
+				tmp <<= 2;
+				tx_power = cpu_to_le32((unsigned char)tmp);
+			}
+		}
+	}
+
+	devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
+
+	if (le32_to_cpu(tx_power) != 0) {
+		if (priv->caps & CAP_SUPPORT_TXPOWER) {
+			/* turn radio on first */
+			if (!priv->radio_on)
+				disassociate(usbdev, 1);
+
+			ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
+						&tx_power, sizeof(tx_power));
+			if (ret != 0)
+				ret = -EOPNOTSUPP;
+			return ret;
+		} else {
+			/* txpower unsupported, just turn radio on */
+			if (!priv->radio_on)
+				return disassociate(usbdev, 1);
+			return 0; /* all ready on */
+		}
+	}
+
+	/* tx_power == 0, turn off radio */
+	return disassociate(usbdev, 0);
+}
+
+
+static int rndis_iw_get_rate(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	__le32 tmp;
+	int ret, len;
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len);
+	if (ret == 0) {
+		wrqu->bitrate.value = le32_to_cpu(tmp) * 100;
+		wrqu->bitrate.disabled = 0;
+		wrqu->bitrate.flags = 1;
+	}
+	return ret;
+}
+
+
+static int rndis_iw_set_mlme(struct net_device *dev,
+    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+	unsigned char bssid[ETH_ALEN];
+
+	get_bssid(usbdev, bssid);
+
+	if (memcmp(bssid, mlme->addr.sa_data, ETH_ALEN))
+		return -EINVAL;
+
+	switch (mlme->cmd) {
+	case IW_MLME_DEAUTH:
+		return deauthenticate(usbdev);
+	case IW_MLME_DISASSOC:
+		return disassociate(usbdev, priv->radio_on);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+
+static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->stats_lock, flags);
+	memcpy(&priv->iwstats, &priv->privstats, sizeof(priv->iwstats));
+	spin_unlock_irqrestore(&priv->stats_lock, flags);
+
+	return &priv->iwstats;
+}
+
+
+#define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
+static const iw_handler rndis_iw_handler[] =
+{
+	IW_IOCTL(SIOCSIWCOMMIT)    = rndis_iw_commit,
+	IW_IOCTL(SIOCGIWNAME)      = rndis_iw_get_name,
+	IW_IOCTL(SIOCSIWFREQ)      = rndis_iw_set_freq,
+	IW_IOCTL(SIOCGIWFREQ)      = rndis_iw_get_freq,
+	IW_IOCTL(SIOCSIWMODE)      = rndis_iw_set_mode,
+	IW_IOCTL(SIOCGIWMODE)      = rndis_iw_get_mode,
+	IW_IOCTL(SIOCGIWRANGE)     = rndis_iw_get_range,
+	IW_IOCTL(SIOCSIWAP)        = rndis_iw_set_bssid,
+	IW_IOCTL(SIOCGIWAP)        = rndis_iw_get_bssid,
+	IW_IOCTL(SIOCSIWSCAN)      = rndis_iw_set_scan,
+	IW_IOCTL(SIOCGIWSCAN)      = rndis_iw_get_scan,
+	IW_IOCTL(SIOCSIWESSID)     = rndis_iw_set_essid,
+	IW_IOCTL(SIOCGIWESSID)     = rndis_iw_get_essid,
+	IW_IOCTL(SIOCSIWNICKN)     = rndis_iw_set_nick,
+	IW_IOCTL(SIOCGIWNICKN)     = rndis_iw_get_nick,
+	IW_IOCTL(SIOCGIWRATE)      = rndis_iw_get_rate,
+	IW_IOCTL(SIOCSIWRTS)       = rndis_iw_set_rts,
+	IW_IOCTL(SIOCGIWRTS)       = rndis_iw_get_rts,
+	IW_IOCTL(SIOCSIWFRAG)      = rndis_iw_set_frag,
+	IW_IOCTL(SIOCGIWFRAG)      = rndis_iw_get_frag,
+	IW_IOCTL(SIOCSIWTXPOW)     = rndis_iw_set_txpower,
+	IW_IOCTL(SIOCGIWTXPOW)     = rndis_iw_get_txpower,
+	IW_IOCTL(SIOCSIWENCODE)    = rndis_iw_set_encode,
+	IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext,
+	IW_IOCTL(SIOCSIWAUTH)      = rndis_iw_set_auth,
+	IW_IOCTL(SIOCGIWAUTH)      = rndis_iw_get_auth,
+	IW_IOCTL(SIOCSIWGENIE)     = rndis_iw_set_genie,
+	IW_IOCTL(SIOCGIWGENIE)     = rndis_iw_get_genie,
+	IW_IOCTL(SIOCSIWMLME)      = rndis_iw_set_mlme,
+};
+
+static const iw_handler rndis_wext_private_handler[] = {
+};
+
+static const struct iw_priv_args rndis_wext_private_args[] = {
+};
+
+
+static const struct iw_handler_def rndis_iw_handlers = {
+	.num_standard = ARRAY_SIZE(rndis_iw_handler),
+	.num_private  = ARRAY_SIZE(rndis_wext_private_handler),
+	.num_private_args = ARRAY_SIZE(rndis_wext_private_args),
+	.standard = (iw_handler *)rndis_iw_handler,
+	.private  = (iw_handler *)rndis_wext_private_handler,
+	.private_args = (struct iw_priv_args *)rndis_wext_private_args,
+	.get_wireless_stats = rndis_get_wireless_stats,
+};
+
+
+static void rndis_wext_worker(struct work_struct *work)
+{
+	struct rndis_wext_private *priv =
+		container_of(work, struct rndis_wext_private, work);
+	struct usbnet *usbdev = priv->usbdev;
+	union iwreq_data evt;
+	unsigned char bssid[ETH_ALEN];
+	int ret;
+
+	if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) {
+		ret = get_bssid(usbdev, bssid);
+
+		if (!ret) {
+			evt.data.flags = 0;
+			evt.data.length = 0;
+			memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
+			wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
+		}
+	}
+
+	if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
+		set_multicast_list(usbdev);
+}
+
+static void rndis_wext_set_multicast_list(struct net_device *dev)
+{
+	struct usbnet *usbdev = dev->priv;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+	set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending);
+	queue_work(priv->workqueue, &priv->work);
+}
+
+static void rndis_wext_link_change(struct usbnet *dev, int state)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	union iwreq_data evt;
+
+	if (state) {
+		/* queue work to avoid recursive calls into rndis_command */
+		set_bit(WORK_CONNECTION_EVENT, &priv->work_pending);
+		queue_work(priv->workqueue, &priv->work);
+	} else {
+		evt.data.flags = 0;
+		evt.data.length = 0;
+		memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
+		wireless_send_event(dev->net, SIOCGIWAP, &evt, NULL);
+	}
+}
+
+
+static int rndis_wext_get_caps(struct usbnet *dev)
+{
+	struct {
+		__le32	num_items;
+		__le32	items[8];
+	} networks_supported;
+	int len, retval, i, n;
+	__le32 tx_power;
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+
+	/* determine if supports setting txpower */
+	len = sizeof(tx_power);
+	retval = rndis_query_oid(dev, OID_802_11_TX_POWER_LEVEL, &tx_power,
+								&len);
+	if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
+		priv->caps |= CAP_SUPPORT_TXPOWER;
+
+	/* determine supported modes */
+	len = sizeof(networks_supported);
+	retval = rndis_query_oid(dev, OID_802_11_NETWORK_TYPES_SUPPORTED,
+						&networks_supported, &len);
+	if (retval >= 0) {
+		n = le32_to_cpu(networks_supported.num_items);
+		if (n > 8)
+			n = 8;
+		for (i = 0; i < n; i++) {
+			switch (le32_to_cpu(networks_supported.items[i])) {
+			case Ndis802_11FH:
+			case Ndis802_11DS:
+				priv->caps |= CAP_MODE_80211B;
+				break;
+			case Ndis802_11OFDM5:
+				priv->caps |= CAP_MODE_80211A;
+				break;
+			case Ndis802_11OFDM24:
+				priv->caps |= CAP_MODE_80211G;
+				break;
+			}
+		}
+		if (priv->caps & CAP_MODE_80211A)
+			strcat(priv->name, "a");
+		if (priv->caps & CAP_MODE_80211B)
+			strcat(priv->name, "b");
+		if (priv->caps & CAP_MODE_80211G)
+			strcat(priv->name, "g");
+	}
+
+	return retval;
+}
+
+
+#define STATS_UPDATE_JIFFIES (HZ)
+static void rndis_update_wireless_stats(struct work_struct *work)
+{
+	struct rndis_wext_private *priv =
+		container_of(work, struct rndis_wext_private, stats_work.work);
+	struct usbnet *usbdev = priv->usbdev;
+	struct iw_statistics iwstats;
+	__le32 rssi, tmp;
+	int len, ret, bitrate, j;
+	unsigned long flags;
+	int update_jiffies = STATS_UPDATE_JIFFIES;
+	void *buf;
+
+	spin_lock_irqsave(&priv->stats_lock, flags);
+	memcpy(&iwstats, &priv->privstats, sizeof(iwstats));
+	spin_unlock_irqrestore(&priv->stats_lock, flags);
+
+	/* only update stats when connected */
+	if (!is_associated(usbdev)) {
+		iwstats.qual.qual = 0;
+		iwstats.qual.level = 0;
+		iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
+				| IW_QUAL_LEVEL_UPDATED
+				| IW_QUAL_NOISE_INVALID
+				| IW_QUAL_QUAL_INVALID
+				| IW_QUAL_LEVEL_INVALID;
+		goto end;
+	}
+
+	len = sizeof(rssi);
+	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+
+	devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret,
+							le32_to_cpu(rssi));
+	if (ret == 0) {
+		memset(&iwstats.qual, 0, sizeof(iwstats.qual));
+		iwstats.qual.qual  = level_to_qual(le32_to_cpu(rssi));
+		iwstats.qual.level = le32_to_cpu(rssi);
+		iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
+				| IW_QUAL_LEVEL_UPDATED
+				| IW_QUAL_NOISE_INVALID;
+	}
+
+	memset(&iwstats.discard, 0, sizeof(iwstats.discard));
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_GEN_XMIT_ERROR, &tmp, &len);
+	if (ret == 0)
+		iwstats.discard.misc += le32_to_cpu(tmp);
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_GEN_RCV_ERROR, &tmp, &len);
+	if (ret == 0)
+		iwstats.discard.misc += le32_to_cpu(tmp);
+
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_GEN_RCV_NO_BUFFER, &tmp, &len);
+	if (ret == 0)
+		iwstats.discard.misc += le32_to_cpu(tmp);
+
+	/* Workaround transfer stalls on poor quality links. */
+	len = sizeof(tmp);
+	ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len);
+	if (ret == 0) {
+		bitrate = le32_to_cpu(tmp) * 100;
+		if (bitrate > 11000000)
+			goto end;
+
+		/* Decrease stats worker interval to catch stalls.
+		 * faster. Faster than 400-500ms causes packet loss,
+		 * Slower doesn't catch stalls fast enough.
+		 */
+		j = msecs_to_jiffies(priv->param_workaround_interval);
+		if (j > STATS_UPDATE_JIFFIES)
+			j = STATS_UPDATE_JIFFIES;
+		else if (j <= 0)
+			j = 1;
+		update_jiffies = j;
+
+		/* Send scan OID. Use of both OIDs is required to get device
+		 * working.
+		 */
+		tmp = ccpu2(1);
+		rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
+								sizeof(tmp));
+
+		len = CONTROL_BUFFER_SIZE;
+		buf = kmalloc(len, GFP_KERNEL);
+		if (!buf)
+			goto end;
+
+		rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
+		kfree(buf);
+	}
+end:
+	spin_lock_irqsave(&priv->stats_lock, flags);
+	memcpy(&priv->privstats, &iwstats, sizeof(iwstats));
+	spin_unlock_irqrestore(&priv->stats_lock, flags);
+
+	if (update_jiffies >= HZ)
+		update_jiffies = round_jiffies_relative(update_jiffies);
+	else {
+		j = round_jiffies_relative(update_jiffies);
+		if (abs(j - update_jiffies) <= 10)
+			update_jiffies = j;
+	}
+
+	queue_delayed_work(priv->workqueue, &priv->stats_work, update_jiffies);
+}
+
+
+static int bcm4320_early_init(struct usbnet *dev)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	char buf[8];
+
+	/* Early initialization settings, setting these won't have effect
+	 * if called after generic_rndis_bind().
+	 */
+
+	priv->param_country[0] = modparam_country[0];
+	priv->param_country[1] = modparam_country[1];
+	priv->param_country[2] = 0;
+	priv->param_frameburst   = modparam_frameburst;
+	priv->param_afterburner  = modparam_afterburner;
+	priv->param_power_save   = modparam_power_save;
+	priv->param_power_output = modparam_power_output;
+	priv->param_roamtrigger  = modparam_roamtrigger;
+	priv->param_roamdelta    = modparam_roamdelta;
+	priv->param_workaround_interval = modparam_workaround_interval;
+
+	priv->param_country[0] = toupper(priv->param_country[0]);
+	priv->param_country[1] = toupper(priv->param_country[1]);
+	/* doesn't support EU as country code, use FI instead */
+	if (!strcmp(priv->param_country, "EU"))
+		strcpy(priv->param_country, "FI");
+
+	if (priv->param_power_save < 0)
+		priv->param_power_save = 0;
+	else if (priv->param_power_save > 2)
+		priv->param_power_save = 2;
+
+	if (priv->param_roamtrigger < -80)
+		priv->param_roamtrigger = -80;
+	else if (priv->param_roamtrigger > -60)
+		priv->param_roamtrigger = -60;
+
+	if (priv->param_roamdelta < 0)
+		priv->param_roamdelta = 0;
+	else if (priv->param_roamdelta > 2)
+		priv->param_roamdelta = 2;
+
+	if (priv->param_workaround_interval < 0)
+		priv->param_workaround_interval = 500;
+
+	rndis_set_config_parameter_str(dev, "Country", priv->param_country);
+	rndis_set_config_parameter_str(dev, "FrameBursting",
+					priv->param_frameburst ? "1" : "0");
+	rndis_set_config_parameter_str(dev, "Afterburner",
+					priv->param_afterburner ? "1" : "0");
+	sprintf(buf, "%d", priv->param_power_save);
+	rndis_set_config_parameter_str(dev, "PowerSaveMode", buf);
+	sprintf(buf, "%d", priv->param_power_output);
+	rndis_set_config_parameter_str(dev, "PwrOut", buf);
+	sprintf(buf, "%d", priv->param_roamtrigger);
+	rndis_set_config_parameter_str(dev, "RoamTrigger", buf);
+	sprintf(buf, "%d", priv->param_roamdelta);
+	rndis_set_config_parameter_str(dev, "RoamDelta", buf);
+
+	return 0;
+}
+
+
+static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct net_device *net = dev->net;
+	struct rndis_wext_private *priv;
+	int retval, len;
+	__le32 tmp;
+
+	/* allocate rndis private data */
+	priv = kmalloc(sizeof(struct rndis_wext_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* These have to be initialized before calling generic_rndis_bind().
+	 * Otherwise we'll be in big trouble in rndis_wext_early_init().
+	 */
+	dev->driver_priv = priv;
+	memset(priv, 0, sizeof(*priv));
+	memset(priv->name, 0, sizeof(priv->name));
+	strcpy(priv->name, "IEEE802.11");
+	net->wireless_handlers = &rndis_iw_handlers;
+	priv->usbdev = dev;
+
+	mutex_init(&priv->command_lock);
+	spin_lock_init(&priv->stats_lock);
+
+	/* try bind rndis_host */
+	retval = generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_WIRELESS);
+	if (retval < 0)
+		goto fail;
+
+	/* generic_rndis_bind set packet filter to multicast_all+
+	 * promisc mode which doesn't work well for our devices (device
+	 * picks up rssi to closest station instead of to access point).
+	 *
+	 * rndis_host wants to avoid all OID as much as possible
+	 * so do promisc/multicast handling in rndis_wext.
+	 */
+	dev->net->set_multicast_list = rndis_wext_set_multicast_list;
+	tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
+	retval = rndis_set_oid(dev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
+								sizeof(tmp));
+
+	len = sizeof(tmp);
+	retval = rndis_query_oid(dev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, &len);
+	priv->multicast_size = le32_to_cpu(tmp);
+	if (retval < 0 || priv->multicast_size < 0)
+		priv->multicast_size = 0;
+	if (priv->multicast_size > 0)
+		dev->net->flags |= IFF_MULTICAST;
+	else
+		dev->net->flags &= ~IFF_MULTICAST;
+
+	priv->iwstats.qual.qual = 0;
+	priv->iwstats.qual.level = 0;
+	priv->iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
+					| IW_QUAL_LEVEL_UPDATED
+					| IW_QUAL_NOISE_INVALID
+					| IW_QUAL_QUAL_INVALID
+					| IW_QUAL_LEVEL_INVALID;
+
+	rndis_wext_get_caps(dev);
+	set_default_iw_params(dev);
+
+	/* turn radio on */
+	priv->radio_on = 1;
+	disassociate(dev, 1);
+
+	/* because rndis_command() sleeps we need to use workqueue */
+	priv->workqueue = create_singlethread_workqueue("rndis_wlan");
+	INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
+	queue_delayed_work(priv->workqueue, &priv->stats_work,
+		round_jiffies_relative(STATS_UPDATE_JIFFIES));
+	INIT_WORK(&priv->work, rndis_wext_worker);
+
+	return 0;
+
+fail:
+	kfree(priv);
+	return retval;
+}
+
+
+static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+
+	/* turn radio off */
+	disassociate(dev, 0);
+
+	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_work_sync(&priv->work);
+	flush_workqueue(priv->workqueue);
+	destroy_workqueue(priv->workqueue);
+
+	if (priv && priv->wpa_ie_len)
+		kfree(priv->wpa_ie);
+	kfree(priv);
+
+	rndis_unbind(dev, intf);
+}
+
+
+static int rndis_wext_reset(struct usbnet *dev)
+{
+	return deauthenticate(dev);
+}
+
+
+static const struct driver_info	bcm4320b_info = {
+	.description =	"Wireless RNDIS device, BCM4320b based",
+	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+	.bind =		rndis_wext_bind,
+	.unbind =	rndis_wext_unbind,
+	.status =	rndis_status,
+	.rx_fixup =	rndis_rx_fixup,
+	.tx_fixup =	rndis_tx_fixup,
+	.reset =	rndis_wext_reset,
+	.early_init =	bcm4320_early_init,
+	.link_change =	rndis_wext_link_change,
+};
+
+static const struct driver_info	bcm4320a_info = {
+	.description =	"Wireless RNDIS device, BCM4320a based",
+	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+	.bind =		rndis_wext_bind,
+	.unbind =	rndis_wext_unbind,
+	.status =	rndis_status,
+	.rx_fixup =	rndis_rx_fixup,
+	.tx_fixup =	rndis_tx_fixup,
+	.reset =	rndis_wext_reset,
+	.early_init =	bcm4320_early_init,
+	.link_change =	rndis_wext_link_change,
+};
+
+static const struct driver_info rndis_wext_info = {
+	.description =	"Wireless RNDIS device",
+	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+	.bind =		rndis_wext_bind,
+	.unbind =	rndis_wext_unbind,
+	.status =	rndis_status,
+	.rx_fixup =	rndis_rx_fixup,
+	.tx_fixup =	rndis_tx_fixup,
+	.reset =	rndis_wext_reset,
+	.early_init =	bcm4320_early_init,
+	.link_change =	rndis_wext_link_change,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products [] = {
+#define	RNDIS_MASTER_INTERFACE \
+	.bInterfaceClass	= USB_CLASS_COMM, \
+	.bInterfaceSubClass	= 2 /* ACM */, \
+	.bInterfaceProtocol	= 0x0ff
+
+/* INF driver for these devices have DriverVer >= 4.xx.xx.xx and many custom
+ * parameters available. Chipset marked as 'BCM4320SKFBG' in NDISwrapper-wiki.
+ */
+{
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0411,
+	.idProduct		= 0x00bc,	/* Buffalo WLI-U2-KG125S */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0baf,
+	.idProduct		= 0x011b,	/* U.S. Robotics USR5421 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x050d,
+	.idProduct		= 0x011b,	/* Belkin F5D7051 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x1799,	/* Belkin has two vendor ids */
+	.idProduct		= 0x011b,	/* Belkin F5D7051 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x13b1,
+	.idProduct		= 0x0014,	/* Linksys WUSB54GSv2 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x13b1,
+	.idProduct		= 0x0026,	/* Linksys WUSB54GSC */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0b05,
+	.idProduct		= 0x1717,	/* Asus WL169gE */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0a5c,
+	.idProduct		= 0xd11b,	/* Eminent EM4045 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x1690,
+	.idProduct		= 0x0715,	/* BT Voyager 1055 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320b_info,
+},
+/* These devices have DriverVer < 4.xx.xx.xx and do not have any custom
+ * parameters available, hardware probably contain older firmware version with
+ * no way of updating. Chipset marked as 'BCM4320????' in NDISwrapper-wiki.
+ */
+{
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x13b1,
+	.idProduct		= 0x000e,	/* Linksys WUSB54GSv1 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320a_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0baf,
+	.idProduct		= 0x0111,	/* U.S. Robotics USR5420 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320a_info,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x0411,
+	.idProduct		= 0x004b,	/* BUFFALO WLI-USB-G54 */
+	RNDIS_MASTER_INTERFACE,
+	.driver_info		= (unsigned long) &bcm4320a_info,
+},
+/* Generic Wireless RNDIS devices that we don't have exact
+ * idVendor/idProduct/chip yet.
+ */
+{
+	/* RNDIS is MSFT's un-official variant of CDC ACM */
+	USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+	.driver_info = (unsigned long) &rndis_wext_info,
+}, {
+	/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
+	USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
+	.driver_info = (unsigned long) &rndis_wext_info,
+},
+	{ },		// END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver rndis_wlan_driver = {
+	.name =		"rndis_wlan",
+	.id_table =	products,
+	.probe =	usbnet_probe,
+	.disconnect =	usbnet_disconnect,
+	.suspend =	usbnet_suspend,
+	.resume =	usbnet_resume,
+};
+
+static int __init rndis_wlan_init(void)
+{
+	return usb_register(&rndis_wlan_driver);
+}
+module_init(rndis_wlan_init);
+
+static void __exit rndis_wlan_exit(void)
+{
+	usb_deregister(&rndis_wlan_driver);
+}
+module_exit(rndis_wlan_exit);
+
+MODULE_AUTHOR("Bjorge Dijkstra");
+MODULE_AUTHOR("Jussi Kivilinna");
+MODULE_DESCRIPTION("Driver for RNDIS based USB Wireless adapters");
+MODULE_LICENSE("GPL");
+

+ 2 - 1
drivers/net/wireless/rt2x00/rt61pci.c

@@ -1736,7 +1736,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 			WARNING(rt2x00dev,
 				"TX status report missed for entry %p\n",
 				entry_done);
-			rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0);
+			rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
+					 0);
 			entry_done = rt2x00_get_data_entry_done(ring);
 		}
 

+ 1 - 0
drivers/net/wireless/rtl8180_dev.c

@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
 static struct pci_device_id rtl8180_table[] __devinitdata = {
 	/* rtl8185 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) },
 
 	/* rtl8180 */

+ 2 - 0
include/asm-alpha/socket.h

@@ -60,4 +60,6 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	20
 #define SO_SECURITY_ENCRYPTION_NETWORK		21
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-arm/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-avr32/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* __ASM_AVR32_SOCKET_H */

+ 3 - 0
include/asm-blackfin/socket.h

@@ -50,4 +50,7 @@
 #define SO_PASSSEC		34
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
+
+#define SO_MARK			36
+
 #endif				/* _ASM_SOCKET_H */

+ 2 - 0
include/asm-cris/socket.h

@@ -54,6 +54,8 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */
 
 

+ 2 - 0
include/asm-frv/socket.h

@@ -52,5 +52,7 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */
 

+ 2 - 0
include/asm-h8300/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-ia64/socket.h

@@ -61,4 +61,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_IA64_SOCKET_H */

+ 2 - 0
include/asm-m32r/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_M32R_SOCKET_H */

+ 2 - 0
include/asm-m68k/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-mips/socket.h

@@ -73,6 +73,8 @@ To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types

+ 2 - 0
include/asm-parisc/socket.h

@@ -52,4 +52,6 @@
 #define SO_PEERSEC		0x401d
 #define SO_PASSSEC		0x401e
 
+#define SO_MARK			0x401f
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-powerpc/socket.h

@@ -59,4 +59,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif	/* _ASM_POWERPC_SOCKET_H */

+ 2 - 0
include/asm-s390/socket.h

@@ -60,4 +60,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-sh/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* __ASM_SH_SOCKET_H */

+ 2 - 0
include/asm-sparc/socket.h

@@ -52,6 +52,8 @@
 #define SO_TIMESTAMPNS		0x0021
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			0x0022
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002

+ 1 - 0
include/asm-sparc64/socket.h

@@ -57,4 +57,5 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
+#define SO_MARK			0x0022
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-v850/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* __V850_SOCKET_H__ */

+ 2 - 0
include/asm-x86/socket.h

@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif /* _ASM_SOCKET_H */

+ 2 - 0
include/asm-xtensa/socket.h

@@ -63,4 +63,6 @@
 #define SO_TIMESTAMPNS		35
 #define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
+#define SO_MARK			36
+
 #endif	/* _XTENSA_SOCKET_H */

+ 0 - 2
include/linux/inetdevice.h

@@ -17,8 +17,6 @@ struct ipv4_devconf
 	DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
 };
 
-extern struct ipv4_devconf ipv4_devconf;
-
 struct in_device
 {
 	struct net_device	*dev;

+ 2 - 0
include/linux/input.h

@@ -371,6 +371,8 @@ struct input_absinfo {
 #define KEY_BRIGHTNESS_ZERO	244	/* brightness off, use ambient */
 #define KEY_DISPLAY_OFF		245	/* display device to off state */
 
+#define KEY_WIMAX		246
+
 #define BTN_MISC		0x100
 #define BTN_0			0x100
 #define BTN_1			0x101

+ 10 - 2
include/linux/ipv6.h

@@ -457,14 +457,22 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
 #define inet_v6_ipv6only(__sk)		0
 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 
-#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\
-	(((__sk)->sk_hash == (__hash))				&& \
+#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&& \
 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))  	&& \
 	 ((__sk)->sk_family		== AF_INET6)		&& \
 	 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))	&& \
 	 ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr))	&& \
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 
+#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&& \
+	 (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports))	&& \
+	 ((__sk)->sk_family	       == PF_INET6)			&& \
+	 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)))	&& \
+	 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \
+	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+
 #endif /* __KERNEL__ */
 
 #endif /* _IPV6_H */

+ 4 - 0
include/linux/netdevice.h

@@ -1414,12 +1414,16 @@ extern void		dev_set_rx_mode(struct net_device *dev);
 extern void		__dev_set_rx_mode(struct net_device *dev);
 extern int		dev_unicast_delete(struct net_device *dev, void *addr, int alen);
 extern int		dev_unicast_add(struct net_device *dev, void *addr, int alen);
+extern int		dev_unicast_sync(struct net_device *to, struct net_device *from);
+extern void		dev_unicast_unsync(struct net_device *to, struct net_device *from);
 extern int 		dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
 extern int		dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
 extern int		dev_mc_sync(struct net_device *to, struct net_device *from);
 extern void		dev_mc_unsync(struct net_device *to, struct net_device *from);
 extern int 		__dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
 extern int		__dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
+extern int		__dev_addr_sync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count);
+extern void		__dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct dev_addr_list **from, int *from_count);
 extern void		dev_set_promiscuity(struct net_device *dev, int inc);
 extern void		dev_set_allmulti(struct net_device *dev, int inc);
 extern void		netdev_state_change(struct net_device *dev);

+ 1 - 1
include/linux/netfilter/nf_conntrack_pptp.h

@@ -4,7 +4,7 @@
 
 #include <linux/netfilter/nf_conntrack_common.h>
 
-extern const char *pptp_msg_name[];
+extern const char *const pptp_msg_name[];
 
 /* state of the control session */
 enum pptp_ctrlsess_state {

+ 3 - 3
include/linux/netfilter/nf_conntrack_sip.h

@@ -30,9 +30,9 @@ extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
 				       struct nf_conntrack_expect *exp,
 				       const char *dptr);
 
-extern int ct_sip_get_info(struct nf_conn *ct, const char *dptr, size_t dlen,
-			   unsigned int *matchoff, unsigned int *matchlen,
-			   enum sip_header_pos pos);
+extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
+                           size_t dlen, unsigned int *matchoff,
+                           unsigned int *matchlen, enum sip_header_pos pos);
 extern int ct_sip_lnlen(const char *line, const char *limit);
 extern const char *ct_sip_search(const char *needle, const char *haystack,
 				 size_t needle_len, size_t haystack_len,

+ 15 - 13
include/linux/netfilter/x_tables.h

@@ -214,7 +214,7 @@ struct xt_match
 	/* Free to use by each match */
 	unsigned long data;
 
-	char *table;
+	const char *table;
 	unsigned int matchsize;
 	unsigned int compatsize;
 	unsigned int hooks;
@@ -261,7 +261,7 @@ struct xt_target
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
 	struct module *me;
 
-	char *table;
+	const char *table;
 	unsigned int targetsize;
 	unsigned int compatsize;
 	unsigned int hooks;
@@ -277,7 +277,7 @@ struct xt_table
 	struct list_head list;
 
 	/* A unique name... */
-	char name[XT_TABLE_MAXNAMELEN];
+	const char name[XT_TABLE_MAXNAMELEN];
 
 	/* What hooks you will enter on */
 	unsigned int valid_hooks;
@@ -335,9 +335,10 @@ extern int xt_check_target(const struct xt_target *target, unsigned short family
 			   unsigned int size, const char *table, unsigned int hook,
 			   unsigned short proto, int inv_proto);
 
-extern int xt_register_table(struct xt_table *table,
-			     struct xt_table_info *bootstrap,
-			     struct xt_table_info *newinfo);
+extern struct xt_table *xt_register_table(struct net *net,
+					  struct xt_table *table,
+					  struct xt_table_info *bootstrap,
+					  struct xt_table_info *newinfo);
 extern void *xt_unregister_table(struct xt_table *table);
 
 extern struct xt_table_info *xt_replace_table(struct xt_table *table,
@@ -352,11 +353,12 @@ extern struct xt_target *xt_request_find_target(int af, const char *name,
 extern int xt_find_revision(int af, const char *name, u8 revision, int target,
 			    int *err);
 
-extern struct xt_table *xt_find_table_lock(int af, const char *name);
+extern struct xt_table *xt_find_table_lock(struct net *net, int af,
+					   const char *name);
 extern void xt_table_unlock(struct xt_table *t);
 
-extern int xt_proto_init(int af);
-extern void xt_proto_fini(int af);
+extern int xt_proto_init(struct net *net, int af);
+extern void xt_proto_fini(struct net *net, int af);
 
 extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
 extern void xt_free_table_info(struct xt_table_info *info);
@@ -430,15 +432,15 @@ extern short xt_compat_calc_jump(int af, unsigned int offset);
 
 extern int xt_compat_match_offset(struct xt_match *match);
 extern int xt_compat_match_from_user(struct xt_entry_match *m,
-				     void **dstptr, int *size);
+				     void **dstptr, unsigned int *size);
 extern int xt_compat_match_to_user(struct xt_entry_match *m,
-				   void __user **dstptr, int *size);
+				   void __user **dstptr, unsigned int *size);
 
 extern int xt_compat_target_offset(struct xt_target *target);
 extern void xt_compat_target_from_user(struct xt_entry_target *t,
-				       void **dstptr, int *size);
+				       void **dstptr, unsigned int *size);
 extern int xt_compat_target_to_user(struct xt_entry_target *t,
-				    void __user **dstptr, int *size);
+				    void __user **dstptr, unsigned int *size);
 
 #endif /* CONFIG_COMPAT */
 #endif /* __KERNEL__ */

+ 18 - 12
include/linux/netfilter/xt_conntrack.h

@@ -6,9 +6,6 @@
 #define _XT_CONNTRACK_H
 
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
-#ifdef __KERNEL__
-#	include <linux/in.h>
-#endif
 
 #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define XT_CONNTRACK_STATE_INVALID (1 << 0)
@@ -18,14 +15,21 @@
 #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
 
 /* flags, invflags: */
-#define XT_CONNTRACK_STATE	0x01
-#define XT_CONNTRACK_PROTO	0x02
-#define XT_CONNTRACK_ORIGSRC	0x04
-#define XT_CONNTRACK_ORIGDST	0x08
-#define XT_CONNTRACK_REPLSRC	0x10
-#define XT_CONNTRACK_REPLDST	0x20
-#define XT_CONNTRACK_STATUS	0x40
-#define XT_CONNTRACK_EXPIRES	0x80
+enum {
+	XT_CONNTRACK_STATE        = 1 << 0,
+	XT_CONNTRACK_PROTO        = 1 << 1,
+	XT_CONNTRACK_ORIGSRC      = 1 << 2,
+	XT_CONNTRACK_ORIGDST      = 1 << 3,
+	XT_CONNTRACK_REPLSRC      = 1 << 4,
+	XT_CONNTRACK_REPLDST      = 1 << 5,
+	XT_CONNTRACK_STATUS       = 1 << 6,
+	XT_CONNTRACK_EXPIRES      = 1 << 7,
+	XT_CONNTRACK_ORIGSRC_PORT = 1 << 8,
+	XT_CONNTRACK_ORIGDST_PORT = 1 << 9,
+	XT_CONNTRACK_REPLSRC_PORT = 1 << 10,
+	XT_CONNTRACK_REPLDST_PORT = 1 << 11,
+	XT_CONNTRACK_DIRECTION    = 1 << 12,
+};
 
 /* This is exposed to userspace, so remains frozen in time. */
 struct ip_conntrack_old_tuple
@@ -70,8 +74,10 @@ struct xt_conntrack_mtinfo1 {
 	union nf_inet_addr repldst_addr, repldst_mask;
 	u_int32_t expires_min, expires_max;
 	u_int16_t l4proto;
+	__be16 origsrc_port, origdst_port;
+	__be16 replsrc_port, repldst_port;
+	u_int16_t match_flags, invert_flags;
 	u_int8_t state_mask, status_mask;
-	u_int8_t match_flags, invert_flags;
 };
 
 #endif /*_XT_CONNTRACK_H*/

+ 32 - 5
include/linux/netfilter/xt_hashlimit.h

@@ -9,13 +9,16 @@
 /* details of this structure hidden by the implementation */
 struct xt_hashlimit_htable;
 
-#define XT_HASHLIMIT_HASH_DIP	0x0001
-#define XT_HASHLIMIT_HASH_DPT	0x0002
-#define XT_HASHLIMIT_HASH_SIP	0x0004
-#define XT_HASHLIMIT_HASH_SPT	0x0008
+enum {
+	XT_HASHLIMIT_HASH_DIP = 1 << 0,
+	XT_HASHLIMIT_HASH_DPT = 1 << 1,
+	XT_HASHLIMIT_HASH_SIP = 1 << 2,
+	XT_HASHLIMIT_HASH_SPT = 1 << 3,
+	XT_HASHLIMIT_INVERT   = 1 << 4,
+};
 
 struct hashlimit_cfg {
-	u_int32_t mode;	  /* bitmask of IPT_HASHLIMIT_HASH_* */
+	u_int32_t mode;	  /* bitmask of XT_HASHLIMIT_HASH_* */
 	u_int32_t avg;    /* Average secs between packets * scale */
 	u_int32_t burst;  /* Period multiplier for upper limit. */
 
@@ -37,4 +40,28 @@ struct xt_hashlimit_info {
 		struct xt_hashlimit_info *master;
 	} u;
 };
+
+struct hashlimit_cfg1 {
+	u_int32_t mode;	  /* bitmask of XT_HASHLIMIT_HASH_* */
+	u_int32_t avg;    /* Average secs between packets * scale */
+	u_int32_t burst;  /* Period multiplier for upper limit. */
+
+	/* user specified */
+	u_int32_t size;		/* how many buckets */
+	u_int32_t max;		/* max number of entries */
+	u_int32_t gc_interval;	/* gc interval */
+	u_int32_t expire;	/* when do entries expire? */
+
+	u_int8_t srcmask, dstmask;
+};
+
+struct xt_hashlimit_mtinfo1 {
+	char name[IFNAMSIZ];
+	struct hashlimit_cfg1 cfg;
+
+	/* Used internally by the kernel */
+	struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
+	struct xt_hashlimit_mtinfo1 *master __attribute__((aligned(8)));
+};
+
 #endif /*_XT_HASHLIMIT_H*/

+ 2 - 2
include/linux/netfilter/xt_owner.h

@@ -8,8 +8,8 @@ enum {
 };
 
 struct xt_owner_match_info {
-	u_int32_t uid;
-	u_int32_t gid;
+	u_int32_t uid_min, uid_max;
+	u_int32_t gid_min, gid_max;
 	u_int8_t match, invert;
 };
 

+ 3 - 2
include/linux/netfilter_arp/arp_tables.h

@@ -271,8 +271,9 @@ struct arpt_error
  	xt_register_target(tgt); })
 #define arpt_unregister_target(tgt) xt_unregister_target(tgt)
 
-extern int arpt_register_table(struct arpt_table *table,
-			       const struct arpt_replace *repl);
+extern struct arpt_table *arpt_register_table(struct net *net,
+					      struct arpt_table *table,
+					      const struct arpt_replace *repl);
 extern void arpt_unregister_table(struct arpt_table *table);
 extern unsigned int arpt_do_table(struct sk_buff *skb,
 				  unsigned int hook,

+ 3 - 2
include/linux/netfilter_ipv4/ip_tables.h

@@ -244,8 +244,9 @@ ipt_get_target(struct ipt_entry *e)
 #include <linux/init.h>
 extern void ipt_init(void) __init;
 
-extern int ipt_register_table(struct xt_table *table,
-			      const struct ipt_replace *repl);
+extern struct xt_table *ipt_register_table(struct net *net,
+					   struct xt_table *table,
+					   const struct ipt_replace *repl);
 extern void ipt_unregister_table(struct xt_table *table);
 
 /* Standard entry. */

+ 3 - 2
include/linux/netfilter_ipv6/ip6_tables.h

@@ -305,8 +305,9 @@ ip6t_get_target(struct ip6t_entry *e)
 #include <linux/init.h>
 extern void ip6t_init(void) __init;
 
-extern int ip6t_register_table(struct xt_table *table,
-			       const struct ip6t_replace *repl);
+extern struct xt_table *ip6t_register_table(struct net *net,
+					    struct xt_table *table,
+					    const struct ip6t_replace *repl);
 extern void ip6t_unregister_table(struct xt_table *table);
 extern unsigned int ip6t_do_table(struct sk_buff *skb,
 				  unsigned int hook,

+ 1 - 1
include/linux/netlink.h

@@ -219,7 +219,7 @@ struct netlink_callback
 	int		(*dump)(struct sk_buff * skb, struct netlink_callback *cb);
 	int		(*done)(struct netlink_callback *cb);
 	int		family;
-	long		args[5];
+	long		args[6];
 };
 
 struct netlink_notify

+ 6 - 0
include/linux/pfkeyv2.h

@@ -298,6 +298,12 @@ struct sadb_x_sec_ctx {
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_EALG_NULL			11
 #define SADB_X_EALG_AESCBC		12
+#define SADB_X_EALG_AES_CCM_ICV8	14
+#define SADB_X_EALG_AES_CCM_ICV12	15
+#define SADB_X_EALG_AES_CCM_ICV16	16
+#define SADB_X_EALG_AES_GCM_ICV8	18
+#define SADB_X_EALG_AES_GCM_ICV12	19
+#define SADB_X_EALG_AES_GCM_ICV16	20
 #define SADB_X_EALG_CAMELLIACBC		22
 #define SADB_EALG_MAX                   253 /* last EALG */
 /* private allocations should use 249-255 (RFC2407) */

+ 50 - 0
include/linux/pkt_cls.h

@@ -328,6 +328,56 @@ enum
 
 #define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
 
+/* Flow filter */
+
+enum
+{
+	FLOW_KEY_SRC,
+	FLOW_KEY_DST,
+	FLOW_KEY_PROTO,
+	FLOW_KEY_PROTO_SRC,
+	FLOW_KEY_PROTO_DST,
+	FLOW_KEY_IIF,
+	FLOW_KEY_PRIORITY,
+	FLOW_KEY_MARK,
+	FLOW_KEY_NFCT,
+	FLOW_KEY_NFCT_SRC,
+	FLOW_KEY_NFCT_DST,
+	FLOW_KEY_NFCT_PROTO_SRC,
+	FLOW_KEY_NFCT_PROTO_DST,
+	FLOW_KEY_RTCLASSID,
+	FLOW_KEY_SKUID,
+	FLOW_KEY_SKGID,
+	__FLOW_KEY_MAX,
+};
+
+#define FLOW_KEY_MAX	(__FLOW_KEY_MAX - 1)
+
+enum
+{
+	FLOW_MODE_MAP,
+	FLOW_MODE_HASH,
+};
+
+enum
+{
+	TCA_FLOW_UNSPEC,
+	TCA_FLOW_KEYS,
+	TCA_FLOW_MODE,
+	TCA_FLOW_BASECLASS,
+	TCA_FLOW_RSHIFT,
+	TCA_FLOW_ADDEND,
+	TCA_FLOW_MASK,
+	TCA_FLOW_XOR,
+	TCA_FLOW_DIVISOR,
+	TCA_FLOW_ACT,
+	TCA_FLOW_POLICE,
+	TCA_FLOW_EMATCHES,
+	__TCA_FLOW_MAX
+};
+
+#define TCA_FLOW_MAX	(__TCA_FLOW_MAX - 1)
+
 /* Basic filter */
 
 enum

+ 5 - 0
include/linux/pkt_sched.h

@@ -150,6 +150,11 @@ struct tc_sfq_qopt
 	unsigned	flows;		/* Maximal number of flows  */
 };
 
+struct tc_sfq_xstats
+{
+	__s32		allot;
+};
+
 /*
  *  NOTE: limit, divisor and flows are hardwired to code at the moment.
  *

+ 2 - 0
include/linux/rfkill.h

@@ -33,11 +33,13 @@
  * RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device.
  * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device.
  * RFKILL_TYPE_UWB: switch is on a ultra wideband device.
+ * RFKILL_TYPE_WIMAX: switch is on a WiMAX device.
  */
 enum rfkill_type {
 	RFKILL_TYPE_WLAN ,
 	RFKILL_TYPE_BLUETOOTH,
 	RFKILL_TYPE_UWB,
+	RFKILL_TYPE_WIMAX,
 	RFKILL_TYPE_MAX,
 };
 

+ 0 - 3
include/linux/skbuff.h

@@ -108,9 +108,6 @@ struct nf_bridge_info {
 	atomic_t use;
 	struct net_device *physindev;
 	struct net_device *physoutdev;
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-	struct net_device *netoutdev;
-#endif
 	unsigned int mask;
 	unsigned long data[32 / sizeof(unsigned long)];
 };

+ 2 - 1
include/linux/snmp.h

@@ -227,7 +227,7 @@ enum
 	LINUX_MIB_XFRMINNOSTATES,		/* XfrmInNoStates */
 	LINUX_MIB_XFRMINSTATEPROTOERROR,	/* XfrmInStateProtoError */
 	LINUX_MIB_XFRMINSTATEMODEERROR,		/* XfrmInStateModeError */
-	LINUX_MIB_XFRMINSEQOUTOFWINDOW,		/* XfrmInSeqOutOfWindow */
+	LINUX_MIB_XFRMINSTATESEQERROR,		/* XfrmInStateSeqError */
 	LINUX_MIB_XFRMINSTATEEXPIRED,		/* XfrmInStateExpired */
 	LINUX_MIB_XFRMINSTATEMISMATCH,		/* XfrmInStateMismatch */
 	LINUX_MIB_XFRMINSTATEINVALID,		/* XfrmInStateInvalid */
@@ -241,6 +241,7 @@ enum
 	LINUX_MIB_XFRMOUTNOSTATES,		/* XfrmOutNoStates */
 	LINUX_MIB_XFRMOUTSTATEPROTOERROR,	/* XfrmOutStateProtoError */
 	LINUX_MIB_XFRMOUTSTATEMODEERROR,	/* XfrmOutStateModeError */
+	LINUX_MIB_XFRMOUTSTATESEQERROR,		/* XfrmOutStateSeqError */
 	LINUX_MIB_XFRMOUTSTATEEXPIRED,		/* XfrmOutStateExpired */
 	LINUX_MIB_XFRMOUTPOLBLOCK,		/* XfrmOutPolBlock */
 	LINUX_MIB_XFRMOUTPOLDEAD,		/* XfrmOutPolDead */

+ 2 - 2
include/linux/sysctl.h

@@ -440,8 +440,8 @@ enum
 
 enum {
 	NET_IPV4_ROUTE_FLUSH=1,
-	NET_IPV4_ROUTE_MIN_DELAY=2,
-	NET_IPV4_ROUTE_MAX_DELAY=3,
+	NET_IPV4_ROUTE_MIN_DELAY=2, /* obsolete since 2.6.25 */
+	NET_IPV4_ROUTE_MAX_DELAY=3, /* obsolete since 2.6.25 */
 	NET_IPV4_ROUTE_GC_THRESH=4,
 	NET_IPV4_ROUTE_MAX_SIZE=5,
 	NET_IPV4_ROUTE_GC_MIN_INTERVAL=6,

+ 1 - 1
include/linux/types.h

@@ -126,7 +126,7 @@ typedef		__s64		int64_t;
 #endif
 
 /* this is a special 64bit data type that is 8-byte aligned */
-#define aligned_u64 unsigned long long __attribute__((aligned(8)))
+#define aligned_u64 __u64 __attribute__((aligned(8)))
 #define aligned_be64 __be64 __attribute__((aligned(8)))
 #define aligned_le64 __le64 __attribute__((aligned(8)))
 

+ 274 - 0
include/linux/usb/rndis_host.h

@@ -0,0 +1,274 @@
+/*
+ * Host Side support for RNDIS Networking Links
+ * Copyright (C) 2005 by David Brownell
+ *
+ * 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	__RNDIS_HOST_H
+#define	__RNDIS_HOST_H
+
+
+/*
+ * CONTROL uses CDC "encapsulated commands" with funky notifications.
+ *  - control-out:  SEND_ENCAPSULATED
+ *  - interrupt-in:  RESPONSE_AVAILABLE
+ *  - control-in:  GET_ENCAPSULATED
+ *
+ * We'll try to ignore the RESPONSE_AVAILABLE notifications.
+ *
+ * REVISIT some RNDIS implementations seem to have curious issues still
+ * to be resolved.
+ */
+struct rndis_msg_hdr {
+	__le32	msg_type;			/* RNDIS_MSG_* */
+	__le32	msg_len;
+	// followed by data that varies between messages
+	__le32	request_id;
+	__le32	status;
+	// ... and more
+} __attribute__ ((packed));
+
+/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */
+#define	CONTROL_BUFFER_SIZE		1025
+
+/* RNDIS defines an (absurdly huge) 10 second control timeout,
+ * but ActiveSync seems to use a more usual 5 second timeout
+ * (which matches the USB 2.0 spec).
+ */
+#define	RNDIS_CONTROL_TIMEOUT_MS	(5 * 1000)
+
+
+#define ccpu2 __constant_cpu_to_le32
+
+#define RNDIS_MSG_COMPLETION	ccpu2(0x80000000)
+
+/* codes for "msg_type" field of rndis messages;
+ * only the data channel uses packet messages (maybe batched);
+ * everything else goes on the control channel.
+ */
+#define RNDIS_MSG_PACKET	ccpu2(0x00000001)	/* 1-N packets */
+#define RNDIS_MSG_INIT		ccpu2(0x00000002)
+#define RNDIS_MSG_INIT_C	(RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_HALT		ccpu2(0x00000003)
+#define RNDIS_MSG_QUERY		ccpu2(0x00000004)
+#define RNDIS_MSG_QUERY_C	(RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_SET		ccpu2(0x00000005)
+#define RNDIS_MSG_SET_C		(RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_RESET		ccpu2(0x00000006)
+#define RNDIS_MSG_RESET_C	(RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_INDICATE	ccpu2(0x00000007)
+#define RNDIS_MSG_KEEPALIVE	ccpu2(0x00000008)
+#define RNDIS_MSG_KEEPALIVE_C	(RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
+
+/* codes for "status" field of completion messages */
+#define	RNDIS_STATUS_SUCCESS		ccpu2(0x00000000)
+#define	RNDIS_STATUS_FAILURE		ccpu2(0xc0000001)
+#define	RNDIS_STATUS_INVALID_DATA	ccpu2(0xc0010015)
+#define	RNDIS_STATUS_NOT_SUPPORTED	ccpu2(0xc00000bb)
+#define	RNDIS_STATUS_MEDIA_CONNECT	ccpu2(0x4001000b)
+#define	RNDIS_STATUS_MEDIA_DISCONNECT	ccpu2(0x4001000c)
+
+/* codes for OID_GEN_PHYSICAL_MEDIUM */
+#define	RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED	ccpu2(0x00000000)
+#define	RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN	ccpu2(0x00000001)
+#define	RNDIS_PHYSICAL_MEDIUM_CABLE_MODEM	ccpu2(0x00000002)
+#define	RNDIS_PHYSICAL_MEDIUM_PHONE_LINE	ccpu2(0x00000003)
+#define	RNDIS_PHYSICAL_MEDIUM_POWER_LINE	ccpu2(0x00000004)
+#define	RNDIS_PHYSICAL_MEDIUM_DSL		ccpu2(0x00000005)
+#define	RNDIS_PHYSICAL_MEDIUM_FIBRE_CHANNEL	ccpu2(0x00000006)
+#define	RNDIS_PHYSICAL_MEDIUM_1394		ccpu2(0x00000007)
+#define	RNDIS_PHYSICAL_MEDIUM_WIRELESS_WAN	ccpu2(0x00000008)
+#define	RNDIS_PHYSICAL_MEDIUM_MAX		ccpu2(0x00000009)
+
+struct rndis_data_hdr {
+	__le32	msg_type;		/* RNDIS_MSG_PACKET */
+	__le32	msg_len;		// rndis_data_hdr + data_len + pad
+	__le32	data_offset;		// 36 -- right after header
+	__le32	data_len;		// ... real packet size
+
+	__le32	oob_data_offset;	// zero
+	__le32	oob_data_len;		// zero
+	__le32	num_oob;		// zero
+	__le32	packet_data_offset;	// zero
+
+	__le32	packet_data_len;	// zero
+	__le32	vc_handle;		// zero
+	__le32	reserved;		// zero
+} __attribute__ ((packed));
+
+struct rndis_init {		/* OUT */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_INIT */
+	__le32	msg_len;			// 24
+	__le32	request_id;
+	__le32	major_version;			// of rndis (1.0)
+	__le32	minor_version;
+	__le32	max_transfer_size;
+} __attribute__ ((packed));
+
+struct rndis_init_c {		/* IN */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_INIT_C */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	status;
+	__le32	major_version;			// of rndis (1.0)
+	__le32	minor_version;
+	__le32	device_flags;
+	__le32	medium;				// zero == 802.3
+	__le32	max_packets_per_message;
+	__le32	max_transfer_size;
+	__le32	packet_alignment;		// max 7; (1<<n) bytes
+	__le32	af_list_offset;			// zero
+	__le32	af_list_size;			// zero
+} __attribute__ ((packed));
+
+struct rndis_halt {		/* OUT (no reply) */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_HALT */
+	__le32	msg_len;
+	__le32	request_id;
+} __attribute__ ((packed));
+
+struct rndis_query {		/* OUT */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_QUERY */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	oid;
+	__le32	len;
+	__le32	offset;
+/*?*/	__le32	handle;				// zero
+} __attribute__ ((packed));
+
+struct rndis_query_c {		/* IN */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_QUERY_C */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	status;
+	__le32	len;
+	__le32	offset;
+} __attribute__ ((packed));
+
+struct rndis_set {		/* OUT */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_SET */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	oid;
+	__le32	len;
+	__le32	offset;
+/*?*/	__le32	handle;				// zero
+} __attribute__ ((packed));
+
+struct rndis_set_c {		/* IN */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_SET_C */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	status;
+} __attribute__ ((packed));
+
+struct rndis_reset {		/* IN */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_RESET */
+	__le32	msg_len;
+	__le32	reserved;
+} __attribute__ ((packed));
+
+struct rndis_reset_c {		/* OUT */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_RESET_C */
+	__le32	msg_len;
+	__le32	status;
+	__le32	addressing_lost;
+} __attribute__ ((packed));
+
+struct rndis_indicate {		/* IN (unrequested) */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_INDICATE */
+	__le32	msg_len;
+	__le32	status;
+	__le32	length;
+	__le32	offset;
+/**/	__le32	diag_status;
+	__le32	error_offset;
+/**/	__le32	message;
+} __attribute__ ((packed));
+
+struct rndis_keepalive {	/* OUT (optionally IN) */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE */
+	__le32	msg_len;
+	__le32	request_id;
+} __attribute__ ((packed));
+
+struct rndis_keepalive_c {	/* IN (optionally OUT) */
+	// header and:
+	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE_C */
+	__le32	msg_len;
+	__le32	request_id;
+	__le32	status;
+} __attribute__ ((packed));
+
+/* NOTE:  about 30 OIDs are "mandatory" for peripherals to support ... and
+ * there are gobs more that may optionally be supported.  We'll avoid as much
+ * of that mess as possible.
+ */
+#define OID_802_3_PERMANENT_ADDRESS	ccpu2(0x01010101)
+#define OID_GEN_MAXIMUM_FRAME_SIZE	ccpu2(0x00010106)
+#define OID_GEN_CURRENT_PACKET_FILTER	ccpu2(0x0001010e)
+#define OID_GEN_PHYSICAL_MEDIUM		ccpu2(0x00010202)
+
+/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */
+#define RNDIS_PACKET_TYPE_DIRECTED		ccpu2(0x00000001)
+#define RNDIS_PACKET_TYPE_MULTICAST		ccpu2(0x00000002)
+#define RNDIS_PACKET_TYPE_ALL_MULTICAST		ccpu2(0x00000004)
+#define RNDIS_PACKET_TYPE_BROADCAST		ccpu2(0x00000008)
+#define RNDIS_PACKET_TYPE_SOURCE_ROUTING	ccpu2(0x00000010)
+#define RNDIS_PACKET_TYPE_PROMISCUOUS		ccpu2(0x00000020)
+#define RNDIS_PACKET_TYPE_SMT			ccpu2(0x00000040)
+#define RNDIS_PACKET_TYPE_ALL_LOCAL		ccpu2(0x00000080)
+#define RNDIS_PACKET_TYPE_GROUP			ccpu2(0x00001000)
+#define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL	ccpu2(0x00002000)
+#define RNDIS_PACKET_TYPE_FUNCTIONAL		ccpu2(0x00004000)
+#define RNDIS_PACKET_TYPE_MAC_FRAME		ccpu2(0x00008000)
+
+/* default filter used with RNDIS devices */
+#define RNDIS_DEFAULT_FILTER ( \
+	RNDIS_PACKET_TYPE_DIRECTED | \
+	RNDIS_PACKET_TYPE_BROADCAST | \
+	RNDIS_PACKET_TYPE_ALL_MULTICAST | \
+	RNDIS_PACKET_TYPE_PROMISCUOUS)
+
+/* Flags to require specific physical medium type for generic_rndis_bind() */
+#define FLAG_RNDIS_PHYM_NOT_WIRELESS	0x0001
+#define FLAG_RNDIS_PHYM_WIRELESS	0x0002
+
+
+extern void rndis_status(struct usbnet *dev, struct urb *urb);
+extern int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf);
+extern int
+generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags);
+extern void rndis_unbind(struct usbnet *dev, struct usb_interface *intf);
+extern int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb);
+extern struct sk_buff *
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
+
+#endif	/* __RNDIS_HOST_H */
+

+ 12 - 0
drivers/net/usb/usbnet.h → include/linux/usb/usbnet.h

@@ -31,6 +31,7 @@ struct usbnet {
 	struct usb_interface	*intf;
 	struct driver_info	*driver_info;
 	const char		*driver_name;
+	void			*driver_priv;
 	wait_queue_head_t	*wait;
 	struct mutex		phy_mutex;
 	unsigned char		suspend_count;
@@ -87,6 +88,8 @@ struct driver_info {
 #define FLAG_ETHER	0x0020		/* maybe use "eth%d" names */
 
 #define FLAG_FRAMING_AX 0x0040		/* AX88772/178 packets */
+#define FLAG_WLAN	0x0080		/* use "wlan%d" names */
+
 
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
@@ -113,6 +116,15 @@ struct driver_info {
 	struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
 				struct sk_buff *skb, gfp_t flags);
 
+	/* early initialization code, can sleep. This is for minidrivers
+	 * having 'subminidrivers' that need to do extra initialization
+	 * right after minidriver have initialized hardware. */
+	int	(*early_init)(struct usbnet *dev);
+
+	/* called by minidriver when link state changes, state: 0=disconnect,
+	 * 1=connect */
+	void	(*link_change)(struct usbnet *dev, int state);
+
 	/* for new devices, use the descriptor-reading code instead */
 	int		in;		/* rx endpoint */
 	int		out;		/* tx endpoint */

+ 8 - 0
include/linux/xfrm.h

@@ -96,6 +96,13 @@ struct xfrm_algo {
 	char		alg_key[0];
 };
 
+struct xfrm_algo_aead {
+	char	alg_name[64];
+	int	alg_key_len;	/* in bits */
+	int	alg_icv_len;	/* in bits */
+	char	alg_key[0];
+};
+
 struct xfrm_stats {
 	__u32	replay_window;
 	__u32	replay;
@@ -270,6 +277,7 @@ enum xfrm_attr_type_t {
 	XFRMA_LASTUSED,
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
 	XFRMA_MIGRATE,
+	XFRMA_ALG_AEAD,		/* struct xfrm_algo_aead */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)

+ 5 - 3
include/net/arp.h

@@ -13,15 +13,17 @@ extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int	arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
 extern void     arp_send(int type, int ptype, __be32 dest_ip,
 			 struct net_device *dev, __be32 src_ip,
-			 unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
+			 const unsigned char *dest_hw,
+			 const unsigned char *src_hw, const unsigned char *th);
 extern int	arp_bind_neighbour(struct dst_entry *dst);
 extern int	arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
 extern void	arp_ifdown(struct net_device *dev);
 
 extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
 				  struct net_device *dev, __be32 src_ip,
-				  unsigned char *dest_hw, unsigned char *src_hw,
-				  unsigned char *target_hw);
+				  const unsigned char *dest_hw,
+				  const unsigned char *src_hw,
+				  const unsigned char *target_hw);
 extern void arp_xmit(struct sk_buff *skb);
 
 extern struct neigh_ops arp_broken_ops;

+ 8 - 46
include/net/esp.h

@@ -1,58 +1,20 @@
 #ifndef _NET_ESP_H
 #define _NET_ESP_H
 
-#include <linux/crypto.h>
-#include <net/xfrm.h>
-#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
 
-#define ESP_NUM_FAST_SG		4
+struct crypto_aead;
 
-struct esp_data
-{
-	struct scatterlist		sgbuf[ESP_NUM_FAST_SG];
-
-	/* Confidentiality */
-	struct {
-		int			padlen;		/* 0..255 */
-		/* ivlen is offset from enc_data, where encrypted data start.
-		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
-		 * We assume that it is either zero (no ivec), or
-		 * >= crypto_tfm_alg_ivsize(tfm). */
-		int			ivlen;
-		int			ivinitted;
-		u8			*ivec;		/* ivec buffer */
-		struct crypto_blkcipher	*tfm;		/* crypto handle */
-	} conf;
-
-	/* Integrity. It is active when icv_full_len != 0 */
-	struct {
-		u8			*work_icv;
-		int			icv_full_len;
-		int			icv_trunc_len;
-		struct crypto_hash	*tfm;
-	} auth;
+struct esp_data {
+	/* 0..255 */
+	int padlen;
+
+	/* Confidentiality & Integrity */
+	struct crypto_aead *aead;
 };
 
 extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
 
-static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
-				 int offset, int len)
-{
-	struct hash_desc desc;
-	int err;
-
-	desc.tfm = esp->auth.tfm;
-	desc.flags = 0;
-
-	err = crypto_hash_init(&desc);
-	if (unlikely(err))
-		return err;
-	err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update);
-	if (unlikely(err))
-		return err;
-	return crypto_hash_final(&desc, esp->auth.work_icv);
-}
-
 struct ip_esp_hdr;
 
 static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)

+ 10 - 7
include/net/inet6_hashtables.h

@@ -57,34 +57,37 @@ extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
  *
  * The sockhash lock must be held as a reader here.
  */
-extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet6_lookup_established(struct net *net,
+					   struct inet_hashinfo *hashinfo,
 					   const struct in6_addr *saddr,
 					   const __be16 sport,
 					   const struct in6_addr *daddr,
 					   const u16 hnum,
 					   const int dif);
 
-extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
+extern struct sock *inet6_lookup_listener(struct net *net,
+					  struct inet_hashinfo *hashinfo,
 					  const struct in6_addr *daddr,
 					  const unsigned short hnum,
 					  const int dif);
 
-static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
+static inline struct sock *__inet6_lookup(struct net *net,
+					  struct inet_hashinfo *hashinfo,
 					  const struct in6_addr *saddr,
 					  const __be16 sport,
 					  const struct in6_addr *daddr,
 					  const u16 hnum,
 					  const int dif)
 {
-	struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport,
-						     daddr, hnum, dif);
+	struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
+						sport, daddr, hnum, dif);
 	if (sk)
 		return sk;
 
-	return inet6_lookup_listener(hashinfo, daddr, hnum, dif);
+	return inet6_lookup_listener(net, hashinfo, daddr, hnum, dif);
 }
 
-extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
+extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
 				 const struct in6_addr *saddr, const __be16 sport,
 				 const struct in6_addr *daddr, const __be16 dport,
 				 const int dif);

+ 34 - 21
include/net/inet_hashtables.h

@@ -74,6 +74,7 @@ struct inet_ehash_bucket {
  * ports are created in O(1) time?  I thought so. ;-)	-DaveM
  */
 struct inet_bind_bucket {
+	struct net		*ib_net;
 	unsigned short		port;
 	signed short		fastreuse;
 	struct hlist_node	node;
@@ -194,6 +195,7 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
 
 extern struct inet_bind_bucket *
 		    inet_bind_bucket_create(struct kmem_cache *cachep,
+					    struct net *net,
 					    struct inet_bind_hashbucket *head,
 					    const unsigned short snum);
 extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
@@ -300,15 +302,17 @@ out:
 		wake_up(&hashinfo->lhash_wait);
 }
 
-extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet_lookup_listener(struct net *net,
+					   struct inet_hashinfo *hashinfo,
 					   const __be32 daddr,
 					   const unsigned short hnum,
 					   const int dif);
 
-static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
-						__be32 daddr, __be16 dport, int dif)
+static inline struct sock *inet_lookup_listener(struct net *net,
+		struct inet_hashinfo *hashinfo,
+		__be32 daddr, __be16 dport, int dif)
 {
-	return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
+	return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif);
 }
 
 /* Socket demux engine toys. */
@@ -342,26 +346,26 @@ typedef __u64 __bitwise __addrpair;
 				   (((__force __u64)(__be32)(__daddr)) << 32) | \
 				   ((__force __u64)(__be32)(__saddr)));
 #endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-	(((__sk)->sk_hash == (__hash))				&&	\
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
 	 ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))	&&	\
 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-	(((__sk)->sk_hash == (__hash))				&&	\
+#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
 	 ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&	\
 	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)	\
-	(((__sk)->sk_hash == (__hash))				&&	\
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)	\
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
 	 (inet_sk(__sk)->daddr		== (__saddr))		&&	\
 	 (inet_sk(__sk)->rcv_saddr	== (__daddr))		&&	\
 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif)	\
-	(((__sk)->sk_hash == (__hash))				&&	\
+#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif)	\
+	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
 	 (inet_twsk(__sk)->tw_daddr	== (__saddr))		&&	\
 	 (inet_twsk(__sk)->tw_rcv_saddr	== (__daddr))		&&	\
 	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
@@ -374,32 +378,36 @@ typedef __u64 __bitwise __addrpair;
  *
  * Local BH must be disabled here.
  */
-extern struct sock * __inet_lookup_established(struct inet_hashinfo *hashinfo,
+extern struct sock * __inet_lookup_established(struct net *net,
+		struct inet_hashinfo *hashinfo,
 		const __be32 saddr, const __be16 sport,
 		const __be32 daddr, const u16 hnum, const int dif);
 
 static inline struct sock *
-	inet_lookup_established(struct inet_hashinfo *hashinfo,
+	inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
 				const __be32 saddr, const __be16 sport,
 				const __be32 daddr, const __be16 dport,
 				const int dif)
 {
-	return __inet_lookup_established(hashinfo, saddr, sport, daddr,
+	return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
 					 ntohs(dport), dif);
 }
 
-static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
+static inline struct sock *__inet_lookup(struct net *net,
+					 struct inet_hashinfo *hashinfo,
 					 const __be32 saddr, const __be16 sport,
 					 const __be32 daddr, const __be16 dport,
 					 const int dif)
 {
 	u16 hnum = ntohs(dport);
-	struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
-						    hnum, dif);
-	return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif);
+	struct sock *sk = __inet_lookup_established(net, hashinfo,
+				saddr, sport, daddr, hnum, dif);
+
+	return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif);
 }
 
-static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
+static inline struct sock *inet_lookup(struct net *net,
+				       struct inet_hashinfo *hashinfo,
 				       const __be32 saddr, const __be16 sport,
 				       const __be32 daddr, const __be16 dport,
 				       const int dif)
@@ -407,12 +415,17 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
 	struct sock *sk;
 
 	local_bh_disable();
-	sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif);
+	sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif);
 	local_bh_enable();
 
 	return sk;
 }
 
+extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+		struct sock *sk,
+		int (*check_established)(struct inet_timewait_death_row *,
+			struct sock *, __u16, struct inet_timewait_sock **),
+		void (*hash)(struct inet_hashinfo *, struct sock *));
 extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
 			     struct sock *sk);
 #endif /* _INET_HASHTABLES_H */

+ 3 - 1
include/net/ip_fib.h

@@ -69,6 +69,7 @@ struct fib_nh {
 struct fib_info {
 	struct hlist_node	fib_hash;
 	struct hlist_node	fib_lhash;
+	struct net		*fib_net;
 	int			fib_treeref;
 	atomic_t		fib_clntref;
 	int			fib_dead;
@@ -218,7 +219,8 @@ extern void fib_select_default(struct net *net, const struct flowi *flp,
 
 /* Exported by fib_semantics.c */
 extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
-extern int fib_sync_down(__be32 local, struct net_device *dev, int force);
+extern int fib_sync_down_dev(struct net_device *dev, int force);
+extern int fib_sync_down_addr(struct net *net, __be32 local);
 extern int fib_sync_up(struct net_device *dev);
 extern __be32  __fib_res_prefsrc(struct fib_result *res);
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);

Some files were not shown because too many files changed in this diff