From f04e2be7d9b73a1da7be99a08b3695074e14970c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 25 Sep 2006 15:33:20 -0500 Subject: [PATCH] bcm43xx: output proper link quality with scans The bcm43xx-softmac driver fails to set two quantities needed for iwlist to compute wireless quality when scanning. As a result, userland programs using the quality to determine the best connection fail. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a1b783813d8..2ffc0d5b54e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3688,6 +3688,8 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) phy_type); return -ENODEV; }; + bcm->ieee->perfect_rssi = RX_RSSI_MAX; + bcm->ieee->worst_rssi = 0; if (!phy_rev_ok) { printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", phy_rev); -- cgit v1.2.3 From f3d1fca3eb05cf6ff3879a385a15d24fbf556c57 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Sun, 15 Oct 2006 23:18:11 -0500 Subject: [PATCH] bcm43xx: add PCI-E code The current bcm43xx driver does not contain code to handle PCI-E interfaces such as the BCM4311 and BCM4312. This patch, originally written by Stefano Brivio adds the necessary code to enable these interfaces. Signed-off-by: Stefano Brivio Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 143 +++++++++++++++++++++------- 1 file changed, 106 insertions(+), 37 deletions(-) (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 2ffc0d5b54e..c6bd86889f1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4307 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4311 802.11(a)/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4312 802.11a/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4318 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4319 802.11a/b/g */ @@ -2600,8 +2604,9 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) /* fetch sb_id_hi from core information registers */ sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - core_id = (sb_id_hi & 0xFFF0) >> 4; - core_rev = (sb_id_hi & 0xF); + core_id = (sb_id_hi & 0x8FF0) >> 4; + core_rev = (sb_id_hi & 0x7000) >> 8; + core_rev |= (sb_id_hi & 0xF); core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; /* if present, chipcommon is always core 0; read the chipid from it */ @@ -2711,6 +2716,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core = NULL; switch (core_id) { case BCM43xx_COREID_PCI: + case BCM43xx_COREID_PCIE: core = &bcm->core_pci; if (core->available) { printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); @@ -2749,12 +2755,12 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) case 6: case 7: case 9: + case 10: break; default: - printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", + printk(KERN_WARNING PFX + "Unsupported 80211 core revision %u\n", core_rev); - err = -ENODEV; - goto out; } bcm->nr_80211_available++; core->priv = ext_80211; @@ -2868,16 +2874,11 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, u32 sbimconfiglow; u8 limit; - if (bcm->chip_rev < 5) { + if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) - sbimconfiglow |= 0x32; - else if (bcm->bustype == BCM43xx_BUSTYPE_SB) - sbimconfiglow |= 0x53; - else - assert(0); + sbimconfiglow |= 0x32; bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); } @@ -3004,22 +3005,64 @@ static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) { - int err; - struct bcm43xx_coreinfo *old_core; + int err = 0; - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; + bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + if (bcm->core_chipcommon.available) { + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err) + goto out; + + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + /* this function is always called when a PCI core is mapped */ + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + } else + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm43xx_switch_core(bcm, old_core); - assert(err == 0); out: return err; } +static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address) +{ + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); + return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA); +} + +static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address, + u32 data) +{ + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data); +} + +static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg, + u16 data) +{ + int i; + + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082); + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST | + BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) | + (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA | + data); + udelay(10); + + for (i = 0; i < 10; i++) { + if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) & + BCM43xx_PCIE_MDIO_TC) + break; + msleep(1); + } + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0); +} + /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. * To enable core 0, pass a core_mask of 1<<0 */ @@ -3039,7 +3082,8 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, if (err) goto out; - if (bcm->core_pci.rev < 6) { + if (bcm->current_core->rev < 6 || + bcm->current_core->id == BCM43xx_COREID_PCI) { value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); value |= (1 << backplane_flag_nr); bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); @@ -3057,21 +3101,46 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, } } - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - - if (bcm->core_pci.rev < 5) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); - err = bcm43xx_pcicore_commit_settings(bcm); - assert(err == 0); + if (bcm->current_core->id == BCM43xx_COREID_PCI) { + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + + if (bcm->current_core->rev < 5) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); + err = bcm43xx_pcicore_commit_settings(bcm); + assert(err == 0); + } else if (bcm->current_core->rev >= 11) { + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + } + } else { + if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) { + value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND); + value |= 0x8; + bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND, + value); + } + if (bcm->current_core->rev == 0) { + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_RXTIMER, 0x8128); + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_CDR, 0x0100); + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_CDR_BW, 0x1466); + } else if (bcm->current_core->rev == 1) { + value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL); + value |= 0x40; + bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL, + value); + } } - out_switch_back: err = bcm43xx_switch_core(bcm, old_core); out: @@ -3676,7 +3745,7 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; break; case BCM43xx_PHYTYPE_G: - if (phy_rev > 7) + if (phy_rev > 8) phy_rev_ok = 0; bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; -- cgit v1.2.3 From 08c3103a562ed83c4f9ac8fad6f5cb1ebb1f29a0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 1 Nov 2006 18:11:18 -0600 Subject: [PATCH] bcm43xx: remove badness variable and related routine When the periodic work function in bcm43xx was converted for voluntary preemption to reduce latency, a new function was created to estimate the "badness" of each step, and this quantity was used to determine if preemption should be enabled when periodic work was undertaken. This concept was quite useful while debugging of periodic work was in progress. Now that this routine seems to be working correctly, it is time to simplify the code. This patch keeps the functionality intact, but simplifies the code. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 41 +++++------------------------ 1 file changed, 7 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c6bd86889f1..b199d32c37e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3209,55 +3209,27 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) static void do_periodic_work(struct bcm43xx_private *bcm) { - unsigned int state; - - state = bcm->periodic_state; - if (state % 8 == 0) + if (bcm->periodic_state % 8 == 0) bcm43xx_periodic_every120sec(bcm); - if (state % 4 == 0) + if (bcm->periodic_state % 4 == 0) bcm43xx_periodic_every60sec(bcm); - if (state % 2 == 0) + if (bcm->periodic_state % 2 == 0) bcm43xx_periodic_every30sec(bcm); - if (state % 1 == 0) - bcm43xx_periodic_every15sec(bcm); - bcm->periodic_state = state + 1; + bcm43xx_periodic_every15sec(bcm); schedule_delayed_work(&bcm->periodic_work, HZ * 15); } -/* Estimate a "Badness" value based on the periodic work - * state-machine state. "Badness" is worse (bigger), if the - * periodic work will take longer. - */ -static int estimate_periodic_work_badness(unsigned int state) -{ - int badness = 0; - - if (state % 8 == 0) /* every 120 sec */ - badness += 10; - if (state % 4 == 0) /* every 60 sec */ - badness += 5; - if (state % 2 == 0) /* every 30 sec */ - badness += 1; - if (state % 1 == 0) /* every 15 sec */ - badness += 1; - -#define BADNESS_LIMIT 4 - return badness; -} - static void bcm43xx_periodic_work_handler(void *d) { struct bcm43xx_private *bcm = d; struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; - int badness; unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); - badness = estimate_periodic_work_badness(bcm->periodic_state); - if (badness > BADNESS_LIMIT) { + if (unlikely(bcm->periodic_state % 4 == 0)) { /* Periodic work will take a long time, so we want it to * be preemtible. */ @@ -3289,7 +3261,7 @@ static void bcm43xx_periodic_work_handler(void *d) do_periodic_work(bcm); - if (badness > BADNESS_LIMIT) { + if (unlikely(bcm->periodic_state % 4 == 0)) { spin_lock_irqsave(&bcm->irq_lock, flags); tasklet_enable(&bcm->isr_tasklet); bcm43xx_interrupt_enable(bcm, savedirqs); @@ -3300,6 +3272,7 @@ static void bcm43xx_periodic_work_handler(void *d) net_dev->trans_start = orig_trans_start; } mmiowb(); + bcm->periodic_state++; spin_unlock_irqrestore(&bcm->irq_lock, flags); mutex_unlock(&bcm->mutex); } -- cgit v1.2.3 From 7f424ff4825adeae8d236fb3eafd699e6b2665e1 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 2 Nov 2006 21:56:52 -0600 Subject: [PATCH] bcm43xx: Remove useless core enable/disable messages In the softmac version of bcm43xx, the core scan logs whether each core is enabled or disabled. This information is useless as one of the next steps is to enable all cores. This patch removes this output from the log. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b199d32c37e..60a97450a6e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2684,14 +2684,10 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) bcm->chip_id, bcm->chip_rev); dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); if (bcm->core_chipcommon.available) { - dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", - core_id, core_rev, core_vendor, - bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); - } - - if (bcm->core_chipcommon.available) + dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n", + core_id, core_rev, core_vendor); current_core = 1; - else + } else current_core = 0; for ( ; current_core < core_count; current_core++) { struct bcm43xx_coreinfo *core; @@ -2709,9 +2705,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core_rev = (sb_id_hi & 0xF); core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", - current_core, core_id, core_rev, core_vendor, - bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" ); + dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n", + current_core, core_id, core_rev, core_vendor); core = NULL; switch (core_id) { -- cgit v1.2.3 From 718cc4ca2bfb3263c7ea3ceba9c194f9cd7292e2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 03:15:46 +0000 Subject: [PATCH] ieee80211: Provide generic get_stats implementation bcm43xx and ipw2100 currently duplicate the same simplistic get_stats handler. Additionally, zd1211rw requires the same handler to fix a bug where all stats are reported as 0. This patch adds a generic implementation to the ieee80211 layer, which drivers are free to override. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 60a97450a6e..5b3c27359a1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4013,11 +4013,6 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, return NETDEV_TX_OK; } -static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) -{ - return &(bcm43xx_priv(net_dev)->ieee->stats); -} - static void bcm43xx_net_tx_timeout(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); @@ -4131,7 +4126,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, net_dev->open = bcm43xx_net_open; net_dev->stop = bcm43xx_net_stop; - net_dev->get_stats = bcm43xx_net_get_stats; net_dev->tx_timeout = bcm43xx_net_tx_timeout; #ifdef CONFIG_NET_POLL_CONTROLLER net_dev->poll_controller = bcm43xx_net_poll_controller; -- cgit v1.2.3