linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Please pull "upstream" branch of wireless-2.6
  2007-02-02 21:27 Please pull "upstream-fixes" " John W. Linville
@ 2007-02-02 21:28 ` John W. Linville
  2007-02-07  0:06 ` Please pull "upstream-fixes" " Jeff Garzik
  1 sibling, 0 replies; 27+ messages in thread
From: John W. Linville @ 2007-02-02 21:28 UTC (permalink / raw)
  To: jeff; +Cc: netdev, linux-wireless

This patches are intended for 2.6.21.

---

The following changes since commit 541c654cfdeb5cc6d2e945988985570384ee2a43:
  John W. Linville (1):
        Merge branch 'upstream-fixes' into upstream

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (1):
      zd1211rw: Remove noisy debug message

Larry Finger (3):
      bcm43xx: Fix problem with >1 GB RAM
      bcm43xx: Fix scaling error for 'iwlist rate' information
      bcm43xx: Fix scaling error for 'iwlist freq' information

Michael Buesch (1):
      bcm43xx: Enable fwpostfix in nondebug bcm43xx

Robert P. J. Day (1):
      Rename IPW2100 debugging macros to not look like config options.

Ulrich Kunitz (3):
      zd1211rw: Reset device in the probe call
      zd1211rw: Fixed array size issue in reset_mode
      zd1211rw: Added error stats update

 drivers/net/wireless/bcm43xx/bcm43xx.h      |    1 +
 drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |  171 +++++++++++++++++++--------
 drivers/net/wireless/bcm43xx/bcm43xx_main.c |    6 +-
 drivers/net/wireless/bcm43xx/bcm43xx_wx.c   |   28 ++--
 drivers/net/wireless/ipw2100.c              |   16 ++--
 drivers/net/wireless/zd1211rw/zd_mac.c      |   44 ++++++--
 drivers/net/wireless/zd1211rw/zd_usb.c      |   11 ++
 7 files changed, 193 insertions(+), 84 deletions(-)

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 3a064de..0e790ef 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -771,6 +771,7 @@ struct bcm43xx_private {
 	 * This is currently always BCM43xx_BUSTYPE_PCI
 	 */
 	u8 bustype;
+	u64 dma_mask;
 
 	u16 board_vendor;
 	u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed09..6e0dc76 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
 			  int tx)
 {
 	dma_addr_t dmaaddr;
+	int direction = PCI_DMA_FROMDEVICE;
 
-	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-					 buf, len,
-					 DMA_TO_DEVICE);
-	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+	if (tx)
+		direction = PCI_DMA_TODEVICE;
+
+	dmaaddr = pci_map_single(ring->bcm->pci_dev,
 					 buf, len,
-					 DMA_FROM_DEVICE);
-	}
+					 direction);
 
 	return dmaaddr;
 }
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dmaring *ring,
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_TO_DEVICE);
+				 PCI_DMA_TODEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_FROM_DEVICE);
+				 PCI_DMA_FROMDEVICE);
 	}
 }
 
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-				addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-				   addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
-
-	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					    &(ring->dmabase), GFP_KERNEL);
+	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase));
 	if (!ring->descbase) {
-		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-		return -ENOMEM;
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+		if (!rx_ring)
+			goto out_err;
+
+		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+					     BCM43xx_DMA_RINGMEMSIZE,
+					     PCI_DMA_BIDIRECTIONAL);
+
+		if (pci_dma_mapping_error(rx_ring_dma) ||
+		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+			/* Sigh... */
+			if (!pci_dma_mapping_error(rx_ring_dma))
+				pci_unmap_single(ring->bcm->pci_dev,
+						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			if (pci_dma_mapping_error(rx_ring_dma) ||
+			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+				assert(0);
+				if (!pci_dma_mapping_error(rx_ring_dma))
+					pci_unmap_single(ring->bcm->pci_dev,
+							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+							 PCI_DMA_BIDIRECTIONAL);
+				goto out_err;
+			}
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
 	}
 	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
+out_err:
+	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+	return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	/* This hardware bug work-around adapted from the b44 driver.
+	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+	if (pci_dma_mapping_error(dmaaddr) ||
+	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+		/* This one has 30-bit addressing... */
+		if (!pci_dma_mapping_error(dmaaddr))
+			pci_unmap_single(ring->bcm->pci_dev,
+					 dmaaddr, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+					 skb->data, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(dmaaddr) ||
+		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+			assert(0);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
 	err = dmacontroller_setup(ring);
 	if (err)
 		goto err_free_ringmemory;
+	return ring;
 
 out:
+	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
 	return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-	int nobits;
 
-	if (mask == DMA_64BIT_MASK) {
+	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+	if (bcm->dma_mask == DMA_64BIT_MASK)
 		dma64 = 1;
-		nobits = 64;
-	} else if (mask == DMA_32BIT_MASK)
-		nobits = 32;
-	else
-		nobits = 30;
-	err = pci_set_dma_mask(bcm->pci_dev, mask);
-	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-	if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-		printk(KERN_WARNING PFX "DMA not supported on this device."
-					" Falling back to PIO.\n");
-		bcm->__using_pio = 1;
-		return -ENOSYS;
-#else
-		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-				    "Please recompile the driver with PIO support.\n");
-		return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-	}
+	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
+	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
 	err = 0;
 out:
 	return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
 err_destroy_tx0:
 	bcm43xx_destroy_dmaring(dma->tx_ring0);
 	dma->tx_ring0 = NULL;
-	goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+	printk(KERN_WARNING PFX "DMA not supported on this device."
+				" Falling back to PIO.\n");
+	bcm->__using_pio = 1;
+	return -ENOSYS;
+#else
+	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+			    "Please recompile the driver with PIO support.\n");
+	return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	dma_addr_t dmaaddr;
+	struct sk_buff *bounce_skb;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 			       skb->len - sizeof(struct bcm43xx_txhdr),
 			       (cur_frag == 0),
 			       generate_cookie(ring, slot));
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+		if (!dma_mapping_error(dmaaddr))
+			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+		if (!bounce_skb)
+			return;
+		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+			if (!dma_mapping_error(dmaaddr))
+				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+			dev_kfree_skb_any(bounce_skb);
+			assert(0);
+			return;
+		}
+		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+	}
 
 	meta->skb = skb;
-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = dmaaddr;
 
 	fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 23aaf1e..8c93419 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@ static int modparam_noleds;
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index a659442..6961be6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -261,22 +261,22 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 	if (phy->type == BCM43xx_PHYTYPE_A ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates = 8;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
 	}
 	if (phy->type == BCM43xx_PHYTYPE_B ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates += 4;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
 	}
 
 	geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +286,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].m = geo->a[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
@@ -294,7 +294,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].m = geo->bg[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b85857a..d0639a4 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG	/* Reception debugging */
+#define IPW2100_RX_DEBUG	/* Reception debugging */
 #endif
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
 	priv->snapshot[0] = NULL;
 }
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
 	int i;
@@ -2314,13 +2314,13 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
  * The size of the constructed ethernet
  *
  */
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 #endif
 
 static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	struct ipw2100_status *status = &priv->status_queue.drv[i];
 	u32 match, reg;
 	int j;
@@ -2342,7 +2342,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 	}
 #endif
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	/* Halt the fimrware so we can get a good image */
 	write_register(priv->net_dev, IPW_REG_RESET_REG,
 		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 
 	skb_put(packet->skb, status->frame_size);
 
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 	/* Make a copy of the frame so we can dump it to the logs if
 	 * ieee80211_rx fails */
 	memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 #endif
 
 	if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 		IPW_DEBUG_DROP("%s: Non consumed packet:\n",
 			       priv->net_dev->name);
 		printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -4912,7 +4912,7 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level)
 	else
 		priv->power_mode = IPW_POWER_ENABLED | power_level;
 
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
 	if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
 		/* Set beacon interval */
 		cmd.host_command = TX_POWER_INDEX;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a085241..4c5f78e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,7 +156,7 @@ void zd_mac_clear(struct zd_mac *mac)
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-	struct zd_ioreq32 ioreqs[3] = {
+	struct zd_ioreq32 ioreqs[] = {
 		{ CR_RX_FILTER, STA_RX_FILTER },
 		{ CR_SNIFFER_ON, 0U },
 	};
@@ -164,10 +164,9 @@ static int reset_mode(struct zd_mac *mac)
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ioreqs[0].value = 0xffffffff;
 		ioreqs[1].value = 0x1;
-		ioreqs[2].value = ENC_SNIFFER;
 	}
 
-	return zd_iowrite32a(&mac->chip, ioreqs, 3);
+	return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@ static int fill_ctrlset(struct zd_mac *mac,
 static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
 {
 	int i, r;
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
 	for (i = 0; i < txb->nr_frags; i++) {
 		struct sk_buff *skb = txb->fragments[i];
 
 		r = fill_ctrlset(mac, txb, i);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 		r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 	}
 
 	/* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
 
 	*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
 	if (status->frame_status & ZD_RX_ERROR) {
-		/* FIXME: update? */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+			ieee->stats.rx_missed_errors++;
+		else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+			ieee->stats.rx_fifo_errors++;
+		else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+			ieee->ieee_stats.rx_discards_undecryptable++;
+		else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+			ieee->stats.rx_crc_errors++;
+			ieee->ieee_stats.rx_fcs_errors++;
+		}
+		else if (status->frame_status & ZD_RX_CRC16_ERROR)
+			ieee->stats.rx_crc_errors++;
 		return -EINVAL;
 	}
+
 	memset(stats, 0, sizeof(struct ieee80211_rx_stats));
 	stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
 		               + sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
 	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
 	{
-		dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
-			 skb->len);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		goto free_skb;
 	}
 
 	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
 	if (r) {
-		/* Only packets with rx errors are included here. */
+		/* Only packets with rx errors are included here.
+		 * The error stats have already been set in fill_rx_stats.
+		 */
 		goto free_skb;
 	}
 
@@ -1114,8 +1134,10 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 
 	r = filter_rx(ieee, skb->data, skb->len, &stats);
 	if (r <= 0) {
-		if (r < 0)
+		if (r < 0) {
+			ieee->stats.rx_errors++;
 			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+		}
 		goto free_skb;
 	}
 
@@ -1146,7 +1168,9 @@ int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
 
 	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
 	if (!skb) {
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+		ieee->stats.rx_dropped++;
 		return -ENOMEM;
 	}
 	skb_reserve(skb, sizeof(struct zd_rt_hdr));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 49e6c26..aac8a1c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -313,6 +313,12 @@ out:
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+	struct zd_usb *usb = urb->context;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+	ieee->stats.tx_errors++;
+	ieee->ieee_stats.tx_retry_limit_exceeded++;
 	dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -487,6 +493,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
 	if (length < sizeof(struct rx_length_info)) {
 		/* It's not a complete packet anyhow. */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		return;
 	}
 	length_info = (struct rx_length_info *)
@@ -923,6 +932,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 		goto error;
 	}
 
+	usb_reset_device(interface_to_usbdev(intf));
+
 	netdev = zd_netdev_alloc(intf);
 	if (netdev == NULL) {
 		r = -ENOMEM;
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Please pull "upstream" branch of wireless-2.6
  2007-02-07  0:06 ` Please pull "upstream-fixes" " Jeff Garzik
@ 2007-02-07 21:11   ` John W. Linville
  2007-02-09 20:13     ` John W. Linville
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-02-07 21:11 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-wireless

On Tue, Feb 06, 2007 at 07:06:07PM -0500, Jeff Garzik wrote:
> Would you mind rebasing & resending, kind sir?

By your command! :-)

---

The following changes since commit 62d0cfcb27cf755cebdc93ca95dabc83608007cd:
  Linus Torvalds (1):
        Linux 2.6.20

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (1):
      zd1211rw: Remove noisy debug message

Larry Finger (3):
      bcm43xx: Fix problem with >1 GB RAM
      bcm43xx: Fix scaling error for 'iwlist rate' information
      bcm43xx: Fix scaling error for 'iwlist freq' information

Maxime Austruy (1):
      zd1211rw: fix potential leak in usb_init

Michael Buesch (1):
      bcm43xx: Enable fwpostfix in nondebug bcm43xx

Robert P. J. Day (1):
      Rename IPW2100 debugging macros to not look like config options.

Ulrich Kunitz (3):
      zd1211rw: Reset device in the probe call
      zd1211rw: Fixed array size issue in reset_mode
      zd1211rw: Added error stats update

 drivers/net/wireless/bcm43xx/bcm43xx.h      |    1 +
 drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |  171 +++++++++++++++++++--------
 drivers/net/wireless/bcm43xx/bcm43xx_main.c |    6 +-
 drivers/net/wireless/bcm43xx/bcm43xx_wx.c   |   28 ++--
 drivers/net/wireless/ipw2100.c              |   16 ++--
 drivers/net/wireless/zd1211rw/zd_mac.c      |   44 ++++++--
 drivers/net/wireless/zd1211rw/zd_usb.c      |   12 ++
 7 files changed, 194 insertions(+), 84 deletions(-)

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 8286678..4168b1a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -766,6 +766,7 @@ struct bcm43xx_private {
 	 * This is currently always BCM43xx_BUSTYPE_PCI
 	 */
 	u8 bustype;
+	u64 dma_mask;
 
 	u16 board_vendor;
 	u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed09..6e0dc76 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
 			  int tx)
 {
 	dma_addr_t dmaaddr;
+	int direction = PCI_DMA_FROMDEVICE;
 
-	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-					 buf, len,
-					 DMA_TO_DEVICE);
-	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+	if (tx)
+		direction = PCI_DMA_TODEVICE;
+
+	dmaaddr = pci_map_single(ring->bcm->pci_dev,
 					 buf, len,
-					 DMA_FROM_DEVICE);
-	}
+					 direction);
 
 	return dmaaddr;
 }
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dmaring *ring,
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_TO_DEVICE);
+				 PCI_DMA_TODEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_FROM_DEVICE);
+				 PCI_DMA_FROMDEVICE);
 	}
 }
 
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-				addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-				   addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
-
-	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					    &(ring->dmabase), GFP_KERNEL);
+	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase));
 	if (!ring->descbase) {
-		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-		return -ENOMEM;
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+		if (!rx_ring)
+			goto out_err;
+
+		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+					     BCM43xx_DMA_RINGMEMSIZE,
+					     PCI_DMA_BIDIRECTIONAL);
+
+		if (pci_dma_mapping_error(rx_ring_dma) ||
+		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+			/* Sigh... */
+			if (!pci_dma_mapping_error(rx_ring_dma))
+				pci_unmap_single(ring->bcm->pci_dev,
+						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			if (pci_dma_mapping_error(rx_ring_dma) ||
+			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+				assert(0);
+				if (!pci_dma_mapping_error(rx_ring_dma))
+					pci_unmap_single(ring->bcm->pci_dev,
+							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+							 PCI_DMA_BIDIRECTIONAL);
+				goto out_err;
+			}
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
 	}
 	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
+out_err:
+	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+	return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	/* This hardware bug work-around adapted from the b44 driver.
+	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+	if (pci_dma_mapping_error(dmaaddr) ||
+	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+		/* This one has 30-bit addressing... */
+		if (!pci_dma_mapping_error(dmaaddr))
+			pci_unmap_single(ring->bcm->pci_dev,
+					 dmaaddr, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+					 skb->data, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(dmaaddr) ||
+		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+			assert(0);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
 	err = dmacontroller_setup(ring);
 	if (err)
 		goto err_free_ringmemory;
+	return ring;
 
 out:
+	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
 	return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-	int nobits;
 
-	if (mask == DMA_64BIT_MASK) {
+	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+	if (bcm->dma_mask == DMA_64BIT_MASK)
 		dma64 = 1;
-		nobits = 64;
-	} else if (mask == DMA_32BIT_MASK)
-		nobits = 32;
-	else
-		nobits = 30;
-	err = pci_set_dma_mask(bcm->pci_dev, mask);
-	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-	if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-		printk(KERN_WARNING PFX "DMA not supported on this device."
-					" Falling back to PIO.\n");
-		bcm->__using_pio = 1;
-		return -ENOSYS;
-#else
-		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-				    "Please recompile the driver with PIO support.\n");
-		return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-	}
+	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
+	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
 	err = 0;
 out:
 	return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
 err_destroy_tx0:
 	bcm43xx_destroy_dmaring(dma->tx_ring0);
 	dma->tx_ring0 = NULL;
-	goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+	printk(KERN_WARNING PFX "DMA not supported on this device."
+				" Falling back to PIO.\n");
+	bcm->__using_pio = 1;
+	return -ENOSYS;
+#else
+	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+			    "Please recompile the driver with PIO support.\n");
+	return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	dma_addr_t dmaaddr;
+	struct sk_buff *bounce_skb;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 			       skb->len - sizeof(struct bcm43xx_txhdr),
 			       (cur_frag == 0),
 			       generate_cookie(ring, slot));
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+		if (!dma_mapping_error(dmaaddr))
+			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+		if (!bounce_skb)
+			return;
+		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+			if (!dma_mapping_error(dmaaddr))
+				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+			dev_kfree_skb_any(bounce_skb);
+			assert(0);
+			return;
+		}
+		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+	}
 
 	meta->skb = skb;
-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = dmaaddr;
 
 	fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 91b752e..62c6235 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@ static int modparam_noleds;
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index a659442..6961be6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -261,22 +261,22 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 	if (phy->type == BCM43xx_PHYTYPE_A ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates = 8;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
 	}
 	if (phy->type == BCM43xx_PHYTYPE_B ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates += 4;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
 	}
 
 	geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +286,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].m = geo->a[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
@@ -294,7 +294,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].m = geo->bg[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b85857a..d0639a4 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG	/* Reception debugging */
+#define IPW2100_RX_DEBUG	/* Reception debugging */
 #endif
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
 	priv->snapshot[0] = NULL;
 }
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
 	int i;
@@ -2314,13 +2314,13 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
  * The size of the constructed ethernet
  *
  */
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 #endif
 
 static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	struct ipw2100_status *status = &priv->status_queue.drv[i];
 	u32 match, reg;
 	int j;
@@ -2342,7 +2342,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 	}
 #endif
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	/* Halt the fimrware so we can get a good image */
 	write_register(priv->net_dev, IPW_REG_RESET_REG,
 		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 
 	skb_put(packet->skb, status->frame_size);
 
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 	/* Make a copy of the frame so we can dump it to the logs if
 	 * ieee80211_rx fails */
 	memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 #endif
 
 	if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 		IPW_DEBUG_DROP("%s: Non consumed packet:\n",
 			       priv->net_dev->name);
 		printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -4912,7 +4912,7 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level)
 	else
 		priv->power_mode = IPW_POWER_ENABLED | power_level;
 
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
 	if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
 		/* Set beacon interval */
 		cmd.host_command = TX_POWER_INDEX;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a085241..4c5f78e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,7 +156,7 @@ void zd_mac_clear(struct zd_mac *mac)
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-	struct zd_ioreq32 ioreqs[3] = {
+	struct zd_ioreq32 ioreqs[] = {
 		{ CR_RX_FILTER, STA_RX_FILTER },
 		{ CR_SNIFFER_ON, 0U },
 	};
@@ -164,10 +164,9 @@ static int reset_mode(struct zd_mac *mac)
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ioreqs[0].value = 0xffffffff;
 		ioreqs[1].value = 0x1;
-		ioreqs[2].value = ENC_SNIFFER;
 	}
 
-	return zd_iowrite32a(&mac->chip, ioreqs, 3);
+	return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@ static int fill_ctrlset(struct zd_mac *mac,
 static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
 {
 	int i, r;
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
 	for (i = 0; i < txb->nr_frags; i++) {
 		struct sk_buff *skb = txb->fragments[i];
 
 		r = fill_ctrlset(mac, txb, i);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 		r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 	}
 
 	/* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
 
 	*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
 	if (status->frame_status & ZD_RX_ERROR) {
-		/* FIXME: update? */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+			ieee->stats.rx_missed_errors++;
+		else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+			ieee->stats.rx_fifo_errors++;
+		else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+			ieee->ieee_stats.rx_discards_undecryptable++;
+		else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+			ieee->stats.rx_crc_errors++;
+			ieee->ieee_stats.rx_fcs_errors++;
+		}
+		else if (status->frame_status & ZD_RX_CRC16_ERROR)
+			ieee->stats.rx_crc_errors++;
 		return -EINVAL;
 	}
+
 	memset(stats, 0, sizeof(struct ieee80211_rx_stats));
 	stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
 		               + sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
 	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
 	{
-		dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
-			 skb->len);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		goto free_skb;
 	}
 
 	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
 	if (r) {
-		/* Only packets with rx errors are included here. */
+		/* Only packets with rx errors are included here.
+		 * The error stats have already been set in fill_rx_stats.
+		 */
 		goto free_skb;
 	}
 
@@ -1114,8 +1134,10 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 
 	r = filter_rx(ieee, skb->data, skb->len, &stats);
 	if (r <= 0) {
-		if (r < 0)
+		if (r < 0) {
+			ieee->stats.rx_errors++;
 			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+		}
 		goto free_skb;
 	}
 
@@ -1146,7 +1168,9 @@ int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
 
 	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
 	if (!skb) {
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+		ieee->stats.rx_dropped++;
 		return -ENOMEM;
 	}
 	skb_reserve(skb, sizeof(struct zd_rt_hdr));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 605e96e..a3217a8 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -401,6 +401,12 @@ out:
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+	struct zd_usb *usb = urb->context;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+	ieee->stats.tx_errors++;
+	ieee->ieee_stats.tx_retry_limit_exceeded++;
 	dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -575,6 +581,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
 	if (length < sizeof(struct rx_length_info)) {
 		/* It's not a complete packet anyhow. */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		return;
 	}
 	length_info = (struct rx_length_info *)
@@ -1027,6 +1036,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 		goto error;
 	}
 
+	usb_reset_device(interface_to_usbdev(intf));
+
 	netdev = zd_netdev_alloc(intf);
 	if (netdev == NULL) {
 		r = -ENOMEM;
@@ -1128,6 +1139,7 @@ static int __init usb_init(void)
 
 	r = usb_register(&driver);
 	if (r) {
+		destroy_workqueue(zd_workqueue);
 		printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
 		       driver.name, r);
 		return r;

-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Please pull "upstream" branch of wireless-2.6
  2007-02-07 21:11   ` Please pull "upstream" " John W. Linville
@ 2007-02-09 20:13     ` John W. Linville
  2007-02-09 21:12       ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-02-09 20:13 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-wireless

On Wed, Feb 07, 2007 at 04:11:17PM -0500, John W. Linville wrote:
> On Tue, Feb 06, 2007 at 07:06:07PM -0500, Jeff Garzik wrote:
> > Would you mind rebasing & resending, kind sir?
> 
> By your command! :-)

And once more, now with feeling! :-)

---

The following changes since commit 62d0cfcb27cf755cebdc93ca95dabc83608007cd:
  Linus Torvalds (1):
        Linux 2.6.20

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (1):
      zd1211rw: Remove noisy debug message

Larry Finger (5):
      bcm43xx: Fix problem with >1 GB RAM
      bcm43xx: Fix scaling error for 'iwlist rate' information
      bcm43xx: Fix scaling error for 'iwlist freq' information
      bcm43xx: Check error returns in initialization routines
      ieee80211: Fix sparse warning

Maxime Austruy (1):
      zd1211rw: fix potential leak in usb_init

Michael Buesch (1):
      bcm43xx: Enable fwpostfix in nondebug bcm43xx

Robert P. J. Day (2):
      Rename IPW2100 debugging macros to not look like config options.
      Replace incorrect macro name "WIRELESS_EXT" with "CONFIG_WIRELESS_EXT"

Ulrich Kunitz (3):
      zd1211rw: Reset device in the probe call
      zd1211rw: Fixed array size issue in reset_mode
      zd1211rw: Added error stats update

 drivers/net/wireless/bcm43xx/bcm43xx.h      |    1 +
 drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |  171 +++++++++++++++++++--------
 drivers/net/wireless/bcm43xx/bcm43xx_main.c |   25 +++--
 drivers/net/wireless/bcm43xx/bcm43xx_wx.c   |   28 ++--
 drivers/net/wireless/ipw2100.c              |   16 ++--
 drivers/net/wireless/zd1211rw/zd_mac.c      |   44 ++++++--
 drivers/net/wireless/zd1211rw/zd_usb.c      |   12 ++
 net/core/net-sysfs.c                        |    4 +-
 net/ieee80211/ieee80211_tx.c                |    3 -
 9 files changed, 210 insertions(+), 94 deletions(-)

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 8286678..4168b1a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -766,6 +766,7 @@ struct bcm43xx_private {
 	 * This is currently always BCM43xx_BUSTYPE_PCI
 	 */
 	u8 bustype;
+	u64 dma_mask;
 
 	u16 board_vendor;
 	u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed09..6e0dc76 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
 			  int tx)
 {
 	dma_addr_t dmaaddr;
+	int direction = PCI_DMA_FROMDEVICE;
 
-	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-					 buf, len,
-					 DMA_TO_DEVICE);
-	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+	if (tx)
+		direction = PCI_DMA_TODEVICE;
+
+	dmaaddr = pci_map_single(ring->bcm->pci_dev,
 					 buf, len,
-					 DMA_FROM_DEVICE);
-	}
+					 direction);
 
 	return dmaaddr;
 }
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dmaring *ring,
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_TO_DEVICE);
+				 PCI_DMA_TODEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_FROM_DEVICE);
+				 PCI_DMA_FROMDEVICE);
 	}
 }
 
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-				addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-				   addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
-
-	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					    &(ring->dmabase), GFP_KERNEL);
+	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase));
 	if (!ring->descbase) {
-		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-		return -ENOMEM;
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+		if (!rx_ring)
+			goto out_err;
+
+		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+					     BCM43xx_DMA_RINGMEMSIZE,
+					     PCI_DMA_BIDIRECTIONAL);
+
+		if (pci_dma_mapping_error(rx_ring_dma) ||
+		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+			/* Sigh... */
+			if (!pci_dma_mapping_error(rx_ring_dma))
+				pci_unmap_single(ring->bcm->pci_dev,
+						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			if (pci_dma_mapping_error(rx_ring_dma) ||
+			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+				assert(0);
+				if (!pci_dma_mapping_error(rx_ring_dma))
+					pci_unmap_single(ring->bcm->pci_dev,
+							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+							 PCI_DMA_BIDIRECTIONAL);
+				goto out_err;
+			}
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
 	}
 	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
+out_err:
+	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+	return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	/* This hardware bug work-around adapted from the b44 driver.
+	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+	if (pci_dma_mapping_error(dmaaddr) ||
+	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+		/* This one has 30-bit addressing... */
+		if (!pci_dma_mapping_error(dmaaddr))
+			pci_unmap_single(ring->bcm->pci_dev,
+					 dmaaddr, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+					 skb->data, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(dmaaddr) ||
+		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+			assert(0);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
 	err = dmacontroller_setup(ring);
 	if (err)
 		goto err_free_ringmemory;
+	return ring;
 
 out:
+	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
 	return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-	int nobits;
 
-	if (mask == DMA_64BIT_MASK) {
+	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+	if (bcm->dma_mask == DMA_64BIT_MASK)
 		dma64 = 1;
-		nobits = 64;
-	} else if (mask == DMA_32BIT_MASK)
-		nobits = 32;
-	else
-		nobits = 30;
-	err = pci_set_dma_mask(bcm->pci_dev, mask);
-	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-	if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-		printk(KERN_WARNING PFX "DMA not supported on this device."
-					" Falling back to PIO.\n");
-		bcm->__using_pio = 1;
-		return -ENOSYS;
-#else
-		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-				    "Please recompile the driver with PIO support.\n");
-		return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-	}
+	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
+	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
 	err = 0;
 out:
 	return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
 err_destroy_tx0:
 	bcm43xx_destroy_dmaring(dma->tx_ring0);
 	dma->tx_ring0 = NULL;
-	goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+	printk(KERN_WARNING PFX "DMA not supported on this device."
+				" Falling back to PIO.\n");
+	bcm->__using_pio = 1;
+	return -ENOSYS;
+#else
+	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+			    "Please recompile the driver with PIO support.\n");
+	return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	dma_addr_t dmaaddr;
+	struct sk_buff *bounce_skb;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
 			       skb->len - sizeof(struct bcm43xx_txhdr),
 			       (cur_frag == 0),
 			       generate_cookie(ring, slot));
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+		if (!dma_mapping_error(dmaaddr))
+			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+		if (!bounce_skb)
+			return;
+		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+			if (!dma_mapping_error(dmaaddr))
+				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+			dev_kfree_skb_any(bounce_skb);
+			assert(0);
+			return;
+		}
+		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+	}
 
 	meta->skb = skb;
-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = dmaaddr;
 
 	fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 91b752e..63fc16f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@ static int modparam_noleds;
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
@@ -2980,8 +2976,10 @@ static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
 		goto out;
-	bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
-	bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+	err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+	if (err)
+		goto out;
+	err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
 
 out:
 	return err;
@@ -3778,12 +3776,18 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
 	}
 	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
 	                          &bcm->board_vendor);
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
 	                          &bcm->board_type);
-	bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
 	                          &bcm->board_revision);
+	if (err)
+		goto err_iounmap;
 
 	err = bcm43xx_chipset_attach(bcm);
 	if (err)
@@ -3874,6 +3878,7 @@ err_pci_release:
 	pci_release_regions(pci_dev);
 err_pci_disable:
 	pci_disable_device(pci_dev);
+	printk(KERN_ERR PFX "Unable to attach board\n");
 	goto out;
 }
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index a659442..6961be6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -261,22 +261,22 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 	if (phy->type == BCM43xx_PHYTYPE_A ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates = 8;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
 	}
 	if (phy->type == BCM43xx_PHYTYPE_B ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates += 4;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
 	}
 
 	geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +286,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].m = geo->a[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
@@ -294,7 +294,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].m = geo->bg[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b85857a..d0639a4 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG	/* Reception debugging */
+#define IPW2100_RX_DEBUG	/* Reception debugging */
 #endif
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
 	priv->snapshot[0] = NULL;
 }
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
 	int i;
@@ -2314,13 +2314,13 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
  * The size of the constructed ethernet
  *
  */
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 #endif
 
 static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	struct ipw2100_status *status = &priv->status_queue.drv[i];
 	u32 match, reg;
 	int j;
@@ -2342,7 +2342,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 	}
 #endif
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	/* Halt the fimrware so we can get a good image */
 	write_register(priv->net_dev, IPW_REG_RESET_REG,
 		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 
 	skb_put(packet->skb, status->frame_size);
 
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 	/* Make a copy of the frame so we can dump it to the logs if
 	 * ieee80211_rx fails */
 	memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
 #endif
 
 	if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 		IPW_DEBUG_DROP("%s: Non consumed packet:\n",
 			       priv->net_dev->name);
 		printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -4912,7 +4912,7 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level)
 	else
 		priv->power_mode = IPW_POWER_ENABLED | power_level;
 
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
 	if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
 		/* Set beacon interval */
 		cmd.host_command = TX_POWER_INDEX;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a085241..4c5f78e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,7 +156,7 @@ void zd_mac_clear(struct zd_mac *mac)
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-	struct zd_ioreq32 ioreqs[3] = {
+	struct zd_ioreq32 ioreqs[] = {
 		{ CR_RX_FILTER, STA_RX_FILTER },
 		{ CR_SNIFFER_ON, 0U },
 	};
@@ -164,10 +164,9 @@ static int reset_mode(struct zd_mac *mac)
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ioreqs[0].value = 0xffffffff;
 		ioreqs[1].value = 0x1;
-		ioreqs[2].value = ENC_SNIFFER;
 	}
 
-	return zd_iowrite32a(&mac->chip, ioreqs, 3);
+	return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@ static int fill_ctrlset(struct zd_mac *mac,
 static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
 {
 	int i, r;
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
 	for (i = 0; i < txb->nr_frags; i++) {
 		struct sk_buff *skb = txb->fragments[i];
 
 		r = fill_ctrlset(mac, txb, i);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 		r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 	}
 
 	/* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
 
 	*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
 	if (status->frame_status & ZD_RX_ERROR) {
-		/* FIXME: update? */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+			ieee->stats.rx_missed_errors++;
+		else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+			ieee->stats.rx_fifo_errors++;
+		else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+			ieee->ieee_stats.rx_discards_undecryptable++;
+		else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+			ieee->stats.rx_crc_errors++;
+			ieee->ieee_stats.rx_fcs_errors++;
+		}
+		else if (status->frame_status & ZD_RX_CRC16_ERROR)
+			ieee->stats.rx_crc_errors++;
 		return -EINVAL;
 	}
+
 	memset(stats, 0, sizeof(struct ieee80211_rx_stats));
 	stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
 		               + sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
 	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
 	{
-		dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
-			 skb->len);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		goto free_skb;
 	}
 
 	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
 	if (r) {
-		/* Only packets with rx errors are included here. */
+		/* Only packets with rx errors are included here.
+		 * The error stats have already been set in fill_rx_stats.
+		 */
 		goto free_skb;
 	}
 
@@ -1114,8 +1134,10 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 
 	r = filter_rx(ieee, skb->data, skb->len, &stats);
 	if (r <= 0) {
-		if (r < 0)
+		if (r < 0) {
+			ieee->stats.rx_errors++;
 			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+		}
 		goto free_skb;
 	}
 
@@ -1146,7 +1168,9 @@ int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
 
 	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
 	if (!skb) {
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+		ieee->stats.rx_dropped++;
 		return -ENOMEM;
 	}
 	skb_reserve(skb, sizeof(struct zd_rt_hdr));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 605e96e..a3217a8 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -401,6 +401,12 @@ out:
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+	struct zd_usb *usb = urb->context;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+	ieee->stats.tx_errors++;
+	ieee->ieee_stats.tx_retry_limit_exceeded++;
 	dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -575,6 +581,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
 	if (length < sizeof(struct rx_length_info)) {
 		/* It's not a complete packet anyhow. */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		return;
 	}
 	length_info = (struct rx_length_info *)
@@ -1027,6 +1036,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 		goto error;
 	}
 
+	usb_reset_device(interface_to_usbdev(intf));
+
 	netdev = zd_netdev_alloc(intf);
 	if (netdev == NULL) {
 		r = -ENOMEM;
@@ -1128,6 +1139,7 @@ static int __init usb_init(void)
 
 	r = usb_register(&driver);
 	if (r) {
+		destroy_workqueue(zd_workqueue);
 		printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
 		       driver.name, r);
 		return r;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index f47f319..44e69a2 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -329,7 +329,7 @@ static struct attribute_group netstat_group = {
 	.attrs  = netstat_attrs,
 };
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 /* helper function that does all the locking etc for wireless stats */
 static ssize_t wireless_show(struct class_device *cd, char *buf,
 			     ssize_t (*format)(const struct iw_statistics *,
@@ -462,7 +462,7 @@ int netdev_register_sysfs(struct net_device *net)
 	if (net->get_stats)
 		*groups++ = &netstat_group;
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 	if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
 		*groups++ = &wireless_group;
 #endif
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 854fc13..54e0116 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -502,9 +502,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
 		else if (host_build_iv) {
-			struct ieee80211_crypt_data *crypt;
-
-			crypt = ieee->crypt[ieee->tx_keyidx];
 			atomic_inc(&crypt->refcnt);
 			if (crypt->ops->build_iv)
 				crypt->ops->build_iv(skb_frag, hdr_len,
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull "upstream" branch of wireless-2.6
  2007-02-09 20:13     ` John W. Linville
@ 2007-02-09 21:12       ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-02-09 21:12 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev, linux-wireless

John W. Linville wrote:
> On Wed, Feb 07, 2007 at 04:11:17PM -0500, John W. Linville wrote:
>> On Tue, Feb 06, 2007 at 07:06:07PM -0500, Jeff Garzik wrote:
>>> Would you mind rebasing & resending, kind sir?
>> By your command! :-)
> 
> And once more, now with feeling! :-)
> 
> ---
> 
> The following changes since commit 62d0cfcb27cf755cebdc93ca95dabc83608007cd:
>   Linus Torvalds (1):
>         Linux 2.6.20
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (1):
>       zd1211rw: Remove noisy debug message
> 
> Larry Finger (5):
>       bcm43xx: Fix problem with >1 GB RAM
>       bcm43xx: Fix scaling error for 'iwlist rate' information
>       bcm43xx: Fix scaling error for 'iwlist freq' information
>       bcm43xx: Check error returns in initialization routines
>       ieee80211: Fix sparse warning
> 
> Maxime Austruy (1):
>       zd1211rw: fix potential leak in usb_init
> 
> Michael Buesch (1):
>       bcm43xx: Enable fwpostfix in nondebug bcm43xx
> 
> Robert P. J. Day (2):
>       Rename IPW2100 debugging macros to not look like config options.
>       Replace incorrect macro name "WIRELESS_EXT" with "CONFIG_WIRELESS_EXT"
> 
> Ulrich Kunitz (3):
>       zd1211rw: Reset device in the probe call
>       zd1211rw: Fixed array size issue in reset_mode
>       zd1211rw: Added error stats update
> 
>  drivers/net/wireless/bcm43xx/bcm43xx.h      |    1 +
>  drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |  171 +++++++++++++++++++--------
>  drivers/net/wireless/bcm43xx/bcm43xx_main.c |   25 +++--
>  drivers/net/wireless/bcm43xx/bcm43xx_wx.c   |   28 ++--
>  drivers/net/wireless/ipw2100.c              |   16 ++--
>  drivers/net/wireless/zd1211rw/zd_mac.c      |   44 ++++++--
>  drivers/net/wireless/zd1211rw/zd_usb.c      |   12 ++
>  net/core/net-sysfs.c                        |    4 +-
>  net/ieee80211/ieee80211_tx.c                |    3 -
>  9 files changed, 210 insertions(+), 94 deletions(-)

