]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/bcm43xx/bcm43xx_main.c
Merge branch 'audit.b37' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit...
[linux-2.6] / drivers / net / wireless / bcm43xx / bcm43xx_main.c
index 5b3c27359a1840ba2c2bf59bd1264da401fd720e..2e400aacc436e2a72d10ab2f18a7875a15e0bfa5 100644 (file)
@@ -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,
@@ -2441,6 +2437,9 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
        if (err)
                goto err_gpio_cleanup;
        bcm43xx_radio_turn_on(bcm);
+       bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+       dprintk(KERN_INFO PFX "Radio %s by hardware\n",
+               (bcm->radio_hw_enable == 0) ? "disabled" : "enabled");
 
        bcm43xx_write16(bcm, 0x03E6, 0x0000);
        err = bcm43xx_phy_init(bcm);
@@ -2701,8 +2700,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
                sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
 
                /* extract core_id, core_rev, core_vendor */
-               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 & 0xF) | ((sb_id_hi & 0x7000) >> 8));
                core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
 
                dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
@@ -2873,7 +2872,10 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
                sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
                sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
                sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-               sbimconfiglow |= 0x32;
+               if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+                       sbimconfiglow |= 0x32;
+               else
+                       sbimconfiglow |= 0x53;
                bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
        }
 
@@ -2977,8 +2979,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;
@@ -3077,7 +3081,7 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
        if (err)
                goto out;
 
-       if (bcm->current_core->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);
@@ -3171,10 +3175,25 @@ static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
 }
 
 static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
+{
+       bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
+       //TODO for APHY (temperature?)
+}
+
+static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+       int radio_hw_enable;
 
+       /* check if radio hardware enabled status changed */
+       radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+       if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) {
+               bcm->radio_hw_enable = radio_hw_enable;
+               dprintk(KERN_INFO PFX "Radio hardware status changed to %s\n",
+                      (radio_hw_enable == 0) ? "disabled" : "enabled");
+               bcm43xx_leds_update(bcm, 0);
+       }
        if (phy->type == BCM43xx_PHYTYPE_G) {
                //TODO: update_aci_moving_average
                if (radio->aci_enable && radio->aci_wlan_automatic) {
@@ -3198,33 +3217,34 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
                        //TODO: implement rev1 workaround
                }
        }
-       bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
-       //TODO for APHY (temperature?)
 }
 
 static void do_periodic_work(struct bcm43xx_private *bcm)
 {
-       if (bcm->periodic_state % 8 == 0)
+       if (bcm->periodic_state % 120 == 0)
                bcm43xx_periodic_every120sec(bcm);
-       if (bcm->periodic_state % 4 == 0)
+       if (bcm->periodic_state % 60 == 0)
                bcm43xx_periodic_every60sec(bcm);
-       if (bcm->periodic_state % 2 == 0)
+       if (bcm->periodic_state % 30 == 0)
                bcm43xx_periodic_every30sec(bcm);
-       bcm43xx_periodic_every15sec(bcm);
+       if (bcm->periodic_state % 15 == 0)
+               bcm43xx_periodic_every15sec(bcm);
+       bcm43xx_periodic_every1sec(bcm);
 
-       schedule_delayed_work(&bcm->periodic_work, HZ * 15);
+       schedule_delayed_work(&bcm->periodic_work, HZ);
 }
 
-static void bcm43xx_periodic_work_handler(void *d)
+static void bcm43xx_periodic_work_handler(struct work_struct *work)
 {
-       struct bcm43xx_private *bcm = d;
+       struct bcm43xx_private *bcm =
+               container_of(work, struct bcm43xx_private, periodic_work.work);
        struct net_device *net_dev = bcm->net_dev;
        unsigned long flags;
        u32 savedirqs = 0;
        unsigned long orig_trans_start = 0;
 
        mutex_lock(&bcm->mutex);
-       if (unlikely(bcm->periodic_state % 4 == 0)) {
+       if (unlikely(bcm->periodic_state % 60 == 0)) {
                /* Periodic work will take a long time, so we want it to
                 * be preemtible.
                 */
@@ -3256,7 +3276,7 @@ static void bcm43xx_periodic_work_handler(void *d)
 
        do_periodic_work(bcm);
 
-       if (unlikely(bcm->periodic_state % 4 == 0)) {
+       if (unlikely(bcm->periodic_state % 60 == 0)) {
                spin_lock_irqsave(&bcm->irq_lock, flags);
                tasklet_enable(&bcm->isr_tasklet);
                bcm43xx_interrupt_enable(bcm, savedirqs);
@@ -3279,11 +3299,11 @@ void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
 
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-       struct work_struct *work = &(bcm->periodic_work);
+       struct delayed_work *work = &bcm->periodic_work;
 
        assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-       INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
-       schedule_work(work);
+       INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
+       schedule_delayed_work(work, 0);
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3635,7 +3655,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
        bcm43xx_periodic_tasks_setup(bcm);
 
        /*FIXME: This should be handled by softmac instead. */
-       schedule_work(&bcm->softmac->associnfo.work);
+       schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
 
 out:
        mutex_unlock(&(bcm)->mutex);
@@ -3774,12 +3794,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)
@@ -3870,6 +3896,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;
 }
 
@@ -4182,9 +4209,10 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
 /* Hard-reset the chip. Do not call this directly.
  * Use bcm43xx_controller_restart()
  */
-static void bcm43xx_chip_reset(void *_bcm)
+static void bcm43xx_chip_reset(struct work_struct *work)
 {
-       struct bcm43xx_private *bcm = _bcm;
+       struct bcm43xx_private *bcm =
+               container_of(work, struct bcm43xx_private, restart_work);
        struct bcm43xx_phyinfo *phy;
        int err = -ENODEV;
 
@@ -4211,7 +4239,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
        if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
                return;
        printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
-       INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
+       INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
        schedule_work(&bcm->restart_work);
 }