A number of the calls in the initialization routines fail to check the returned value for errors. This patch adds the necessary checks and logs any errors found when appropriate. Signed-off-by: Larry Finger --- To be applied to wireless-2.6. A number of the calls in the initialization routines fail to check the returned value for errors. This patch adds the necessary checks and logs any errors found when appropriate. Signed-off-by: Larry Finger --- To be applied to wireless-2.6. Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_main.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3679,7 +3679,7 @@ static int bcm43xx_read_phyinfo(struct b { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; - u8 phy_version; + u8 phy_analog; u8 phy_type; u8 phy_rev; int phy_rev_ok = 1; @@ -3687,12 +3687,12 @@ static int bcm43xx_read_phyinfo(struct b value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); - phy_version = (value & 0xF000) >> 12; + phy_analog = (value & 0xF000) >> 12; phy_type = (value & 0x0F00) >> 8; phy_rev = (value & 0x000F); - dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n", - phy_version, phy_type, phy_rev); + dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n", + phy_analog, phy_type, phy_rev); switch (phy_type) { case BCM43xx_PHYTYPE_A: @@ -3735,7 +3735,7 @@ static int bcm43xx_read_phyinfo(struct b phy_rev); } - phy->version = phy_version; + phy->analog = phy_analog; phy->type = phy_type; phy->rev = phy_rev; if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { @@ -4258,6 +4258,7 @@ static int bcm43xx_resume(struct pci_dev { struct net_device *net_dev = pci_get_drvdata(pdev); struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); int err = 0; dprintk(KERN_INFO PFX "Resuming...\n"); @@ -4279,6 +4280,9 @@ static int bcm43xx_resume(struct pci_dev } netif_device_attach(net_dev); + if (mac->associnfo.associated) + ieee80211softmac_try_reassoc(mac); + dprintk(KERN_INFO PFX "Device resumed.\n"); return 0; Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_dma.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx 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_dma 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 bcm4 { 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 b { 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 bcm43 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 bc 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_d 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_priv 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,9 +819,12 @@ int bcm43xx_dma_init(struct bcm43xx_priv 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: + if(err)BUG(); return err; err_destroy_rx0: @@ -800,7 +848,18 @@ 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; + BUG(); + 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 +964,7 @@ static void dma_tx_fragment(struct bcm43 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 +984,28 @@ static void dma_tx_fragment(struct bcm43 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, Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx.h =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx.h +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -333,7 +333,7 @@ #define BCM43xx_SBF_PS2 0x04000000 #define BCM43xx_SBF_NO_SSID_BCAST 0x08000000 #define BCM43xx_SBF_TIME_UPDATE 0x10000000 -#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ +#define BCM43xx_SBF_MODE_G 0x80000000 /* Microcode */ #define BCM43xx_UCODE_REVISION 0x0000 @@ -538,7 +538,7 @@ struct bcm43xx_lopair { struct bcm43xx_phyinfo { /* Hardware Data */ - u8 version; + u8 analog; u8 type; u8 rev; u16 antenna_diversity; @@ -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; Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_wx.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -261,22 +261,22 @@ static int bcm43xx_wx_get_rangeparams(st 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(st 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(st 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++; } Index: linux-2.6.20/net/ieee80211/ieee80211_tx.c =================================================================== --- linux-2.6.20.orig/net/ieee80211/ieee80211_tx.c +++ linux-2.6.20/net/ieee80211/ieee80211_tx.c @@ -502,9 +502,6 @@ int ieee80211_xmit(struct sk_buff *skb, 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, Index: linux-2.6.20/include/net/ieee80211softmac.h =================================================================== --- linux-2.6.20.orig/include/net/ieee80211softmac.h +++ linux-2.6.20/include/net/ieee80211softmac.h @@ -254,6 +254,7 @@ struct ieee80211softmac_device { }; extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm); +extern void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac); static inline void * ieee80211softmac_priv(struct net_device *dev) { Index: linux-2.6.20/net/ieee80211/softmac/ieee80211softmac_assoc.c =================================================================== --- linux-2.6.20.orig/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ linux-2.6.20/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -441,6 +441,7 @@ ieee80211softmac_try_reassoc(struct ieee schedule_delayed_work(&mac->associnfo.work, 0); spin_unlock_irqrestore(&mac->lock, flags); } +EXPORT_SYMBOL_GPL(ieee80211softmac_try_reassoc); int ieee80211softmac_handle_disassoc(struct net_device * dev, Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_phy.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -205,8 +205,8 @@ static void bcm43xx_phy_init_pctl(struct (bcm->board_type == 0x0416)) return; - bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); bcm43xx_phy_write(bcm, 0x0028, 0x8018); + bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); if (phy->type == BCM43xx_PHYTYPE_G) { if (!phy->connected) @@ -317,6 +317,13 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_ilt_write(bcm, offset + 0x0801, 7); bcm43xx_ilt_write(bcm, offset + 0x0802, 16); bcm43xx_ilt_write(bcm, offset + 0x0803, 28); + + if (phy->rev >= 6) { + bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) + & 0xFFFC)); + bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) + & 0xEFFF)); + } } static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) @@ -337,7 +344,7 @@ static void bcm43xx_phy_setupg(struct bc for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); } else { /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); @@ -377,7 +384,7 @@ static void bcm43xx_phy_setupg(struct bc if (phy->rev == 1) { for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); for (i = 0; i < 4; i++) { bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020); bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020); @@ -500,10 +507,10 @@ static void bcm43xx_phy_setupa(struct bc for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); bcm43xx_phy_init_noisescaletbl(bcm); for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); break; case 3: for (i = 0; i < 64; i++) @@ -729,19 +736,19 @@ static void bcm43xx_phy_initb5(struct bc struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset; + u16 value; + u8 old_channel; - if (phy->version == 1 && - radio->version == 0x2050) { + if (phy->analog == 1) bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0050); - } - if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type != 0x0416)) { + if (!(bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x0416)) { + value = 0x2120; for (offset = 0x00A8 ; offset < 0x00C7; offset++) { - bcm43xx_phy_write(bcm, offset, - (bcm43xx_phy_read(bcm, offset) + 0x2020) - & 0x3F3F); + bcm43xx_phy_write(bcm, offset, value); + value += 0x0202; } } bcm43xx_phy_write(bcm, 0x0035, @@ -776,7 +783,7 @@ static void bcm43xx_phy_initb5(struct bc bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11)); } - if (phy->version == 1 && radio->version == 0x2050) { + if (phy->analog == 1) { bcm43xx_phy_write(bcm, 0x0026, 0xCE00); bcm43xx_phy_write(bcm, 0x0021, 0x3763); bcm43xx_phy_write(bcm, 0x0022, 0x1BC3); @@ -787,14 +794,15 @@ static void bcm43xx_phy_initb5(struct bc bcm43xx_phy_write(bcm, 0x0030, 0x00C6); bcm43xx_write16(bcm, 0x03EC, 0x3F22); - if (phy->version == 1 && radio->version == 0x2050) + if (phy->analog == 1) bcm43xx_phy_write(bcm, 0x0020, 0x3E1C); else bcm43xx_phy_write(bcm, 0x0020, 0x301C); - if (phy->version == 0) + if (phy->analog == 0) bcm43xx_write16(bcm, 0x03E4, 0x3000); + old_channel = radio->channel; /* Force to channel 7, even if not supported. */ bcm43xx_radio_selectchannel(bcm, 7, 0); @@ -816,11 +824,11 @@ static void bcm43xx_phy_initb5(struct bc bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007); - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + bcm43xx_radio_selectchannel(bcm, old_channel, 0); bcm43xx_phy_write(bcm, 0x0014, 0x0080); bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - bcm43xx_phy_write(bcm, 0x88A3, 0x002A); + bcm43xx_phy_write(bcm, 0x002A, 0x88A3); bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); @@ -835,61 +843,29 @@ static void bcm43xx_phy_initb6(struct bc struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; + u8 old_channel; bcm43xx_phy_write(bcm, 0x003E, 0x817A); bcm43xx_radio_write16(bcm, 0x007A, (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058)); - if ((radio->manufact == 0x17F) && - (radio->version == 0x2050) && - (radio->revision == 3 || - radio->revision == 4 || - radio->revision == 5)) { - bcm43xx_radio_write16(bcm, 0x0051, 0x001F); - bcm43xx_radio_write16(bcm, 0x0052, 0x0040); - bcm43xx_radio_write16(bcm, 0x0053, 0x005B); - bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + if (radio->revision == 4 || + radio->revision == 5) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0037); + bcm43xx_radio_write16(bcm, 0x0052, 0x0070); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B3); + bcm43xx_radio_write16(bcm, 0x0054, 0x009B); bcm43xx_radio_write16(bcm, 0x005A, 0x0088); bcm43xx_radio_write16(bcm, 0x005B, 0x0088); bcm43xx_radio_write16(bcm, 0x005D, 0x0088); bcm43xx_radio_write16(bcm, 0x005E, 0x0088); bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + | 0x00000200)); } - if ((radio->manufact == 0x17F) && - (radio->version == 0x2050) && - (radio->revision == 6)) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0000); - bcm43xx_radio_write16(bcm, 0x0052, 0x0040); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); - bcm43xx_radio_write16(bcm, 0x0054, 0x0098); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x008B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B5); - bcm43xx_radio_write16(bcm, 0x005D, 0x0088); - bcm43xx_radio_write16(bcm, 0x005E, 0x0088); - bcm43xx_radio_write16(bcm, 0x007D, 0x0088); - bcm43xx_radio_write16(bcm, 0x007C, 0x0001); - bcm43xx_radio_write16(bcm, 0x007E, 0x0008); - } - if ((radio->manufact == 0x17F) && - (radio->version == 0x2050) && - (radio->revision == 7)) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0000); - bcm43xx_radio_write16(bcm, 0x0052, 0x0040); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); - bcm43xx_radio_write16(bcm, 0x0054, 0x0098); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x00A8); - bcm43xx_radio_write16(bcm, 0x005C, 0x0075); - bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); - bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); - bcm43xx_radio_write16(bcm, 0x007D, 0x00E8); - bcm43xx_radio_write16(bcm, 0x007C, 0x0001); - bcm43xx_radio_write16(bcm, 0x007E, 0x0008); - bcm43xx_radio_write16(bcm, 0x007B, 0x0000); - } - if ((radio->manufact == 0x17F) && - (radio->version == 0x2050) && - (radio->revision == 8)) { + if (radio->revision == 8) { bcm43xx_radio_write16(bcm, 0x0051, 0x0000); bcm43xx_radio_write16(bcm, 0x0052, 0x0040); bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); @@ -933,20 +909,26 @@ static void bcm43xx_phy_initb6(struct bc bcm43xx_phy_read(bcm, 0x0802) | 0x0100); bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000); + bcm43xx_phy_write(bcm, 0x5B, 0x0000); + bcm43xx_phy_write(bcm, 0x5C, 0x0000); } - /* Force to channel 7, even if not supported. */ - bcm43xx_radio_selectchannel(bcm, 7, 0); + old_channel = radio->channel; + if (old_channel >= 8) + bcm43xx_radio_selectchannel(bcm, 1, 0); + else + bcm43xx_radio_selectchannel(bcm, 13, 0); bcm43xx_radio_write16(bcm, 0x0050, 0x0020); bcm43xx_radio_write16(bcm, 0x0050, 0x0023); udelay(40); - bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002)); - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - if (radio->manufact == 0x17F && - radio->version == 0x2050 && - radio->revision <= 2) { + if (radio->revision < 6 || radio-> revision == 8) { + bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) + | 0x0002)); bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + } + if (radio->revision <= 2) { + bcm43xx_radio_write16(bcm, 0x007C, 0x0020); bcm43xx_radio_write16(bcm, 0x005A, 0x0070); bcm43xx_radio_write16(bcm, 0x005B, 0x007B); bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); @@ -954,46 +936,42 @@ static void bcm43xx_phy_initb6(struct bc bcm43xx_radio_write16(bcm, 0x007A, (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007); - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + bcm43xx_radio_selectchannel(bcm, old_channel, 0); bcm43xx_phy_write(bcm, 0x0014, 0x0200); - if (radio->version == 0x2050){ - if (radio->revision == 3 || - radio->revision == 4 || - radio->revision == 5) - bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); - else - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - } + if (radio->revision >= 6) + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + else + bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); bcm43xx_phy_write(bcm, 0x0038, 0x0668); bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - if (radio->version == 0x2050) { - if (radio->revision == 3 || - radio->revision == 4 || - radio->revision == 5) - bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003); - else if (radio->revision <= 2) - bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - } + if (radio->revision <= 5) + bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) + & 0xFF80) | 0x0003); + if (radio->revision <= 2) + bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - if (phy->rev == 4) - bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); - else + if (phy->analog == 4){ bcm43xx_write16(bcm, 0x03E4, 0x0009); + bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF); + } else { + bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); + } + if (phy->type == BCM43xx_PHYTYPE_G) + bcm43xx_write16(bcm, 0x03E6, 0x0); if (phy->type == BCM43xx_PHYTYPE_B) { bcm43xx_write16(bcm, 0x03E6, 0x8140); bcm43xx_phy_write(bcm, 0x0016, 0x0410); bcm43xx_phy_write(bcm, 0x0017, 0x0820); bcm43xx_phy_write(bcm, 0x0062, 0x0007); - (void) bcm43xx_radio_calibrationvalue(bcm); - bcm43xx_phy_lo_b_measure(bcm); + bcm43xx_radio_init2050(bcm); + bcm43xx_phy_lo_g_measure(bcm); if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { bcm43xx_calc_nrssi_slope(bcm); bcm43xx_calc_nrssi_threshold(bcm); } bcm43xx_phy_init_pctl(bcm); - } else - bcm43xx_write16(bcm, 0x03E6, 0x0); + } } static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) @@ -1063,7 +1041,7 @@ static void bcm43xx_calc_loopback_gain(s bcm43xx_phy_write(bcm, 0x005A, 0x0780); bcm43xx_phy_write(bcm, 0x0059, 0xC810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->version == 0) { + if (phy->analog == 0) { bcm43xx_phy_write(bcm, 0x0003, 0x0122); } else { bcm43xx_phy_write(bcm, 0x000A, @@ -1207,25 +1185,25 @@ static void bcm43xx_phy_initg(struct bcm bcm43xx_phy_write(bcm, 0x0815, 0x0000); if (phy->rev == 2) bcm43xx_phy_write(bcm, 0x0811, 0x0000); - else if (phy->rev >= 3) + if (phy->rev >= 3) bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - if (phy->connected) { - tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp < 6) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - if (tmp != 3) { - bcm43xx_phy_write(bcm, 0x04CC, - (bcm43xx_phy_read(bcm, 0x04CC) - & 0x00FF) | 0x1F00); - } - } + } + if (phy->connected) { + tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; + if (tmp == 3 || tmp < 6) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8006); + } + if (tmp < 6) { + bcm43xx_phy_write(bcm, 0x04CC, + (bcm43xx_phy_read(bcm, 0x04CC) + & 0x00FF) | 0x1F00); } } if (phy->rev < 3 && phy->connected) bcm43xx_phy_write(bcm, 0x047E, 0x0078); - if (phy->rev >= 6 && phy->rev <= 8) { + if (radio->revision == 8) { bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); } @@ -1638,14 +1616,14 @@ void bcm43xx_phy_set_baseband_attenuatio struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; - if (phy->version == 0) { + if (phy->analog == 0) { value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); value |= (baseband_attenuation & 0x000F); bcm43xx_write16(bcm, 0x03E6, value); return; } - if (phy->version > 1) { + if (phy->analog > 1) { value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; value |= (baseband_attenuation << 2) & 0x003C; } else { Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_radio.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -458,7 +458,7 @@ static void bcm43xx_calc_nrssi_offset(st bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0x0810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->rev == 0) { + if (phy->analog == 0) { bcm43xx_phy_write(bcm, 0x0003, 0x0122); } else { bcm43xx_phy_write(bcm, 0x000A, @@ -570,9 +570,9 @@ void bcm43xx_calc_nrssi_slope(struct bcm nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_write16(bcm, 0x03E6, 0x0040); - } else if (phy->rev == 0) { + } else if (phy->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, @@ -596,7 +596,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm bcm43xx_phy_write(bcm, 0x0015, backup[5]); bcm43xx_phy_write(bcm, 0x002A, backup[6]); bcm43xx_synth_pu_workaround(bcm, radio->channel); - if (phy->rev != 0) + if (phy->analog != 0) bcm43xx_write16(bcm, 0x03F4, backup[13]); bcm43xx_phy_write(bcm, 0x0020, backup[7]); @@ -692,7 +692,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); @@ -1343,11 +1343,83 @@ u16 bcm43xx_radio_calibrationvalue(struc return ret; } +static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 l, u8 p, u8 d) +{ + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + u16 val, loop_or = 0; + u16 adj_loopback_gain; + u8 loop; + u16 extern_lna_control; + + if (!phy->connected) + return 0; + if (phy->rev <= 1 && !phy->connected) { + val = 0x00B2; + if (!d) + val |= 1; + if (p) + val |= 0x0F00; + if (phy->rev < 7 || !(bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA)) { + if (l) + val |= 0x3000; + } else { + if (l) + val |= 0x2000; + else + val |= 0x8000; + } + } else { + if (radio->revision == 8) + adj_loopback_gain = phy->loopback_gain[0] - 0x003E; + else + adj_loopback_gain = phy->loopback_gain[0] - 0x0026; + if (adj_loopback_gain >= 0x46) { + adj_loopback_gain -= 0x46; + extern_lna_control = 0x3000; + } else if (adj_loopback_gain >= 0x3A) { + adj_loopback_gain -= 0x3A; + extern_lna_control = 0x2000; + } else if (adj_loopback_gain >= 0x2E) { + adj_loopback_gain -= 0x2E; + extern_lna_control = 0x1000; + } else { + adj_loopback_gain -= 0x10; + extern_lna_control = 0x0000; + } + for (loop = 0; loop < 16; loop++) { + u16 tmp = adj_loopback_gain - 6 * loop; + if (tmp < 6) + break; + } + + val = 0x0092; + if (!d) + val |= 1; + if (p) { + val |= 0x0F00; + if (phy->rev < 7 || !(bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA)) + val |= 0x8000; + return val; + } + loop_or = (loop << 8) | extern_lna_control; + if (phy->rev >= 7 && bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { + loop_or |= 0x8000; + if (l) + val |= 0x2000; + else + val |= 0x8000; + } + val |= loop_or; + } + return val; +} + u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup[19] = { 0 }; + u16 backup[21] = { 0 }; u16 ret; u16 i, j; u32 tmp1 = 0, tmp2 = 0; @@ -1380,12 +1452,23 @@ u16 bcm43xx_radio_init2050(struct bcm43x (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF)); bcm43xx_phy_write(bcm, 0x0802, (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); - bcm43xx_phy_write(bcm, 0x0811, 0x01B3); - bcm43xx_phy_write(bcm, 0x0812, 0x0FB2); + if (phy->rev > 1) { + backup[19] = bcm43xx_phy_read(bcm, 0x080F); + backup[20] = bcm43xx_phy_read(bcm, 0x0810); + if (phy->rev >= 3) + bcm43xx_phy_write(bcm, 0x080F, 0xC020); + else + bcm43xx_phy_write(bcm, 0x080F, 0x8020); + } + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 0, 1, 1)); + if (phy->rev < 7 || !(bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA)) + bcm43xx_phy_write(bcm, 0x0811, 0x01B3); + else + bcm43xx_phy_write(bcm, 0x0811, 0x09B3); } - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); backup[10] = bcm43xx_phy_read(bcm, 0x0035); bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); @@ -1393,11 +1476,12 @@ u16 bcm43xx_radio_init2050(struct bcm43x backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); // Initialization - if (phy->version == 0) { + if (phy->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { - if (phy->version >= 2) - bcm43xx_write16(bcm, 0x03E6, 0x0040); + if (phy->analog >= 2) + bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) + & 0xFFBF) | 0x0040); bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000)); } @@ -1407,16 +1491,22 @@ u16 bcm43xx_radio_init2050(struct bcm43x if (phy->type == BCM43xx_PHYTYPE_B) bcm43xx_radio_write16(bcm, 0x0078, 0x0003); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 0, 1, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); bcm43xx_phy_write(bcm, 0x002B, 0x1403); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x00B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 0, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); bcm43xx_radio_write16(bcm, 0x0051, (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - bcm43xx_radio_write16(bcm, 0x0043, - bcm43xx_radio_read16(bcm, 0x0043) | 0x0009); + if (radio->revision == 8) + bcm43xx_radio_write16(bcm, 0x0043, 0x001F); + else { + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + bcm43xx_radio_write16(bcm, 0x0043, + (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 0x0009); + } bcm43xx_phy_write(bcm, 0x0058, 0x0000); for (i = 0; i < 16; i++) { @@ -1424,21 +1514,21 @@ u16 bcm43xx_radio_init2050(struct bcm43x bcm43xx_phy_write(bcm, 0x0059, 0xC810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 0)); bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); - udelay(10); + udelay(20); tmp1 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); } @@ -1456,21 +1546,21 @@ u16 bcm43xx_radio_init2050(struct bcm43x bcm43xx_phy_write(bcm, 0x0059, 0xC810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */ + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 0)); bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); udelay(10); tmp2 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, 1, 0, 1)); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); } tmp2++; @@ -1488,7 +1578,7 @@ u16 bcm43xx_radio_init2050(struct bcm43x bcm43xx_phy_write(bcm, 0x0059, backup[17]); bcm43xx_phy_write(bcm, 0x0058, backup[18]); bcm43xx_write16(bcm, 0x03E6, backup[11]); - if (phy->version != 0) + if (phy->analog != 0) bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); bcm43xx_phy_write(bcm, 0x0035, backup[10]); bcm43xx_radio_selectchannel(bcm, radio->channel, 1); @@ -1496,15 +1586,21 @@ u16 bcm43xx_radio_init2050(struct bcm43x bcm43xx_phy_write(bcm, 0x0030, backup[2]); bcm43xx_write16(bcm, 0x03EC, backup[3]); } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); if (phy->connected) { + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); bcm43xx_phy_write(bcm, 0x0811, backup[4]); bcm43xx_phy_write(bcm, 0x0812, backup[5]); bcm43xx_phy_write(bcm, 0x0814, backup[6]); bcm43xx_phy_write(bcm, 0x0815, backup[7]); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); bcm43xx_phy_write(bcm, 0x0802, backup[9]); + if (phy->rev > 1) { + bcm43xx_phy_write(bcm, 0x080F, backup[19]); + bcm43xx_phy_write(bcm, 0x0810, backup[20]); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); } } if (i >= 15) Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -325,6 +325,21 @@ void bcm43xx_ilt_write(struct bcm43xx_pr } } +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) +{ + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + mmiowb(); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + mmiowb(); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF); + } +} + u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) { if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { Index: linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h =================================================================== --- linux-2.6.20.orig/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h +++ linux-2.6.20/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h @@ -27,6 +27,7 @@ extern const u16 bcm43xx_ilt_sigmasqr2[B void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val); +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset); #endif /* BCM43xx_ILT_H_ */ Index: linux-2.6.20/net/ieee80211/softmac/ieee80211softmac_module.c =================================================================== --- linux-2.6.20.orig/net/ieee80211/softmac/ieee80211softmac_module.c +++ linux-2.6.20/net/ieee80211/softmac/ieee80211softmac_module.c @@ -270,13 +270,11 @@ void ieee80211softmac_init_bss(struct ie can manually change it if they really need to, but 11M is more reliable. Note similar logic in ieee80211softmac_wx_set_rate() */ - if (ieee->modulation & IEEE80211_CCK_MODULATION) { + if (ieee->modulation & IEEE80211_OFDM_MODULATION) { + txrates->user_rate = IEEE80211_OFDM_RATE_24MB; + } else { txrates->user_rate = IEEE80211_CCK_RATE_11MB; - } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) { - txrates->user_rate = IEEE80211_OFDM_RATE_54MB; - } else - assert(0); - + } txrates->default_rate = IEEE80211_CCK_RATE_1MB; change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;