pulled, thanks



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
  2007-02-27 20:50 Please pull 'upstream-fixes' " John W. Linville
@ 2007-02-27 20:51 ` John W. Linville
  2007-03-03  0:42   ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-02-27 20:51 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless

The following changes since commit 357efd57f229716fd6a1494b970c5a66c0c465ef:
  Stefano Brivio (1):
        bcm43xx: fix for 4309

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

John W. Linville (1):
      wireless: remove obsolete text files

Larry Finger (1):
      bcm43xx: Update Documentation/bcm43xx.txt

Pavel Roskin (1):
      Use offsetof() instead of own equivalent

Ulrich Kunitz (1):
      zd1211rw: changed GFP_NOFS to GFP_KERNEL

Zhu Yi (1):
      ipw2200: add channels sysfs entry

 Documentation/networking/bcm43xx.txt        |   97 +++++++++++++++++++++------
 drivers/net/wireless/README                 |   25 -------
 drivers/net/wireless/hostap/hostap_common.h |    4 +-
 drivers/net/wireless/ipw2200.c              |   47 +++++++++++++
 drivers/net/wireless/todo.txt               |   15 ----
 drivers/net/wireless/zd1211rw/zd_chip.c     |    4 +-
 drivers/net/wireless/zd1211rw/zd_usb.c      |   20 +++---
 7 files changed, 136 insertions(+), 76 deletions(-)
 delete mode 100644 drivers/net/wireless/README
 delete mode 100644 drivers/net/wireless/todo.txt

diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
index 28541d2..a136721 100644
--- a/Documentation/networking/bcm43xx.txt
+++ b/Documentation/networking/bcm43xx.txt
@@ -2,35 +2,88 @@
 			BCM43xx Linux Driver Project
 			============================
 
-About this software
--------------------
+Introduction
+------------
 
-The goal of this project is to develop a linux driver for Broadcom
-BCM43xx chips, based on the specification at 
-http://bcm-specs.sipsolutions.net/
+Many of the wireless devices found in modern notebook computers are
+based on the wireless chips produced by Broadcom. These devices have
+been a problem for Linux users as there is no open-source driver
+available. In addition, Broadcom has not released specifications
+for the device, and driver availability has been limited to the
+binary-only form used in the GPL versions of AP hardware such as the
+Linksys WRT54G, and the Windows and OS X drivers.  Before this project
+began, the only way to use these devices were to use the Windows or
+OS X drivers with either the Linuxant or ndiswrapper modules. There
+is a strong penalty if this method is used as loading the binary-only
+module "taints" the kernel, and no kernel developer will help diagnose
+any kernel problems.
 
-The project page is http://bcm43xx.berlios.de/
+Development
+-----------
 
+This driver has been developed using
+a clean-room technique that is described at
+http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal
+reasons, none of the clean-room crew works on the on the Linux driver,
+and none of the Linux developers sees anything but the specifications,
+which are the ultimate product of the reverse-engineering group.
 
-Requirements
-------------
+Software
+--------
+
+Since the release of the 2.6.17 kernel, the bcm43xx driver has been
+distributed with the kernel source, and is prebuilt in most, if not
+all, distributions.  There is, however, additional software that is
+required. The firmware used by the chip is the intellectual property
+of Broadcom and they have not given the bcm43xx team redistribution
+rights to this firmware.  Since we cannot legally redistribute
+the firwmare we cannot include it with the driver. Furthermore, it
+cannot be placed in the downloadable archives of any distributing
+organization; therefore, the user is responsible for obtaining the
+firmware and placing it in the appropriate location so that the driver
+can find it when initializing.
+
+To help with this process, the bcm43xx developers provide a separate
+program named bcm43xx-fwcutter to "cut" the firmware out of a
+Windows or OS X driver and write the extracted files to the proper
+location. This program is usually provided with the distribution;
+however, it may be downloaded from
+
+http://developer.berlios.de/project/showfiles.php?group_id=4547
 
-1)	Linux Kernel 2.6.16 or later
-	http://www.kernel.org/
+The firmware is available in two versions. V3 firmware is used with
+the in-kernel bcm43xx driver that uses a software MAC layer called
+SoftMAC, and will have a microcode revision of 0x127 or smaller. The
+V4 firmware is used by an out-of-kernel driver employing a variation of
+the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches
+a satisfactory level of development, it will replace bcm43xx-softmac
+in the kernel as it is much more flexible and powerful.
 
-	You may want to configure your kernel with:
+A source for the latest V3 firmware is
 
-	CONFIG_DEBUG_FS (optional):
-		-> Kernel hacking
-		  -> Debug Filesystem
+http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o
 
-2)	SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211
-	modules:
-	http://softmac.sipsolutions.net/
+Once this file is downloaded, the command
+'bcm43xx-fwcutter -w <dir> <filename>'
+will extract the microcode and write it to directory
+<dir>. The correct directory will depend on your distribution;
+however, most use '/lib/firmware'. Once this step is completed,
+the bcm3xx driver should load when the system is booted. To see
+any messages relating to the driver, issue the command 'dmesg |
+grep bcm43xx' from a terminal window. If there are any problems,
+please send that output to Bcm43xx-dev@lists.berlios.de.
 
-3)	Firmware Files
+Although the driver has been in-kernel since 2.6.17, the earliest
+version is quite limited in its capability. Patches that include
+all features of later versions are available for the stable kernel
+versions from 2.6.18. These will be needed if you use a BCM4318,
+or a PCI Express version (BCM4311 and BCM4312). In addition, if you
+have an early BCM4306 and more than 1 GB RAM, your kernel will need
+to be patched.	These patches, which are being updated regularly,
+are available at ftp://lwfinger.dynalias.org/patches. Look for
+combined_2.6.YY.patch. Of course you will need kernel source downloaded
+from kernel.org, or the source from your distribution.
 
-	Please try fwcutter. Fwcutter can extract the firmware from various 
-	binary driver files. It supports driver files from Windows, MacOS and 
-	Linux. You can get fwcutter from http://bcm43xx.berlios.de/.
-	Also, fwcutter comes with a README file for further instructions.
+If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG
+and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is
+essential for solving any problems.
diff --git a/drivers/net/wireless/README b/drivers/net/wireless/README
deleted file mode 100644
index 0c274bf..0000000
--- a/drivers/net/wireless/README
+++ /dev/null
@@ -1,25 +0,0 @@
-	README
-	------
-
-	This directory is mostly for Wireless LAN drivers, in their
-various incarnations (ISA, PCI, Pcmcia...).
-	This separate directory is needed because a lot of driver work
-on different bus (typically PCI + Pcmcia) and share 95% of the
-code. This allow the code and the config options to be in one single
-place instead of scattered all over the driver tree, which is never
-100% satisfactory.
-
-	Note : if you want more info on the topic of Wireless LANs,
-you are kindly invited to have a look at the Wireless Howto :
-		http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
-	Some Wireless LAN drivers, like orinoco_cs, require the use of
-Wireless Tools to be configured :
-		http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
-
-	Special notes for distribution maintainers :
-	1) wvlan_cs will be discontinued soon in favor of orinoco_cs
-	2) Please add Wireless Tools support in your scripts
-
-	Have fun...
-
-	Jean
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 0162400..b31e6a0 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -368,9 +368,9 @@ enum {
 
 #define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
 #define PRISM2_HOSTAPD_RID_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+offsetof(struct prism2_hostapd_param, u.rid.data)
 #define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+offsetof(struct prism2_hostapd_param, u.generic_elem.data)
 
 /* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
  */
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index c878a2f..99c517a 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1847,6 +1847,52 @@ static ssize_t store_net_stats(struct device *d, struct device_attribute *attr,
 static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO,
 		   show_net_stats, store_net_stats);
 
+static ssize_t show_channels(struct device *d,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct ipw_priv *priv = dev_get_drvdata(d);
+	const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+	int len = 0, i;
+
+	len = sprintf(&buf[len],
+		      "Displaying %d channels in 2.4Ghz band "
+		      "(802.11bg):\n", geo->bg_channels);
+
+	for (i = 0; i < geo->bg_channels; i++) {
+		len += sprintf(&buf[len], "%d: BSS%s%s, %s, Band %s.\n",
+			       geo->bg[i].channel,
+			       geo->bg[i].flags & IEEE80211_CH_RADAR_DETECT ?
+			       " (radar spectrum)" : "",
+			       ((geo->bg[i].flags & IEEE80211_CH_NO_IBSS) ||
+				(geo->bg[i].flags & IEEE80211_CH_RADAR_DETECT))
+			       ? "" : ", IBSS",
+			       geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY ?
+			       "passive only" : "active/passive",
+			       geo->bg[i].flags & IEEE80211_CH_B_ONLY ?
+			       "B" : "B/G");
+	}
+
+	len += sprintf(&buf[len],
+		       "Displaying %d channels in 5.2Ghz band "
+		       "(802.11a):\n", geo->a_channels);
+	for (i = 0; i < geo->a_channels; i++) {
+		len += sprintf(&buf[len], "%d: BSS%s%s, %s.\n",
+			       geo->a[i].channel,
+			       geo->a[i].flags & IEEE80211_CH_RADAR_DETECT ?
+			       " (radar spectrum)" : "",
+			       ((geo->a[i].flags & IEEE80211_CH_NO_IBSS) ||
+				(geo->a[i].flags & IEEE80211_CH_RADAR_DETECT))
+			       ? "" : ", IBSS",
+			       geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY ?
+			       "passive only" : "active/passive");
+	}
+
+	return len;
+}
+
+static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+
 static void notify_wx_assoc_event(struct ipw_priv *priv)
 {
 	union iwreq_data wrqu;
@@ -11383,6 +11429,7 @@ static struct attribute *ipw_sysfs_entries[] = {
 	&dev_attr_led.attr,
 	&dev_attr_speed_scan.attr,
 	&dev_attr_net_stats.attr,
+	&dev_attr_channels.attr,
 #ifdef CONFIG_IPW2200_PROMISCUOUS
 	&dev_attr_rtap_iface.attr,
 	&dev_attr_rtap_filter.attr,
diff --git a/drivers/net/wireless/todo.txt b/drivers/net/wireless/todo.txt
deleted file mode 100644
index 3223401..0000000
--- a/drivers/net/wireless/todo.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-	Wireless Todo
-	-------------
-
-1) Bring other kernel Wireless LAN drivers here
-	Completed
-
-2) Bring new Wireless LAN driver not yet in the kernel there
-	See my web page for details
-	In particular : HostAP
-
-3) Misc
-	o Mark wavelan, wavelan_cs, netwave_cs drivers as obsolete
-	o Maybe arlan.c, ray_cs.c and strip.c also deserve to be obsolete
-
-	Jean II
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 9c64f89..f97288d 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -114,7 +114,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
 	/* Allocate a single memory block for values and addresses. */
 	count16 = 2*count;
 	a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
-		                   GFP_NOFS);
+		                   GFP_KERNEL);
 	if (!a16) {
 		dev_dbg_f(zd_chip_dev(chip),
 			  "error ENOMEM in allocation of a16\n");
@@ -163,7 +163,7 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
 
 	/* Allocate a single memory block for values and addresses. */
 	count16 = 2*count;
-	ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS);
+	ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL);
 	if (!ioreqs16) {
 		r = -ENOMEM;
 		dev_dbg_f(zd_chip_dev(chip),
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index aac8a1c..5e67106 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -412,7 +412,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
 
 	dev_dbg_f(zd_usb_dev(usb), "\n");
 
-	urb = usb_alloc_urb(0, GFP_NOFS);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
 		r = -ENOMEM;
 		goto out;
@@ -430,7 +430,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
 
 	/* TODO: make it a DMA buffer */
 	r = -ENOMEM;
-	transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS);
+	transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL);
 	if (!transfer_buffer) {
 		dev_dbg_f(zd_usb_dev(usb),
 			"couldn't allocate transfer_buffer\n");
@@ -444,7 +444,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
 			 intr->interval);
 
 	dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
-	r = usb_submit_urb(urb, GFP_NOFS);
+	r = usb_submit_urb(urb, GFP_KERNEL);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
 			 "Couldn't submit urb. Error number %d\n", r);
@@ -593,10 +593,10 @@ static struct urb *alloc_urb(struct zd_usb *usb)
 	struct urb *urb;
 	void *buffer;
 
-	urb = usb_alloc_urb(0, GFP_NOFS);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb)
 		return NULL;
-	buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS,
+	buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
 		                  &urb->transfer_dma);
 	if (!buffer) {
 		usb_free_urb(urb);
@@ -629,7 +629,7 @@ int zd_usb_enable_rx(struct zd_usb *usb)
 	dev_dbg_f(zd_usb_dev(usb), "\n");
 
 	r = -ENOMEM;
-	urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS);
+	urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
 	if (!urbs)
 		goto error;
 	for (i = 0; i < URBS_COUNT; i++) {
@@ -650,7 +650,7 @@ int zd_usb_enable_rx(struct zd_usb *usb)
 	spin_unlock_irq(&rx->lock);
 
 	for (i = 0; i < URBS_COUNT; i++) {
-		r = usb_submit_urb(urbs[i], GFP_NOFS);
+		r = usb_submit_urb(urbs[i], GFP_KERNEL);
 		if (r)
 			goto error_submit;
 	}
@@ -1156,7 +1156,7 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 	}
 
 	req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
-	req = kmalloc(req_len, GFP_NOFS);
+	req = kmalloc(req_len, GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 	req->id = cpu_to_le16(USB_REQ_READ_REGS);
@@ -1219,7 +1219,7 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 
 	req_len = sizeof(struct usb_req_write_regs) +
 		  count * sizeof(struct reg_data);
-	req = kmalloc(req_len, GFP_NOFS);
+	req = kmalloc(req_len, GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 
@@ -1299,7 +1299,7 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 	bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
 
 	req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
-	req = kmalloc(req_len, GFP_NOFS);
+	req = kmalloc(req_len, GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-02-27 20:51 ` Please pull 'upstream' " John W. Linville
@ 2007-03-03  0:42   ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-03  0:42 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

John W. Linville wrote:
> The following changes since commit 357efd57f229716fd6a1494b970c5a66c0c465ef:
>   Stefano Brivio (1):
>         bcm43xx: fix for 4309
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> John W. Linville (1):
>       wireless: remove obsolete text files
> 
> Larry Finger (1):
>       bcm43xx: Update Documentation/bcm43xx.txt
> 
> Pavel Roskin (1):
>       Use offsetof() instead of own equivalent
> 
> Ulrich Kunitz (1):
>       zd1211rw: changed GFP_NOFS to GFP_KERNEL
> 
> Zhu Yi (1):
>       ipw2200: add channels sysfs entry
> 
>  Documentation/networking/bcm43xx.txt        |   97 +++++++++++++++++++++------
>  drivers/net/wireless/README                 |   25 -------
>  drivers/net/wireless/hostap/hostap_common.h |    4 +-
>  drivers/net/wireless/ipw2200.c              |   47 +++++++++++++
>  drivers/net/wireless/todo.txt               |   15 ----
>  drivers/net/wireless/zd1211rw/zd_chip.c     |    4 +-
>  drivers/net/wireless/zd1211rw/zd_usb.c      |   20 +++---
>  7 files changed, 136 insertions(+), 76 deletions(-)
>  delete mode 100644 drivers/net/wireless/README
>  delete mode 100644 drivers/net/wireless/todo.txt

pulled



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
  2007-03-08  3:30 Please pull 'upstream-fixes' " John W. Linville
@ 2007-03-08  3:32 ` John W. Linville
  2007-03-09 16:59   ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-03-08  3:32 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless

The following changes since commit 9b73d945c4269f61d2ecf0555150b577a965bc99:
  John W. Linville (1):
        Merge branch 'upstream-fixes' into upstream

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Andrew Morton (1):
      ipw2200: fix ieee80211_get_geo typo

Jouni Malinen (1):
      hostap: Add D-Link DWL-650 Rev. P1 product id

Sam Ravnborg (1):
      bcm43xx: do not rebuild when kernel version changes

 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c |    4 ++--
 drivers/net/wireless/hostap/hostap_cs.c        |    5 +++++
 drivers/net/wireless/ipw2200.c                 |    2 +-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
index c947025..d2df6a0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
@@ -32,7 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/pci.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <linux/utsname.h>
 
 
 static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -40,7 +40,7 @@ static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
 	struct bcm43xx_private *bcm = bcm43xx_priv(dev);
 
 	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-	strncpy(info->version, UTS_RELEASE, sizeof(info->version));
+	strncpy(info->version, utsname()->release, sizeof(info->version));
 	strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 8d8f4b9..534da85 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -848,6 +848,11 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
 		"Intersil", "PRISM 2_5 PCMCIA ADAPTER",	"ISL37300P",
 		"Eval-RevA",
 		0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e),
+	/* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */
+	PCMCIA_DEVICE_PROD_ID1234(
+		"D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10",
+		"A3",
+		0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52),
 	PCMCIA_DEVICE_PROD_ID123(
 		"Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
 		0xe6ec52ce, 0x08649af2, 0x4b74baa0),
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 99c517a..4372438 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1852,7 +1852,7 @@ static ssize_t show_channels(struct device *d,
 			     char *buf)
 {
 	struct ipw_priv *priv = dev_get_drvdata(d);
-	const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+	const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
 	int len = 0, i;
 
 	len = sprintf(&buf[len],
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-03-08  3:32 ` Please pull 'upstream' " John W. Linville
@ 2007-03-09 16:59   ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-09 16:59 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

John W. Linville wrote:
> The following changes since commit 9b73d945c4269f61d2ecf0555150b577a965bc99:
>   John W. Linville (1):
>         Merge branch 'upstream-fixes' into upstream
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Andrew Morton (1):
>       ipw2200: fix ieee80211_get_geo typo
> 
> Jouni Malinen (1):
>       hostap: Add D-Link DWL-650 Rev. P1 product id
> 
> Sam Ravnborg (1):
>       bcm43xx: do not rebuild when kernel version changes
> 
>  drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c |    4 ++--
>  drivers/net/wireless/hostap/hostap_cs.c        |    5 +++++
>  drivers/net/wireless/ipw2200.c                 |    2 +-
>  3 files changed, 8 insertions(+), 3 deletions(-)
> 

pulled




^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
  2007-03-16 21:31 Please pull 'upstream-fixes' " John W. Linville
@ 2007-03-16 21:34 ` John W. Linville
  2007-03-23  5:55   ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-03-16 21:34 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless

The following changes since commit 0e39a919461842a38e406702fe0e94c6138ddfef
  John W. Linville (1):
        Merge branch 'upstream-fixes' into upstream

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (4):
      zd1211rw: Use compare_ether_addr()
      zd1211rw: Reject AL2230S devices
      zd1211rw: Add AL2230S RF support
      zd1211rw: More device IDs

Larry Finger (2):
      bcm43xx: MANUALWLAN fixes
      bcm43xx:Eliminate some 'G Mode Enable' magic numbers

Michal Schmidt (3):
      airo: Fix an error path memory leak
      airo: Don't check for NULL before kfree()
      airo: Make /sys/bus/pci/drivers/airo/{,un}bind work

 drivers/net/wireless/airo.c                  |   74 ++++++++++-------------
 drivers/net/wireless/bcm43xx/bcm43xx.h       |    3 +
 drivers/net/wireless/bcm43xx/bcm43xx_main.c  |    4 +-
 drivers/net/wireless/bcm43xx/bcm43xx_phy.c   |    8 +-
 drivers/net/wireless/bcm43xx/bcm43xx_radio.c |   14 ++--
 drivers/net/wireless/zd1211rw/zd_chip.c      |    6 +-
 drivers/net/wireless/zd1211rw/zd_chip.h      |    2 +-
 drivers/net/wireless/zd1211rw/zd_mac.c       |   10 ++--
 drivers/net/wireless/zd1211rw/zd_rf.c        |    2 +-
 drivers/net/wireless/zd1211rw/zd_rf.h        |    2 +-
 drivers/net/wireless/zd1211rw/zd_rf_al2230.c |   83 ++++++++++++++++++++++---
 drivers/net/wireless/zd1211rw/zd_usb.c       |    3 +
 12 files changed, 136 insertions(+), 75 deletions(-)

diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a8c2bfe..254f285 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1145,6 +1145,7 @@ static void airo_networks_free(struct airo_info *ai);
 struct airo_info {
 	struct net_device_stats	stats;
 	struct net_device             *dev;
+	struct list_head              dev_list;
 	/* Note, we can have MAX_FIDS outstanding.  FIDs are 16-bits, so we
 	   use the high bit to mark whether it is in use. */
 #define MAX_FIDS 6
@@ -2360,6 +2361,21 @@ static int airo_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
+static LIST_HEAD(airo_devices);
+
+static void add_airo_dev(struct airo_info *ai)
+{
+	/* Upper layers already keep track of PCI devices,
+	 * so we only need to remember our non-PCI cards. */
+	if (!ai->pci)
+		list_add_tail(&ai->dev_list, &airo_devices);
+}
+
+static void del_airo_dev(struct airo_info *ai)
+{
+	if (!ai->pci)
+		list_del(&ai->dev_list);
+}
 
 static int airo_close(struct net_device *dev) {
 	struct airo_info *ai = dev->priv;
@@ -2381,8 +2397,6 @@ static int airo_close(struct net_device *dev) {
 	return 0;
 }
 
-static void del_airo_dev( struct net_device *dev );
-
 void stop_airo_card( struct net_device *dev, int freeres )
 {
 	struct airo_info *ai = dev->priv;
@@ -2434,14 +2448,12 @@ void stop_airo_card( struct net_device *dev, int freeres )
 		}
         }
 	crypto_free_cipher(ai->tfm);
-	del_airo_dev( dev );
+	del_airo_dev(ai);
 	free_netdev( dev );
 }
 
 EXPORT_SYMBOL(stop_airo_card);
 
-static int add_airo_dev( struct net_device *dev );
-
 static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
 {
 	memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
@@ -2740,8 +2752,6 @@ static int airo_networks_allocate(struct airo_info *ai)
 
 static void airo_networks_free(struct airo_info *ai)
 {
-	if (!ai->networks)
-		return;
 	kfree(ai->networks);
 	ai->networks = NULL;
 }
@@ -2816,12 +2826,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
 	if (IS_ERR(ai->airo_thread_task))
 		goto err_out_free;
 	ai->tfm = NULL;
-	rc = add_airo_dev( dev );
-	if (rc)
-		goto err_out_thr;
+	add_airo_dev(ai);
 
 	if (airo_networks_allocate (ai))
-		goto err_out_unlink;
+		goto err_out_thr;
 	airo_networks_initialize (ai);
 
 	/* The Airo-specific entries in the device structure. */
@@ -2852,7 +2860,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
 	if (rc) {
 		airo_print_err(dev->name, "register interrupt %d failed, rc %d",
 				irq, rc);
-		goto err_out_unlink;
+		goto err_out_nets;
 	}
 	if (!is_pcmcia) {
 		if (!request_region( dev->base_addr, 64, dev->name )) {
@@ -2935,9 +2943,10 @@ err_out_res:
 	        release_region( dev->base_addr, 64 );
 err_out_irq:
 	free_irq(dev->irq, dev);
-err_out_unlink:
-	del_airo_dev(dev);
+err_out_nets:
+	airo_networks_free(ai);
 err_out_thr:
+	del_airo_dev(ai);
 	set_bit(JOB_DIE, &ai->jobs);
 	kthread_stop(ai->airo_thread_task);
 err_out_free:
@@ -5536,11 +5545,6 @@ static int proc_close( struct inode *inode, struct file *file )
 	return 0;
 }
 
-static struct net_device_list {
-	struct net_device *dev;
-	struct net_device_list *next;
-} *airo_devices;
-
 /* Since the card doesn't automatically switch to the right WEP mode,
    we will make it do it.  If the card isn't associated, every secs we
    will switch WEP modes to see if that will help.  If the card is
@@ -5583,26 +5587,6 @@ static void timer_func( struct net_device *dev ) {
 	apriv->expires = RUN_AT(HZ*3);
 }
 
-static int add_airo_dev( struct net_device *dev ) {
-	struct net_device_list *node = kmalloc( sizeof( *node ), GFP_KERNEL );
-	if ( !node )
-		return -ENOMEM;
-
-	node->dev = dev;
-	node->next = airo_devices;
-	airo_devices = node;
-
-	return 0;
-}
-
-static void del_airo_dev( struct net_device *dev ) {
-	struct net_device_list **p = &airo_devices;
-	while( *p && ( (*p)->dev != dev ) )
-		p = &(*p)->next;
-	if ( *p && (*p)->dev == dev )
-		*p = (*p)->next;
-}
-
 #ifdef CONFIG_PCI
 static int __devinit airo_pci_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *pent)
@@ -5626,6 +5610,10 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
 
 static void __devexit airo_pci_remove(struct pci_dev *pdev)
 {
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	airo_print_info(dev->name, "Unregistering...");
+	stop_airo_card(dev, 1);
 }
 
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -5751,9 +5739,11 @@ static int __init airo_init_module( void )
 
 static void __exit airo_cleanup_module( void )
 {
-	while( airo_devices ) {
-		airo_print_info(airo_devices->dev->name, "Unregistering...\n");
-		stop_airo_card( airo_devices->dev, 1 );
+	struct airo_info *ai;
+	while(!list_empty(&airo_devices)) {
+		ai = list_entry(airo_devices.next, struct airo_info, dev_list);
+		airo_print_info(ai->dev->name, "Unregistering...");
+		stop_airo_card(ai->dev, 1);
 	}
 #ifdef CONFIG_PCI
 	pci_unregister_driver(&airo_driver);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 95ff175..f8483c1 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -277,11 +277,14 @@
 #define BCM43xx_SBTMSTATELOW_REJECT		0x02
 #define BCM43xx_SBTMSTATELOW_CLOCK		0x10000
 #define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK	0x20000
+#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE	0x20000000
 
 /* sbtmstatehigh state flags */
 #define BCM43xx_SBTMSTATEHIGH_SERROR		0x00000001
 #define BCM43xx_SBTMSTATEHIGH_BUSY		0x00000004
 #define BCM43xx_SBTMSTATEHIGH_TIMEOUT		0x00000020
+#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL	0x00010000
+#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL	0x00020000
 #define BCM43xx_SBTMSTATEHIGH_COREFLAGS		0x1FFF0000
 #define BCM43xx_SBTMSTATEHIGH_DMA64BIT		0x10000000
 #define BCM43xx_SBTMSTATEHIGH_GATEDCLK		0x20000000
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 80cb88e..282f98f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -1389,7 +1389,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
 				& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
 	} else {
 		if (connect_phy)
-			flags |= 0x20000000;
+			flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
 		bcm43xx_phy_connect(bcm, connect_phy);
 		bcm43xx_core_enable(bcm, flags);
 		bcm43xx_write16(bcm, 0x03E6, 0x0000);
@@ -3586,7 +3586,7 @@ int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
 		u32 sbtmstatelow;
 
 		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-		sbtmstatelow |= 0x20000000;
+		sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
 	}
 	err = wireless_core_up(bcm, 1);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index cae8925..8a99790 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -168,16 +168,16 @@ int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
 
 	flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
 	if (connect) {
-		if (!(flags & 0x00010000))
+		if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL))
 			return -ENODEV;
 		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-		flags |= (0x800 << 18);
+		flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
 	} else {
-		if (!(flags & 0x00020000))
+		if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL))
 			return -ENODEV;
 		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-		flags &= ~(0x800 << 18);
+		flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
 	}
 out:
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index 32beb91..ee1e7a2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -882,10 +882,10 @@ static void _stack_save(u32 *_stackptr, size_t *stackidx,
 {
 	u32 *stackptr = &(_stackptr[*stackidx]);
 
-	assert((offset & 0xF000) == 0x0000);
-	assert((id & 0xF0) == 0x00);
+	assert((offset & 0xE000) == 0x0000);
+	assert((id & 0xF8) == 0x00);
 	*stackptr = offset;
-	*stackptr |= ((u32)id) << 12;
+	*stackptr |= ((u32)id) << 13;
 	*stackptr |= ((u32)value) << 16;
 	(*stackidx)++;
 	assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
@@ -896,12 +896,12 @@ static u16 _stack_restore(u32 *stackptr,
 {
 	size_t i;
 
-	assert((offset & 0xF000) == 0x0000);
-	assert((id & 0xF0) == 0x00);
+	assert((offset & 0xE000) == 0x0000);
+	assert((id & 0xF8) == 0x00);
 	for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
-		if ((*stackptr & 0x00000FFF) != offset)
+		if ((*stackptr & 0x00001FFF) != offset)
 			continue;
-		if (((*stackptr & 0x0000F000) >> 12) != id)
+		if (((*stackptr & 0x00007000) >> 13) != id)
 			continue;
 		return ((*stackptr & 0xFFFF0000) >> 16);
 	}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index f97288d..f6861da 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -67,11 +67,12 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
 	i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
 	i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
-	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type,
+	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
 		chip->patch_cck_gain ? 'g' : '-',
 		chip->patch_cr157 ? '7' : '-',
 		chip->patch_6m_band_edge ? '6' : '-',
-		chip->new_phy_layout ? 'N' : '-');
+		chip->new_phy_layout ? 'N' : '-',
+		chip->al2230s_bit ? 'S' : '-');
 	return i;
 }
 
@@ -337,6 +338,7 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
 	chip->patch_cr157 = (value >> 13) & 0x1;
 	chip->patch_6m_band_edge = (value >> 21) & 0x1;
 	chip->new_phy_layout = (value >> 31) & 0x1;
+	chip->al2230s_bit = (value >> 7) & 0x1;
 	chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
 	chip->supports_tx_led = 1;
 	if (value & (1 << 24)) { /* LED scenario */
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index b07569e..ae39c22 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -711,7 +711,7 @@ struct zd_chip {
 	u16 link_led;
 	unsigned int pa_type:4,
 		patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-		new_phy_layout:1,
+		new_phy_layout:1, al2230s_bit:1,
 		is_zd1211b:1, supports_tx_led:1;
 };
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 4c5f78e..19172f5 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -974,14 +974,14 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
 	switch (ieee->iw_mode) {
 	case IW_MODE_ADHOC:
 		if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 ||
-		    memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0)
+		    compare_ether_addr(hdr->addr3, ieee->bssid) != 0)
 			return 0;
 		break;
 	case IW_MODE_AUTO:
 	case IW_MODE_INFRA:
 		if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) !=
 		    IEEE80211_FCTL_FROMDS ||
-		    memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0)
+		    compare_ether_addr(hdr->addr2, ieee->bssid) != 0)
 			return 0;
 		break;
 	default:
@@ -989,9 +989,9 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
 		return 0;
 	}
 
-	return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
+	return compare_ether_addr(hdr->addr1, netdev->dev_addr) == 0 ||
 	       (is_multicast_ether_addr(hdr->addr1) &&
-		memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) ||
+		compare_ether_addr(hdr->addr3, netdev->dev_addr) != 0) ||
 	       (netdev->flags & IFF_PROMISC);
 }
 
@@ -1047,7 +1047,7 @@ static void update_qual_rssi(struct zd_mac *mac,
 	hdr = (struct ieee80211_hdr_3addr *)buffer;
 	if (length < offsetof(struct ieee80211_hdr_3addr, addr3))
 		return;
-	if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0)
+	if (compare_ether_addr(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid) != 0)
 		return;
 
 	spin_lock_irqsave(&mac->lock, flags);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index f50cff3..e6d604b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -34,7 +34,7 @@ static const char *rfs[] = {
 	[AL2210_RF]	= "AL2210_RF",
 	[MAXIM_NEW_RF]	= "MAXIM_NEW_RF",
 	[UW2453_RF]	= "UW2453_RF",
-	[AL2230S_RF]	= "AL2230S_RF",
+	[UNKNOWN_A_RF]	= "UNKNOWN_A_RF",
 	[RALINK_RF]	= "RALINK_RF",
 	[INTERSIL_RF]	= "INTERSIL_RF",
 	[RF2959_RF]	= "RF2959_RF",
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index a57732e..ee8ac3a 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -26,7 +26,7 @@
 #define AL2210_RF			0x7
 #define MAXIM_NEW_RF			0x8
 #define UW2453_RF			0x9
-#define AL2230S_RF			0xa
+#define UNKNOWN_A_RF			0xa
 #define RALINK_RF			0xb
 #define INTERSIL_RF			0xc
 #define RF2959_RF			0xd
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 25323a1..85a9ad2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -59,6 +59,18 @@ static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
 	{ CR240, 0x57 }, { CR9,   0xe0 },
 };
 
+static const struct zd_ioreq16 ioreqs_init_al2230s[] = {
+	{ CR47,   0x1e }, /* MARK_002 */
+	{ CR106,  0x22 },
+	{ CR107,  0x2a }, /* MARK_002 */
+	{ CR109,  0x13 }, /* MARK_002 */
+	{ CR118,  0xf8 }, /* MARK_002 */
+	{ CR119,  0x12 }, { CR122,  0xe0 },
+	{ CR128,  0x10 }, /* MARK_001 from 0xe->0x10 */
+	{ CR129,  0x0e }, /* MARK_001 from 0xd->0x0e */
+	{ CR130,  0x10 }, /* MARK_001 from 0xb->0x0d */
+};
+
 static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
 {
 	int r;
@@ -90,7 +102,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 	int r;
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	static const struct zd_ioreq16 ioreqs[] = {
+	static const struct zd_ioreq16 ioreqs_init[] = {
 		{ CR15,   0x20 }, { CR23,   0x40 }, { CR24,  0x20 },
 		{ CR26,   0x11 }, { CR28,   0x3e }, { CR29,  0x00 },
 		{ CR44,   0x33 }, { CR106,  0x2a }, { CR107, 0x1a },
@@ -117,10 +129,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 		{ CR119,  0x10 }, { CR120,  0x4f }, { CR121, 0x77 },
 		{ CR122,  0xe0 }, { CR137,  0x88 }, { CR252, 0xff },
 		{ CR253,  0xff },
+	};
 
-		/* These following happen separately in the vendor driver */
-		{ },
-
+	static const struct zd_ioreq16 ioreqs_pll[] = {
 		/* shdnb(PLL_ON)=0 */
 		{ CR251,  0x2f },
 		/* shdnb(PLL_ON)=1 */
@@ -128,7 +139,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 		{ CR138,  0x28 }, { CR203,  0x06 },
 	};
 
-	static const u32 rv[] = {
+	static const u32 rv1[] = {
 		/* Channel 1 */
 		0x03f790,
 		0x033331,
@@ -137,6 +148,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 		0x0b3331,
 		0x03b812,
 		0x00fff3,
+	};
+
+	static const u32 rv2[] = {
 		0x000da4,
 		0x0f4dc5, /* fix freq shift, 0x04edc5 */
 		0x0805b6,
@@ -148,8 +162,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 		0x0bdffc,
 		0x00000d,
 		0x00500f,
+	};
 
-		/* These writes happen separately in the vendor driver */
+	static const u32 rv3[] = {
 		0x00d00f,
 		0x004c0f,
 		0x00540f,
@@ -157,11 +172,38 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
 		0x00500f,
 	};
 
-	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	r = zd_iowrite16a_locked(chip, ioreqs_init, ARRAY_SIZE(ioreqs_init));
+	if (r)
+		return r;
+
+	if (chip->al2230s_bit) {
+		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+			ARRAY_SIZE(ioreqs_init_al2230s));
+		if (r)
+			return r;
+	}
+
+	r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+	if (r)
+		return r;
+
+	/* improve band edge for AL2230S */
+	if (chip->al2230s_bit)
+		r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
+	else
+		r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
 	if (r)
 		return r;
 
-	r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+	r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs_pll, ARRAY_SIZE(ioreqs_pll));
+	if (r)
+		return r;
+
+	r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
 	if (r)
 		return r;
 
@@ -227,7 +269,9 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
 		0x481dc0,
 		0xcfff00,
 		0x25a000,
+	};
 
+	static const u32 rv2[] = {
 		/* To improve AL2230 yield, improve phase noise, 4713 */
 		0x25a000,
 		0xa3b2f0,
@@ -250,7 +294,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
 		{ CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
 	};
 
-	static const u32 rv2[] = {
+	static const u32 rv3[] = {
 		/* To improve AL2230 yield, 4713 */
 		0xf01b00,
 		0xf01e00,
@@ -269,18 +313,37 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
 	r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
 	if (r)
 		return r;
+
+	if (chip->al2230s_bit) {
+		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+			ARRAY_SIZE(ioreqs_init_al2230s));
+		if (r)
+			return r;
+	}
+
 	r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
 	if (r)
 		return r;
 	r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
 	if (r)
 		return r;
-	r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+
+	if (chip->al2230s_bit)
+		r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
+	else
+		r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
 	if (r)
 		return r;
+
 	r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
 	if (r)
 		return r;
+	r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+	if (r)
+		return r;
+	r = zd_rfwritev_cr_locked(chip, rv3, ARRAY_SIZE(rv3));
+	if (r)
+		return r;
 	r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
 	if (r)
 		return r;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 5e67106..145ad61 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -62,6 +62,9 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
 	/* "Driverless" devices that need ejecting */
 	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
 	{}
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-03-16 21:34 ` Please pull 'upstream' " John W. Linville
@ 2007-03-23  5:55   ` Jeff Garzik
  2007-03-23 12:02     ` Dan Williams
  0 siblings, 1 reply; 27+ messages in thread
