Commit c925f1ea authored by Jeff Garzik's avatar Jeff Garzik
Browse files

Merge branch 'upstream' of...

parents 8083e165 884d3a2b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -306,6 +306,13 @@
#define BCM43xx_SBF_TIME_UPDATE		0x10000000
#define BCM43xx_SBF_80000000		0x80000000 /*FIXME: fix name*/

/* Microcode */
#define BCM43xx_UCODE_REVISION		0x0000
#define BCM43xx_UCODE_PATCHLEVEL	0x0002
#define BCM43xx_UCODE_DATE		0x0004
#define BCM43xx_UCODE_TIME		0x0006
#define BCM43xx_UCODE_STATUS		0x0040

/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
#define BCM43xx_UCODEFLAGS_OFFSET	0x005E

+50 −28
Original line number Diff line number Diff line
@@ -519,6 +519,7 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
		return -EBUSY;
	}
	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
	spin_unlock_irqrestore(&bcm->irq_lock, flags);
	bcm43xx_synchronize_irq(bcm);

@@ -1545,17 +1546,7 @@ static void handle_irq_noise(struct bcm43xx_private *bcm)
		else
			average -= 48;

/* FIXME: This is wrong, but people want fancy stats. well... */
		bcm->stats.noise = average;
		if (average > -65)
			bcm->stats.link_quality = 0;
		else if (average > -75)
			bcm->stats.link_quality = 1;
		else if (average > -85)
			bcm->stats.link_quality = 2;
		else
			bcm->stats.link_quality = 3;
//		dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
drop_calculation:
		bcm->noisecalc.calculation_running = 0;
		return;
@@ -2393,6 +2384,33 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
	}
	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */

	value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				     BCM43xx_UCODE_REVISION);

	dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
		"(20%.2i-%.2i-%.2i  %.2i:%.2i:%.2i)\n", value16,
		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				   BCM43xx_UCODE_PATCHLEVEL),
		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				    BCM43xx_UCODE_DATE) >> 12) & 0xf,
		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				    BCM43xx_UCODE_DATE) >> 8) & 0xf,
		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				   BCM43xx_UCODE_DATE) & 0xff,
		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				   BCM43xx_UCODE_TIME) >> 11) & 0x1f,
		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				   BCM43xx_UCODE_TIME) >> 5) & 0x3f,
		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				   BCM43xx_UCODE_TIME) & 0x1f);

	if ( value16 > 0x128 ) {
		dprintk(KERN_ERR PFX
			"Firmware: no support for microcode rev > 0x128\n");
		err = -1;
		goto err_release_fw;
	}

	err = bcm43xx_gpio_init(bcm);
	if (err)
		goto err_release_fw;
@@ -3150,6 +3168,7 @@ static void bcm43xx_periodic_work_handler(void *d)
		/* Periodic work will take a long time, so we want it to
		 * be preemtible.
		 */
		mutex_lock(&bcm->mutex);
		netif_stop_queue(bcm->net_dev);
		synchronize_net();
		spin_lock_irqsave(&bcm->irq_lock, flags);
@@ -3158,7 +3177,6 @@ static void bcm43xx_periodic_work_handler(void *d)
			bcm43xx_pio_freeze_txqueues(bcm);
		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
		spin_unlock_irqrestore(&bcm->irq_lock, flags);
		mutex_lock(&bcm->mutex);
		bcm43xx_synchronize_irq(bcm);
	} else {
		/* Periodic work should take short time, so we want low
@@ -3172,13 +3190,11 @@ static void bcm43xx_periodic_work_handler(void *d)

	if (badness > BADNESS_LIMIT) {
		spin_lock_irqsave(&bcm->irq_lock, flags);
		if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
		tasklet_enable(&bcm->isr_tasklet);
		bcm43xx_interrupt_enable(bcm, savedirqs);
		if (bcm43xx_using_pio(bcm))
			bcm43xx_pio_thaw_txqueues(bcm);
		bcm43xx_mac_enable(bcm);
		}
		netif_wake_queue(bcm->net_dev);
	}
	mmiowb();
@@ -3186,12 +3202,12 @@ static void bcm43xx_periodic_work_handler(void *d)
	mutex_unlock(&bcm->mutex);
}

static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
{
	cancel_rearming_delayed_work(&bcm->periodic_work);
}

static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
{
	struct work_struct *work = &(bcm->periodic_work);

@@ -3539,14 +3555,13 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
	err = bcm43xx_select_wireless_core(bcm, -1);
	if (err)
		goto err_crystal_off;

	bcm43xx_periodic_tasks_setup(bcm);
	err = bcm43xx_sysfs_register(bcm);
	if (err)
		goto err_wlshutdown;
	err = bcm43xx_rng_init(bcm);
	if (err)
		goto err_sysfs_unreg;
	bcm43xx_periodic_tasks_setup(bcm);

	/*FIXME: This should be handled by softmac instead. */
	schedule_work(&bcm->softmac->associnfo.work);
@@ -3969,6 +3984,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
	err = bcm43xx_disable_interrupts_sync(bcm);
	assert(!err);
	bcm43xx_free_board(bcm);
	flush_scheduled_work();

	return 0;
}
@@ -4119,11 +4135,16 @@ static void bcm43xx_chip_reset(void *_bcm)
{
	struct bcm43xx_private *bcm = _bcm;
	struct bcm43xx_phyinfo *phy;
	int err;
	int err = -ENODEV;

	mutex_lock(&(bcm)->mutex);
	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
		bcm43xx_periodic_tasks_delete(bcm);
		phy = bcm43xx_current_phy(bcm);
		err = bcm43xx_select_wireless_core(bcm, phy->type);
		if (!err)
			bcm43xx_periodic_tasks_setup(bcm);
	}
	mutex_unlock(&(bcm)->mutex);

	printk(KERN_ERR PFX "Controller restart%s\n",
@@ -4132,11 +4153,12 @@ static void bcm43xx_chip_reset(void *_bcm)

/* Hard-reset the chip.
 * This can be called from interrupt or process context.
 * bcm->irq_lock must be locked.
 */
void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
{
	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
	bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
	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);
	schedule_work(&bcm->restart_work);
+3 −0
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
void bcm43xx_mac_enable(struct bcm43xx_private *bcm);

void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm);
void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);