From: Jeff Garzik @ 2007-03-23  5:55 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

John W. Linville wrote:
> The following changes since commit 0e39a919461842a38e406702fe0e94c6138ddfef
>   John W. Linville (1):
>         Merge branch 'upstream-fixes' into upstream
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

pulled this and upstream-fixes.  libertas had a merge conflict that I 
would prefer you sort out.

You should merge libertas branch into upstream anyway

	Jeff




^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-03-23  5:55   ` Jeff Garzik
@ 2007-03-23 12:02     ` Dan Williams
  0 siblings, 0 replies; 27+ messages in thread
From: Dan Williams @ 2007-03-23 12:02 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: John W. Linville, linux-wireless

On Fri, 2007-03-23 at 01:55 -0400, Jeff Garzik wrote:
> John W. Linville wrote:
> > The following changes since commit 0e39a919461842a38e406702fe0e94c6138ddfef
> >   John W. Linville (1):
> >         Merge branch 'upstream-fixes' into upstream
> > 
> > are found in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> pulled this and upstream-fixes.  libertas had a merge conflict that I 
> would prefer you sort out.
> 
> You should merge libertas branch into upstream anyway

Could you elaborate a bit?  We definitely need to get that fixed.

Dan



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
  2007-03-27 18:26 Please pull 'upstream-fixes' " John W. Linville
@ 2007-03-27 18:26 ` John W. Linville
  2007-03-29 12:31   ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-03-27 18:26 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless

The following changes since commit b1944354101f15f4afeffd842e12c7d70fb7e822:
  John W. Linville (1):
        Merge branch 'upstream-fixes' into upstream

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (3):
      zd1211rw: Mark some data const
      zd1211rw: Don't handle broken frames in monitor mode
      zd1211rw: Add another ID for Linksys WUSBF54G

Jouni Malinen (1):
      Update my email address from jkmaline@cc.hut.fi to j@w1.fi

 MAINTAINERS                                   |    5 +++--
 crypto/michael_mic.c                          |    4 ++--
 drivers/net/wireless/hostap/hostap_ap.c       |    4 ++--
 drivers/net/wireless/hostap/hostap_cs.c       |    2 +-
 drivers/net/wireless/hostap/hostap_hw.c       |    4 ++--
 drivers/net/wireless/hostap/hostap_main.c     |    4 ++--
 drivers/net/wireless/hostap/hostap_pci.c      |    2 +-
 drivers/net/wireless/hostap/hostap_plx.c      |    2 +-
 drivers/net/wireless/ipw2100.c                |    4 ++--
 drivers/net/wireless/zd1211rw/zd_mac.c        |   13 ++-----------
 drivers/net/wireless/zd1211rw/zd_rf.c         |    2 +-
 drivers/net/wireless/zd1211rw/zd_rf_al7230b.c |    4 ++--
 drivers/net/wireless/zd1211rw/zd_rf_rf2959.c  |    4 ++--
 drivers/net/wireless/zd1211rw/zd_usb.c        |    1 +
 include/linux/wireless.h                      |    2 +-
 include/net/ieee80211.h                       |    4 ++--
 include/net/ieee80211_crypt.h                 |    4 ++--
 net/ieee80211/ieee80211_crypt.c               |    2 +-
 net/ieee80211/ieee80211_crypt_ccmp.c          |    2 +-
 net/ieee80211/ieee80211_crypt_tkip.c          |    2 +-
 net/ieee80211/ieee80211_crypt_wep.c           |    2 +-
 net/ieee80211/ieee80211_module.c              |    4 ++--
 net/ieee80211/ieee80211_rx.c                  |    4 ++--
 net/ieee80211/ieee80211_wx.c                  |    4 ++--
 24 files changed, 39 insertions(+), 46 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index dd6978b..3fe1335 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1537,8 +1537,9 @@ S:	Supported
  
 HOST AP DRIVER
 P:	Jouni Malinen
-M:	jkmaline@cc.hut.fi
-L:	hostap@shmoo.com
+M:	j@w1.fi
+L:	hostap@shmoo.com (subscribers-only)
+L:	linux-wireless@vger.kernel.org
 W:	http://hostap.epitest.fi/
 S:	Maintained
 
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 094397b..9e917b8 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -3,7 +3,7 @@
  *
  * Michael MIC (IEEE 802.11i/TKIP) keyed digest
  *
- * Copyright (c) 2004 Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004 Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -173,4 +173,4 @@ module_exit(michael_mic_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Michael MIC");
-MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");
+MODULE_AUTHOR("Jouni Malinen <j@w1.fi>");
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index efb8cf3..9ec32fa 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -1,8 +1,8 @@
 /*
  * Intersil Prism2 driver with Host AP (software access point) support
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
  *
  * This file is to be included into hostap.c when S/W AP functionality is
  * compiled.
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 534da85..4b81c7d 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,7 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static dev_info_t dev_info = "hostap_cs";
 
 MODULE_AUTHOR("Jouni Malinen");
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 3079378..d21b8a9 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3,8 +3,8 @@
  * Intersil Prism2/2.5/3.
  *
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 9077e6e..71ec281 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -3,8 +3,8 @@
  * Intersil Prism2/2.5/3 - hostap.o module, common routines
  *
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index c4f6020..db4899e 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,7 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_pci";
 
 
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index e235e06..f0fd5ec 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,7 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_plx";
 
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index ad6e4a4..61706c9 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -28,8 +28,8 @@
 
   Portions of this file are based on the Host AP project,
   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
-    <jkmaline@cc.hut.fi>
-  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+    <j@w1.fi>
+  Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
 
   Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and
   ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 19172f5..6753d24 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,17 +156,8 @@ void zd_mac_clear(struct zd_mac *mac)
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-	struct zd_ioreq32 ioreqs[] = {
-		{ CR_RX_FILTER, STA_RX_FILTER },
-		{ CR_SNIFFER_ON, 0U },
-	};
-
-	if (ieee->iw_mode == IW_MODE_MONITOR) {
-		ioreqs[0].value = 0xffffffff;
-		ioreqs[1].value = 0x1;
-	}
-
-	return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
+	u32 filter = (ieee->iw_mode == IW_MODE_MONITOR) ? ~0 : STA_RX_FILTER;
+	return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
 }
 
 int zd_mac_open(struct net_device *netdev)
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index e6d604b..4ddc2cb 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -23,7 +23,7 @@
 #include "zd_ieee80211.h"
 #include "zd_chip.h"
 
-static const char *rfs[] = {
+static const char * const rfs[] = {
 	[0]		= "unknown RF0",
 	[1]		= "unknown RF1",
 	[UW2451_RF]	= "UW2451_RF",
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index a289f95..bd07c9b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -183,12 +183,12 @@ static int al7230b_set_channel(struct zd_rf *rf, u8 channel)
 	const u32 *rv = chan_rv[channel-1];
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	struct zd_ioreq16 ioreqs_1[] = {
+	static const struct zd_ioreq16 ioreqs_1[] = {
 		{ CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
 		{ CR38,  0x38 }, { CR136, 0xdf },
 	};
 
-	struct zd_ioreq16 ioreqs_2[] = {
+	static const struct zd_ioreq16 ioreqs_2[] = {
 		/* PLL_ON */
 		{ CR251, 0x3f },
 		{ CR203, 0x06 }, { CR240, 0x08 },
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
index 5824727..2d736bd 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
@@ -21,7 +21,7 @@
 #include "zd_usb.h"
 #include "zd_chip.h"
 
-static u32 rf2959_table[][2] = {
+static const u32 rf2959_table[][2] = {
 	RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
 	RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
 	RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
@@ -228,7 +228,7 @@ static int rf2959_init_hw(struct zd_rf *rf)
 static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
 {
 	int i, r;
-	u32 *rv = rf2959_table[channel-1];
+	const u32 *rv = rf2959_table[channel-1];
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	for (i = 0; i < 2; i++) {
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 145ad61..55f4c61 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -52,6 +52,7 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
 	{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 48759b2..0987aa7 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -186,7 +186,7 @@
  *	- Wireless Event capability in struct iw_range
  *	- Add support for relative TxPower (yick !)
  *
- * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * V17 to V18 (From Jouni Malinen <j@w1.fi>)
  * ----------
  *	- Add support for WPA/WPA2
  *	- Add extended encoding configuration (SIOCSIWENCODEEXT and
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index e02d85f..d56b292 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -6,8 +6,8 @@
  * LAN access point) driver for Intersil Prism2/2.5/3.
  *
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
  *
  * Adaption to a generic IEEE 802.11 stack by James Ketrenos
  * <jketreno@linux.intel.com>
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index eb47641..b3d65e0 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -3,8 +3,8 @@
  * for Intersil Prism2/2.5/3.
  *
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
  *
  * Adaption to a generic IEEE 802.11 stack by James Ketrenos
  * <jketreno@linux.intel.com>
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 5ed0a98..df5592c 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -1,7 +1,7 @@
 /*
  * Host AP crypto routines
  *
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
  * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 35aa342..7ec8314 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -1,7 +1,7 @@
 /*
  * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
  *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index fc1f99a..bd0988f 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -1,7 +1,7 @@
 /*
  * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
  *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index ec6d885..1213d70 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -1,7 +1,7 @@
 /*
  * Host AP crypt: host-based WEP encryption implementation for Host AP driver
  *
- * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index b1c6d1f..7630434 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -5,8 +5,8 @@
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
-  <jkmaline@cc.hut.fi>
-  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+  <j@w1.fi>
+  Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 4084909..9d33546 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -3,8 +3,8 @@
  * for Intersil Prism2/2.5/3 - hostap.o module, common routines
  *
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * <j@w1.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
  * Copyright (c) 2004-2005, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 40d7a55..cee5e13 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -5,8 +5,8 @@
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
-  <jkmaline@cc.hut.fi>
-  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+  <j@w1.fi>
+  Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-03-27 18:26 ` Please pull 'upstream' " John W. Linville
@ 2007-03-29 12:31   ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-29 12:31 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

John W. Linville wrote:
> The following changes since commit b1944354101f15f4afeffd842e12c7d70fb7e822:
>   John W. Linville (1):
>         Merge branch 'upstream-fixes' into upstream
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (3):
>       zd1211rw: Mark some data const
>       zd1211rw: Don't handle broken frames in monitor mode
>       zd1211rw: Add another ID for Linksys WUSBF54G
> 
> Jouni Malinen (1):
>       Update my email address from jkmaline@cc.hut.fi to j@w1.fi
> 
>  MAINTAINERS                                   |    5 +++--
>  crypto/michael_mic.c                          |    4 ++--
>  drivers/net/wireless/hostap/hostap_ap.c       |    4 ++--
>  drivers/net/wireless/hostap/hostap_cs.c       |    2 +-
>  drivers/net/wireless/hostap/hostap_hw.c       |    4 ++--
>  drivers/net/wireless/hostap/hostap_main.c     |    4 ++--
>  drivers/net/wireless/hostap/hostap_pci.c      |    2 +-
>  drivers/net/wireless/hostap/hostap_plx.c      |    2 +-
>  drivers/net/wireless/ipw2100.c                |    4 ++--
>  drivers/net/wireless/zd1211rw/zd_mac.c        |   13 ++-----------
>  drivers/net/wireless/zd1211rw/zd_rf.c         |    2 +-
>  drivers/net/wireless/zd1211rw/zd_rf_al7230b.c |    4 ++--
>  drivers/net/wireless/zd1211rw/zd_rf_rf2959.c  |    4 ++--
>  drivers/net/wireless/zd1211rw/zd_usb.c        |    1 +
>  include/linux/wireless.h                      |    2 +-
>  include/net/ieee80211.h                       |    4 ++--
>  include/net/ieee80211_crypt.h                 |    4 ++--
>  net/ieee80211/ieee80211_crypt.c               |    2 +-
>  net/ieee80211/ieee80211_crypt_ccmp.c          |    2 +-
>  net/ieee80211/ieee80211_crypt_tkip.c          |    2 +-
>  net/ieee80211/ieee80211_crypt_wep.c           |    2 +-
>  net/ieee80211/ieee80211_module.c              |    4 ++--
>  net/ieee80211/ieee80211_rx.c                  |    4 ++--
>  net/ieee80211/ieee80211_wx.c                  |    4 ++--
>  24 files changed, 39 insertions(+), 46 deletions(-)

hrm, it doesn't seem to like my #upstream, can you wait a bit for 
kernel.org propagation, and then redo with these already merged?  Also, 
please pull branch libertas into your #upstream.

Auto-merged MAINTAINERS
Auto-merged drivers/net/wireless/libertas/debugfs.c
CONFLICT (add/add): Merge conflict in 
drivers/net/wireless/libertas/debugfs.c
Auto-merged include/net/ieee80211_radiotap.h
CONFLICT (content): Merge conflict in include/net/ieee80211_radiotap.h
Automatic merge failed; fix conflicts and then commit the result.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
@ 2007-05-07 17:51 John W. Linville
  2007-05-07 21:15 ` Dan Williams
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: John W. Linville @ 2007-05-07 17:51 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless, netdev

The following changes since commit 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37:
  Linus Torvalds (1):
        Merge git://git.kernel.org/.../sam/kbuild

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (1):
      zd1211rw: Add ID for ZyXEL AG-225H v2

Geert Uytterhoeven (1):
      mac80211: include <linux/delay.h> instead of <asm/delay.h>

Ivo van Doorn (1):
      Add 93cx6 eeprom library

John W. Linville (1):
      libertas: fix for wireless Kconfig changes

Larry Finger (3):
      ieee80211: add ieee80211_channel_to_freq
      ieee80211: include frequency in scan results
      bcm43xx: Remove dead configuration variable CONFIG_947XX

Matthew Davidson (1):
      zd1211rw: Add ID for Sitecom WL-117

Michael Wu (1):
      Add rtl8187 wireless driver

Ulrich Kunitz (1):
      zd1211rw: Added new USB id for Planex GW-US54ZGL

 MAINTAINERS                                    |   10 +
 drivers/misc/Kconfig                           |    6 +
 drivers/misc/Makefile                          |    1 +
 drivers/misc/eeprom_93cx6.c                    |  347 +++++++++++
 drivers/net/wireless/Kconfig                   |    4 +-
 drivers/net/wireless/Makefile                  |    3 +
 drivers/net/wireless/bcm43xx/bcm43xx.h         |   18 +-
 drivers/net/wireless/bcm43xx/bcm43xx_dma.c     |    4 -
 drivers/net/wireless/bcm43xx/bcm43xx_main.c    |   81 ---
 drivers/net/wireless/bcm43xx/bcm43xx_main.h    |   19 -
 drivers/net/wireless/rtl818x/Kconfig           |   16 +
 drivers/net/wireless/rtl818x/Makefile          |    2 +
 drivers/net/wireless/rtl818x/rtl8187.h         |  125 ++++
 drivers/net/wireless/rtl818x/rtl8187_dev.c     |  730 +++++++++++++++++++++++
 drivers/net/wireless/rtl818x/rtl8187_rtl8225.c |  744 ++++++++++++++++++++++++
 drivers/net/wireless/rtl818x/rtl8187_rtl8225.h |   30 +
 drivers/net/wireless/rtl818x/rtl818x.h         |  212 +++++++
 drivers/net/wireless/zd1211rw/zd_usb.c         |    4 +
 include/linux/eeprom_93cx6.h                   |   77 +++
 include/net/ieee80211.h                        |    2 +
 net/ieee80211/ieee80211_geo.c                  |   16 +
 net/ieee80211/ieee80211_wx.c                   |    8 +-
 net/mac80211/ieee80211_sta.c                   |    2 +-
 23 files changed, 2338 insertions(+), 123 deletions(-)
 create mode 100644 drivers/misc/eeprom_93cx6.c
 create mode 100644 drivers/net/wireless/rtl818x/Kconfig
 create mode 100644 drivers/net/wireless/rtl818x/Makefile
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187.h
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_dev.c
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
 create mode 100644 drivers/net/wireless/rtl818x/rtl818x.h
 create mode 100644 include/linux/eeprom_93cx6.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 0492dd8..c72774f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2935,6 +2935,16 @@ S:	Maintained
 RISCOM8 DRIVER
 S:	Orphan
 
+RTL818X WIRELESS DRIVER
+P:	Michael Wu
+M:	flamingice@sourmilk.net
+P:	Andrea Merello
+M:	andreamrl@tiscali.it
+L:	linux-wireless@vger.kernel.org
+W:	http://linuxwireless.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
+S:	Maintained
+
 S3 SAVAGE FRAMEBUFFER DRIVER
 P:	Antonino Daplas
 M:	adaplas@gmail.com
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3c525b..607a180 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -178,4 +178,10 @@ config THINKPAD_ACPI_BAY
 
 	  If you are not sure, say Y here.
 
+config EEPROM_93CX6
+	tristate "EEPROM 93CX6 support"
+	---help---
+	  This is a driver for the EEPROM chipsets 93c46 and 93c66.
+	  The driver supports both read as well as write commands.
+
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e325164..42b34a9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 0000000..a948ddc
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,347 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader routines for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 1;
+	eeprom->register_write(eeprom);
+	udelay(1);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 0;
+	eeprom->register_write(eeprom);
+	udelay(1);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear all flags, and enable chip select.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+	eeprom->reg_data_clock = 0;
+	eeprom->reg_chip_select = 1;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear chip_select and data_in flags.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_chip_select = 0;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+	const u16 data, const u16 count)
+{
+	unsigned int i;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start writing all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		/*
+		 * Check if this bit needs to be set.
+		 */
+		eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+		/*
+		 * Write the bit to the eeprom register.
+		 */
+		eeprom->register_write(eeprom);
+
+		/*
+		 * Kick a pulse.
+		 */
+		eeprom_93cx6_pulse_high(eeprom);
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	eeprom->reg_data_in = 0;
+	eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+	u16 *data, const u16 count)
+{
+	unsigned int i;
+	u16 buf = 0;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start reading all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		eeprom_93cx6_pulse_high(eeprom);
+
+		eeprom->register_read(eeprom);
+
+		/*
+		 * Clear data_in flag.
+		 */
+		eeprom->reg_data_in = 0;
+
+		/*
+		 * Read if the bit has been set.
+		 */
+		if (eeprom->reg_data_out)
+			buf |= (1 << (i - 1));
+
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	*data = buf;
+}
+
+static void eeprom_93cx6_ewen(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the read opcode and the word to be read.
+	 */
+	eeprom_93cx6_write_bits(eeprom, PCI_EEPROM_EWEN_OPCODE, 5);
+	eeprom_93cx6_write_bits(eeprom, 0, 6);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+
+static void eeprom_93cx6_ewds(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the read opcode and the word to be read.
+	 */
+	eeprom_93cx6_write_bits(eeprom, PCI_EEPROM_EWDS_OPCODE, 5);
+	eeprom_93cx6_write_bits(eeprom, 0, 6);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+	u16 *data)
+{
+	u16 command;
+
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the read opcode and the word to be read.
+	 */
+	command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+	eeprom_93cx6_write_bits(eeprom, command,
+		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+	/*
+	 * Read the requested 16 bits.
+	 */
+	eeprom_93cx6_read_bits(eeprom, data, 16);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+	__le16 *data, const u16 words)
+{
+	unsigned int i;
+	u16 tmp;
+
+	for (i = 0; i < words; i++) {
+		tmp = 0;
+		eeprom_93cx6_read(eeprom, word + i, &tmp);
+		data[i] = cpu_to_le16(tmp);
+	}
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
+/**
+ * eeprom_93cx6_write - Write multiple words to the eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start writing
+ * @data: Data that will be written
+ *
+ * This function will write the eeprom data as host-endian word
+ * from the given data pointer.
+ */
+void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, const u8 word,
+	u16 data)
+{
+	u16 command;
+
+	/*
+	 * select the ewen opcode.
+	 */
+	eeprom_93cx6_ewen(eeprom);
+
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the write opcode and the word to be read.
+	 */
+	command = (PCI_EEPROM_WRITE_OPCODE << eeprom->width) | word;
+	eeprom_93cx6_write_bits(eeprom, command,
+		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+	/*
+	 * Write the requested 16 bits.
+	 */
+	eeprom_93cx6_write_bits(eeprom, data, 16);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+
+	/*
+	 * Take a short break.
+	 */
+	msleep(10000);
+
+	/*
+	 * select the ewen opcode.
+	 */
+	eeprom_93cx6_ewds(eeprom);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
+
+
+/**
+ * eeprom_93cx6_multiwrite - Write multiple words to the eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start writing
+ * @data: Pointer where the information will be read from
+ * @words: Number of words that should be written.
+ *
+ * This function will write all requested words to the eeprom,
+ * this is done by calling eeprom_93cx6_write() multiple times.
+ * This method accepts little endian data, so it will first be
+ * converted into host endian.
+ */
+void eeprom_93cx6_multiwrite(struct eeprom_93cx6 *eeprom, const u8 word,
+	__le16 *data, const u16 words)
+{
+	unsigned int i;
+
+	for (i = 0; i < words; i++)
+		eeprom_93cx6_write(eeprom, word + i, le16_to_cpu(data[i]));
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiwrite);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 0184614..6ff5a8a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -267,7 +267,7 @@ config IPW2200_DEBUG
 
 config LIBERTAS_USB
 	tristate "Marvell Libertas 8388 802.11a/b/g cards"
-	depends on NET_RADIO && USB
+	depends on USB && WLAN_80211
 	select FW_LOADER
 	---help---
 	  A driver for Marvell Libertas 8388 USB devices.
@@ -542,4 +542,6 @@ source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
 
+source "drivers/net/wireless/rtl818x/Kconfig"
+
 endmenu
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d212460..198c992 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
 
 obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 obj-$(CONFIG_LIBERTAS_USB)     += libertas/
+
+# Drivers using mac80211 stack (net/mac80211)
+obj-$(CONFIG_RTL818X)		+= rtl818x/
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index f8483c1..10e07e8 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -658,12 +658,6 @@ struct bcm43xx_pio {
 
 #define BCM43xx_MAX_80211_CORES		2
 
-#ifdef CONFIG_BCM947XX
-#define core_offset(bcm) (bcm)->current_core_offset
-#else
-#define core_offset(bcm) 0
-#endif
-
 /* Generic information about a core. */
 struct bcm43xx_coreinfo {
 	u8 available:1,
@@ -789,10 +783,6 @@ struct bcm43xx_private {
 
 	/* The currently active core. */
 	struct bcm43xx_coreinfo *current_core;
-#ifdef CONFIG_BCM947XX
-	/** current core memory offset */
-	u32 current_core_offset;
-#endif
 	struct bcm43xx_coreinfo *active_80211_core;
 	/* coreinfo structs for all possible cores follow.
 	 * Note that a core might not exist.
@@ -943,25 +933,25 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
 static inline
 u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread16(bcm->mmio_addr + offset);
 }
 
 static inline
 void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
 {
-	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite16(value, bcm->mmio_addr + offset);
 }
 
 static inline
 u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread32(bcm->mmio_addr + offset);
 }
 
 static inline
 void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
 {
-	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite32(value, bcm->mmio_addr + offset);
 }
 
 static inline
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index e3d2e61..1f7731f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -660,10 +660,6 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
 	ring->routing = BCM43xx_DMA32_CLIENTTRANS;
 	if (dma64)
 		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
-		ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS;
-#endif
 
 	ring->bcm = bcm;
 	ring->nr_slots = nr_slots;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 5e96bca..ef6b253 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -61,10 +61,6 @@ MODULE_AUTHOR("Stefano Brivio");
 MODULE_AUTHOR("Michael Buesch");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_BCM947XX
-extern char *nvram_get(char *name);
-#endif
-
 #if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
 static int modparam_pio;
 module_param_named(pio, modparam_pio, int, 0444);
@@ -142,10 +138,6 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple fi
 	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 43XG 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#ifdef CONFIG_BCM947XX
-	/* SB bus on BCM947xx */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
@@ -786,9 +778,6 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 {
 	u16 value;
 	u16 *sprom;
-#ifdef CONFIG_BCM947XX
-	char *c;
-#endif
 
 	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
 			GFP_KERNEL);
@@ -796,28 +785,7 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 		printk(KERN_ERR PFX "sprom_extract OOM\n");
 		return -ENOMEM;
 	}
-#ifdef CONFIG_BCM947XX
-	sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
-	sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
-
-	if ((c = nvram_get("il0macaddr")) != NULL)
-		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
-
-	if ((c = nvram_get("et1macaddr")) != NULL)
-		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
-
-	sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
-	sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
-	sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
-
-	sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
-	sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
-	sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
-
-	sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
-#else
 	bcm43xx_sprom_read(bcm, sprom);
-#endif
 
 	/* boardflags2 */
 	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
@@ -1225,12 +1193,6 @@ static int _switch_core(struct bcm43xx_private *bcm, int core)
 			goto error;
 		udelay(10);
 	}
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
-		bcm->current_core_offset = 0x1000 * core;
-	else
-		bcm->current_core_offset = 0;
-#endif
 
 	return 0;
 error:
@@ -1387,19 +1349,6 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
 
 	if ((bcm43xx_core_enabled(bcm)) &&
 	    !bcm43xx_using_pio(bcm)) {
-//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
-#if 0
-#ifndef CONFIG_BCM947XX
-		/* reset all used DMA controllers. */
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
-		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
-		if (bcm->current_core->rev < 5)
-			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
-#endif
-#endif
 	}
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
@@ -2140,32 +2089,11 @@ out:
 	return err;
 }
 
-#ifdef CONFIG_BCM947XX
-static struct pci_device_id bcm43xx_47xx_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
-	{ 0 }
-};
-#endif
-
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
 {
 	int err;
 
 	bcm->irq = bcm->pci_dev->irq;
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0) {
-		struct pci_dev *d;
-		struct pci_device_id *id;
-		for (id = bcm43xx_47xx_ids; id->vendor; id++) {
-			d = pci_get_device(id->vendor, id->device, NULL);
-			if (d != NULL) {
-				bcm->irq = d->irq;
-				pci_dev_put(d);
-				break;
-			}
-		}
-	}
-#endif
 	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
 			  IRQF_SHARED, KBUILD_MODNAME, bcm);
 	if (err)
@@ -2645,10 +2573,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
 			chip_id_16 = 0x4610;
 		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
 			chip_id_16 = 0x4710;
-#ifdef CONFIG_BCM947XX
-		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
-			chip_id_16 = 0x4309;
-#endif
 		else {
 			printk(KERN_ERR PFX "Could not determine Chip ID\n");
 			return -ENODEV;
@@ -4144,11 +4068,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
 	struct bcm43xx_private *bcm;
 	int err;
 
-#ifdef CONFIG_BCM947XX
-	if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
-		return -ENODEV;
-#endif
-
 #ifdef DEBUG_SINGLE_DEVICE_ONLY
 	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
 		return -ENODEV;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index f763571..c8f3c53 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -33,25 +33,6 @@
 
 #include "bcm43xx.h"
 
-#ifdef CONFIG_BCM947XX
-#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
-
-static inline void e_aton(char *str, char *dest)
-{
-	int i = 0;
-	u16 *d = (u16 *) dest;
-
-	for (;;) {
-		dest[i++] = (char) simple_strtoul(str, NULL, 16);
-		str += 2;
-		if (!*str++ || i == 6)
-			break;
-	}
-	for (i = 0; i < 3; i++)
-		d[i] = cpu_to_be16(d[i]);
-}
-#endif
-
 #define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
 #define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
 /* Magic helper macro to pad structures. Ignore those above. It's magic. */
diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig
new file mode 100644
index 0000000..e2c27f8
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/Kconfig
@@ -0,0 +1,16 @@
+config RTL818X
+	bool
+	default n
+
+config RTL8187
+	tristate "Realtek 8187 USB support"
+	depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+	select RTL818X
+	select EEPROM_93CX6
+	---help---
+	  This is a driver for RTL8187 based cards.
+	  These are USB based chips found in cards such as:
+
+	  Netgear WG111v2
+
+	  Thanks to Realtek for their support!
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
new file mode 100644
index 0000000..fe5dd6f
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/Makefile
@@ -0,0 +1,2 @@
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
new file mode 100644
index 0000000..bd0b6f9
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -0,0 +1,125 @@
+#ifndef RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_REQT_READ	0xC0
+#define RTL8187_REQT_WRITE	0x40
+#define RTL8187_REQ_GET_REG	0x05
+#define RTL8187_REQ_SET_REG	0x05
+
+#define RTL8187_MAX_RX		0x9C4
+
+struct rtl8187_rx_info {
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+	__le16 len;
+	__le16 rate;
+	u8 noise;
+	u8 signal;
+	u8 agc;
+	u8 reserved;
+	__le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+	struct ieee80211_tx_control *control;
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+	__le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT	(1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG	(1 << 17)
+#define RTL8187_TX_FLAG_CTS		(1 << 18)
+#define RTL8187_TX_FLAG_RTS		(1 << 23)
+	__le16 rts_duration;
+	__le16 len;
+	__le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+	/* common between rtl818x drivers */
+	struct rtl818x_csr *map;
+	void (*rf_init)(struct ieee80211_hw *);
+	int mode;
+
+	/* rtl8187 specific */
+	struct ieee80211_channel channels[14];
+	struct ieee80211_rate rates[12];
+	struct ieee80211_hw_mode modes[2];
+	struct usb_device *udev;
+	u8 *hwaddr;
+	u16 txpwr_base;
+	u8 asic_rev;
+	struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+	u8 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+	__le16 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+	__le32 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+				    u8 *addr, u8 val)
+{
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+				     __le16 *addr, u16 val)
+{
+	__le16 buf = cpu_to_le16(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+				     __le32 *addr, u32 val)
+{
+	__le32 buf = cpu_to_le32(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
new file mode 100644
index 0000000..8f9e781
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -0,0 +1,730 @@
+
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+	/* Realtek */
+	{USB_DEVICE(0x0bda, 0x8187)},
+	/* Netgear */
+	{USB_DEVICE(0x0846, 0x6100)},
+	{USB_DEVICE(0x0846, 0x6a00)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	data <<= 8;
+	data |= addr | 0x80;
+
+	rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+	mdelay(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+	struct ieee80211_tx_status status = { {0} };
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+	usb_free_urb(info->urb);
+	if (info->control)
+		memcpy(&status.control, info->control, sizeof(status.control));
+	kfree(info->control);
+	skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+	status.flags |= IEEE80211_TX_STATUS_ACK;
+	ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+		      struct ieee80211_tx_control *control)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_tx_hdr *hdr;
+	struct rtl8187_tx_info *info;
+	struct urb *urb;
+	u32 tmp;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree_skb(skb);
+		return 0;
+	}
+
+	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+	tmp = skb->len - sizeof(*hdr);
+	tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+	tmp |= control->rts_cts_rate << 19;
+	tmp |= control->tx_rate << 24;
+	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+		tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+		tmp |= RTL8187_TX_FLAG_RTS;
+		hdr->rts_duration =
+			ieee80211_rts_duration(dev, skb->len, control);
+	}
+	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+		tmp |= RTL8187_TX_FLAG_CTS;
+	hdr->flags = cpu_to_le32(tmp);
+	hdr->len = 0;
+	tmp = control->retry_limit << 8;
+	hdr->retry = cpu_to_le32(tmp);
+
+	info = (struct rtl8187_tx_info *)skb->cb;
+	info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+	info->urb = urb;
+	info->dev = dev;
+	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+			  hdr, skb->len, rtl8187_tx_cb, skb);
+	usb_submit_urb(urb, GFP_ATOMIC);
+
+	return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+	struct ieee80211_hw *dev = info->dev;
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_hdr *hdr;
+	struct ieee80211_rx_status rx_status = { 0 };
+	int rate, signal;
+
+	if (unlikely(urb->status)) {
+		info->urb = NULL;
+		usb_free_urb(urb);
+		return;
+	}
+
+	skb_unlink(skb, &priv->rx_queue);
+	skb_put(skb, urb->actual_length);
+	hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+	skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+	signal = hdr->agc >> 1;
+	rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+	if (rate > 3) {	/* OFDM rate */
+		if (signal > 90)
+			signal = 90;
+		else if (signal < 25)
+			signal = 25;
+		signal = 90 - signal;
+	} else {	/* CCK rate */
+		if (signal > 95)
+			signal = 95;
+		else if (signal < 30)
+			signal = 30;
+		signal = 95 - signal;
+	}
+
+	rx_status.antenna = (hdr->signal >> 7) & 1;
+	rx_status.signal = 64 - min(hdr->noise, (u8)64);
+	rx_status.ssi = signal;
+	rx_status.rate = rate;
+	rx_status.freq = dev->conf.freq;
+	rx_status.channel = dev->conf.channel;
+	rx_status.phymode = dev->conf.phymode;
+	rx_status.mactime = le64_to_cpu(hdr->mac_time);
+	ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+	skb = dev_alloc_skb(RTL8187_MAX_RX);
+	if (unlikely(!skb)) {
+		usb_free_urb(urb);
+		/* TODO check rx queue length and refill *somewhere* */
+		return;
+	}
+
+	info = (struct rtl8187_rx_info *)skb->cb;
+	info->urb = urb;
+	info->dev = dev;
+	urb->transfer_buffer = skb_tail_pointer(skb);
+	urb->context = skb;
+	skb_queue_tail(&priv->rx_queue, skb);
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct urb *entry;
+	struct sk_buff *skb;
+	struct rtl8187_rx_info *info;
+
+	while (skb_queue_len(&priv->rx_queue) < 8) {
+		skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+		if (!skb)
+			break;
+		entry = usb_alloc_urb(0, GFP_KERNEL);
+		if (!entry) {
+			kfree_skb(skb);
+			break;
+		}
+		usb_fill_bulk_urb(entry, priv->udev,
+				  usb_rcvbulkpipe(priv->udev, 1),
+				  skb_tail_pointer(skb),
+				  RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+		info = (struct rtl8187_rx_info *)skb->cb;
+		info->urb = entry;
+		info->dev = dev;
+		skb_queue_tail(&priv->rx_queue, skb);
+		usb_submit_urb(entry, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg;
+	int i;
+
+	/* reset */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	mdelay(200);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+	mdelay(200);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= (1 << 1);
+	reg |= RTL818X_CMD_RESET;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	i = 10;
+	do {
+		mdelay(2);
+		if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+		      RTL818X_CMD_RESET))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	/* reload registers from eeprom */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+	i = 10;
+	do {
+		mdelay(4);
+		if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+		      RTL818X_EEPROM_CMD_CONFIG))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: eeprom reset timeout!\n",
+		       wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	/* setup card */
+	rtl818x_iowrite8(priv, (u8 *)0xFF85, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+	rtl818x_iowrite8(priv, (u8 *)0xFF85, 4);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+	rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+	reg &= 0x3F;
+	reg |= 0x80;
+	rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+	rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+	rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+	// TODO: set RESP_RATE and BRSR properly
+	rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+	/* host_usb_init */
+	rtl818x_iowrite8(priv, (u8 *)0xFF85, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+	reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+	rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+	rtl818x_iowrite8(priv, (u8 *)0xFF85, 4);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+	mdelay(100);
+
+	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+	mdelay(100);
+
+	priv->rf_init(dev);
+
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+	rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+	rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+	rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+	return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	u32 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+	/* Enable TX loopback on MAC level to avoid TX during channel
+	 * changes, as this has be seen to causes problems and the
+	 * card will stop work until next reset
+	 */
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+			  reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+	mdelay(10);
+	rtl8225_rf_set_channel(dev, channel);
+	mdelay(10);
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u32 reg;
+	int ret;
+
+	ret = rtl8187_init_hw(dev);
+	if (ret)
+		return ret;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+	rtl8187_init_urbs(dev);
+
+	reg = RTL818X_RX_CONF_ONLYERLPKT |
+	      RTL818X_RX_CONF_RX_AUTORESETPHY |
+	      RTL818X_RX_CONF_BSSID |
+	      RTL818X_RX_CONF_MGMT |
+	      RTL818X_RX_CONF_CTRL |
+	      RTL818X_RX_CONF_DATA |
+	      (7 << 13 /* RX FIFO threshold NONE */) |
+	      (7 << 10 /* MAX RX DMA */) |
+	      RTL818X_RX_CONF_BROADCAST |
+	      RTL818X_RX_CONF_MULTICAST |
+	      RTL818X_RX_CONF_NICMAC;
+	if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+		reg |= RTL818X_RX_CONF_MONITOR;
+
+	rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+	reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+	rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+	reg  = RTL818X_TX_CONF_CW_MIN |
+	       (7 << 21 /* MAX TX DMA */) |
+	       RTL818X_TX_CONF_NO_ICV;
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg |= RTL818X_CMD_TX_ENABLE;
+	reg |= RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_info *info;
+	struct sk_buff *skb;
+	u32 reg;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= ~RTL818X_CMD_TX_ENABLE;
+	reg &= ~RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	rtl8225_rf_stop(dev);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	while ((skb = skb_dequeue(&priv->rx_queue))) {
+		info = (struct rtl8187_rx_info *)skb->cb;
+		if (!info->urb)
+			continue;
+
+		usb_kill_urb(info->urb);
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+				 struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	/* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+	if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+		return -1;
+
+	switch (conf->type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_MNTR:
+		priv->mode = conf->type;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	priv->hwaddr = conf->mac_addr;
+
+	return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+				     struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	rtl8187_set_channel(dev, conf->channel);
+
+	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+	else
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+
+	switch (conf->phymode) {
+	case MODE_IEEE80211B:
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+		break;
+	case MODE_IEEE80211G:
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+	rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+	return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+				    struct ieee80211_if_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+	if (is_valid_ether_addr(conf->bssid))
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+	else
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+	return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+	.tx			= rtl8187_tx,
+	.open			= rtl8187_open,
+	.stop			= rtl8187_stop,
+	.add_interface		= rtl8187_add_interface,
+	.remove_interface	= rtl8187_remove_interface,
+	.config			= rtl8187_config,
+	.config_interface	= rtl8187_config_interface,
+};
+
+static void rtl8187_register_read(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_register_write(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+	if (eeprom->reg_data_in)
+		reg |= RTL818X_EEPROM_CMD_WRITE;
+	if (eeprom->reg_data_out)
+		reg |= RTL818X_EEPROM_CMD_READ;
+	if (eeprom->reg_data_clock)
+		reg |= RTL818X_EEPROM_CMD_CK;
+	if (eeprom->reg_chip_select)
+		reg |= RTL818X_EEPROM_CMD_CS;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+	udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+				   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct ieee80211_hw *dev;
+	struct rtl8187_priv *priv;
+	struct eeprom_93cx6 eeprom;
+	struct ieee80211_channel *channel;
+	u16 txpwr, reg;
+	int err, i;
+
+	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+	if (!dev) {
+		printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+		return -ENOMEM;
+	}
+
+	priv = dev->priv;
+
+	SET_IEEE80211_DEV(dev, &intf->dev);
+	usb_set_intfdata(intf, dev);
+	priv->udev = udev;
+
+	usb_get_dev(udev);
+
+	skb_queue_head_init(&priv->rx_queue);
+	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+	priv->map = (struct rtl818x_csr *)0xFF00;
+	priv->modes[0].mode = MODE_IEEE80211G;
+	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+	priv->modes[0].rates = priv->rates;
+	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[0].channels = priv->channels;
+	priv->modes[1].mode = MODE_IEEE80211B;
+	priv->modes[1].num_rates = 4;
+	priv->modes[1].rates = priv->rates;
+	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[1].channels = priv->channels;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		     IEEE80211_HW_RX_INCLUDES_FCS |
+		     IEEE80211_HW_WEP_INCLUDE_IV |
+		     IEEE80211_HW_DATA_NULLFUNC_ACK;
+	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+	dev->queues = 1;
+	dev->max_rssi = 65;
+	dev->max_signal = 64;
+
+	for (i = 0; i < 2; i++)
+		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+			goto err_free_dev;
+
+	eeprom.data = dev;
+	eeprom.register_read = rtl8187_register_read;
+	eeprom.register_write = rtl8187_register_write;
+	if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+		eeprom.width = PCI_EEPROM_WIDTH_93C66;
+	else
+		eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	udelay(10);
+
+	eeprom_93cx6_multiread(&eeprom, 0x7,
+			       (__le16 __force *)dev->wiphy->perm_addr, 3);
+	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+		printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly generated MAC address\n");
+		random_ether_addr(dev->wiphy->perm_addr);
+	}
+
+	channel = priv->channels;
+	for (i = 0; i < 3; i++) {
+		eeprom_93cx6_read(&eeprom, 0x16 + i, &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, 0x3D + i, &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, 0x1B + i, &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+
+	eeprom_93cx6_read(&eeprom, 0x05, &priv->txpwr_base);
+
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+	/* 0 means asic B-cut, we should use SW 3 wire
+	 * bit-by-bit banging for radio. 1 means we can use
+	 * USB specific request to write radio registers */
+	priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write(dev, 0, 0x1B7);
+
+	if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+		priv->rf_init = rtl8225_rf_init;
+	else
+		priv->rf_init = rtl8225z2_rf_init;
+
+	rtl8225_write(dev, 0, 0x0B7);
+
+	err = ieee80211_register_hw(dev);
+	if (err) {
+		printk(KERN_ERR "rtl8187: Cannot register device\n");
+		goto err_free_dev;
+	}
+
+	printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+	       wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+	       priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+	       "rtl8225" : "rtl8225z2");
+
+	return 0;
+
+ err_free_dev:
+	ieee80211_free_hw(dev);
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(udev);
+	return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+	struct rtl8187_priv *priv;
+
+	if (!dev)
+		return;
+
+	ieee80211_unregister_hw(dev);
+
+	priv = dev->priv;
+	usb_put_dev(interface_to_usbdev(intf));
+	ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= rtl8187_table,
+	.probe		= rtl8187_probe,
+	.disconnect	= rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+	return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+	usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
new file mode 100644
index 0000000..a89f023
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -0,0 +1,744 @@
+
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg84, reg82;
+	u32 bangdata;
+	int i;
+
+	bangdata = (data << 4) | (addr & 0xf);
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	for (i = 15; i >= 0; i--) {
+		u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+		if (i & 1)
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+		if (!(i & 1))
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	mdelay(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~(0x3 << 2);
+	reg84 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	mdelay(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->asic_rev)
+		rtl8225_write_8051(dev, addr, data);
+	else
+		rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84, out;
+	int i;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(4);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(5);
+
+	for (i = 4; i >= 0; i--) {
+		u16 reg = reg80 | ((addr >> i) & 1);
+
+		if (!(i & 1)) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+
+		if (i & 1) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 1));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+
+	out = 0;
+	for (i = 11; i >= 0; i--) {
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(1);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+
+		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+			out |= 1 << i;
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(2);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+	return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
+	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
+	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
+	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
+	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)11);
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+	if (channel == 14)
+		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+	else
+		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	mdelay(1); // FIXME: optional?
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 6, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+	rtl8225_write_phy_ofdm(dev, 5, *tmp);
+	rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+	mdelay(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x067); mdelay(1);
+	rtl8225_write(dev, 0x1, 0xFE0); mdelay(1);
+	rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
+	rtl8225_write(dev, 0x3, 0x441); mdelay(1);
+	rtl8225_write(dev, 0x4, 0x486); mdelay(1);
+	rtl8225_write(dev, 0x5, 0xBC0); mdelay(1);
+	rtl8225_write(dev, 0x6, 0xAE6); mdelay(1);
+	rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
+	rtl8225_write(dev, 0x8, 0x01F); mdelay(1);
+	rtl8225_write(dev, 0x9, 0x334); mdelay(1);
+	rtl8225_write(dev, 0xA, 0xFD4); mdelay(1);
+	rtl8225_write(dev, 0xB, 0x391); mdelay(1);
+	rtl8225_write(dev, 0xC, 0x050); mdelay(1);
+	rtl8225_write(dev, 0xD, 0x6DB); mdelay(1);
+	rtl8225_write(dev, 0xE, 0x029); mdelay(1);
+	rtl8225_write(dev, 0xF, 0x914); mdelay(100);
+
+	rtl8225_write(dev, 0x2, 0xC4D); mdelay(200);
+	rtl8225_write(dev, 0x2, 0x44D); mdelay(200);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0c4d);
+		mdelay(200);
+		rtl8225_write(dev, 0x02, 0x044d);
+		mdelay(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	rtl8225_write(dev, 0x0, 0x127);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x0, 0x027);
+	rtl8225_write(dev, 0x0, 0x22F);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		mdelay(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		mdelay(1);
+	}
+
+	mdelay(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x1f); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x1e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x1a); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x15); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x10); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x0a); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x05); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x02); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+	rtl8225_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	mdelay(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+	/* set sensitivity */
+	rtl8225_write(dev, 0x0c, 0x50);
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+	0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)15);
+	cck_power += priv->txpwr_base & 0xF;
+	cck_power = min(cck_power, (u8)35);
+
+	ofdm_power = min(ofdm_power, (u8)15);
+	ofdm_power += priv->txpwr_base >> 4;
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	if (channel == 14)
+		tmp = rtl8225z2_tx_power_cck_ch14;
+	else
+		tmp = rtl8225z2_tx_power_cck;
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+	mdelay(1);
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 5, 0x00);
+	rtl8225_write_phy_ofdm(dev, 6, 0x40);
+	rtl8225_write_phy_ofdm(dev, 7, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+	mdelay(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+	0x23, 0x15, 0xa5, /* -82-1dBm */
+	0x23, 0x15, 0xb5, /* -82-2dBm */
+	0x23, 0x15, 0xc5, /* -82-3dBm */
+	0x33, 0x15, 0xc5, /* -78dBm */
+	0x43, 0x15, 0xc5, /* -74dBm */
+	0x53, 0x15, 0xc5, /* -70dBm */
+	0x63, 0x15, 0xc5  /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x2BF); mdelay(1);
+	rtl8225_write(dev, 0x1, 0xEE0); mdelay(1);
+	rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
+	rtl8225_write(dev, 0x3, 0x441); mdelay(1);
+	rtl8225_write(dev, 0x4, 0x8C3); mdelay(1);
+	rtl8225_write(dev, 0x5, 0xC72); mdelay(1);
+	rtl8225_write(dev, 0x6, 0x0E6); mdelay(1);
+	rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
+	rtl8225_write(dev, 0x8, 0x03F); mdelay(1);
+	rtl8225_write(dev, 0x9, 0x335); mdelay(1);
+	rtl8225_write(dev, 0xa, 0x9D4); mdelay(1);
+	rtl8225_write(dev, 0xb, 0x7BB); mdelay(1);
+	rtl8225_write(dev, 0xc, 0x850); mdelay(1);
+	rtl8225_write(dev, 0xd, 0xCDF); mdelay(1);
+	rtl8225_write(dev, 0xe, 0x02B); mdelay(1);
+	rtl8225_write(dev, 0xf, 0x114); mdelay(100);
+
+	rtl8225_write(dev, 0x0, 0x1B7);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x3, 0x080);
+	rtl8225_write(dev, 0x5, 0x004);
+	rtl8225_write(dev, 0x0, 0x0B7);
+	rtl8225_write(dev, 0x2, 0xc4D);
+
+	mdelay(200);
+	rtl8225_write(dev, 0x2, 0x44D);
+	mdelay(100);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0C4D);
+		mdelay(200);
+		rtl8225_write(dev, 0x02, 0x044D);
+		mdelay(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	mdelay(200);
+
+	rtl8225_write(dev, 0x0, 0x2BF);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		mdelay(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		mdelay(1);
+	}
+
+	mdelay(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); //FIXME: not needed?
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x36); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x35); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x25); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x12); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); mdelay(1);
+
+	rtl8225z2_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	mdelay(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+	u8 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	rtl8225_write(dev, 0x4, 0x1f); mdelay(1);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->rf_init == rtl8225_rf_init)
+		rtl8225_rf_set_tx_power(dev, channel);
+	else
+		rtl8225z2_rf_set_tx_power(dev, channel);
+
+	rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+	mdelay(10);
+}
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
new file mode 100644
index 0000000..ed28118
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
@@ -0,0 +1,30 @@
+#ifndef RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON	0xa0000a59
+#define RTL8225_ANAPARAM2_ON	0x860c7312
+#define RTL8225_ANAPARAM_OFF	0xa00beb59
+#define RTL8225_ANAPARAM2_OFF	0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16  rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+					  u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+					 u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
new file mode 100644
index 0000000..e4ee946
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -0,0 +1,212 @@
+#ifndef RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+	u8	MAC[6];
+	u8	reserved_0[2];
+	__le32	MAR[2];
+	u8	RX_FIFO_COUNT;
+	u8	reserved_1;
+	u8	TX_FIFO_COUNT;
+	u8	BQREQ;
+	u8	reserved_2[4];
+	__le32	TSFT[2];
+	__le32	TLPDA;
+	__le32	TNPDA;
+	__le32	THPDA;
+	__le16	BRSR;
+	u8	BSSID[6];
+	u8	RESP_RATE;
+	u8	EIFS;
+	u8	reserved_3[1];
+	u8	CMD;
+#define RTL818X_CMD_TX_ENABLE		(1 << 2)
+#define RTL818X_CMD_RX_ENABLE		(1 << 3)
+#define RTL818X_CMD_RESET		(1 << 4)
+	u8	reserved_4[4];
+	__le16	INT_MASK;
+	__le16	INT_STATUS;
+#define RTL818X_INT_RX_OK		(1 <<  0)
+#define RTL818X_INT_RX_ERR		(1 <<  1)
+#define RTL818X_INT_TXL_OK		(1 <<  2)
+#define RTL818X_INT_TXL_ERR		(1 <<  3)
+#define RTL818X_INT_RX_DU		(1 <<  4)
+#define RTL818X_INT_RX_FO		(1 <<  5)
+#define RTL818X_INT_TXN_OK		(1 <<  6)
+#define RTL818X_INT_TXN_ERR		(1 <<  7)
+#define RTL818X_INT_TXH_OK		(1 <<  8)
+#define RTL818X_INT_TXH_ERR		(1 <<  9)
+#define RTL818X_INT_TXB_OK		(1 << 10)
+#define RTL818X_INT_TXB_ERR		(1 << 11)
+#define RTL818X_INT_ATIM		(1 << 12)
+#define RTL818X_INT_BEACON		(1 << 13)
+#define RTL818X_INT_TIME_OUT		(1 << 14)
+#define RTL818X_INT_TX_FO		(1 << 15)
+	__le32	TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC	(1 << 17)
+#define RTL818X_TX_CONF_NO_ICV		(1 << 19)
+#define RTL818X_TX_CONF_DISCW		(1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD	(2 << 25)
+#define RTL818X_TX_CONF_R8180_F		(3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC	(4 << 25)
+#define RTL818X_TX_CONF_R8185_D		(5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK	(7 << 25)
+#define RTL818X_TX_CONF_CW_MIN		(1 << 31)
+	__le32	RX_CONF;
+#define RTL818X_RX_CONF_MONITOR		(1 <<  0)
+#define RTL818X_RX_CONF_NICMAC		(1 <<  1)
+#define RTL818X_RX_CONF_MULTICAST	(1 <<  2)
+#define RTL818X_RX_CONF_BROADCAST	(1 <<  3)
+#define RTL818X_RX_CONF_DATA		(1 << 18)
+#define RTL818X_RX_CONF_CTRL		(1 << 19)
+#define RTL818X_RX_CONF_MGMT		(1 << 20)
+#define RTL818X_RX_CONF_BSSID		(1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY	(1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT	(1 << 31)
+	__le32	INT_TIMEOUT;
+	__le32	TBDA;
+	u8	EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ		(1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
+#define RTL818X_EEPROM_CMD_CK		(1 << 2)
+#define RTL818X_EEPROM_CMD_CS		(1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL	(0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD		(1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM	(2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG	(3 << 6)
+	u8	CONFIG0;
+	u8	CONFIG1;
+	u8	CONFIG2;
+	__le32	ANAPARAM;
+	u8	MSR;
+#define RTL818X_MSR_NO_LINK		(0 << 2)
+#define RTL818X_MSR_ADHOC		(1 << 2)
+#define RTL818X_MSR_INFRA		(2 << 2)
+	u8	CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE	(1 << 6)
+	u8	CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF	(1 << 6)
+#define RTL818X_CONFIG4_VCOOFF		(1 << 7)
+	u8	TESTR;
+	u8	reserved_9[2];
+	__le16	PGSELECT;
+	__le32	ANAPARAM2;
+	u8	reserved_10[12];
+	__le16	BEACON_INTERVAL;
+	__le16	ATIM_WND;
+	__le16	BEACON_INTERVAL_TIME;
+	__le16	ATIMTR_INTERVAL;
+	u8	reserved_11[4];
+	u8	PHY[4];
+	__le16	RFPinsOutput;
+	__le16	RFPinsEnable;
+	__le16	RFPinsSelect;
+	__le16	RFPinsInput;
+	__le32	RF_PARA;
+	__le32	RF_TIMING;
+	u8	GP_ENABLE;
+	u8	GPIO;
+	u8	reserved_12[10];
+	u8	TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT		(1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT	(1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT			(1 << 2)
+	u8	TX_GAIN_CCK;
+	u8	TX_GAIN_OFDM;
+	u8	TX_ANTENNA;
+	u8	reserved_13[16];
+	u8	WPA_CONF;
+	u8	reserved_14[3];
+	u8	SIFS;
+	u8	DIFS;
+	u8	SLOT;
+	u8	reserved_15[5];
+	u8	CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT	(1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT	(1 << 1)
+	u8	CW_VAL;
+	u8	RATE_FALLBACK;
+	u8	reserved_16[25];
+	u8	CONFIG5;
+	u8	TX_DMA_POLLING;
+	u8	reserved_17[2];
+	__le16	CWR;
+	u8	RETRY_CTR;
+	u8	reserved_18[5];
+	__le32	RDSAR;
+	u8	reserved_19[18];
+	u16	TALLY_CNT;
+	u8	TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+	{ .rate = 10,
+	  .val = 0,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 20,
+	  .val = 1,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 55,
+	  .val = 2,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 110,
+	  .val = 3,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 60,
+	  .val = 4,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 90,
+	  .val = 5,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 120,
+	  .val = 6,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 180,
+	  .val = 7,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 240,
+	  .val = 8,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 360,
+	  .val = 9,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 480,
+	  .val = 10,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 540,
+	  .val = 11,
+	  .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+	{ .chan = 1,
+	  .freq = 2412},
+	{ .chan = 2,
+	  .freq = 2417},
+	{ .chan = 3,
+	  .freq = 2422},
+	{ .chan = 4,
+	  .freq = 2427},
+	{ .chan = 5,
+	  .freq = 2432},
+	{ .chan = 6,
+	  .freq = 2437},
+	{ .chan = 7,
+	  .freq = 2442},
+	{ .chan = 8,
+	  .freq = 2447},
+	{ .chan = 9,
+	  .freq = 2452},
+	{ .chan = 10,
+	  .freq = 2457},
+	{ .chan = 11,
+	  .freq = 2462},
+	{ .chan = 12,
+	  .freq = 2467},
+	{ .chan = 13,
+	  .freq = 2472},
+	{ .chan = 14,
+	  .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index e04cffc..8459549 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -40,6 +40,7 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
@@ -67,8 +68,11 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
 	/* "Driverless" devices that need ejecting */
 	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
+	{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
 	{}
 };
 
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 0000000..4b9be59
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,77 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader datastructures for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+/*
+ * EEPROM operation defines.
+ */
+#define PCI_EEPROM_WIDTH_93C46	6
+#define PCI_EEPROM_WIDTH_93C66	8
+#define PCI_EEPROM_WIDTH_OPCODE	3
+#define PCI_EEPROM_WRITE_OPCODE	0x05
+#define PCI_EEPROM_READ_OPCODE	0x06
+#define PCI_EEPROM_EWDS_OPCODE	0x10
+#define PCI_EEPROM_EWEN_OPCODE	0x13
+
+/**
+ * struct eeprom_93cx6 - control structure for setting the commands
+ * for reading the eeprom data.
+ * @data: private pointer for the driver.
+ * @register_read(struct eeprom_93cx6 *eeprom): handler to
+ * read the eeprom register, this function should set all reg_* fields.
+ * @register_write(struct eeprom_93cx6 *eeprom): handler to
+ * write to the eeprom register by using all reg_* fields.
+ * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @reg_data_in: register field to indicate data input
+ * @reg_data_out: register field to indicate data output
+ * @reg_data_clock: register field to set the data clock
+ * @reg_chip_select: register field to set the chip select
+ *
+ * This structure is used for the communication between the driver
+ * and the eeprom_93cx6 handlers for reading the eeprom.
+ */
+struct eeprom_93cx6 {
+	void *data;
+
+	void (*register_read)(struct eeprom_93cx6 *eeprom);
+	void (*register_write)(struct eeprom_93cx6 *eeprom);
+
+	int width;
+
+	char reg_data_in;
+	char reg_data_out;
+	char reg_data_clock;
+	char reg_chip_select;
+};
+
+extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
+	const u8 word, u16 *data);
+extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
+	const u8 word, __le16 *data, const u16 words);
+
+extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom,
+	const u8 word, u16 data);
+extern void eeprom_93cx6_multiwrite(struct eeprom_93cx6 *eeprom,
+	const u8 word, __le16 *data, const u16 words);
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index d56b292..bbd85cd 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1291,6 +1291,8 @@ extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
 extern const struct ieee80211_channel *ieee80211_get_channel(struct
 							     ieee80211_device
 							     *ieee, u8 channel);
+extern u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee,
+				      u8 channel);
 
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
index 305a09d..960ad13 100644
--- a/net/ieee80211/ieee80211_geo.c
+++ b/net/ieee80211/ieee80211_geo.c
@@ -94,6 +94,21 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
 	return -1;
 }
 
+u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel)
+{
+	const struct ieee80211_channel * ch;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+		return 0;
+
+	ch = ieee80211_get_channel(ieee, channel);
+	if (!ch->channel)
+		return 0;
+	return ch->freq;
+}
+
 u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
 {
 	int i;
@@ -174,6 +189,7 @@ EXPORT_SYMBOL(ieee80211_get_channel);
 EXPORT_SYMBOL(ieee80211_get_channel_flags);
 EXPORT_SYMBOL(ieee80211_is_valid_channel);
 EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_freq);
 EXPORT_SYMBOL(ieee80211_channel_to_index);
 EXPORT_SYMBOL(ieee80211_set_geo);
 EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index cee5e13..523a137 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -89,15 +89,17 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
 		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
 	}
 
-	/* Add frequency/channel */
+	/* Add channel and frequency */
 	iwe.cmd = SIOCGIWFREQ;
-/*	iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
-	iwe.u.freq.e = 3; */
 	iwe.u.freq.m = network->channel;
 	iwe.u.freq.e = 0;
 	iwe.u.freq.i = 0;
 	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
 
+	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
+	iwe.u.freq.e = 6;
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+
 	/* Add encryption capability */
 	iwe.cmd = SIOCGIWENCODE;
 	if (network->capability & WLAN_CAPABILITY_PRIVACY)
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 822917d..3e07e9d 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -17,6 +17,7 @@
  * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
  *    SSID)
  */
+#include <linux/delay.h>
 #include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -27,7 +28,6 @@
 #include <linux/rtnetlink.h>
 #include <net/iw_handler.h>
 #include <asm/types.h>
-#include <asm/delay.h>
 
 #include <net/mac80211.h>
 #include "ieee80211_i.h"
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 17:51 John W. Linville
@ 2007-05-07 21:15 ` Dan Williams
  2007-05-07 22:51   ` John W. Linville
  2007-05-08  8:49   ` Johannes Berg
  2007-05-07 23:09 ` Jeff Garzik
  2007-05-08 17:38 ` John W. Linville
  2 siblings, 2 replies; 27+ messages in thread