void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);

int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
+65 −9
Original line number Diff line number Diff line
@@ -176,7 +176,6 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
					    char *buf)
{
	struct bcm43xx_private *bcm = dev_to_bcm(dev);
	int err;
	ssize_t count = 0;

	if (!capable(CAP_NET_ADMIN))
@@ -197,11 +196,10 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
	default:
		assert(0);
	}
	err = 0;

	mutex_unlock(&bcm->mutex);

	return err ? err : count;
	return count;

}

@@ -259,7 +257,6 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
					  char *buf)
{
	struct bcm43xx_private *bcm = dev_to_bcm(dev);
	int err;
	ssize_t count;

	if (!capable(CAP_NET_ADMIN))
@@ -272,10 +269,9 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
	else
		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");

	err = 0;
	mutex_unlock(&bcm->mutex);

	return err ? err : count;
	return count;
}

static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
@@ -284,7 +280,6 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
{
	struct bcm43xx_private *bcm = dev_to_bcm(dev);
	unsigned long flags;
	int err;
	int value;

	if (!capable(CAP_NET_ADMIN))
@@ -298,11 +293,10 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,

	bcm->short_preamble = !!value;

	err = 0;
	spin_unlock_irqrestore(&bcm->irq_lock, flags);
	mutex_unlock(&bcm->mutex);

	return err ? err : count;
	return count;
}

static DEVICE_ATTR(shortpreamble, 0644,
@@ -333,8 +327,11 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
		goto out;
	}

	bcm43xx_periodic_tasks_delete(bcm);
	mutex_lock(&(bcm)->mutex);
	err = bcm43xx_select_wireless_core(bcm, phytype);
	if (!err)
		bcm43xx_periodic_tasks_setup(bcm);
	mutex_unlock(&(bcm)->mutex);
	if (err == -ESRCH)
		err = -ENODEV;
@@ -373,6 +370,59 @@ static DEVICE_ATTR(phymode, 0644,
		   bcm43xx_attr_phymode_show,
		   bcm43xx_attr_phymode_store);

static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
					   struct device_attribute *attr,
					   char *buf)
{
	unsigned long flags;
	struct bcm43xx_private *bcm = dev_to_bcm(dev);
	ssize_t count = 0;
	u16 status;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	mutex_lock(&(bcm)->mutex);
	spin_lock_irqsave(&bcm->irq_lock, flags);
	status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
				    BCM43xx_UCODE_STATUS);

	spin_unlock_irqrestore(&bcm->irq_lock, flags);
	mutex_unlock(&(bcm)->mutex);
	switch (status) {
	case 0x0000:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
				 status);
		break;
	case 0x0001:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
				 status);
		break;
	case 0x0002:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
				 status);
		break;
	case 0x0003:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
				 status);
		break;
	case 0x0004:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
				 status);
		break;
	default:
		count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
				 status);
		break;
	}

	return count;
}

static DEVICE_ATTR(microcodestatus, 0444,
		   bcm43xx_attr_microcode_show,
		   NULL);

int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
{
	struct device *dev = &bcm->pci_dev->dev;
@@ -392,9 +442,14 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
	err = device_create_file(dev, &dev_attr_phymode);
	if (err)
		goto err_remove_shortpreamble;
	err = device_create_file(dev, &dev_attr_microcodestatus);
	if (err)
		goto err_remove_phymode;

out:
	return err;
err_remove_phymode:
	device_remove_file(dev, &dev_attr_phymode);
err_remove_shortpreamble:
	device_remove_file(dev, &dev_attr_shortpreamble);
err_remove_interfmode:
@@ -408,6 +463,7 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
{
	struct device *dev = &bcm->pci_dev->dev;

	device_remove_file(dev, &dev_attr_microcodestatus);
	device_remove_file(dev, &dev_attr_phymode);
	device_remove_file(dev, &dev_attr_shortpreamble);
	device_remove_file(dev, &dev_attr_interference);
+1 −0
Original line number Diff line number Diff line
@@ -847,6 +847,7 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002),
	PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL",
					 0x74c5e40d),
	PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil",
Loading