From: Dan Williams @ 2007-05-07 21:15 UTC (permalink / raw)
  To: John W. Linville; +Cc: jeff, linux-wireless, netdev

On Mon, 2007-05-07 at 13:51 -0400, John W. Linville wrote:
> The following changes since commit 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37:
>   Linus Torvalds (1):
>         Merge git://git.kernel.org/.../sam/kbuild
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (1):
>       zd1211rw: Add ID for ZyXEL AG-225H v2
> 
> Geert Uytterhoeven (1):
>       mac80211: include <linux/delay.h> instead of <asm/delay.h>
> 
> Ivo van Doorn (1):
>       Add 93cx6 eeprom library
> 
> John W. Linville (1):
>       libertas: fix for wireless Kconfig changes

So the kconfig changes with s/NET_RADIO/NET_80211 (or whatever it was)
are in for 2.6.22?  Or is that for 2.6.23?

Dan

> Larry Finger (3):
>       ieee80211: add ieee80211_channel_to_freq
>       ieee80211: include frequency in scan results
>       bcm43xx: Remove dead configuration variable CONFIG_947XX
> 
> Matthew Davidson (1):
>       zd1211rw: Add ID for Sitecom WL-117
> 
> Michael Wu (1):
>       Add rtl8187 wireless driver
> 
> Ulrich Kunitz (1):
>       zd1211rw: Added new USB id for Planex GW-US54ZGL
> 
>  MAINTAINERS                                    |   10 +
>  drivers/misc/Kconfig                           |    6 +
>  drivers/misc/Makefile                          |    1 +
>  drivers/misc/eeprom_93cx6.c                    |  347 +++++++++++
>  drivers/net/wireless/Kconfig                   |    4 +-
>  drivers/net/wireless/Makefile                  |    3 +
>  drivers/net/wireless/bcm43xx/bcm43xx.h         |   18 +-
>  drivers/net/wireless/bcm43xx/bcm43xx_dma.c     |    4 -
>  drivers/net/wireless/bcm43xx/bcm43xx_main.c    |   81 ---
>  drivers/net/wireless/bcm43xx/bcm43xx_main.h    |   19 -
>  drivers/net/wireless/rtl818x/Kconfig           |   16 +
>  drivers/net/wireless/rtl818x/Makefile          |    2 +
>  drivers/net/wireless/rtl818x/rtl8187.h         |  125 ++++
>  drivers/net/wireless/rtl818x/rtl8187_dev.c     |  730 +++++++++++++++++++++++
>  drivers/net/wireless/rtl818x/rtl8187_rtl8225.c |  744 ++++++++++++++++++++++++
>  drivers/net/wireless/rtl818x/rtl8187_rtl8225.h |   30 +
>  drivers/net/wireless/rtl818x/rtl818x.h         |  212 +++++++
>  drivers/net/wireless/zd1211rw/zd_usb.c         |    4 +
>  include/linux/eeprom_93cx6.h                   |   77 +++
>  include/net/ieee80211.h                        |    2 +
>  net/ieee80211/ieee80211_geo.c                  |   16 +
>  net/ieee80211/ieee80211_wx.c                   |    8 +-
>  net/mac80211/ieee80211_sta.c                   |    2 +-
>  23 files changed, 2338 insertions(+), 123 deletions(-)
>  create mode 100644 drivers/misc/eeprom_93cx6.c
>  create mode 100644 drivers/net/wireless/rtl818x/Kconfig
>  create mode 100644 drivers/net/wireless/rtl818x/Makefile
>  create mode 100644 drivers/net/wireless/rtl818x/rtl8187.h
>  create mode 100644 drivers/net/wireless/rtl818x/rtl8187_dev.c
>  create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
>  create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
>  create mode 100644 drivers/net/wireless/rtl818x/rtl818x.h
>  create mode 100644 include/linux/eeprom_93cx6.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0492dd8..c72774f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2935,6 +2935,16 @@ S:	Maintained
>  RISCOM8 DRIVER
>  S:	Orphan
>  
> +RTL818X WIRELESS DRIVER
> +P:	Michael Wu
> +M:	flamingice@sourmilk.net
> +P:	Andrea Merello
> +M:	andreamrl@tiscali.it
> +L:	linux-wireless@vger.kernel.org
> +W:	http://linuxwireless.org/
> +T:	git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
> +S:	Maintained
> +
>  S3 SAVAGE FRAMEBUFFER DRIVER
>  P:	Antonino Daplas
>  M:	adaplas@gmail.com
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index a3c525b..607a180 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -178,4 +178,10 @@ config THINKPAD_ACPI_BAY
>  
>  	  If you are not sure, say Y here.
>  
> +config EEPROM_93CX6
> +	tristate "EEPROM 93CX6 support"
> +	---help---
> +	  This is a driver for the EEPROM chipsets 93c46 and 93c66.
> +	  The driver supports both read as well as write commands.
> +
>  endmenu
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index e325164..42b34a9 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -13,3 +13,4 @@ obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
>  obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
>  obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
>  obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
> +obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
> diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
> new file mode 100644
> index 0000000..a948ddc
> --- /dev/null
> +++ b/drivers/misc/eeprom_93cx6.c
> @@ -0,0 +1,347 @@
> +/*
> +	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
> +	<http://rt2x00.serialmonkey.com>
> +
> +	This program is free software; you can redistribute it and/or modify
> +	it under the terms of the GNU General Public License as published by
> +	the Free Software Foundation; either version 2 of the License, or
> +	(at your option) any later version.
> +
> +	This program is distributed in the hope that it will be useful,
> +	but WITHOUT ANY WARRANTY; without even the implied warranty of
> +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +	GNU General Public License for more details.
> +
> +	You should have received a copy of the GNU General Public License
> +	along with this program; if not, write to the
> +	Free Software Foundation, Inc.,
> +	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +/*
> +	Module: eeprom_93cx6
> +	Abstract: EEPROM reader routines for 93cx6 chipsets.
> +	Supported chipsets: 93c46 & 93c66.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/version.h>
> +#include <linux/delay.h>
> +#include <linux/eeprom_93cx6.h>
> +
> +MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
> +MODULE_VERSION("1.0");
> +MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
> +MODULE_LICENSE("GPL");
> +
> +static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
> +{
> +	eeprom->reg_data_clock = 1;
> +	eeprom->register_write(eeprom);
> +	udelay(1);
> +}
> +
> +static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
> +{
> +	eeprom->reg_data_clock = 0;
> +	eeprom->register_write(eeprom);
> +	udelay(1);
> +}
> +
> +static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
> +{
> +	/*
> +	 * Clear all flags, and enable chip select.
> +	 */
> +	eeprom->register_read(eeprom);
> +	eeprom->reg_data_in = 0;
> +	eeprom->reg_data_out = 0;
> +	eeprom->reg_data_clock = 0;
> +	eeprom->reg_chip_select = 1;
> +	eeprom->register_write(eeprom);
> +
> +	/*
> +	 * kick a pulse.
> +	 */
> +	eeprom_93cx6_pulse_high(eeprom);
> +	eeprom_93cx6_pulse_low(eeprom);
> +}
> +
> +static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
> +{
> +	/*
> +	 * Clear chip_select and data_in flags.
> +	 */
> +	eeprom->register_read(eeprom);
> +	eeprom->reg_data_in = 0;
> +	eeprom->reg_chip_select = 0;
> +	eeprom->register_write(eeprom);
> +
> +	/*
> +	 * kick a pulse.
> +	 */
> +	eeprom_93cx6_pulse_high(eeprom);
> +	eeprom_93cx6_pulse_low(eeprom);
> +}
> +
> +static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
> +	const u16 data, const u16 count)
> +{
> +	unsigned int i;
> +
> +	eeprom->register_read(eeprom);
> +
> +	/*
> +	 * Clear data flags.
> +	 */
> +	eeprom->reg_data_in = 0;
> +	eeprom->reg_data_out = 0;
> +
> +	/*
> +	 * Start writing all bits.
> +	 */
> +	for (i = count; i > 0; i--) {
> +		/*
> +		 * Check if this bit needs to be set.
> +		 */
> +		eeprom->reg_data_in = !!(data & (1 << (i - 1)));
> +
> +		/*
> +		 * Write the bit to the eeprom register.
> +		 */
> +		eeprom->register_write(eeprom);
> +
> +		/*
> +		 * Kick a pulse.
> +		 */
> +		eeprom_93cx6_pulse_high(eeprom);
> +		eeprom_93cx6_pulse_low(eeprom);
> +	}
> +
> +	eeprom->reg_data_in = 0;
> +	eeprom->register_write(eeprom);
> +}
> +
> +static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
> +	u16 *data, const u16 count)
> +{
> +	unsigned int i;
> +	u16 buf = 0;
> +
> +	eeprom->register_read(eeprom);
> +
> +	/*
> +	 * Clear data flags.
> +	 */
> +	eeprom->reg_data_in = 0;
> +	eeprom->reg_data_out = 0;
> +
> +	/*
> +	 * Start reading all bits.
> +	 */
> +	for (i = count; i > 0; i--) {
> +		eeprom_93cx6_pulse_high(eeprom);
> +
> +		eeprom->register_read(eeprom);
> +
> +		/*
> +		 * Clear data_in flag.
> +		 */
> +		eeprom->reg_data_in = 0;
> +
> +		/*
> +		 * Read if the bit has been set.
> +		 */
> +		if (eeprom->reg_data_out)
> +			buf |= (1 << (i - 1));
> +
> +		eeprom_93cx6_pulse_low(eeprom);
> +	}
> +
> +	*data = buf;
> +}
> +
> +static void eeprom_93cx6_ewen(struct eeprom_93cx6 *eeprom)
> +{
> +	/*
> +	 * Initialize the eeprom register
> +	 */
> +	eeprom_93cx6_startup(eeprom);
> +
> +	/*
> +	 * Select the read opcode and the word to be read.
> +	 */
> +	eeprom_93cx6_write_bits(eeprom, PCI_EEPROM_EWEN_OPCODE, 5);
> +	eeprom_93cx6_write_bits(eeprom, 0, 6);
> +
> +	/*
> +	 * Cleanup eeprom register.
> +	 */
> +	eeprom_93cx6_cleanup(eeprom);
> +}
> +
> +static void eeprom_93cx6_ewds(struct eeprom_93cx6 *eeprom)
> +{
> +	/*
> +	 * Initialize the eeprom register
> +	 */
> +	eeprom_93cx6_startup(eeprom);
> +
> +	/*
> +	 * Select the read opcode and the word to be read.
> +	 */
> +	eeprom_93cx6_write_bits(eeprom, PCI_EEPROM_EWDS_OPCODE, 5);
> +	eeprom_93cx6_write_bits(eeprom, 0, 6);
> +
> +	/*
> +	 * Cleanup eeprom register.
> +	 */
> +	eeprom_93cx6_cleanup(eeprom);
> +}
> +
> +/**
> + * eeprom_93cx6_read - Read multiple words from eeprom
> + * @eeprom: Pointer to eeprom structure
> + * @word: Word index from where we should start reading
> + * @data: target pointer where the information will have to be stored
> + *
> + * This function will read the eeprom data as host-endian word
> + * into the given data pointer.
> + */
> +void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
> +	u16 *data)
> +{
> +	u16 command;
> +
> +	/*
> +	 * Initialize the eeprom register
> +	 */
> +	eeprom_93cx6_startup(eeprom);
> +
> +	/*
> +	 * Select the read opcode and the word to be read.
> +	 */
> +	command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
> +	eeprom_93cx6_write_bits(eeprom, command,
> +		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
> +
> +	/*
> +	 * Read the requested 16 bits.
> +	 */
> +	eeprom_93cx6_read_bits(eeprom, data, 16);
> +
> +	/*
> +	 * Cleanup eeprom register.
> +	 */
> +	eeprom_93cx6_cleanup(eeprom);
> +}
> +EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
> +
> +/**
> + * eeprom_93cx6_multiread - Read multiple words from eeprom
> + * @eeprom: Pointer to eeprom structure
> + * @word: Word index from where we should start reading
> + * @data: target pointer where the information will have to be stored
> + * @words: Number of words that should be read.
> + *
> + * This function will read all requested words from the eeprom,
> + * this is done by calling eeprom_93cx6_read() multiple times.
> + * But with the additional change that while the eeprom_93cx6_read
> + * will return host ordered bytes, this method will return little
> + * endian words.
> + */
> +void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
> +	__le16 *data, const u16 words)
> +{
> +	unsigned int i;
> +	u16 tmp;
> +
> +	for (i = 0; i < words; i++) {
> +		tmp = 0;
> +		eeprom_93cx6_read(eeprom, word + i, &tmp);
> +		data[i] = cpu_to_le16(tmp);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
> +
> +/**
> + * eeprom_93cx6_write - Write multiple words to the eeprom
> + * @eeprom: Pointer to eeprom structure
> + * @word: Word index from where we should start writing
> + * @data: Data that will be written
> + *
> + * This function will write the eeprom data as host-endian word
> + * from the given data pointer.
> + */
> +void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, const u8 word,
> +	u16 data)
> +{
> +	u16 command;
> +
> +	/*
> +	 * select the ewen opcode.
> +	 */
> +	eeprom_93cx6_ewen(eeprom);
> +
> +	/*
> +	 * Initialize the eeprom register
> +	 */
> +	eeprom_93cx6_startup(eeprom);
> +
> +	/*
> +	 * Select the write opcode and the word to be read.
> +	 */
> +	command = (PCI_EEPROM_WRITE_OPCODE << eeprom->width) | word;
> +	eeprom_93cx6_write_bits(eeprom, command,
> +		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
> +
> +	/*
> +	 * Write the requested 16 bits.
> +	 */
> +	eeprom_93cx6_write_bits(eeprom, data, 16);
> +
> +	/*
> +	 * Cleanup eeprom register.
> +	 */
> +	eeprom_93cx6_cleanup(eeprom);
> +
> +	/*
> +	 * Take a short break.
> +	 */
> +	msleep(10000);
> +
> +	/*
> +	 * select the ewen opcode.
> +	 */
> +	eeprom_93cx6_ewds(eeprom);
> +
> +	/*
> +	 * Cleanup eeprom register.
> +	 */
> +	eeprom_93cx6_cleanup(eeprom);
> +}
> +EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
> +
> +
> +/**
> + * eeprom_93cx6_multiwrite - Write multiple words to the eeprom
> + * @eeprom: Pointer to eeprom structure
> + * @word: Word index from where we should start writing
> + * @data: Pointer where the information will be read from
> + * @words: Number of words that should be written.
> + *
> + * This function will write all requested words to the eeprom,
> + * this is done by calling eeprom_93cx6_write() multiple times.
> + * This method accepts little endian data, so it will first be
> + * converted into host endian.
> + */
> +void eeprom_93cx6_multiwrite(struct eeprom_93cx6 *eeprom, const u8 word,
> +	__le16 *data, const u16 words)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < words; i++)
> +		eeprom_93cx6_write(eeprom, word + i, le16_to_cpu(data[i]));
> +}
> +EXPORT_SYMBOL_GPL(eeprom_93cx6_multiwrite);
> diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
> index 0184614..6ff5a8a 100644
> --- a/drivers/net/wireless/Kconfig
> +++ b/drivers/net/wireless/Kconfig
> @@ -267,7 +267,7 @@ config IPW2200_DEBUG
>  
>  config LIBERTAS_USB
>  	tristate "Marvell Libertas 8388 802.11a/b/g cards"
> -	depends on NET_RADIO && USB
> +	depends on USB && WLAN_80211
>  	select FW_LOADER
>  	---help---
>  	  A driver for Marvell Libertas 8388 USB devices.
> @@ -542,4 +542,6 @@ source "drivers/net/wireless/hostap/Kconfig"
>  source "drivers/net/wireless/bcm43xx/Kconfig"
>  source "drivers/net/wireless/zd1211rw/Kconfig"
>  
> +source "drivers/net/wireless/rtl818x/Kconfig"
> +
>  endmenu
> diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
> index d212460..198c992 100644
> --- a/drivers/net/wireless/Makefile
> +++ b/drivers/net/wireless/Makefile
> @@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
>  
>  obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
>  obj-$(CONFIG_LIBERTAS_USB)     += libertas/
> +
> +# Drivers using mac80211 stack (net/mac80211)
> +obj-$(CONFIG_RTL818X)		+= rtl818x/
> diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
> index f8483c1..10e07e8 100644
> --- a/drivers/net/wireless/bcm43xx/bcm43xx.h
> +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
> @@ -658,12 +658,6 @@ struct bcm43xx_pio {
>  
>  #define BCM43xx_MAX_80211_CORES		2
>  
> -#ifdef CONFIG_BCM947XX
> -#define core_offset(bcm) (bcm)->current_core_offset
> -#else
> -#define core_offset(bcm) 0
> -#endif
> -
>  /* Generic information about a core. */
>  struct bcm43xx_coreinfo {
>  	u8 available:1,
> @@ -789,10 +783,6 @@ struct bcm43xx_private {
>  
>  	/* The currently active core. */
>  	struct bcm43xx_coreinfo *current_core;
> -#ifdef CONFIG_BCM947XX
> -	/** current core memory offset */
> -	u32 current_core_offset;
> -#endif
>  	struct bcm43xx_coreinfo *active_80211_core;
>  	/* coreinfo structs for all possible cores follow.
>  	 * Note that a core might not exist.
> @@ -943,25 +933,25 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
>  static inline
>  u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
>  {
> -	return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
> +	return ioread16(bcm->mmio_addr + offset);
>  }
>  
>  static inline
>  void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
>  {
> -	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
> +	iowrite16(value, bcm->mmio_addr + offset);
>  }
>  
>  static inline
>  u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
>  {
> -	return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
> +	return ioread32(bcm->mmio_addr + offset);
>  }
>  
>  static inline
>  void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
>  {
> -	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
> +	iowrite32(value, bcm->mmio_addr + offset);
>  }
>  
>  static inline
> diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
> index e3d2e61..1f7731f 100644
> --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
> +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
> @@ -660,10 +660,6 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
>  	ring->routing = BCM43xx_DMA32_CLIENTTRANS;
>  	if (dma64)
>  		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
> -#ifdef CONFIG_BCM947XX
> -	if (bcm->pci_dev->bus->number == 0)
> -		ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS;
> -#endif
>  
>  	ring->bcm = bcm;
>  	ring->nr_slots = nr_slots;
> diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> index 5e96bca..ef6b253 100644
> --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> @@ -61,10 +61,6 @@ MODULE_AUTHOR("Stefano Brivio");
>  MODULE_AUTHOR("Michael Buesch");
>  MODULE_LICENSE("GPL");
>  
> -#ifdef CONFIG_BCM947XX
> -extern char *nvram_get(char *name);
> -#endif
> -
>  #if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
>  static int modparam_pio;
>  module_param_named(pio, modparam_pio, int, 0444);
> @@ -142,10 +138,6 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple fi
>  	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
>  	/* Broadcom 43XG 802.11b/g */
>  	{ PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -#ifdef CONFIG_BCM947XX
> -	/* SB bus on BCM947xx */
> -	{ PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -#endif
>  	{ 0 },
>  };
>  MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
> @@ -786,9 +778,6 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
>  {
>  	u16 value;
>  	u16 *sprom;
> -#ifdef CONFIG_BCM947XX
> -	char *c;
> -#endif
>  
>  	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
>  			GFP_KERNEL);
> @@ -796,28 +785,7 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
>  		printk(KERN_ERR PFX "sprom_extract OOM\n");
>  		return -ENOMEM;
>  	}
> -#ifdef CONFIG_BCM947XX
> -	sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
> -	sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
> -
> -	if ((c = nvram_get("il0macaddr")) != NULL)
> -		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
> -
> -	if ((c = nvram_get("et1macaddr")) != NULL)
> -		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
> -
> -	sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
> -	sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
> -	sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
> -
> -	sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
> -	sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
> -	sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
> -
> -	sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
> -#else
>  	bcm43xx_sprom_read(bcm, sprom);
> -#endif
>  
>  	/* boardflags2 */
>  	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
> @@ -1225,12 +1193,6 @@ static int _switch_core(struct bcm43xx_private *bcm, int core)
>  			goto error;
>  		udelay(10);
>  	}
> -#ifdef CONFIG_BCM947XX
> -	if (bcm->pci_dev->bus->number == 0)
> -		bcm->current_core_offset = 0x1000 * core;
> -	else
> -		bcm->current_core_offset = 0;
> -#endif
>  
>  	return 0;
>  error:
> @@ -1387,19 +1349,6 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
>  
>  	if ((bcm43xx_core_enabled(bcm)) &&
>  	    !bcm43xx_using_pio(bcm)) {
> -//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
> -#if 0
> -#ifndef CONFIG_BCM947XX
> -		/* reset all used DMA controllers. */
> -		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
> -		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
> -		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
> -		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
> -		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
> -		if (bcm->current_core->rev < 5)
> -			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
> -#endif
> -#endif
>  	}
>  	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
>  		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
> @@ -2140,32 +2089,11 @@ out:
>  	return err;
>  }
>  
> -#ifdef CONFIG_BCM947XX
> -static struct pci_device_id bcm43xx_47xx_ids[] = {
> -	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
> -	{ 0 }
> -};
> -#endif
> -
>  static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
>  {
>  	int err;
>  
>  	bcm->irq = bcm->pci_dev->irq;
> -#ifdef CONFIG_BCM947XX
> -	if (bcm->pci_dev->bus->number == 0) {
> -		struct pci_dev *d;
> -		struct pci_device_id *id;
> -		for (id = bcm43xx_47xx_ids; id->vendor; id++) {
> -			d = pci_get_device(id->vendor, id->device, NULL);
> -			if (d != NULL) {
> -				bcm->irq = d->irq;
> -				pci_dev_put(d);
> -				break;
> -			}
> -		}
> -	}
> -#endif
>  	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
>  			  IRQF_SHARED, KBUILD_MODNAME, bcm);
>  	if (err)
> @@ -2645,10 +2573,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
>  			chip_id_16 = 0x4610;
>  		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
>  			chip_id_16 = 0x4710;
> -#ifdef CONFIG_BCM947XX
> -		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
> -			chip_id_16 = 0x4309;
> -#endif
>  		else {
>  			printk(KERN_ERR PFX "Could not determine Chip ID\n");
>  			return -ENODEV;
> @@ -4144,11 +4068,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
>  	struct bcm43xx_private *bcm;
>  	int err;
>  
> -#ifdef CONFIG_BCM947XX
> -	if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
> -		return -ENODEV;
> -#endif
> -
>  #ifdef DEBUG_SINGLE_DEVICE_ONLY
>  	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
>  		return -ENODEV;
> diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
> index f763571..c8f3c53 100644
> --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
> +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
> @@ -33,25 +33,6 @@
>  
>  #include "bcm43xx.h"
>  
> -#ifdef CONFIG_BCM947XX
> -#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
> -
> -static inline void e_aton(char *str, char *dest)
> -{
> -	int i = 0;
> -	u16 *d = (u16 *) dest;
> -
> -	for (;;) {
> -		dest[i++] = (char) simple_strtoul(str, NULL, 16);
> -		str += 2;
> -		if (!*str++ || i == 6)
> -			break;
> -	}
> -	for (i = 0; i < 3; i++)
> -		d[i] = cpu_to_be16(d[i]);
> -}
> -#endif
> -
>  #define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
>  #define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
>  /* Magic helper macro to pad structures. Ignore those above. It's magic. */
> diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig
> new file mode 100644
> index 0000000..e2c27f8
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/Kconfig
> @@ -0,0 +1,16 @@
> +config RTL818X
> +	bool
> +	default n
> +
> +config RTL8187
> +	tristate "Realtek 8187 USB support"
> +	depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
> +	select RTL818X
> +	select EEPROM_93CX6
> +	---help---
> +	  This is a driver for RTL8187 based cards.
> +	  These are USB based chips found in cards such as:
> +
> +	  Netgear WG111v2
> +
> +	  Thanks to Realtek for their support!
> diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
> new file mode 100644
> index 0000000..fe5dd6f
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/Makefile
> @@ -0,0 +1,2 @@
> +rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
> +obj-$(CONFIG_RTL8187)	+= rtl8187.o
> diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
> new file mode 100644
> index 0000000..bd0b6f9
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/rtl8187.h
> @@ -0,0 +1,125 @@
> +#ifndef RTL8187_H
> +#define RTL8187_H
> +
> +#include "rtl818x.h"
> +
> +#define RTL8187_REQT_READ	0xC0
> +#define RTL8187_REQT_WRITE	0x40
> +#define RTL8187_REQ_GET_REG	0x05
> +#define RTL8187_REQ_SET_REG	0x05
> +
> +#define RTL8187_MAX_RX		0x9C4
> +
> +struct rtl8187_rx_info {
> +	struct urb *urb;
> +	struct ieee80211_hw *dev;
> +};
> +
> +struct rtl8187_rx_hdr {
> +	__le16 len;
> +	__le16 rate;
> +	u8 noise;
> +	u8 signal;
> +	u8 agc;
> +	u8 reserved;
> +	__le64 mac_time;
> +} __attribute__((packed));
> +
> +struct rtl8187_tx_info {
> +	struct ieee80211_tx_control *control;
> +	struct urb *urb;
> +	struct ieee80211_hw *dev;
> +};
> +
> +struct rtl8187_tx_hdr {
> +	__le32 flags;
> +#define RTL8187_TX_FLAG_NO_ENCRYPT	(1 << 15)
> +#define RTL8187_TX_FLAG_MORE_FRAG	(1 << 17)
> +#define RTL8187_TX_FLAG_CTS		(1 << 18)
> +#define RTL8187_TX_FLAG_RTS		(1 << 23)
> +	__le16 rts_duration;
> +	__le16 len;
> +	__le32 retry;
> +} __attribute__((packed));
> +
> +struct rtl8187_priv {
> +	/* common between rtl818x drivers */
> +	struct rtl818x_csr *map;
> +	void (*rf_init)(struct ieee80211_hw *);
> +	int mode;
> +
> +	/* rtl8187 specific */
> +	struct ieee80211_channel channels[14];
> +	struct ieee80211_rate rates[12];
> +	struct ieee80211_hw_mode modes[2];
> +	struct usb_device *udev;
> +	u8 *hwaddr;
> +	u16 txpwr_base;
> +	u8 asic_rev;
> +	struct sk_buff_head rx_queue;
> +};
> +
> +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
> +
> +static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
> +{
> +	u8 val;
> +
> +	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
> +			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
> +
> +	return val;
> +}
> +
> +static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
> +{
> +	__le16 val;
> +
> +	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
> +			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
> +
> +	return le16_to_cpu(val);
> +}
> +
> +static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
> +{
> +	__le32 val;
> +
> +	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
> +			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
> +
> +	return le32_to_cpu(val);
> +}
> +
> +static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
> +				    u8 *addr, u8 val)
> +{
> +	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
> +			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
> +}
> +
> +static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
> +				     __le16 *addr, u16 val)
> +{
> +	__le16 buf = cpu_to_le16(val);
> +
> +	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
> +			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
> +}
> +
> +static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
> +				     __le32 *addr, u32 val)
> +{
> +	__le32 buf = cpu_to_le32(val);
> +
> +	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
> +			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
> +}
> +
> +#endif /* RTL8187_H */
> diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
> new file mode 100644
> index 0000000..8f9e781
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
> @@ -0,0 +1,730 @@
> +
> +/*
> + * Linux device driver for RTL8187
> + *
> + * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
> + *
> + * Based on the r8187 driver, which is:
> + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
> + *
> + * Thanks to Realtek for their support!
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/usb.h>
> +#include <linux/delay.h>
> +#include <linux/etherdevice.h>
> +#include <linux/eeprom_93cx6.h>
> +#include <net/mac80211.h>
> +
> +#include "rtl8187.h"
> +#include "rtl8187_rtl8225.h"
> +
> +MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
> +MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
> +MODULE_DESCRIPTION("RTL8187 USB wireless driver");
> +MODULE_LICENSE("GPL");
> +
> +static struct usb_device_id rtl8187_table[] __devinitdata = {
> +	/* Realtek */
> +	{USB_DEVICE(0x0bda, 0x8187)},
> +	/* Netgear */
> +	{USB_DEVICE(0x0846, 0x6100)},
> +	{USB_DEVICE(0x0846, 0x6a00)},
> +	{}
> +};
> +
> +MODULE_DEVICE_TABLE(usb, rtl8187_table);
> +
> +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	data <<= 8;
> +	data |= addr | 0x80;
> +
> +	rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
> +	rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
> +	rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
> +	rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
> +
> +	mdelay(1);
> +}
> +
> +static void rtl8187_tx_cb(struct urb *urb)
> +{
> +	struct ieee80211_tx_status status = { {0} };
> +	struct sk_buff *skb = (struct sk_buff *)urb->context;
> +	struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
> +
> +	usb_free_urb(info->urb);
> +	if (info->control)
> +		memcpy(&status.control, info->control, sizeof(status.control));
> +	kfree(info->control);
> +	skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
> +	status.flags |= IEEE80211_TX_STATUS_ACK;
> +	ieee80211_tx_status_irqsafe(info->dev, skb, &status);
> +}
> +
> +static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
> +		      struct ieee80211_tx_control *control)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	struct rtl8187_tx_hdr *hdr;
> +	struct rtl8187_tx_info *info;
> +	struct urb *urb;
> +	u32 tmp;
> +
> +	urb = usb_alloc_urb(0, GFP_ATOMIC);
> +	if (!urb) {
> +		kfree_skb(skb);
> +		return 0;
> +	}
> +
> +	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
> +	tmp = skb->len - sizeof(*hdr);
> +	tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
> +	tmp |= control->rts_cts_rate << 19;
> +	tmp |= control->tx_rate << 24;
> +	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
> +		tmp |= RTL8187_TX_FLAG_MORE_FRAG;
> +	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
> +		tmp |= RTL8187_TX_FLAG_RTS;
> +		hdr->rts_duration =
> +			ieee80211_rts_duration(dev, skb->len, control);
> +	}
> +	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
> +		tmp |= RTL8187_TX_FLAG_CTS;
> +	hdr->flags = cpu_to_le32(tmp);
> +	hdr->len = 0;
> +	tmp = control->retry_limit << 8;
> +	hdr->retry = cpu_to_le32(tmp);
> +
> +	info = (struct rtl8187_tx_info *)skb->cb;
> +	info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
> +	info->urb = urb;
> +	info->dev = dev;
> +	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
> +			  hdr, skb->len, rtl8187_tx_cb, skb);
> +	usb_submit_urb(urb, GFP_ATOMIC);
> +
> +	return 0;
> +}
> +
> +static void rtl8187_rx_cb(struct urb *urb)
> +{
> +	struct sk_buff *skb = (struct sk_buff *)urb->context;
> +	struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
> +	struct ieee80211_hw *dev = info->dev;
> +	struct rtl8187_priv *priv = dev->priv;
> +	struct rtl8187_rx_hdr *hdr;
> +	struct ieee80211_rx_status rx_status = { 0 };
> +	int rate, signal;
> +
> +	if (unlikely(urb->status)) {
> +		info->urb = NULL;
> +		usb_free_urb(urb);
> +		return;
> +	}
> +
> +	skb_unlink(skb, &priv->rx_queue);
> +	skb_put(skb, urb->actual_length);
> +	hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
> +	skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
> +
> +	signal = hdr->agc >> 1;
> +	rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
> +	if (rate > 3) {	/* OFDM rate */
> +		if (signal > 90)
> +			signal = 90;
> +		else if (signal < 25)
> +			signal = 25;
> +		signal = 90 - signal;
> +	} else {	/* CCK rate */
> +		if (signal > 95)
> +			signal = 95;
> +		else if (signal < 30)
> +			signal = 30;
> +		signal = 95 - signal;
> +	}
> +
> +	rx_status.antenna = (hdr->signal >> 7) & 1;
> +	rx_status.signal = 64 - min(hdr->noise, (u8)64);
> +	rx_status.ssi = signal;
> +	rx_status.rate = rate;
> +	rx_status.freq = dev->conf.freq;
> +	rx_status.channel = dev->conf.channel;
> +	rx_status.phymode = dev->conf.phymode;
> +	rx_status.mactime = le64_to_cpu(hdr->mac_time);
> +	ieee80211_rx_irqsafe(dev, skb, &rx_status);
> +
> +	skb = dev_alloc_skb(RTL8187_MAX_RX);
> +	if (unlikely(!skb)) {
> +		usb_free_urb(urb);
> +		/* TODO check rx queue length and refill *somewhere* */
> +		return;
> +	}
> +
> +	info = (struct rtl8187_rx_info *)skb->cb;
> +	info->urb = urb;
> +	info->dev = dev;
> +	urb->transfer_buffer = skb_tail_pointer(skb);
> +	urb->context = skb;
> +	skb_queue_tail(&priv->rx_queue, skb);
> +
> +	usb_submit_urb(urb, GFP_ATOMIC);
> +}
> +
> +static int rtl8187_init_urbs(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	struct urb *entry;
> +	struct sk_buff *skb;
> +	struct rtl8187_rx_info *info;
> +
> +	while (skb_queue_len(&priv->rx_queue) < 8) {
> +		skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
> +		if (!skb)
> +			break;
> +		entry = usb_alloc_urb(0, GFP_KERNEL);
> +		if (!entry) {
> +			kfree_skb(skb);
> +			break;
> +		}
> +		usb_fill_bulk_urb(entry, priv->udev,
> +				  usb_rcvbulkpipe(priv->udev, 1),
> +				  skb_tail_pointer(skb),
> +				  RTL8187_MAX_RX, rtl8187_rx_cb, skb);
> +		info = (struct rtl8187_rx_info *)skb->cb;
> +		info->urb = entry;
> +		info->dev = dev;
> +		skb_queue_tail(&priv->rx_queue, skb);
> +		usb_submit_urb(entry, GFP_KERNEL);
> +	}
> +
> +	return 0;
> +}
> +
> +static int rtl8187_init_hw(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u8 reg;
> +	int i;
> +
> +	/* reset */
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
> +
> +	mdelay(200);
> +	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
> +	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
> +	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
> +	mdelay(200);
> +
> +	reg = rtl818x_ioread8(priv, &priv->map->CMD);
> +	reg &= (1 << 1);
> +	reg |= RTL818X_CMD_RESET;
> +	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
> +
> +	i = 10;
> +	do {
> +		mdelay(2);
> +		if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
> +		      RTL818X_CMD_RESET))
> +			break;
> +	} while (--i);
> +
> +	if (!i) {
> +		printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* reload registers from eeprom */
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
> +
> +	i = 10;
> +	do {
> +		mdelay(4);
> +		if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
> +		      RTL818X_EEPROM_CMD_CONFIG))
> +			break;
> +	} while (--i);
> +
> +	if (!i) {
> +		printk(KERN_ERR "%s: eeprom reset timeout!\n",
> +		       wiphy_name(dev->wiphy));
> +		return -ETIMEDOUT;
> +	}
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	/* setup card */
> +	rtl818x_iowrite8(priv, (u8 *)0xFF85, 0);
> +	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
> +
> +	rtl818x_iowrite8(priv, (u8 *)0xFF85, 4);
> +	rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
> +	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	for (i = 0; i < ETH_ALEN; i++)
> +		rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
> +
> +	rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
> +	reg &= 0x3F;
> +	reg |= 0x80;
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
> +	rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
> +	rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
> +
> +	// TODO: set RESP_RATE and BRSR properly
> +	rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
> +	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
> +
> +	/* host_usb_init */
> +	rtl818x_iowrite8(priv, (u8 *)0xFF85, 0);
> +	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
> +	reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
> +	rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
> +	rtl818x_iowrite8(priv, (u8 *)0xFF85, 4);
> +	rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
> +	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
> +	mdelay(100);
> +
> +	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
> +	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
> +	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
> +	mdelay(100);
> +
> +	priv->rf_init(dev);
> +
> +	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
> +	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
> +	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
> +	rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
> +	rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
> +	rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
> +	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
> +
> +	return 0;
> +}
> +
> +static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
> +{
> +	u32 reg;
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
> +	/* Enable TX loopback on MAC level to avoid TX during channel
> +	 * changes, as this has be seen to causes problems and the
> +	 * card will stop work until next reset
> +	 */
> +	rtl818x_iowrite32(priv, &priv->map->TX_CONF,
> +			  reg | RTL818X_TX_CONF_LOOPBACK_MAC);
> +	mdelay(10);
> +	rtl8225_rf_set_channel(dev, channel);
> +	mdelay(10);
> +	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
> +}
> +
> +static int rtl8187_open(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u32 reg;
> +	int ret;
> +
> +	ret = rtl8187_init_hw(dev);
> +	if (ret)
> +		return ret;
> +
> +	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
> +
> +	rtl8187_init_urbs(dev);
> +
> +	reg = RTL818X_RX_CONF_ONLYERLPKT |
> +	      RTL818X_RX_CONF_RX_AUTORESETPHY |
> +	      RTL818X_RX_CONF_BSSID |
> +	      RTL818X_RX_CONF_MGMT |
> +	      RTL818X_RX_CONF_CTRL |
> +	      RTL818X_RX_CONF_DATA |
> +	      (7 << 13 /* RX FIFO threshold NONE */) |
> +	      (7 << 10 /* MAX RX DMA */) |
> +	      RTL818X_RX_CONF_BROADCAST |
> +	      RTL818X_RX_CONF_MULTICAST |
> +	      RTL818X_RX_CONF_NICMAC;
> +	if (priv->mode == IEEE80211_IF_TYPE_MNTR)
> +		reg |= RTL818X_RX_CONF_MONITOR;
> +
> +	rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
> +
> +	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
> +	reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
> +	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
> +	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
> +
> +	reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
> +	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
> +	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
> +	reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
> +	rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
> +
> +	reg  = RTL818X_TX_CONF_CW_MIN |
> +	       (7 << 21 /* MAX TX DMA */) |
> +	       RTL818X_TX_CONF_NO_ICV;
> +	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
> +
> +	reg = rtl818x_ioread8(priv, &priv->map->CMD);
> +	reg |= RTL818X_CMD_TX_ENABLE;
> +	reg |= RTL818X_CMD_RX_ENABLE;
> +	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
> +
> +	return 0;
> +}
> +
> +static int rtl8187_stop(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	struct rtl8187_rx_info *info;
> +	struct sk_buff *skb;
> +	u32 reg;
> +
> +	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
> +
> +	reg = rtl818x_ioread8(priv, &priv->map->CMD);
> +	reg &= ~RTL818X_CMD_TX_ENABLE;
> +	reg &= ~RTL818X_CMD_RX_ENABLE;
> +	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
> +
> +	rtl8225_rf_stop(dev);
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	while ((skb = skb_dequeue(&priv->rx_queue))) {
> +		info = (struct rtl8187_rx_info *)skb->cb;
> +		if (!info->urb)
> +			continue;
> +
> +		usb_kill_urb(info->urb);
> +		kfree_skb(skb);
> +	}
> +	return 0;
> +}
> +
> +static int rtl8187_add_interface(struct ieee80211_hw *dev,
> +				 struct ieee80211_if_init_conf *conf)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	/* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
> +	if (priv->mode != IEEE80211_IF_TYPE_MGMT)
> +		return -1;
> +
> +	switch (conf->type) {
> +	case IEEE80211_IF_TYPE_STA:
> +	case IEEE80211_IF_TYPE_MNTR:
> +		priv->mode = conf->type;
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	priv->hwaddr = conf->mac_addr;
> +
> +	return 0;
> +}
> +
> +static void rtl8187_remove_interface(struct ieee80211_hw *dev,
> +				     struct ieee80211_if_init_conf *conf)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	priv->mode = IEEE80211_IF_TYPE_MGMT;
> +}
> +
> +static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	rtl8187_set_channel(dev, conf->channel);
> +
> +	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
> +
> +	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
> +		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
> +	else
> +		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
> +
> +	switch (conf->phymode) {
> +	case MODE_IEEE80211B:
> +		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
> +		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
> +		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
> +		break;
> +	case MODE_IEEE80211G:
> +		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
> +		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
> +		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
> +		break;
> +	default:
> +		BUG();
> +		break;
> +	}
> +
> +	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
> +	rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
> +	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
> +	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
> +	return 0;
> +}
> +
> +static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
> +				    struct ieee80211_if_conf *conf)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	int i;
> +
> +	for (i = 0; i < ETH_ALEN; i++)
> +		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
> +
> +	if (is_valid_ether_addr(conf->bssid))
> +		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
> +	else
> +		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
> +
> +	return 0;
> +}
> +
> +static const struct ieee80211_ops rtl8187_ops = {
> +	.tx			= rtl8187_tx,
> +	.open			= rtl8187_open,
> +	.stop			= rtl8187_stop,
> +	.add_interface		= rtl8187_add_interface,
> +	.remove_interface	= rtl8187_remove_interface,
> +	.config			= rtl8187_config,
> +	.config_interface	= rtl8187_config_interface,
> +};
> +
> +static void rtl8187_register_read(struct eeprom_93cx6 *eeprom)
> +{
> +	struct ieee80211_hw *dev = eeprom->data;
> +	struct rtl8187_priv *priv = dev->priv;
> +	u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
> +
> +	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
> +	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
> +	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
> +	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
> +}
> +
> +static void rtl8187_register_write(struct eeprom_93cx6 *eeprom)
> +{
> +	struct ieee80211_hw *dev = eeprom->data;
> +	struct rtl8187_priv *priv = dev->priv;
> +	u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
> +
> +	if (eeprom->reg_data_in)
> +		reg |= RTL818X_EEPROM_CMD_WRITE;
> +	if (eeprom->reg_data_out)
> +		reg |= RTL818X_EEPROM_CMD_READ;
> +	if (eeprom->reg_data_clock)
> +		reg |= RTL818X_EEPROM_CMD_CK;
> +	if (eeprom->reg_chip_select)
> +		reg |= RTL818X_EEPROM_CMD_CS;
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
> +	udelay(10);
> +}
> +
> +static int __devinit rtl8187_probe(struct usb_interface *intf,
> +				   const struct usb_device_id *id)
> +{
> +	struct usb_device *udev = interface_to_usbdev(intf);
> +	struct ieee80211_hw *dev;
> +	struct rtl8187_priv *priv;
> +	struct eeprom_93cx6 eeprom;
> +	struct ieee80211_channel *channel;
> +	u16 txpwr, reg;
> +	int err, i;
> +
> +	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
> +	if (!dev) {
> +		printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
> +		return -ENOMEM;
> +	}
> +
> +	priv = dev->priv;
> +
> +	SET_IEEE80211_DEV(dev, &intf->dev);
> +	usb_set_intfdata(intf, dev);
> +	priv->udev = udev;
> +
> +	usb_get_dev(udev);
> +
> +	skb_queue_head_init(&priv->rx_queue);
> +	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
> +	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
> +	priv->map = (struct rtl818x_csr *)0xFF00;
> +	priv->modes[0].mode = MODE_IEEE80211G;
> +	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
> +	priv->modes[0].rates = priv->rates;
> +	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
> +	priv->modes[0].channels = priv->channels;
> +	priv->modes[1].mode = MODE_IEEE80211B;
> +	priv->modes[1].num_rates = 4;
> +	priv->modes[1].rates = priv->rates;
> +	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
> +	priv->modes[1].channels = priv->channels;
> +	priv->mode = IEEE80211_IF_TYPE_MGMT;
> +	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
> +		     IEEE80211_HW_RX_INCLUDES_FCS |
> +		     IEEE80211_HW_WEP_INCLUDE_IV |
> +		     IEEE80211_HW_DATA_NULLFUNC_ACK;
> +	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
> +	dev->queues = 1;
> +	dev->max_rssi = 65;
> +	dev->max_signal = 64;
> +
> +	for (i = 0; i < 2; i++)
> +		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
> +			goto err_free_dev;
> +
> +	eeprom.data = dev;
> +	eeprom.register_read = rtl8187_register_read;
> +	eeprom.register_write = rtl8187_register_write;
> +	if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
> +		eeprom.width = PCI_EEPROM_WIDTH_93C66;
> +	else
> +		eeprom.width = PCI_EEPROM_WIDTH_93C46;
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	udelay(10);
> +
> +	eeprom_93cx6_multiread(&eeprom, 0x7,
> +			       (__le16 __force *)dev->wiphy->perm_addr, 3);
> +	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
> +		printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly generated MAC address\n");
> +		random_ether_addr(dev->wiphy->perm_addr);
> +	}
> +
> +	channel = priv->channels;
> +	for (i = 0; i < 3; i++) {
> +		eeprom_93cx6_read(&eeprom, 0x16 + i, &txpwr);
> +		(*channel++).val = txpwr & 0xFF;
> +		(*channel++).val = txpwr >> 8;
> +	}
> +	for (i = 0; i < 2; i++) {
> +		eeprom_93cx6_read(&eeprom, 0x3D + i, &txpwr);
> +		(*channel++).val = txpwr & 0xFF;
> +		(*channel++).val = txpwr >> 8;
> +	}
> +	for (i = 0; i < 2; i++) {
> +		eeprom_93cx6_read(&eeprom, 0x1B + i, &txpwr);
> +		(*channel++).val = txpwr & 0xFF;
> +		(*channel++).val = txpwr >> 8;
> +	}
> +
> +	eeprom_93cx6_read(&eeprom, 0x05, &priv->txpwr_base);
> +
> +	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
> +	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
> +	/* 0 means asic B-cut, we should use SW 3 wire
> +	 * bit-by-bit banging for radio. 1 means we can use
> +	 * USB specific request to write radio registers */
> +	priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
> +	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	rtl8225_write(dev, 0, 0x1B7);
> +
> +	if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
> +		priv->rf_init = rtl8225_rf_init;
> +	else
> +		priv->rf_init = rtl8225z2_rf_init;
> +
> +	rtl8225_write(dev, 0, 0x0B7);
> +
> +	err = ieee80211_register_hw(dev);
> +	if (err) {
> +		printk(KERN_ERR "rtl8187: Cannot register device\n");
> +		goto err_free_dev;
> +	}
> +
> +	printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
> +	       wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
> +	       priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
> +	       "rtl8225" : "rtl8225z2");
> +
> +	return 0;
> +
> + err_free_dev:
> +	ieee80211_free_hw(dev);
> +	usb_set_intfdata(intf, NULL);
> +	usb_put_dev(udev);
> +	return err;
> +}
> +
> +static void __devexit rtl8187_disconnect(struct usb_interface *intf)
> +{
> +	struct ieee80211_hw *dev = usb_get_intfdata(intf);
> +	struct rtl8187_priv *priv;
> +
> +	if (!dev)
> +		return;
> +
> +	ieee80211_unregister_hw(dev);
> +
> +	priv = dev->priv;
> +	usb_put_dev(interface_to_usbdev(intf));
> +	ieee80211_free_hw(dev);
> +}
> +
> +static struct usb_driver rtl8187_driver = {
> +	.name		= KBUILD_MODNAME,
> +	.id_table	= rtl8187_table,
> +	.probe		= rtl8187_probe,
> +	.disconnect	= rtl8187_disconnect,
> +};
> +
> +static int __init rtl8187_init(void)
> +{
> +	return usb_register(&rtl8187_driver);
> +}
> +
> +static void __exit rtl8187_exit(void)
> +{
> +	usb_deregister(&rtl8187_driver);
> +}
> +
> +module_init(rtl8187_init);
> +module_exit(rtl8187_exit);
> diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
> new file mode 100644
> index 0000000..a89f023
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
> @@ -0,0 +1,744 @@
> +
> +/*
> + * Radio tuning for RTL8225 on RTL8187
> + *
> + * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
> + *
> + * Based on the r8187 driver, which is:
> + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
> + *
> + * Thanks to Realtek for their support!
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/usb.h>
> +#include <net/mac80211.h>
> +
> +#include "rtl8187.h"
> +#include "rtl8187_rtl8225.h"
> +
> +static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u16 reg80, reg84, reg82;
> +	u32 bangdata;
> +	int i;
> +
> +	bangdata = (data << 4) | (addr & 0xf);
> +
> +	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
> +	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
> +
> +	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
> +	udelay(10);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	udelay(2);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
> +	udelay(10);
> +
> +	for (i = 15; i >= 0; i--) {
> +		u16 reg = reg80 | (bangdata & (1 << i)) >> i;
> +
> +		if (i & 1)
> +			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
> +
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
> +
> +		if (!(i & 1))
> +			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
> +	}
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	udelay(10);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
> +	mdelay(2);
> +}
> +
> +static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u16 reg80, reg82, reg84;
> +
> +	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
> +	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
> +	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
> +
> +	reg80 &= ~(0x3 << 2);
> +	reg84 &= ~0xF;
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
> +	udelay(10);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	udelay(2);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
> +	udelay(10);
> +
> +	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
> +			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
> +			addr, 0x8225, &data, sizeof(data), HZ / 2);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	udelay(10);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
> +	mdelay(2);
> +}
> +
> +void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	if (priv->asic_rev)
> +		rtl8225_write_8051(dev, addr, data);
> +	else
> +		rtl8225_write_bitbang(dev, addr, data);
> +}
> +
> +u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u16 reg80, reg82, reg84, out;
> +	int i;
> +
> +	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
> +	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
> +	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
> +
> +	reg80 &= ~0xF;
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
> +	udelay(4);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
> +	udelay(5);
> +
> +	for (i = 4; i >= 0; i--) {
> +		u16 reg = reg80 | ((addr >> i) & 1);
> +
> +		if (!(i & 1)) {
> +			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
> +			udelay(1);
> +		}
> +
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg | (1 << 1));
> +		udelay(2);
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg | (1 << 1));
> +		udelay(2);
> +
> +		if (i & 1) {
> +			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
> +			udelay(1);
> +		}
> +	}
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +			  reg80 | (1 << 3) | (1 << 1));
> +	udelay(2);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +			  reg80 | (1 << 3));
> +	udelay(2);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +			  reg80 | (1 << 3));
> +	udelay(2);
> +
> +	out = 0;
> +	for (i = 11; i >= 0; i--) {
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg80 | (1 << 3));
> +		udelay(1);
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg80 | (1 << 3) | (1 << 1));
> +		udelay(2);
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg80 | (1 << 3) | (1 << 1));
> +		udelay(2);
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg80 | (1 << 3) | (1 << 1));
> +		udelay(2);
> +
> +		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
> +			out |= 1 << i;
> +
> +		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +				  reg80 | (1 << 3));
> +		udelay(2);
> +	}
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
> +			  reg80 | (1 << 3) | (1 << 2));
> +	udelay(2);
> +
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
> +	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
> +
> +	return out;
> +}
> +
> +static const u16 rtl8225bcd_rxgain[] = {
> +	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
> +	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
> +	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
> +	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
> +	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
> +	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
> +	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
> +	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
> +	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
> +	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
> +	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
> +	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
> +};
> +
> +static const u8 rtl8225_agc[] = {
> +	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
> +	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
> +	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
> +	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
> +	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
> +	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
> +	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
> +	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
> +	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
> +	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
> +	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
> +	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
> +	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
> +	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
> +	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
> +	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
> +};
> +
> +static const u8 rtl8225_gain[] = {
> +	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
> +	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
> +	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
> +	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
> +	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
> +	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
> +	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
> +};
> +
> +static const u8 rtl8225_threshold[] = {
> +	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
> +};
> +
> +static const u8 rtl8225_tx_gain_cck_ofdm[] = {
> +	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
> +};
> +
> +static const u8 rtl8225_tx_power_cck[] = {
> +	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
> +	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
> +	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
> +	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
> +	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
> +	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
> +};
> +
> +static const u8 rtl8225_tx_power_cck_ch14[] = {
> +	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
> +	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
> +	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
> +	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
> +	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
> +	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
> +};
> +
> +static const u8 rtl8225_tx_power_ofdm[] = {
> +	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
> +};
> +
> +static const u32 rtl8225_chan[] = {
> +	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
> +	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
> +};
> +
> +static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u8 cck_power, ofdm_power;
> +	const u8 *tmp;
> +	u32 reg;
> +	int i;
> +
> +	cck_power = priv->channels[channel - 1].val & 0xF;
> +	ofdm_power = priv->channels[channel - 1].val >> 4;
> +
> +	cck_power = min(cck_power, (u8)11);
> +	ofdm_power = min(ofdm_power, (u8)35);
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
> +			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
> +
> +	if (channel == 14)
> +		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
> +	else
> +		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
> +
> +	for (i = 0; i < 8; i++)
> +		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
> +
> +	mdelay(1); // FIXME: optional?
> +
> +	/* anaparam2 on */
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	rtl8225_write_phy_ofdm(dev, 2, 0x42);
> +	rtl8225_write_phy_ofdm(dev, 6, 0x00);
> +	rtl8225_write_phy_ofdm(dev, 8, 0x00);
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
> +			 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
> +
> +	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
> +
> +	rtl8225_write_phy_ofdm(dev, 5, *tmp);
> +	rtl8225_write_phy_ofdm(dev, 7, *tmp);
> +
> +	mdelay(1);
> +}
> +
> +void rtl8225_rf_init(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	int i;
> +
> +	rtl8225_write(dev, 0x0, 0x067); mdelay(1);
> +	rtl8225_write(dev, 0x1, 0xFE0); mdelay(1);
> +	rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
> +	rtl8225_write(dev, 0x3, 0x441); mdelay(1);
> +	rtl8225_write(dev, 0x4, 0x486); mdelay(1);
> +	rtl8225_write(dev, 0x5, 0xBC0); mdelay(1);
> +	rtl8225_write(dev, 0x6, 0xAE6); mdelay(1);
> +	rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
> +	rtl8225_write(dev, 0x8, 0x01F); mdelay(1);
> +	rtl8225_write(dev, 0x9, 0x334); mdelay(1);
> +	rtl8225_write(dev, 0xA, 0xFD4); mdelay(1);
> +	rtl8225_write(dev, 0xB, 0x391); mdelay(1);
> +	rtl8225_write(dev, 0xC, 0x050); mdelay(1);
> +	rtl8225_write(dev, 0xD, 0x6DB); mdelay(1);
> +	rtl8225_write(dev, 0xE, 0x029); mdelay(1);
> +	rtl8225_write(dev, 0xF, 0x914); mdelay(100);
> +
> +	rtl8225_write(dev, 0x2, 0xC4D); mdelay(200);
> +	rtl8225_write(dev, 0x2, 0x44D); mdelay(200);
> +
> +	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
> +		rtl8225_write(dev, 0x02, 0x0c4d);
> +		mdelay(200);
> +		rtl8225_write(dev, 0x02, 0x044d);
> +		mdelay(100);
> +		if (!(rtl8225_read(dev, 6) & (1 << 7)))
> +			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
> +			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
> +	}
> +
> +	rtl8225_write(dev, 0x0, 0x127);
> +
> +	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
> +		rtl8225_write(dev, 0x1, i + 1);
> +		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
> +	}
> +
> +	rtl8225_write(dev, 0x0, 0x027);
> +	rtl8225_write(dev, 0x0, 0x22F);
> +
> +	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
> +		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
> +		mdelay(1);
> +		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
> +		mdelay(1);
> +	}
> +
> +	mdelay(1);
> +
> +	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
> +
> +	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
> +	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
> +	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
> +	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
> +
> +	rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
> +	rtl8225_write_phy_cck(dev, 0x19, 0x00);
> +	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
> +	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
> +	rtl8225_write_phy_cck(dev, 0x40, 0x86);
> +	rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x44, 0x1f); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x45, 0x1e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x46, 0x1a); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x47, 0x15); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x48, 0x10); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x49, 0x0a); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4a, 0x05); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4b, 0x02); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
> +
> +	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
> +
> +	rtl8225_rf_set_tx_power(dev, 1);
> +
> +	/* RX antenna default to A */
> +	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);	/* B: 0xDB */
> +	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);	/* B: 0x10 */
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
> +	mdelay(1);
> +	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
> +
> +	/* set sensitivity */
> +	rtl8225_write(dev, 0x0c, 0x50);
> +	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
> +	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
> +	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
> +	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
> +	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
> +}
> +
> +static const u8 rtl8225z2_tx_power_cck_ch14[] = {
> +	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
> +};
> +
> +static const u8 rtl8225z2_tx_power_cck[] = {
> +	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
> +};
> +
> +static const u8 rtl8225z2_tx_power_ofdm[] = {
> +	0x42, 0x00, 0x40, 0x00, 0x40
> +};
> +
> +static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
> +	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
> +	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
> +	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
> +	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
> +	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
> +	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
> +};
> +
> +static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	u8 cck_power, ofdm_power;
> +	const u8 *tmp;
> +	u32 reg;
> +	int i;
> +
> +	cck_power = priv->channels[channel - 1].val & 0xF;
> +	ofdm_power = priv->channels[channel - 1].val >> 4;
> +
> +	cck_power = min(cck_power, (u8)15);
> +	cck_power += priv->txpwr_base & 0xF;
> +	cck_power = min(cck_power, (u8)35);
> +
> +	ofdm_power = min(ofdm_power, (u8)15);
> +	ofdm_power += priv->txpwr_base >> 4;
> +	ofdm_power = min(ofdm_power, (u8)35);
> +
> +	if (channel == 14)
> +		tmp = rtl8225z2_tx_power_cck_ch14;
> +	else
> +		tmp = rtl8225z2_tx_power_cck;
> +
> +	for (i = 0; i < 8; i++)
> +		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
> +			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
> +	mdelay(1);
> +
> +	/* anaparam2 on */
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +
> +	rtl8225_write_phy_ofdm(dev, 2, 0x42);
> +	rtl8225_write_phy_ofdm(dev, 5, 0x00);
> +	rtl8225_write_phy_ofdm(dev, 6, 0x40);
> +	rtl8225_write_phy_ofdm(dev, 7, 0x00);
> +	rtl8225_write_phy_ofdm(dev, 8, 0x40);
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
> +			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
> +	mdelay(1);
> +}
> +
> +static const u16 rtl8225z2_rxgain[] = {
> +	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
> +	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
> +	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
> +	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
> +	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
> +	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
> +	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
> +	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
> +	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
> +	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
> +	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
> +	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
> +};
> +
> +static const u8 rtl8225z2_gain_bg[] = {
> +	0x23, 0x15, 0xa5, /* -82-1dBm */
> +	0x23, 0x15, 0xb5, /* -82-2dBm */
> +	0x23, 0x15, 0xc5, /* -82-3dBm */
> +	0x33, 0x15, 0xc5, /* -78dBm */
> +	0x43, 0x15, 0xc5, /* -74dBm */
> +	0x53, 0x15, 0xc5, /* -70dBm */
> +	0x63, 0x15, 0xc5  /* -66dBm */
> +};
> +
> +void rtl8225z2_rf_init(struct ieee80211_hw *dev)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +	int i;
> +
> +	rtl8225_write(dev, 0x0, 0x2BF); mdelay(1);
> +	rtl8225_write(dev, 0x1, 0xEE0); mdelay(1);
> +	rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
> +	rtl8225_write(dev, 0x3, 0x441); mdelay(1);
> +	rtl8225_write(dev, 0x4, 0x8C3); mdelay(1);
> +	rtl8225_write(dev, 0x5, 0xC72); mdelay(1);
> +	rtl8225_write(dev, 0x6, 0x0E6); mdelay(1);
> +	rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
> +	rtl8225_write(dev, 0x8, 0x03F); mdelay(1);
> +	rtl8225_write(dev, 0x9, 0x335); mdelay(1);
> +	rtl8225_write(dev, 0xa, 0x9D4); mdelay(1);
> +	rtl8225_write(dev, 0xb, 0x7BB); mdelay(1);
> +	rtl8225_write(dev, 0xc, 0x850); mdelay(1);
> +	rtl8225_write(dev, 0xd, 0xCDF); mdelay(1);
> +	rtl8225_write(dev, 0xe, 0x02B); mdelay(1);
> +	rtl8225_write(dev, 0xf, 0x114); mdelay(100);
> +
> +	rtl8225_write(dev, 0x0, 0x1B7);
> +
> +	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
> +		rtl8225_write(dev, 0x1, i + 1);
> +		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
> +	}
> +
> +	rtl8225_write(dev, 0x3, 0x080);
> +	rtl8225_write(dev, 0x5, 0x004);
> +	rtl8225_write(dev, 0x0, 0x0B7);
> +	rtl8225_write(dev, 0x2, 0xc4D);
> +
> +	mdelay(200);
> +	rtl8225_write(dev, 0x2, 0x44D);
> +	mdelay(100);
> +
> +	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
> +		rtl8225_write(dev, 0x02, 0x0C4D);
> +		mdelay(200);
> +		rtl8225_write(dev, 0x02, 0x044D);
> +		mdelay(100);
> +		if (!(rtl8225_read(dev, 6) & (1 << 7)))
> +			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
> +			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
> +	}
> +
> +	mdelay(200);
> +
> +	rtl8225_write(dev, 0x0, 0x2BF);
> +
> +	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
> +		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
> +		mdelay(1);
> +		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
> +		mdelay(1);
> +	}
> +
> +	mdelay(1);
> +
> +	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
> +	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); //FIXME: not needed?
> +	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
> +	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
> +
> +	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
> +	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
> +	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
> +	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
> +
> +	rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
> +	rtl8225_write_phy_cck(dev, 0x19, 0x00);
> +	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
> +	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
> +	rtl8225_write_phy_cck(dev, 0x40, 0x86);
> +	rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x44, 0x36); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x45, 0x35); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x47, 0x25); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x49, 0x12); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
> +	rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
> +
> +	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); mdelay(1);
> +
> +	rtl8225z2_rf_set_tx_power(dev, 1);
> +
> +	/* RX antenna default to A */
> +	rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);	/* B: 0xDB */
> +	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);	/* B: 0x10 */
> +
> +	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
> +	mdelay(1);
> +	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
> +}
> +
> +void rtl8225_rf_stop(struct ieee80211_hw *dev)
> +{
> +	u8 reg;
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	rtl8225_write(dev, 0x4, 0x1f); mdelay(1);
> +
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
> +	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
> +	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
> +	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
> +	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
> +}
> +
> +void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
> +{
> +	struct rtl8187_priv *priv = dev->priv;
> +
> +	if (priv->rf_init == rtl8225_rf_init)
> +		rtl8225_rf_set_tx_power(dev, channel);
> +	else
> +		rtl8225z2_rf_set_tx_power(dev, channel);
> +
> +	rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
> +	mdelay(10);
> +}
> diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
> new file mode 100644
> index 0000000..ed28118
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
> @@ -0,0 +1,30 @@
> +#ifndef RTL8187_RTL8225_H
> +#define RTL8187_RTL8225_H
> +
> +#define RTL8225_ANAPARAM_ON	0xa0000a59
> +#define RTL8225_ANAPARAM2_ON	0x860c7312
> +#define RTL8225_ANAPARAM_OFF	0xa00beb59
> +#define RTL8225_ANAPARAM2_OFF	0x840dec11
> +
> +void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
> +u16  rtl8225_read(struct ieee80211_hw *, u8 addr);
> +
> +void rtl8225_rf_init(struct ieee80211_hw *);
> +void rtl8225z2_rf_init(struct ieee80211_hw *);
> +void rtl8225_rf_stop(struct ieee80211_hw *);
> +void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
> +
> +
> +static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
> +					  u8 addr, u32 data)
> +{
> +	rtl8187_write_phy(dev, addr, data);
> +}
> +
> +static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
> +					 u8 addr, u32 data)
> +{
> +	rtl8187_write_phy(dev, addr, data | 0x10000);
> +}
> +
> +#endif /* RTL8187_RTL8225_H */
> diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
> new file mode 100644
> index 0000000..e4ee946
> --- /dev/null
> +++ b/drivers/net/wireless/rtl818x/rtl818x.h
> @@ -0,0 +1,212 @@
> +#ifndef RTL818X_H
> +#define RTL818X_H
> +
> +struct rtl818x_csr {
> +	u8	MAC[6];
> +	u8	reserved_0[2];
> +	__le32	MAR[2];
> +	u8	RX_FIFO_COUNT;
> +	u8	reserved_1;
> +	u8	TX_FIFO_COUNT;
> +	u8	BQREQ;
> +	u8	reserved_2[4];
> +	__le32	TSFT[2];
> +	__le32	TLPDA;
> +	__le32	TNPDA;
> +	__le32	THPDA;
> +	__le16	BRSR;
> +	u8	BSSID[6];
> +	u8	RESP_RATE;
> +	u8	EIFS;
> +	u8	reserved_3[1];
> +	u8	CMD;
> +#define RTL818X_CMD_TX_ENABLE		(1 << 2)
> +#define RTL818X_CMD_RX_ENABLE		(1 << 3)
> +#define RTL818X_CMD_RESET		(1 << 4)
> +	u8	reserved_4[4];
> +	__le16	INT_MASK;
> +	__le16	INT_STATUS;
> +#define RTL818X_INT_RX_OK		(1 <<  0)
> +#define RTL818X_INT_RX_ERR		(1 <<  1)
> +#define RTL818X_INT_TXL_OK		(1 <<  2)
> +#define RTL818X_INT_TXL_ERR		(1 <<  3)
> +#define RTL818X_INT_RX_DU		(1 <<  4)
> +#define RTL818X_INT_RX_FO		(1 <<  5)
> +#define RTL818X_INT_TXN_OK		(1 <<  6)
> +#define RTL818X_INT_TXN_ERR		(1 <<  7)
> +#define RTL818X_INT_TXH_OK		(1 <<  8)
> +#define RTL818X_INT_TXH_ERR		(1 <<  9)
> +#define RTL818X_INT_TXB_OK		(1 << 10)
> +#define RTL818X_INT_TXB_ERR		(1 << 11)
> +#define RTL818X_INT_ATIM		(1 << 12)
> +#define RTL818X_INT_BEACON		(1 << 13)
> +#define RTL818X_INT_TIME_OUT		(1 << 14)
> +#define RTL818X_INT_TX_FO		(1 << 15)
> +	__le32	TX_CONF;
> +#define RTL818X_TX_CONF_LOOPBACK_MAC	(1 << 17)
> +#define RTL818X_TX_CONF_NO_ICV		(1 << 19)
> +#define RTL818X_TX_CONF_DISCW		(1 << 20)
> +#define RTL818X_TX_CONF_R8180_ABCD	(2 << 25)
> +#define RTL818X_TX_CONF_R8180_F		(3 << 25)
> +#define RTL818X_TX_CONF_R8185_ABC	(4 << 25)
> +#define RTL818X_TX_CONF_R8185_D		(5 << 25)
> +#define RTL818X_TX_CONF_HWVER_MASK	(7 << 25)
> +#define RTL818X_TX_CONF_CW_MIN		(1 << 31)
> +	__le32	RX_CONF;
> +#define RTL818X_RX_CONF_MONITOR		(1 <<  0)
> +#define RTL818X_RX_CONF_NICMAC		(1 <<  1)
> +#define RTL818X_RX_CONF_MULTICAST	(1 <<  2)
> +#define RTL818X_RX_CONF_BROADCAST	(1 <<  3)
> +#define RTL818X_RX_CONF_DATA		(1 << 18)
> +#define RTL818X_RX_CONF_CTRL		(1 << 19)
> +#define RTL818X_RX_CONF_MGMT		(1 << 20)
> +#define RTL818X_RX_CONF_BSSID		(1 << 23)
> +#define RTL818X_RX_CONF_RX_AUTORESETPHY	(1 << 28)
> +#define RTL818X_RX_CONF_ONLYERLPKT	(1 << 31)
> +	__le32	INT_TIMEOUT;
> +	__le32	TBDA;
> +	u8	EEPROM_CMD;
> +#define RTL818X_EEPROM_CMD_READ		(1 << 0)
> +#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
> +#define RTL818X_EEPROM_CMD_CK		(1 << 2)
> +#define RTL818X_EEPROM_CMD_CS		(1 << 3)
> +#define RTL818X_EEPROM_CMD_NORMAL	(0 << 6)
> +#define RTL818X_EEPROM_CMD_LOAD		(1 << 6)
> +#define RTL818X_EEPROM_CMD_PROGRAM	(2 << 6)
> +#define RTL818X_EEPROM_CMD_CONFIG	(3 << 6)
> +	u8	CONFIG0;
> +	u8	CONFIG1;
> +	u8	CONFIG2;
> +	__le32	ANAPARAM;
> +	u8	MSR;
> +#define RTL818X_MSR_NO_LINK		(0 << 2)
> +#define RTL818X_MSR_ADHOC		(1 << 2)
> +#define RTL818X_MSR_INFRA		(2 << 2)
> +	u8	CONFIG3;
> +#define RTL818X_CONFIG3_ANAPARAM_WRITE	(1 << 6)
> +	u8	CONFIG4;
> +#define RTL818X_CONFIG4_POWEROFF	(1 << 6)
> +#define RTL818X_CONFIG4_VCOOFF		(1 << 7)
> +	u8	TESTR;
> +	u8	reserved_9[2];
> +	__le16	PGSELECT;
> +	__le32	ANAPARAM2;
> +	u8	reserved_10[12];
> +	__le16	BEACON_INTERVAL;
> +	__le16	ATIM_WND;
> +	__le16	BEACON_INTERVAL_TIME;
> +	__le16	ATIMTR_INTERVAL;
> +	u8	reserved_11[4];
> +	u8	PHY[4];
> +	__le16	RFPinsOutput;
> +	__le16	RFPinsEnable;
> +	__le16	RFPinsSelect;
> +	__le16	RFPinsInput;
> +	__le32	RF_PARA;
> +	__le32	RF_TIMING;
> +	u8	GP_ENABLE;
> +	u8	GPIO;
> +	u8	reserved_12[10];
> +	u8	TX_AGC_CTL;
> +#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT		(1 << 0)
> +#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT	(1 << 1)
> +#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT			(1 << 2)
> +	u8	TX_GAIN_CCK;
> +	u8	TX_GAIN_OFDM;
> +	u8	TX_ANTENNA;
> +	u8	reserved_13[16];
> +	u8	WPA_CONF;
> +	u8	reserved_14[3];
> +	u8	SIFS;
> +	u8	DIFS;
> +	u8	SLOT;
> +	u8	reserved_15[5];
> +	u8	CW_CONF;
> +#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT	(1 << 0)
> +#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT	(1 << 1)
> +	u8	CW_VAL;
> +	u8	RATE_FALLBACK;
> +	u8	reserved_16[25];
> +	u8	CONFIG5;
> +	u8	TX_DMA_POLLING;
> +	u8	reserved_17[2];
> +	__le16	CWR;
> +	u8	RETRY_CTR;
> +	u8	reserved_18[5];
> +	__le32	RDSAR;
> +	u8	reserved_19[18];
> +	u16	TALLY_CNT;
> +	u8	TALLY_SEL;
> +} __attribute__((packed));
> +
> +static const struct ieee80211_rate rtl818x_rates[] = {
> +	{ .rate = 10,
> +	  .val = 0,
> +	  .flags = IEEE80211_RATE_CCK },
> +	{ .rate = 20,
> +	  .val = 1,
> +	  .flags = IEEE80211_RATE_CCK },
> +	{ .rate = 55,
> +	  .val = 2,
> +	  .flags = IEEE80211_RATE_CCK },
> +	{ .rate = 110,
> +	  .val = 3,
> +	  .flags = IEEE80211_RATE_CCK },
> +	{ .rate = 60,
> +	  .val = 4,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 90,
> +	  .val = 5,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 120,
> +	  .val = 6,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 180,
> +	  .val = 7,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 240,
> +	  .val = 8,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 360,
> +	  .val = 9,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 480,
> +	  .val = 10,
> +	  .flags = IEEE80211_RATE_OFDM },
> +	{ .rate = 540,
> +	  .val = 11,
> +	  .flags = IEEE80211_RATE_OFDM },
> +};
> +
> +static const struct ieee80211_channel rtl818x_channels[] = {
> +	{ .chan = 1,
> +	  .freq = 2412},
> +	{ .chan = 2,
> +	  .freq = 2417},
> +	{ .chan = 3,
> +	  .freq = 2422},
> +	{ .chan = 4,
> +	  .freq = 2427},
> +	{ .chan = 5,
> +	  .freq = 2432},
> +	{ .chan = 6,
> +	  .freq = 2437},
> +	{ .chan = 7,
> +	  .freq = 2442},
> +	{ .chan = 8,
> +	  .freq = 2447},
> +	{ .chan = 9,
> +	  .freq = 2452},
> +	{ .chan = 10,
> +	  .freq = 2457},
> +	{ .chan = 11,
> +	  .freq = 2462},
> +	{ .chan = 12,
> +	  .freq = 2467},
> +	{ .chan = 13,
> +	  .freq = 2472},
> +	{ .chan = 14,
> +	  .freq = 2484}
> +};
> +
> +#endif /* RTL818X_H */
> diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
> index e04cffc..8459549 100644
> --- a/drivers/net/wireless/zd1211rw/zd_usb.c
> +++ b/drivers/net/wireless/zd1211rw/zd_usb.c
> @@ -40,6 +40,7 @@ static struct usb_device_id usb_ids[] = {
>  	{ USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
>  	{ USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
>  	{ USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
> +	{ USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
>  	{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
>  	{ USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
>  	{ USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
> @@ -67,8 +68,11 @@ static struct usb_device_id usb_ids[] = {
>  	{ USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
>  	{ USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
>  	{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
> +	{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
> +	{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
>  	/* "Driverless" devices that need ejecting */
>  	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
> +	{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
>  	{}
>  };
>  
> diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
> new file mode 100644
> index 0000000..4b9be59
> --- /dev/null
> +++ b/include/linux/eeprom_93cx6.h
> @@ -0,0 +1,77 @@
> +/*
> +	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
> +	<http://rt2x00.serialmonkey.com>
> +
> +	This program is free software; you can redistribute it and/or modify
> +	it under the terms of the GNU General Public License as published by
> +	the Free Software Foundation; either version 2 of the License, or
> +	(at your option) any later version.
> +
> +	This program is distributed in the hope that it will be useful,
> +	but WITHOUT ANY WARRANTY; without even the implied warranty of
> +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +	GNU General Public License for more details.
> +
> +	You should have received a copy of the GNU General Public License
> +	along with this program; if not, write to the
> +	Free Software Foundation, Inc.,
> +	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +/*
> +	Module: eeprom_93cx6
> +	Abstract: EEPROM reader datastructures for 93cx6 chipsets.
> +	Supported chipsets: 93c46 & 93c66.
> + */
> +
> +/*
> + * EEPROM operation defines.
> + */
> +#define PCI_EEPROM_WIDTH_93C46	6
> +#define PCI_EEPROM_WIDTH_93C66	8
> +#define PCI_EEPROM_WIDTH_OPCODE	3
> +#define PCI_EEPROM_WRITE_OPCODE	0x05
> +#define PCI_EEPROM_READ_OPCODE	0x06
> +#define PCI_EEPROM_EWDS_OPCODE	0x10
> +#define PCI_EEPROM_EWEN_OPCODE	0x13
> +
> +/**
> + * struct eeprom_93cx6 - control structure for setting the commands
> + * for reading the eeprom data.
> + * @data: private pointer for the driver.
> + * @register_read(struct eeprom_93cx6 *eeprom): handler to
> + * read the eeprom register, this function should set all reg_* fields.
> + * @register_write(struct eeprom_93cx6 *eeprom): handler to
> + * write to the eeprom register by using all reg_* fields.
> + * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
> + * @reg_data_in: register field to indicate data input
> + * @reg_data_out: register field to indicate data output
> + * @reg_data_clock: register field to set the data clock
> + * @reg_chip_select: register field to set the chip select
> + *
> + * This structure is used for the communication between the driver
> + * and the eeprom_93cx6 handlers for reading the eeprom.
> + */
> +struct eeprom_93cx6 {
> +	void *data;
> +
> +	void (*register_read)(struct eeprom_93cx6 *eeprom);
> +	void (*register_write)(struct eeprom_93cx6 *eeprom);
> +
> +	int width;
> +
> +	char reg_data_in;
> +	char reg_data_out;
> +	char reg_data_clock;
> +	char reg_chip_select;
> +};
> +
> +extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
> +	const u8 word, u16 *data);
> +extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
> +	const u8 word, __le16 *data, const u16 words);
> +
> +extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom,
> +	const u8 word, u16 data);
> +extern void eeprom_93cx6_multiwrite(struct eeprom_93cx6 *eeprom,
> +	const u8 word, __le16 *data, const u16 words);
> diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
> index d56b292..bbd85cd 100644
> --- a/include/net/ieee80211.h
> +++ b/include/net/ieee80211.h
> @@ -1291,6 +1291,8 @@ extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
>  extern const struct ieee80211_channel *ieee80211_get_channel(struct
>  							     ieee80211_device
>  							     *ieee, u8 channel);
> +extern u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee,
> +				      u8 channel);
>  
>  /* ieee80211_wx.c */
>  extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
> diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
> index 305a09d..960ad13 100644
> --- a/net/ieee80211/ieee80211_geo.c
> +++ b/net/ieee80211/ieee80211_geo.c
> @@ -94,6 +94,21 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
>  	return -1;
>  }
>  
> +u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel)
> +{
> +	const struct ieee80211_channel * ch;
> +
> +	/* Driver needs to initialize the geography map before using
> +	 * these helper functions */
> +	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
> +		return 0;
> +
> +	ch = ieee80211_get_channel(ieee, channel);
> +	if (!ch->channel)
> +		return 0;
> +	return ch->freq;
> +}
> +
>  u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
>  {
>  	int i;
> @@ -174,6 +189,7 @@ EXPORT_SYMBOL(ieee80211_get_channel);
>  EXPORT_SYMBOL(ieee80211_get_channel_flags);
>  EXPORT_SYMBOL(ieee80211_is_valid_channel);
>  EXPORT_SYMBOL(ieee80211_freq_to_channel);
> +EXPORT_SYMBOL(ieee80211_channel_to_freq);
>  EXPORT_SYMBOL(ieee80211_channel_to_index);
>  EXPORT_SYMBOL(ieee80211_set_geo);
>  EXPORT_SYMBOL(ieee80211_get_geo);
> diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
> index cee5e13..523a137 100644
> --- a/net/ieee80211/ieee80211_wx.c
> +++ b/net/ieee80211/ieee80211_wx.c
> @@ -89,15 +89,17 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
>  		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
>  	}
>  
> -	/* Add frequency/channel */
> +	/* Add channel and frequency */
>  	iwe.cmd = SIOCGIWFREQ;
> -/*	iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
> -	iwe.u.freq.e = 3; */
>  	iwe.u.freq.m = network->channel;
>  	iwe.u.freq.e = 0;
>  	iwe.u.freq.i = 0;
>  	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
>  
> +	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
> +	iwe.u.freq.e = 6;
> +	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
> +
>  	/* Add encryption capability */
>  	iwe.cmd = SIOCGIWENCODE;
>  	if (network->capability & WLAN_CAPABILITY_PRIVACY)
> diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
> index 822917d..3e07e9d 100644
> --- a/net/mac80211/ieee80211_sta.c
> +++ b/net/mac80211/ieee80211_sta.c
> @@ -17,6 +17,7 @@
>   * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
>   *    SSID)
>   */
> +#include <linux/delay.h>
>  #include <linux/if_ether.h>
>  #include <linux/skbuff.h>
>  #include <linux/netdevice.h>
> @@ -27,7 +28,6 @@
>  #include <linux/rtnetlink.h>
>  #include <net/iw_handler.h>
>  #include <asm/types.h>
> -#include <asm/delay.h>
>  
>  #include <net/mac80211.h>
>  #include "ieee80211_i.h"


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 21:15 ` Dan Williams
@ 2007-05-07 22:51   ` John W. Linville
  2007-05-08  8:49   ` Johannes Berg
  1 sibling, 0 replies; 27+ messages in thread
From: John W. Linville @ 2007-05-07 22:51 UTC (permalink / raw)
  To: Dan Williams; +Cc: jeff, linux-wireless, netdev

On Mon, May 07, 2007 at 05:15:50PM -0400, Dan Williams wrote:
> On Mon, 2007-05-07 at 13:51 -0400, John W. Linville wrote:

> > John W. Linville (1):
> >       libertas: fix for wireless Kconfig changes
> 
> So the kconfig changes with s/NET_RADIO/NET_80211 (or whatever it was)
> are in for 2.6.22?  Or is that for 2.6.23?

My hope/intent is for Jeff to pull and pass this along in time for 2.6.22.

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 17:51 John W. Linville
  2007-05-07 21:15 ` Dan Williams
@ 2007-05-07 23:09 ` Jeff Garzik
  2007-05-07 23:30   ` Michael Wu
  2007-05-07 23:38   ` John W. Linville
  2007-05-08 17:38 ` John W. Linville
  2 siblings, 2 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-05-07 23:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, netdev

John W. Linville wrote:
> The following changes since commit 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37:
>   Linus Torvalds (1):
>         Merge git://git.kernel.org/.../sam/kbuild
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (1):
>       zd1211rw: Add ID for ZyXEL AG-225H v2
> 
> Geert Uytterhoeven (1):
>       mac80211: include <linux/delay.h> instead of <asm/delay.h>
> 
> Ivo van Doorn (1):
>       Add 93cx6 eeprom library
> 
> John W. Linville (1):
>       libertas: fix for wireless Kconfig changes
> 
> Larry Finger (3):
>       ieee80211: add ieee80211_channel_to_freq
>       ieee80211: include frequency in scan results
>       bcm43xx: Remove dead configuration variable CONFIG_947XX
> 
> Matthew Davidson (1):
>       zd1211rw: Add ID for Sitecom WL-117
> 
> Michael Wu (1):
>       Add rtl8187 wireless driver
> 
> Ulrich Kunitz (1):
>       zd1211rw: Added new USB id for Planex GW-US54ZGL


The normal development process is:

* commit new code to your repository
* that goes into -mm for public testing and review
* merge window opens
* the code that has seen public testing and review goes upstream

The general idea is everything you want in 2.6.22 should be prepared and 
in -mm BEFORE 2.6.21 is released, and the 2.6.22 merge window opens.

It's quite normal for fixes and minor changes to trickle in after the 
push that follows the merge window opening.  But new drivers that have 
not been through this process do not fall under "fixes and minor changes."

I also did not see any response to my "better as a single file driver" 
suggestion.

So, I'll pull if you remove the two late additions.

	Jeff



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 23:09 ` Jeff Garzik
@ 2007-05-07 23:30   ` Michael Wu
  2007-05-07 23:38   ` John W. Linville
  1 sibling, 0 replies; 27+ messages in thread
From: Michael Wu @ 2007-05-07 23:30 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: John W. Linville, linux-wireless, netdev

[-- Attachment #1: Type: text/plain, Size: 255 bytes --]

On Monday 07 May 2007 19:09, Jeff Garzik wrote:
> The general idea is everything you want in 2.6.22 should be prepared and
> in -mm BEFORE 2.6.21 is released, and the 2.6.22 merge window opens.
>
rtl8187 has been in -mm since 2.6.21-rc2-mm1.

-Michael Wu

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 23:09 ` Jeff Garzik
  2007-05-07 23:30   ` Michael Wu
@ 2007-05-07 23:38   ` John W. Linville
  1 sibling, 0 replies; 27+ messages in thread
From: John W. Linville @ 2007-05-07 23:38 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-wireless, netdev

On Mon, May 07, 2007 at 07:09:20PM -0400, Jeff Garzik wrote:
> John W. Linville wrote:

> >Ivo van Doorn (1):
> >      Add 93cx6 eeprom library

> >Michael Wu (1):
> >      Add rtl8187 wireless driver

I presume these are the two parts you question.  (Just checking...)

> The normal development process is:
> 
> * commit new code to your repository
> * that goes into -mm for public testing and review
> * merge window opens
> * the code that has seen public testing and review goes upstream
> 
> The general idea is everything you want in 2.6.22 should be prepared and 
> in -mm BEFORE 2.6.21 is released, and the 2.6.22 merge window opens.
> 
> It's quite normal for fixes and minor changes to trickle in after the 
> push that follows the merge window opening.  But new drivers that have 
> not been through this process do not fall under "fixes and minor changes."
 
I agree whole-heartedly.

The whole mac80211 driver package (including rtl8187) has been in -mm
(and rawhide) for most of the 2.6.21 development cycle.  The rtl8187
driver in particular has been relatively stable for the past couple
of months ("3 files changed, 13 insertions(+), 4 deletions(-)" since
7 March 2007), and it seems to work well.

> I also did not see any response to my "better as a single file driver" 
> suggestion.

Yes, I see that now.  Do you consider this a merge requirement?

My main concern pre-merge would be accidentally destabilizing the code
while stitching the files together.  Other than that, the suggestion
seems worthwhile.  However, I think Michael plans to expand the driver
to support rtl8180 and rtl8185.  This may factor into why he chose
to organize the code the way he has.

> So, I'll pull if you remove the two late additions.

Any chance that you find the comments above persuasive? :-)

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 21:15 ` Dan Williams
  2007-05-07 22:51   ` John W. Linville
@ 2007-05-08  8:49   ` Johannes Berg
  1 sibling, 0 replies; 27+ messages in thread
From: Johannes Berg @ 2007-05-08  8:49 UTC (permalink / raw)
  To: Dan Williams; +Cc: John W. Linville, jeff, linux-wireless, netdev

[-- Attachment #1: Type: text/plain, Size: 310 bytes --]

On Mon, 2007-05-07 at 17:15 -0400, Dan Williams wrote:

> So the kconfig changes with s/NET_RADIO/NET_80211 (or whatever it was)
> are in for 2.6.22?  Or is that for 2.6.23?

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=2a5e1c0eb9efe26eed1dd072fe08de5797a7efd5

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-07 17:51 John W. Linville
  2007-05-07 21:15 ` Dan Williams
  2007-05-07 23:09 ` Jeff Garzik
@ 2007-05-08 17:38 ` John W. Linville
  2 siblings, 0 replies; 27+ messages in thread
From: John W. Linville @ 2007-05-08 17:38 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless, netdev

This request is withdrawn.  New request to follow.

On Mon, May 07, 2007 at 01:51:21PM -0400, John W. Linville wrote:
> The following changes since commit 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37:
>   Linus Torvalds (1):
>         Merge git://git.kernel.org/.../sam/kbuild
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (1):
>       zd1211rw: Add ID for ZyXEL AG-225H v2
> 
> Geert Uytterhoeven (1):
>       mac80211: include <linux/delay.h> instead of <asm/delay.h>
> 
> Ivo van Doorn (1):
>       Add 93cx6 eeprom library
> 
> John W. Linville (1):
>       libertas: fix for wireless Kconfig changes
> 
> Larry Finger (3):
>       ieee80211: add ieee80211_channel_to_freq
>       ieee80211: include frequency in scan results
>       bcm43xx: Remove dead configuration variable CONFIG_947XX
> 
> Matthew Davidson (1):
>       zd1211rw: Add ID for Sitecom WL-117
> 
> Michael Wu (1):
>       Add rtl8187 wireless driver
> 
> Ulrich Kunitz (1):
>       zd1211rw: Added new USB id for Planex GW-US54ZGL

-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
@ 2007-05-08 17:39 John W. Linville
  2007-05-09 22:54 ` Jeff Garzik
  0 siblings, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-05-08 17:39 UTC (permalink / raw)
  To: jeff; +Cc: netdev, linux-wireless

The following changes since commit 5b94f675f57e4ff16c8fda09088d7480a84dcd91:
  Linus Torvalds (1):
        Merge master.kernel.org:/.../davem/sparc-2.6

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Daniel Drake (1):
      zd1211rw: Add ID for ZyXEL AG-225H v2

Larry Finger (3):
      ieee80211: add ieee80211_channel_to_freq
      ieee80211: include frequency in scan results
      bcm43xx: Remove dead configuration variable CONFIG_947XX

Matthew Davidson (1):
      zd1211rw: Add ID for Sitecom WL-117

Ulrich Kunitz (1):
      zd1211rw: Added new USB id for Planex GW-US54ZGL

 drivers/net/wireless/bcm43xx/bcm43xx.h      |   18 +-----
 drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |    4 -
 drivers/net/wireless/bcm43xx/bcm43xx_main.c |   81 ---------------------------
 drivers/net/wireless/bcm43xx/bcm43xx_main.h |   19 ------
 drivers/net/wireless/zd1211rw/zd_usb.c      |    4 +
 include/net/ieee80211.h                     |    2 +
 net/ieee80211/ieee80211_geo.c               |   16 +++++
 net/ieee80211/ieee80211_wx.c                |    8 ++-
 8 files changed, 31 insertions(+), 121 deletions(-)

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index f8483c1..10e07e8 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -658,12 +658,6 @@ struct bcm43xx_pio {
 
 #define BCM43xx_MAX_80211_CORES		2
 
-#ifdef CONFIG_BCM947XX
-#define core_offset(bcm) (bcm)->current_core_offset
-#else
-#define core_offset(bcm) 0
-#endif
-
 /* Generic information about a core. */
 struct bcm43xx_coreinfo {
 	u8 available:1,
@@ -789,10 +783,6 @@ struct bcm43xx_private {
 
 	/* The currently active core. */
 	struct bcm43xx_coreinfo *current_core;
-#ifdef CONFIG_BCM947XX
-	/** current core memory offset */
-	u32 current_core_offset;
-#endif
 	struct bcm43xx_coreinfo *active_80211_core;
 	/* coreinfo structs for all possible cores follow.
 	 * Note that a core might not exist.
@@ -943,25 +933,25 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
 static inline
 u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread16(bcm->mmio_addr + offset);
 }
 
 static inline
 void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
 {
-	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite16(value, bcm->mmio_addr + offset);
 }
 
 static inline
 u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread32(bcm->mmio_addr + offset);
 }
 
 static inline
 void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
 {
-	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite32(value, bcm->mmio_addr + offset);
 }
 
 static inline
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index e3d2e61..1f7731f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -660,10 +660,6 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
 	ring->routing = BCM43xx_DMA32_CLIENTTRANS;
 	if (dma64)
 		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
-		ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS;
-#endif
 
 	ring->bcm = bcm;
 	ring->nr_slots = nr_slots;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 5e96bca..ef6b253 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -61,10 +61,6 @@ MODULE_AUTHOR("Stefano Brivio");
 MODULE_AUTHOR("Michael Buesch");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_BCM947XX
-extern char *nvram_get(char *name);
-#endif
-
 #if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
 static int modparam_pio;
 module_param_named(pio, modparam_pio, int, 0444);
@@ -142,10 +138,6 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple fi
 	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 43XG 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#ifdef CONFIG_BCM947XX
-	/* SB bus on BCM947xx */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
@@ -786,9 +778,6 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 {
 	u16 value;
 	u16 *sprom;
-#ifdef CONFIG_BCM947XX
-	char *c;
-#endif
 
 	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
 			GFP_KERNEL);
@@ -796,28 +785,7 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 		printk(KERN_ERR PFX "sprom_extract OOM\n");
 		return -ENOMEM;
 	}
-#ifdef CONFIG_BCM947XX
-	sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
-	sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
-
-	if ((c = nvram_get("il0macaddr")) != NULL)
-		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
-
-	if ((c = nvram_get("et1macaddr")) != NULL)
-		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
-
-	sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
-	sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
-	sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
-
-	sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
-	sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
-	sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
-
-	sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
-#else
 	bcm43xx_sprom_read(bcm, sprom);
-#endif
 
 	/* boardflags2 */
 	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
@@ -1225,12 +1193,6 @@ static int _switch_core(struct bcm43xx_private *bcm, int core)
 			goto error;
 		udelay(10);
 	}
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
-		bcm->current_core_offset = 0x1000 * core;
-	else
-		bcm->current_core_offset = 0;
-#endif
 
 	return 0;
 error:
@@ -1387,19 +1349,6 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
 
 	if ((bcm43xx_core_enabled(bcm)) &&
 	    !bcm43xx_using_pio(bcm)) {
-//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
-#if 0
-#ifndef CONFIG_BCM947XX
-		/* reset all used DMA controllers. */
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
-		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
-		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
-		if (bcm->current_core->rev < 5)
-			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
-#endif
-#endif
 	}
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
@@ -2140,32 +2089,11 @@ out:
 	return err;
 }
 
-#ifdef CONFIG_BCM947XX
-static struct pci_device_id bcm43xx_47xx_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
-	{ 0 }
-};
-#endif
-
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
 {
 	int err;
 
 	bcm->irq = bcm->pci_dev->irq;
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0) {
-		struct pci_dev *d;
-		struct pci_device_id *id;
-		for (id = bcm43xx_47xx_ids; id->vendor; id++) {
-			d = pci_get_device(id->vendor, id->device, NULL);
-			if (d != NULL) {
-				bcm->irq = d->irq;
-				pci_dev_put(d);
-				break;
-			}
-		}
-	}
-#endif
 	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
 			  IRQF_SHARED, KBUILD_MODNAME, bcm);
 	if (err)
@@ -2645,10 +2573,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
 			chip_id_16 = 0x4610;
 		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
 			chip_id_16 = 0x4710;
-#ifdef CONFIG_BCM947XX
-		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
-			chip_id_16 = 0x4309;
-#endif
 		else {
 			printk(KERN_ERR PFX "Could not determine Chip ID\n");
 			return -ENODEV;
@@ -4144,11 +4068,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
 	struct bcm43xx_private *bcm;
 	int err;
 
-#ifdef CONFIG_BCM947XX
-	if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
-		return -ENODEV;
-#endif
-
 #ifdef DEBUG_SINGLE_DEVICE_ONLY
 	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
 		return -ENODEV;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index f763571..c8f3c53 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -33,25 +33,6 @@
 
 #include "bcm43xx.h"
 
-#ifdef CONFIG_BCM947XX
-#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
-
-static inline void e_aton(char *str, char *dest)
-{
-	int i = 0;
-	u16 *d = (u16 *) dest;
-
-	for (;;) {
-		dest[i++] = (char) simple_strtoul(str, NULL, 16);
-		str += 2;
-		if (!*str++ || i == 6)
-			break;
-	}
-	for (i = 0; i < 3; i++)
-		d[i] = cpu_to_be16(d[i]);
-}
-#endif
-
 #define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
 #define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
 /* Magic helper macro to pad structures. Ignore those above. It's magic. */
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index e04cffc..8459549 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -40,6 +40,7 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
@@ -67,8 +68,11 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
 	/* "Driverless" devices that need ejecting */
 	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
+	{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
 	{}
 };
 
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index d56b292..bbd85cd 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1291,6 +1291,8 @@ extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
 extern const struct ieee80211_channel *ieee80211_get_channel(struct
 							     ieee80211_device
 							     *ieee, u8 channel);
+extern u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee,
+				      u8 channel);
 
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
index 305a09d..960ad13 100644
--- a/net/ieee80211/ieee80211_geo.c
+++ b/net/ieee80211/ieee80211_geo.c
@@ -94,6 +94,21 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
 	return -1;
 }
 
+u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel)
+{
+	const struct ieee80211_channel * ch;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+		return 0;
+
+	ch = ieee80211_get_channel(ieee, channel);
+	if (!ch->channel)
+		return 0;
+	return ch->freq;
+}
+
 u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
 {
 	int i;
@@ -174,6 +189,7 @@ EXPORT_SYMBOL(ieee80211_get_channel);
 EXPORT_SYMBOL(ieee80211_get_channel_flags);
 EXPORT_SYMBOL(ieee80211_is_valid_channel);
 EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_freq);
 EXPORT_SYMBOL(ieee80211_channel_to_index);
 EXPORT_SYMBOL(ieee80211_set_geo);
 EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index cee5e13..523a137 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -89,15 +89,17 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
 		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
 	}
 
-	/* Add frequency/channel */
+	/* Add channel and frequency */
 	iwe.cmd = SIOCGIWFREQ;
-/*	iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
-	iwe.u.freq.e = 3; */
 	iwe.u.freq.m = network->channel;
 	iwe.u.freq.e = 0;
 	iwe.u.freq.i = 0;
 	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
 
+	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
+	iwe.u.freq.e = 6;
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+
 	/* Add encryption capability */
 	iwe.cmd = SIOCGIWENCODE;
 	if (network->capability & WLAN_CAPABILITY_PRIVACY)
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-08 17:39 Please pull 'upstream' " John W. Linville
@ 2007-05-09 22:54 ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-05-09 22:54 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev, linux-wireless

John W. Linville wrote:
> The following changes since commit 5b94f675f57e4ff16c8fda09088d7480a84dcd91:
>   Linus Torvalds (1):
>         Merge master.kernel.org:/.../davem/sparc-2.6
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Daniel Drake (1):
>       zd1211rw: Add ID for ZyXEL AG-225H v2
> 
> Larry Finger (3):
>       ieee80211: add ieee80211_channel_to_freq
>       ieee80211: include frequency in scan results
>       bcm43xx: Remove dead configuration variable CONFIG_947XX
> 
> Matthew Davidson (1):
>       zd1211rw: Add ID for Sitecom WL-117
> 
> Ulrich Kunitz (1):
>       zd1211rw: Added new USB id for Planex GW-US54ZGL
> 
>  drivers/net/wireless/bcm43xx/bcm43xx.h      |   18 +-----
>  drivers/net/wireless/bcm43xx/bcm43xx_dma.c  |    4 -
>  drivers/net/wireless/bcm43xx/bcm43xx_main.c |   81 ---------------------------
>  drivers/net/wireless/bcm43xx/bcm43xx_main.h |   19 ------
>  drivers/net/wireless/zd1211rw/zd_usb.c      |    4 +
>  include/net/ieee80211.h                     |    2 +
>  net/ieee80211/ieee80211_geo.c               |   16 +++++
>  net/ieee80211/ieee80211_wx.c                |    8 ++-
>  8 files changed, 31 insertions(+), 121 deletions(-)

pulled



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Please pull 'upstream-fixes' branch of wireless-2.6
@ 2007-05-29 18:30 John W. Linville
  2007-05-29 18:31 ` Please pull 'upstream' " John W. Linville
  2007-05-30 13:46 ` Please pull 'upstream-fixes' " Jeff Garzik
  0 siblings, 2 replies; 27+ messages in thread
From: John W. Linville @ 2007-05-29 18:30 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless, netdev

The following changes since commit c420bc9f09a0926b708c3edb27eacba434a4=
f4ba:
  Linus Torvalds (1):
        Linux 2.6.22-rc3

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.g=
it upstream-fixes

Akinobu Mita (2):
      ieee80211: fix incomplete error message
      softmac: alloc_ieee80211() NULL check

Bj=F6rn Steinbrink (1):
      prism54: fix monitor mode oops

Brandon Craig Rhodes (1):
      hostap: Allocate enough tailroom for TKIP

 drivers/net/wireless/hostap/hostap_80211_tx.c   |   13 ++++++++-----
 drivers/net/wireless/prism54/islpci_eth.c       |    5 +++--
 net/ieee80211/ieee80211_module.c                |    2 +-
 net/ieee80211/softmac/ieee80211softmac_module.c |    5 ++++-
 4 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/ne=
t/wireless/hostap/hostap_80211_tx.c
index 246fac0..3df3c60 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -311,7 +311,7 @@ static struct sk_buff * hostap_tx_encrypt(struct sk=
_buff *skb,
 	local_info_t *local;
 	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
-	int hdr_len, res;
+	int prefix_len, postfix_len, hdr_len, res;
=20
 	iface =3D netdev_priv(skb->dev);
 	local =3D iface->local;
@@ -337,10 +337,13 @@ static struct sk_buff * hostap_tx_encrypt(struct =
sk_buff *skb,
 	if (skb =3D=3D NULL)
 		return NULL;
=20
-	if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
-	     skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
-	    pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
-			     crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
+	prefix_len =3D crypt->ops->extra_mpdu_prefix_len +
+		crypt->ops->extra_msdu_prefix_len;
+	postfix_len =3D crypt->ops->extra_mpdu_postfix_len +
+		crypt->ops->extra_msdu_postfix_len;
+	if ((skb_headroom(skb) < prefix_len ||
+	     skb_tailroom(skb) < postfix_len) &&
+	    pskb_expand_head(skb, prefix_len, postfix_len, GFP_ATOMIC)) {
 		kfree_skb(skb);
 		return NULL;
 	}
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wi=
reless/prism54/islpci_eth.c
index dd070cc..f49eb06 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -378,9 +378,10 @@ islpci_eth_receive(islpci_private *priv)
 	display_buffer((char *) skb->data, skb->len);
 #endif
 	/* take care of monitor mode and spy monitoring. */
-	if (unlikely(priv->iw_mode =3D=3D IW_MODE_MONITOR))
+	if (unlikely(priv->iw_mode =3D=3D IW_MODE_MONITOR)) {
+		skb->dev =3D ndev;
 		discard =3D islpci_monitor_rx(priv, &skb);
-	else {
+	} else {
 		if (unlikely(skb->data[2 * ETH_ALEN] =3D=3D 0)) {
 			/* The packet has a rx_annex. Read it for spy monitoring, Then
 			 * remove it, while keeping the 2 leading MAC addr.
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211=
_module.c
index 7ec6610..17ad278 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -140,7 +140,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
=20
 	dev =3D alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv)=
;
 	if (!dev) {
-		IEEE80211_ERROR("Unable to network device.\n");
+		IEEE80211_ERROR("Unable to allocate network device.\n");
 		goto failed;
 	}
 	ieee =3D netdev_priv(dev);
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee=
80211/softmac/ieee80211softmac_module.c
index e9cdc66..c308756 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -33,7 +33,10 @@ struct net_device *alloc_ieee80211softmac(int sizeof=
_priv)
 	struct ieee80211softmac_device *softmac;
 	struct net_device *dev;
=20
-	dev =3D alloc_ieee80211(sizeof(struct ieee80211softmac_device) + size=
of_priv);
+	dev =3D alloc_ieee80211(sizeof(*softmac) + sizeof_priv);
+	if (!dev)
+		return NULL;
+
 	softmac =3D ieee80211_priv(dev);
 	softmac->dev =3D dev;
 	softmac->ieee =3D netdev_priv(dev);
--=20
John W. Linville
linville@tuxdriver.com
-
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Please pull 'upstream' branch of wireless-2.6
  2007-05-29 18:30 Please pull 'upstream-fixes' branch of wireless-2.6 John W. Linville
@ 2007-05-29 18:31 ` John W. Linville
  2007-05-30 14:03   ` Jeff Garzik
  2007-05-30 13:46 ` Please pull 'upstream-fixes' " Jeff Garzik
  1 sibling, 1 reply; 27+ messages in thread
From: John W. Linville @ 2007-05-29 18:31 UTC (permalink / raw)
  To: jeff; +Cc: linux-wireless, netdev

The following changes since commit d7ea3be56adc95b17351221fd95e78115f3b01f4:
  Brandon Craig Rhodes (1):
        hostap: Allocate enough tailroom for TKIP

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Akinobu Mita (1):
      softmac: use list_for_each_entry

Daniel Drake (4):
      zd1211rw: Add ID for ZyXEL G-200v2
      zd1211rw: Extend RF layer
      zd1211rw: Add UW2453 RF support
      zd1211rw: Make CCK gain patching conditional on RF type

Jouni Malinen (1):
      hostap: Remove driver version number

Larry Finger (1):
      bcm43xx: Fix deviation from specifications in set_baseband_attenuation

Matthias Kaehlcke (1):
      hostap: Use list_for_each_entry

Pavel Roskin (1):
      hostap: Suppress broadcast if no stations are associated

 drivers/net/wireless/bcm43xx/bcm43xx_phy.c      |    2 +-
 drivers/net/wireless/hostap/hostap_ap.c         |   34 +-
 drivers/net/wireless/hostap/hostap_config.h     |    2 -
 drivers/net/wireless/hostap/hostap_cs.c         |    4 -
 drivers/net/wireless/hostap/hostap_ioctl.c      |    2 -
 drivers/net/wireless/hostap/hostap_main.c       |    1 -
 drivers/net/wireless/hostap/hostap_pci.c        |    5 -
 drivers/net/wireless/hostap/hostap_plx.c        |    5 -
 drivers/net/wireless/zd1211rw/Makefile          |    2 +-
 drivers/net/wireless/zd1211rw/zd_chip.c         |    5 +-
 drivers/net/wireless/zd1211rw/zd_chip.h         |    3 +
 drivers/net/wireless/zd1211rw/zd_rf.c           |   21 +-
 drivers/net/wireless/zd1211rw/zd_rf.h           |   28 ++
 drivers/net/wireless/zd1211rw/zd_rf_al2230.c    |    1 +
 drivers/net/wireless/zd1211rw/zd_rf_al7230b.c   |    1 +
 drivers/net/wireless/zd1211rw/zd_rf_uw2453.c    |  534 +++++++++++++++++++++++
 drivers/net/wireless/zd1211rw/zd_usb.c          |    1 +
 net/ieee80211/softmac/ieee80211softmac_module.c |   32 +-
 18 files changed, 611 insertions(+), 72 deletions(-)
 create mode 100644 drivers/net/wireless/zd1211rw/zd_rf_uw2453.c

diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e3..d779199 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
 		return;
 	}
 
-	if (phy->analog > 1) {
+	if (phy->analog == 1) {
 		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
 		value |= (baseband_attenuation << 2) & 0x003C;
 	} else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd5..9090052 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
 	char *policy_txt;
-	struct list_head *ptr;
 	struct mac_entry *entry;
 
 	if (off != 0) {
@@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
 	p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
 	p += sprintf(p, "MAC list:\n");
 	spin_lock_bh(&ap->mac_restrictions.lock);
-	for (ptr = ap->mac_restrictions.mac_list.next;
-	     ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+	list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
 		if (p - page > PAGE_SIZE - 80) {
 			p += sprintf(p, "All entries did not fit one page.\n");
 			break;
 		}
 
-		entry = list_entry(ptr, struct mac_entry, list);
 		p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
 	}
 	spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
 static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
 			       u8 *mac)
 {
-	struct list_head *ptr;
 	struct mac_entry *entry;
 	int found = 0;
 
@@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
 		return 0;
 
 	spin_lock_bh(&mac_restrictions->lock);
-	for (ptr = mac_restrictions->mac_list.next;
-	     ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, list);
-
+	list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
 		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
 			found = 1;
 			break;
@@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
 {
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
-	struct list_head *ptr;
+	struct sta_info *sta;
 	int i;
 
 	if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
 
 	p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
-
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (!sta->ap)
 			continue;
 
@@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
 
 void hostap_free_data(struct ap_data *ap)
 {
-	struct list_head *n, *ptr;
+	struct sta_info *n, *sta;
 
 	if (ap == NULL || !ap->initialized) {
 		printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
 	ap->crypt = ap->crypt_priv = NULL;
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-	list_for_each_safe(ptr, n, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
 		ap_sta_hash_del(ap, sta);
 		list_del(&sta->list);
 		if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
 
 	if (hdr->addr1[0] & 0x01) {
 		/* broadcast/multicast frame - no AP related processing */
+		if (local->ap->num_sta <= 0)
+			ret = AP_TX_DROP;
 		goto out;
 	}
 
@@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
 
 void hostap_update_rates(local_info_t *local)
 {
-	struct list_head *ptr;
+	struct sta_info *sta;
 	struct ap_data *ap = local->ap;
 
 	if (!ap)
 		return;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		prism2_check_tx_rates(sta);
 	}
 	spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
 void hostap_add_wds_links(local_info_t *local)
 {
 	struct ap_data *ap = local->ap;
-	struct list_head *ptr;
+	struct sta_info *sta;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	list_for_each(ptr, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (sta->ap)
 			hostap_wds_link_oper(local, sta->addr, WDS_ADD);
 	}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5a..30acd39 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
 #ifndef HOSTAP_CONFIG_H
 #define HOSTAP_CONFIG_H
 
-#define PRISM2_VERSION "0.4.4-kernel"
-
 /* In the previous versions of Host AP driver, support for user space version
  * of IEEE 802.11 management (hostapd) used to be disabled in the default
  * configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b..30e723f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static dev_info_t dev_info = "hostap_cs";
 
 MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
 		   "cards (PC Card).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis_vcc;
@@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
 
 static int __init init_prism2_pccard(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
 	return pcmcia_register_driver(&hostap_driver);
 }
 
 static void __exit exit_prism2_pccard(void)
 {
 	pcmcia_unregister_driver(&hostap_driver);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f7..8c71077 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
 	local = iface->local;
 
 	strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
-	strncpy(info->version, PRISM2_VERSION,
-		sizeof(info->version) - 1);
 	snprintf(info->fw_version, sizeof(info->fw_version) - 1,
 		 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
 		 (local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426..446de51 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Host AP common routines");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 #define TX_TIMEOUT (2 * HZ)
 
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899e..0cd48d1 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_pci";
 
 
@@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
 		   "PCI cards.");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 /* struct local_info::hw_priv */
@@ -462,8 +460,6 @@ static struct pci_driver prism2_pci_drv_id = {
 
 static int __init init_prism2_pci(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_pci_drv_id);
 }
 
@@ -471,7 +467,6 @@ static int __init init_prism2_pci(void)
 static void __exit exit_prism2_pci(void)
 {
 	pci_unregister_driver(&prism2_pci_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ec..0183df7 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_plx";
 
 
@@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
 		   "cards (PLX).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis;
@@ -623,8 +621,6 @@ static struct pci_driver prism2_plx_drv_id = {
 
 static int __init init_prism2_plx(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_plx_drv_id);
 }
 
@@ -632,7 +628,6 @@ static int __init init_prism2_plx(void)
 static void __exit exit_prism2_plx(void)
 {
 	pci_unregister_driver(&prism2_plx_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5..4d50590 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
 zd1211rw-objs := zd_chip.o zd_ieee80211.o \
 		zd_mac.o zd_netdev.o \
 		zd_rf_al2230.o zd_rf_rf2959.o \
-		zd_rf_al7230b.o \
+		zd_rf_al7230b.o zd_rf_uw2453.o \
 		zd_rf.o zd_usb.o zd_util.o
 
 ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a..5b624bf 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
 {
 	int r;
 
+	if (!zd_rf_should_update_pwr_int(&chip->rf))
+		return 0;
+
 	r = update_pwr_int(chip, channel);
 	if (r)
 		return r;
@@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
 	int r;
 	u32 value;
 
-	if (!chip->patch_cck_gain)
+	if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
 		return 0;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6..79d0288 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
 #define CR_ZD1211B_TXOP			CTL_REG(0x0b20)
 #define CR_ZD1211B_RETRY_MAX		CTL_REG(0x0b28)
 
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG			((zd_addr_t)0x85c1)
+
 #define CWIN_SIZE			0x007f043f
 
 
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23b..7407409 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
 void zd_rf_init(struct zd_rf *rf)
 {
 	memset(rf, 0, sizeof(*rf));
+
+	/* default to update channel integration, as almost all RF's do want
+	 * this */
+	rf->update_channel_int = 1;
 }
 
 void zd_rf_clear(struct zd_rf *rf)
 {
+	if (rf->clear)
+		rf->clear(rf);
 	ZD_MEMCLEAR(rf, sizeof(*rf));
 }
 
 int zd_rf_init_hw(struct zd_rf *rf, u8 type)
 {
-	int r, t;
+	int r = 0;
+	int t;
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
 	switch (type) {
 	case RF2959_RF:
 		r = zd_rf_init_rf2959(rf);
-		if (r)
-			return r;
 		break;
 	case AL2230_RF:
 		r = zd_rf_init_al2230(rf);
-		if (r)
-			return r;
 		break;
 	case AL7230B_RF:
 		r = zd_rf_init_al7230b(rf);
-		if (r)
-			return r;
+		break;
+	case UW2453_RF:
+		r = zd_rf_init_uw2453(rf);
 		break;
 	default:
 		dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
 		return -ENODEV;
 	}
 
+	if (r)
+		return r;
+
 	rf->type = type;
 
 	r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc10..c6dfd82 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@ struct zd_rf {
 
 	u8 channel;
 
+	/* whether channel integration and calibration should be updated
+	 * defaults to 1 (yes) */
+	u8 update_channel_int:1;
+
+	/* whether CR47 should be patched from the EEPROM, if the appropriate
+	 * flag is set in the POD. The vendor driver suggests that this should
+	 * be done for all RF's, but a bug in their code prevents but their
+	 * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+	u8 patch_cck_gain:1;
+
+	/* private RF driver data */
+	void *priv;
+
 	/* RF-specific functions */
 	int (*init_hw)(struct zd_rf *rf);
 	int (*set_channel)(struct zd_rf *rf, u8 channel);
 	int (*switch_radio_on)(struct zd_rf *rf);
 	int (*switch_radio_off)(struct zd_rf *rf);
 	int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+	void (*clear)(struct zd_rf *rf);
 };
 
 const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
 int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
 int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
 
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+	return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+	return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
 /* Functions for individual RF chips */
 
 int zd_rf_init_rf2959(struct zd_rf *rf);
 int zd_rf_init_al2230(struct zd_rf *rf);
 int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
 
 #endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392a..e7a4ecf 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
 		rf->switch_radio_on = zd1211_al2230_switch_radio_on;
 	}
 	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->patch_cck_gain = 1;
 	return 0;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9dd..f4e8b6a 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
 		rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
 		rf->set_channel = zd1211_al7230b_set_channel;
 		rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+		rf->patch_cck_gain = 1;
 	}
 
 	rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 0000000..414e40d
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+	RF_CHANNEL( 1) = 0x47,
+	RF_CHANNEL( 2) = 0x47,
+	RF_CHANNEL( 3) = 0x67,
+	RF_CHANNEL( 4) = 0x67,
+	RF_CHANNEL( 5) = 0x67,
+	RF_CHANNEL( 6) = 0x67,
+	RF_CHANNEL( 7) = 0x57,
+	RF_CHANNEL( 8) = 0x57,
+	RF_CHANNEL( 9) = 0x57,
+	RF_CHANNEL(10) = 0x57,
+	RF_CHANNEL(11) = 0x77,
+	RF_CHANNEL(12) = 0x77,
+	RF_CHANNEL(13) = 0x77,
+	RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+	RF_CHANNEL( 1) = 0x999,
+	RF_CHANNEL( 2) = 0x99b,
+	RF_CHANNEL( 3) = 0x998,
+	RF_CHANNEL( 4) = 0x99a,
+	RF_CHANNEL( 5) = 0x999,
+	RF_CHANNEL( 6) = 0x99b,
+	RF_CHANNEL( 7) = 0x998,
+	RF_CHANNEL( 8) = 0x99a,
+	RF_CHANNEL( 9) = 0x999,
+	RF_CHANNEL(10) = 0x99b,
+	RF_CHANNEL(11) = 0x998,
+	RF_CHANNEL(12) = 0x99a,
+	RF_CHANNEL(13) = 0x999,
+	RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+	{ /* table 1 */
+		RF_CHANPAIR( 1,  2) = 0x664d,
+		RF_CHANPAIR( 3,  4) = 0x604d,
+		RF_CHANPAIR( 5,  6) = 0x6675,
+		RF_CHANPAIR( 7,  8) = 0x6475,
+		RF_CHANPAIR( 9, 10) = 0x6655,
+		RF_CHANPAIR(11, 12) = 0x6455,
+		RF_CHANPAIR(13, 14) = 0x6665,
+	},
+	{ /* table 2 */
+		RF_CHANPAIR( 1,  2) = 0x666d,
+		RF_CHANPAIR( 3,  4) = 0x606d,
+		RF_CHANPAIR( 5,  6) = 0x664d,
+		RF_CHANPAIR( 7,  8) = 0x644d,
+		RF_CHANPAIR( 9, 10) = 0x6675,
+		RF_CHANPAIR(11, 12) = 0x6475,
+		RF_CHANPAIR(13, 14) = 0x6655,
+	},
+	{ /* table 3 */
+		RF_CHANPAIR( 1,  2) = 0x665d,
+		RF_CHANPAIR( 3,  4) = 0x605d,
+		RF_CHANPAIR( 5,  6) = 0x666d,
+		RF_CHANPAIR( 7,  8) = 0x646d,
+		RF_CHANPAIR( 9, 10) = 0x664d,
+		RF_CHANPAIR(11, 12) = 0x644d,
+		RF_CHANPAIR(13, 14) = 0x6675,
+	},
+	{ /* table 4 */
+		RF_CHANPAIR( 1,  2) = 0x667d,
+		RF_CHANPAIR( 3,  4) = 0x607d,
+		RF_CHANPAIR( 5,  6) = 0x665d,
+		RF_CHANPAIR( 7,  8) = 0x645d,
+		RF_CHANPAIR( 9, 10) = 0x666d,
+		RF_CHANPAIR(11, 12) = 0x646d,
+		RF_CHANPAIR(13, 14) = 0x664d,
+	},
+	{ /* table 5 */
+		RF_CHANPAIR( 1,  2) = 0x6643,
+		RF_CHANPAIR( 3,  4) = 0x6043,
+		RF_CHANPAIR( 5,  6) = 0x667d,
+		RF_CHANPAIR( 7,  8) = 0x647d,
+		RF_CHANPAIR( 9, 10) = 0x665d,
+		RF_CHANPAIR(11, 12) = 0x645d,
+		RF_CHANPAIR(13, 14) = 0x666d,
+	},
+	{ /* table 6 */
+		RF_CHANPAIR( 1,  2) = 0x6663,
+		RF_CHANPAIR( 3,  4) = 0x6063,
+		RF_CHANPAIR( 5,  6) = 0x6643,
+		RF_CHANPAIR( 7,  8) = 0x6443,
+		RF_CHANPAIR( 9, 10) = 0x667d,
+		RF_CHANPAIR(11, 12) = 0x647d,
+		RF_CHANPAIR(13, 14) = 0x665d,
+	},
+	{ /* table 7 */
+		RF_CHANPAIR( 1,  2) = 0x6653,
+		RF_CHANPAIR( 3,  4) = 0x6053,
+		RF_CHANPAIR( 5,  6) = 0x6663,
+		RF_CHANPAIR( 7,  8) = 0x6463,
+		RF_CHANPAIR( 9, 10) = 0x6643,
+		RF_CHANPAIR(11, 12) = 0x6443,
+		RF_CHANPAIR(13, 14) = 0x667d,
+	},
+	{ /* table 8 */
+		RF_CHANPAIR( 1,  2) = 0x6673,
+		RF_CHANPAIR( 3,  4) = 0x6073,
+		RF_CHANPAIR( 5,  6) = 0x6653,
+		RF_CHANPAIR( 7,  8) = 0x6453,
+		RF_CHANPAIR( 9, 10) = 0x6663,
+		RF_CHANPAIR(11, 12) = 0x6463,
+		RF_CHANPAIR(13, 14) = 0x6643,
+	},
+	{ /* table 9 */
+		RF_CHANPAIR( 1,  2) = 0x664b,
+		RF_CHANPAIR( 3,  4) = 0x604b,
+		RF_CHANPAIR( 5,  6) = 0x6673,
+		RF_CHANPAIR( 7,  8) = 0x6473,
+		RF_CHANPAIR( 9, 10) = 0x6653,
+		RF_CHANPAIR(11, 12) = 0x6453,
+		RF_CHANPAIR(13, 14) = 0x6663,
+	},
+	{ /* table 10 */
+		RF_CHANPAIR( 1,  2) = 0x666b,
+		RF_CHANPAIR( 3,  4) = 0x606b,
+		RF_CHANPAIR( 5,  6) = 0x664b,
+		RF_CHANPAIR( 7,  8) = 0x644b,
+		RF_CHANPAIR( 9, 10) = 0x6673,
+		RF_CHANPAIR(11, 12) = 0x6473,
+		RF_CHANPAIR(13, 14) = 0x6653,
+	},
+	{ /* table 11 */
+		RF_CHANPAIR( 1,  2) = 0x665b,
+		RF_CHANPAIR( 3,  4) = 0x605b,
+		RF_CHANPAIR( 5,  6) = 0x666b,
+		RF_CHANPAIR( 7,  8) = 0x646b,
+		RF_CHANPAIR( 9, 10) = 0x664b,
+		RF_CHANPAIR(11, 12) = 0x644b,
+		RF_CHANPAIR(13, 14) = 0x6673,
+	},
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+	RF_CHANNEL( 1) = 0x6847,
+	RF_CHANNEL( 2) = 0x6847,
+	RF_CHANNEL( 3) = 0x6867,
+	RF_CHANNEL( 4) = 0x6867,
+	RF_CHANNEL( 5) = 0x6867,
+	RF_CHANNEL( 6) = 0x6867,
+	RF_CHANNEL( 7) = 0x6857,
+	RF_CHANNEL( 8) = 0x6857,
+	RF_CHANNEL( 9) = 0x6857,
+	RF_CHANNEL(10) = 0x6857,
+	RF_CHANNEL(11) = 0x6877,
+	RF_CHANNEL(12) = 0x6877,
+	RF_CHANNEL(13) = 0x6877,
+	RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+	[0x00] = 0x0e313,
+	[0x01] = 0x0fb13,
+	[0x02] = 0x0e093,
+	[0x03] = 0x0f893,
+	[0x04] = 0x0ea93,
+	[0x05] = 0x1f093,
+	[0x06] = 0x1f493,
+	[0x07] = 0x1f693,
+	[0x08] = 0x1f393,
+	[0x09] = 0x1f35b,
+	[0x0a] = 0x1e6db,
+	[0x0b] = 0x1ff3f,
+	[0x0c] = 0x1ffff,
+	[0x0d] = 0x361d7,
+	[0x0e] = 0x37fbf,
+	[0x0f] = 0x3ff8b,
+	[0x10] = 0x3ff33,
+	[0x11] = 0x3fb3f,
+	[0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+	/* index into synth/VCO config tables where PLL lock was found
+	 * -1 means autocal */
+	int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+	bool autocal)
+{
+	int r;
+	int idx = channel - 1;
+	u32 val;
+
+	if (autocal)
+		val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+	else
+		val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+	r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+	/* vendor driver always sets these upper bits even though the specs say
+	 * they are reserved */
+	u32 val = 0x40000 | value;
+	return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+	static const u32 rv[] = {
+		UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+		UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+		UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+		UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+	};
+
+	return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+	u8 int_value = chip->pwr_int_values[channel - 1];
+
+	if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+		dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+			  "int value %x on channel %d\n", int_value, channel);
+		return 0;
+	}
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+	int i, r;
+	int found_config = -1;
+	u16 intr_status;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR10,  0x89 }, { CR15,  0x20 },
+		{ CR17,  0x28 }, /* 6112 no change */
+		{ CR23,  0x38 }, { CR24,  0x20 }, { CR26,  0x93 },
+		{ CR27,  0x15 }, { CR28,  0x3e }, { CR29,  0x00 },
+		{ CR33,  0x28 }, { CR34,  0x30 },
+		{ CR35,  0x43 }, /* 6112 3e->43 */
+		{ CR41,  0x24 }, { CR44,  0x32 },
+		{ CR46,  0x92 }, /* 6112 96->92 */
+		{ CR47,  0x1e },
+		{ CR48,  0x04 }, /* 5602 Roger */
+		{ CR49,  0xfa }, { CR79,  0x58 }, { CR80,  0x30 },
+		{ CR81,  0x30 }, { CR87,  0x0a }, { CR89,  0x04 },
+		{ CR91,  0x00 }, { CR92,  0x0a }, { CR98,  0x8d },
+		{ CR99,  0x28 }, { CR100, 0x02 },
+		{ CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+		{ CR102, 0x27 },
+		{ CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+		{ CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+		{ CR109, 0x13 },
+		{ CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+		{ CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+		{ CR114, 0x23 }, /* 6221 27->23 */
+		{ CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+		{ CR116, 0x24 }, /* 6220 1c->24 */
+		{ CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+		{ CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+		{ CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+		{ CR120, 0x4f },
+		{ CR121, 0x1f }, /* 6220 4f->1f */
+		{ CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+		{ CR126, 0x6c }, { CR127, 0x03 },
+		{ CR128, 0x14 }, /* 6302 12->11 */
+		{ CR129, 0x12 }, /* 6301 10->0f */
+		{ CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+		{ CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+		{ CR253, 0xff },
+	};
+
+	static const u32 rv[] = {
+		UW2453_REGWRITE(4, 0x2b),    /* configure reciever gain */
+		UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+		UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+		UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+		/* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+		 * RSSI circuit powered down, reduced RSSI range */
+		UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+		/* synthesizer configuration for channel 1 */
+		UW2453_REGWRITE(1, 0x47),
+		UW2453_REGWRITE(2, 0x999),
+
+		/* disable manual VCO band selection */
+		UW2453_REGWRITE(3, 0x7602),
+
+		/* enable manual VCO band selection, configure current level */
+		UW2453_REGWRITE(3, 0x46063),
+	};
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	/* Try all standard VCO configuration settings on channel 1 */
+	for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+		/* Configure synthesizer for channel 1 */
+		r = uw2453_synth_set_channel(chip, 1, false);
+		if (r)
+			return r;
+
+		/* Write VCO config */
+		r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+		if (r)
+			return r;
+
+		/* ack interrupt event */
+		r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		/* check interrupt status */
+		r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		if (!intr_status & 0xf) {
+			dev_dbg_f(zd_chip_dev(chip),
+				"PLL locked on configuration %d\n", i);
+			found_config = i;
+			break;
+		}
+	}
+
+	if (found_config == -1) {
+		/* autocal */
+		dev_dbg_f(zd_chip_dev(chip),
+			"PLL did not lock, using autocal\n");
+
+		r = uw2453_synth_set_channel(chip, 1, true);
+		if (r)
+			return r;
+
+		r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+		if (r)
+			return r;
+	}
+
+	/* To match the vendor driver behaviour, we use the configuration after
+	 * the one that produced a lock. */
+	UW2453_PRIV(rf)->config = found_config + 1;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+	int r;
+	u16 vco_cfg;
+	int config = UW2453_PRIV(rf)->config;
+	bool autocal = (config == -1);
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR80,  0x30 }, { CR81,  0x30 }, { CR79,  0x58 },
+		{ CR12,  0xf0 }, { CR77,  0x1b }, { CR78,  0x58 },
+	};
+
+	r = uw2453_synth_set_channel(chip, channel, autocal);
+	if (r)
+		return r;
+
+	if (autocal)
+		vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+	else
+		vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+	r = uw2453_write_vco_cfg(chip, vco_cfg);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = uw2453_set_tx_gain_level(chip, channel);
+	if (r)
+		return r;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x00 }, { CR251, 0x3f },
+	};
+
+	/* enter RXTX mode */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+	if (r)
+		return r;
+
+	if (chip->is_zd1211b)
+		ioreqs[1].value = 0x7f;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x04 }, { CR251, 0x2f },
+	};
+
+	/* enter IDLE mode */
+	/* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+	kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+	rf->init_hw = uw2453_init_hw;
+	rf->set_channel = uw2453_set_channel;
+	rf->switch_radio_on = uw2453_switch_radio_on;
+	rf->switch_radio_off = uw2453_switch_radio_off;
+	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->clear = uw2453_clear;
+	/* we have our own TX integration code */
+	rf->update_channel_int = 0;
+
+	rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+	if (rf->priv == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549..740a219 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
 	{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
 	{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index c308756..6398e6e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -456,18 +456,13 @@ void
 ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_network *add_net)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return;
 	}
-	if(softmac_net == NULL)
-		list_add(&(add_net->list), &mac->network_list);
+	list_add(&(add_net->list), &mac->network_list);
 }
 
 /* Add a network to the list, with locking */
@@ -506,16 +501,13 @@ struct ieee80211softmac_network *
 ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
 	u8 *bssid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	struct ieee80211softmac_network *softmac_net;
+
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return softmac_net;
 	}
-	return softmac_net;
+	return NULL;
 }
 
 /* Get a network from the list by BSSID with locking */
@@ -537,11 +529,9 @@ struct ieee80211softmac_network *
 ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_essid *essid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if (softmac_net->essid.len == essid->len &&
 			!memcmp(softmac_net->essid.data, essid->data, essid->len))
 			return softmac_net;
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream-fixes' branch of wireless-2.6
  2007-05-29 18:30 Please pull 'upstream-fixes' branch of wireless-2.6 John W. Linville
  2007-05-29 18:31 ` Please pull 'upstream' " John W. Linville
@ 2007-05-30 13:46 ` Jeff Garzik
  1 sibling, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-05-30 13:46 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, netdev

John W. Linville wrote:
> The following changes since commit c420bc9f09a0926b708c3edb27eacba434=
a4f4ba:
>   Linus Torvalds (1):
>         Linux 2.6.22-rc3
>=20
> are found in the git repository at:
>=20
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6=
=2Egit upstream-fixes
>=20
> Akinobu Mita (2):
>       ieee80211: fix incomplete error message
>       softmac: alloc_ieee80211() NULL check
>=20
> Bj=F6rn Steinbrink (1):
>       prism54: fix monitor mode oops
>=20
> Brandon Craig Rhodes (1):
>       hostap: Allocate enough tailroom for TKIP

pulled


-
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: Please pull 'upstream' branch of wireless-2.6
  2007-05-29 18:31 ` Please pull 'upstream' " John W. Linville
@ 2007-05-30 14:03   ` Jeff Garzik
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-05-30 14:03 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, netdev

John W. Linville wrote:
> The following changes since commit d7ea3be56adc95b17351221fd95e78115f3b01f4:
>   Brandon Craig Rhodes (1):
>         hostap: Allocate enough tailroom for TKIP
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream
> 
> Akinobu Mita (1):
>       softmac: use list_for_each_entry
> 
> Daniel Drake (4):
>       zd1211rw: Add ID for ZyXEL G-200v2
>       zd1211rw: Extend RF layer
>       zd1211rw: Add UW2453 RF support
>       zd1211rw: Make CCK gain patching conditional on RF type
> 
> Jouni Malinen (1):
>       hostap: Remove driver version number
> 
> Larry Finger (1):
>       bcm43xx: Fix deviation from specifications in set_baseband_attenuation
> 
> Matthias Kaehlcke (1):
>       hostap: Use list_for_each_entry
> 
> Pavel Roskin (1):
>       hostap: Suppress broadcast if no stations are associated
> 
>  drivers/net/wireless/bcm43xx/bcm43xx_phy.c      |    2 +-
>  drivers/net/wireless/hostap/hostap_ap.c         |   34 +-
>  drivers/net/wireless/hostap/hostap_config.h     |    2 -
>  drivers/net/wireless/hostap/hostap_cs.c         |    4 -
>  drivers/net/wireless/hostap/hostap_ioctl.c      |    2 -
>  drivers/net/wireless/hostap/hostap_main.c       |    1 -
>  drivers/net/wireless/hostap/hostap_pci.c        |    5 -
>  drivers/net/wireless/hostap/hostap_plx.c        |    5 -
>  drivers/net/wireless/zd1211rw/Makefile          |    2 +-
>  drivers/net/wireless/zd1211rw/zd_chip.c         |    5 +-
>  drivers/net/wireless/zd1211rw/zd_chip.h         |    3 +
>  drivers/net/wireless/zd1211rw/zd_rf.c           |   21 +-
>  drivers/net/wireless/zd1211rw/zd_rf.h           |   28 ++
>  drivers/net/wireless/zd1211rw/zd_rf_al2230.c    |    1 +
>  drivers/net/wireless/zd1211rw/zd_rf_al7230b.c   |    1 +
>  drivers/net/wireless/zd1211rw/zd_rf_uw2453.c    |  534 +++++++++++++++++++++++
>  drivers/net/wireless/zd1211rw/zd_usb.c          |    1 +
>  net/ieee80211/softmac/ieee80211softmac_module.c |   32 +-
>  18 files changed, 611 insertions(+), 72 deletions(-)
>  create mode 100644 drivers/net/wireless/zd1211rw/zd_rf_uw2453.c

pulled



^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2007-05-30 14:03 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-29 18:30 Please pull 'upstream-fixes' branch of wireless-2.6 John W. Linville
2007-05-29 18:31 ` Please pull 'upstream' " John W. Linville
2007-05-30 14:03   ` Jeff Garzik
2007-05-30 13:46 ` Please pull 'upstream-fixes' " Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2007-05-08 17:39 Please pull 'upstream' " John W. Linville
2007-05-09 22:54 ` Jeff Garzik
2007-05-07 17:51 John W. Linville
2007-05-07 21:15 ` Dan Williams
2007-05-07 22:51   ` John W. Linville
2007-05-08  8:49   ` Johannes Berg
2007-05-07 23:09 ` Jeff Garzik
2007-05-07 23:30   ` Michael Wu
2007-05-07 23:38   ` John W. Linville
2007-05-08 17:38 ` John W. Linville
2007-03-27 18:26 Please pull 'upstream-fixes' " John W. Linville
2007-03-27 18:26 ` Please pull 'upstream' " John W. Linville
2007-03-29 12:31   ` Jeff Garzik
2007-03-16 21:31 Please pull 'upstream-fixes' " John W. Linville
2007-03-16 21:34 ` Please pull 'upstream' " John W. Linville
2007-03-23  5:55   ` Jeff Garzik
2007-03-23 12:02     ` Dan Williams
2007-03-08  3:30 Please pull 'upstream-fixes' " John W. Linville
2007-03-08  3:32 ` Please pull 'upstream' " John W. Linville
2007-03-09 16:59   ` Jeff Garzik
2007-02-27 20:50 Please pull 'upstream-fixes' " John W. Linville
2007-02-27 20:51 ` Please pull 'upstream' " John W. Linville
2007-03-03  0:42   ` Jeff Garzik
2007-02-02 21:27 Please pull "upstream-fixes" " John W. Linville
2007-02-02 21:28 ` Please pull "upstream" " John W. Linville
2007-02-07  0:06 ` Please pull "upstream-fixes" " Jeff Garzik
2007-02-07 21:11   ` Please pull "upstream" " John W. Linville
2007-02-09 20:13     ` John W. Linville
2007-02-09 21:12       ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).