Commit 650b3b29 authored by Larry Finger's avatar Larry Finger Committed by Greg Kroah-Hartman

bcm43xx: fix regressions in 2.6.18

The bcm43xx code in 2.6.18 has a serious problems not found in 2.6.17, due to
a change in the locking mechanism introduced to reduce latency. The following patch
fixes the problems in locking, reduces the latency associated with the periodic
work tasklet, and contains code needed for those cards that use 64-bit DMA.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7752e010
This diff is collapsed.
...@@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, ...@@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
down(&big_buffer_sem); down(&big_buffer_sem);
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n"); fappend("Board not initialized.\n");
goto out; goto out;
...@@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, ...@@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
fappend("\n"); fappend("\n");
out: out:
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem); up(&big_buffer_sem);
return res; return res;
...@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, ...@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
unsigned long flags; unsigned long flags;
down(&big_buffer_sem); down(&big_buffer_sem);
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n"); fappend("Board not initialized.\n");
goto out; goto out;
...@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, ...@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
out: out:
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem); up(&big_buffer_sem);
return res; return res;
...@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, ...@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
u64 tsf; u64 tsf;
down(&big_buffer_sem); down(&big_buffer_sem);
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n"); fappend("Board not initialized.\n");
goto out; goto out;
...@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, ...@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
(unsigned int)(tsf & 0xFFFFFFFFULL)); (unsigned int)(tsf & 0xFFFFFFFFULL));
out: out:
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem); up(&big_buffer_sem);
return res; return res;
...@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, ...@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
res = -EFAULT; res = -EFAULT;
goto out_up; goto out_up;
} }
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
res = -EFAULT; res = -EFAULT;
...@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, ...@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
res = buf_size; res = buf_size;
out_unlock: out_unlock:
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
out_up: out_up:
up(&big_buffer_sem); up(&big_buffer_sem);
return res; return res;
...@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, ...@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
int i, cnt, j = 0; int i, cnt, j = 0;
down(&big_buffer_sem); down(&big_buffer_sem);
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
BCM43xx_NR_LOGGED_XMITSTATUS); BCM43xx_NR_LOGGED_XMITSTATUS);
...@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, ...@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
} }
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
bcm43xx_lock_irqsafe(bcm, flags); spin_lock_irqsave(&bcm->irq_lock, flags);
if (*ppos == pos) { if (*ppos == pos) {
/* Done. Drop the copied data. */ /* Done. Drop the copied data. */
e->xmitstatus_printing = 0; e->xmitstatus_printing = 0;
} }
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
up(&big_buffer_sem);
return res;
}
static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct bcm43xx_private *bcm = file->private_data;
char *buf = really_big_buffer;
ssize_t buf_size;
ssize_t res;
unsigned long flags;
buf_size = min(count, sizeof (really_big_buffer) - 1);
down(&big_buffer_sem);
if (copy_from_user(buf, user_buf, buf_size)) {
res = -EFAULT;
goto out_up;
}
mutex_lock(&(bcm)->mutex);
spin_lock_irqsave(&(bcm)->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
res = -EFAULT;
goto out_unlock;
}
if (count > 0 && buf[0] == '1') {
bcm43xx_controller_restart(bcm, "manually restarted");
res = count;
} else
res = -EINVAL;
out_unlock:
spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
mutex_unlock(&(bcm)->mutex);
out_up:
up(&big_buffer_sem); up(&big_buffer_sem);
return res; return res;
} }
...@@ -339,6 +385,11 @@ static struct file_operations txstat_fops = { ...@@ -339,6 +385,11 @@ static struct file_operations txstat_fops = {
.open = open_file_generic, .open = open_file_generic,
}; };
static struct file_operations restart_fops = {
.write = restart_write_file,
.open = open_file_generic,
};
void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
{ {
...@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) ...@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
bcm, &txstat_fops); bcm, &txstat_fops);
if (!e->dentry_txstat) if (!e->dentry_txstat)
printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
bcm, &restart_fops);
if (!e->dentry_restart)
printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
} }
void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
...@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) ...@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
debugfs_remove(e->dentry_devinfo); debugfs_remove(e->dentry_devinfo);
debugfs_remove(e->dentry_tsf); debugfs_remove(e->dentry_tsf);
debugfs_remove(e->dentry_txstat); debugfs_remove(e->dentry_txstat);
debugfs_remove(e->dentry_restart);
debugfs_remove(e->subdir); debugfs_remove(e->subdir);
kfree(e->xmitstatus_buffer); kfree(e->xmitstatus_buffer);
kfree(e->xmitstatus_print_buffer); kfree(e->xmitstatus_print_buffer);
......
...@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry { ...@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry {
struct dentry *dentry_spromdump; struct dentry *dentry_spromdump;
struct dentry *dentry_tsf; struct dentry *dentry_tsf;
struct dentry *dentry_txstat; struct dentry *dentry_txstat;
struct dentry *dentry_restart;
struct bcm43xx_private *bcm; struct bcm43xx_private *bcm;
......
This diff is collapsed.
This diff is collapsed.
...@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) ...@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d)
struct bcm43xx_private *bcm = led->bcm; struct bcm43xx_private *bcm = led->bcm;
unsigned long flags; unsigned long flags;
bcm43xx_lock_irqonly(bcm, flags); spin_lock_irqsave(&bcm->leds_lock, flags);
if (led->blink_interval) { if (led->blink_interval) {
bcm43xx_led_changestate(led); bcm43xx_led_changestate(led);
mod_timer(&led->blink_timer, jiffies + led->blink_interval); mod_timer(&led->blink_timer, jiffies + led->blink_interval);
} }
bcm43xx_unlock_irqonly(bcm, flags); spin_unlock_irqrestore(&bcm->leds_lock, flags);
} }
static void bcm43xx_led_blink_start(struct bcm43xx_led *led, static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
...@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ...@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
int i, turn_on; int i, turn_on;
unsigned long interval = 0; unsigned long interval = 0;
u16 ledctl; u16 ledctl;
unsigned long flags;
spin_lock_irqsave(&bcm->leds_lock, flags);
ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
for (i = 0; i < BCM43xx_NR_LEDS; i++) { for (i = 0; i < BCM43xx_NR_LEDS; i++) {
led = &(bcm->leds[i]); led = &(bcm->leds[i]);
...@@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ...@@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
ledctl &= ~(1 << i); ledctl &= ~(1 << i);
} }
bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
spin_unlock_irqrestore(&bcm->leds_lock, flags);
} }
void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
...@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) ...@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
u16 ledctl; u16 ledctl;
int i; int i;
int bit_on; int bit_on;
unsigned long flags;
spin_lock_irqsave(&bcm->leds_lock, flags);
ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
for (i = 0; i < BCM43xx_NR_LEDS; i++) { for (i = 0; i < BCM43xx_NR_LEDS; i++) {
led = &(bcm->leds[i]); led = &(bcm->leds[i]);
...@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) ...@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
ledctl &= ~(1 << i); ledctl &= ~(1 << i);
} }
bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
spin_unlock_irqrestore(&bcm->leds_lock, flags);
} }
This diff is collapsed.
...@@ -133,11 +133,17 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); ...@@ -133,11 +133,17 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
int phytype);
void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
void bcm43xx_mac_enable(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); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
......
...@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = { ...@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = {
static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
static inline
void bcm43xx_voluntary_preempt(void)
{
assert(!in_atomic() && !in_irq() &&
!in_interrupt() && !irqs_disabled());
#ifndef CONFIG_PREEMPT
cond_resched();
#endif /* CONFIG_PREEMPT */
}
void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
...@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) ...@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
unsigned long flags;
bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
if (phy->calibrated) if (phy->calibrated)
return; return;
if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
/* We do not want to be preempted while calibrating
* the hardware.
*/
local_irq_save(flags);
bcm43xx_wireless_core_reset(bcm, 0); bcm43xx_wireless_core_reset(bcm, 0);
bcm43xx_phy_initg(bcm); bcm43xx_phy_initg(bcm);
bcm43xx_wireless_core_reset(bcm, 1); bcm43xx_wireless_core_reset(bcm, 1);
local_irq_restore(flags);
} }
phy->calibrated = 1; phy->calibrated = 1;
} }
...@@ -359,7 +361,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) ...@@ -359,7 +361,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
if (phy->rev <= 2) if (phy->rev <= 2)
for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
else else
...@@ -369,7 +371,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) ...@@ -369,7 +371,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
if (phy->rev == 2) if (phy->rev == 2)
for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
else if ((phy->rev > 2) && (phy->rev <= 7)) else if ((phy->rev > 2) && (phy->rev <= 8))
for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
...@@ -1195,7 +1197,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) ...@@ -1195,7 +1197,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
if (phy->rev == 1) if (phy->rev == 1)
bcm43xx_phy_initb5(bcm); bcm43xx_phy_initb5(bcm);
else if (phy->rev >= 2 && phy->rev <= 7) else
bcm43xx_phy_initb6(bcm); bcm43xx_phy_initb6(bcm);
if (phy->rev >= 2 || phy->connected) if (phy->rev >= 2 || phy->connected)
bcm43xx_phy_inita(bcm); bcm43xx_phy_inita(bcm);
...@@ -1239,23 +1241,22 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) ...@@ -1239,23 +1241,22 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
bcm43xx_phy_lo_g_measure(bcm); bcm43xx_phy_lo_g_measure(bcm);
} else { } else {
if (radio->version == 0x2050 && radio->revision == 8) { if (radio->version == 0x2050 && radio->revision == 8) {
//FIXME bcm43xx_radio_write16(bcm, 0x0052,
(radio->txctl1 << 4) | radio->txctl2);
} else { } else {
bcm43xx_radio_write16(bcm, 0x0052, bcm43xx_radio_write16(bcm, 0x0052,
(bcm43xx_radio_read16(bcm, 0x0052) (bcm43xx_radio_read16(bcm, 0x0052)
& 0xFFF0) | radio->txctl1); & 0xFFF0) | radio->txctl1);
} }
if (phy->rev >= 6) { if (phy->rev >= 6) {
/*
bcm43xx_phy_write(bcm, 0x0036, bcm43xx_phy_write(bcm, 0x0036,
(bcm43xx_phy_read(bcm, 0x0036) (bcm43xx_phy_read(bcm, 0x0036)
& 0xF000) | (FIXME << 12)); & 0xF000) | (radio->txctl2 << 12));
*/
} }
if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
bcm43xx_phy_write(bcm, 0x002E, 0x8075); bcm43xx_phy_write(bcm, 0x002E, 0x8075);
else else
bcm43xx_phy_write(bcm, 0x003E, 0x807F); bcm43xx_phy_write(bcm, 0x002E, 0x807F);
if (phy->rev < 2) if (phy->rev < 2)
bcm43xx_phy_write(bcm, 0x002F, 0x0101); bcm43xx_phy_write(bcm, 0x002F, 0x0101);
else else
...@@ -1299,7 +1300,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) ...@@ -1299,7 +1300,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
{ {
int i; int i;
u16 ret = 0; u16 ret = 0;
unsigned long flags;
local_irq_save(flags);
for (i = 0; i < 10; i++){ for (i = 0; i < 10; i++){
bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
udelay(1); udelay(1);
...@@ -1309,6 +1312,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) ...@@ -1309,6 +1312,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
udelay(40); udelay(40);
ret += bcm43xx_phy_read(bcm, 0x002C); ret += bcm43xx_phy_read(bcm, 0x002C);
} }
local_irq_restore(flags);
bcm43xx_voluntary_preempt();
return ret; return ret;
} }
...@@ -1435,6 +1440,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) ...@@ -1435,6 +1440,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
} }
ret = bcm43xx_phy_read(bcm, 0x002D); ret = bcm43xx_phy_read(bcm, 0x002D);
local_irq_restore(flags); local_irq_restore(flags);
bcm43xx_voluntary_preempt();
return ret; return ret;
} }
...@@ -1760,6 +1766,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) ...@@ -1760,6 +1766,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
bcm43xx_radio_write16(bcm, 0x43, i); bcm43xx_radio_write16(bcm, 0x43, i);
bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
udelay(10); udelay(10);
bcm43xx_voluntary_preempt();
bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
...@@ -1803,6 +1810,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) ...@@ -1803,6 +1810,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
radio->txctl2 radio->txctl2
| (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
udelay(10); udelay(10);
bcm43xx_voluntary_preempt();
bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
...@@ -1824,6 +1832,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) ...@@ -1824,6 +1832,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
udelay(2); udelay(2);
bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
bcm43xx_voluntary_preempt();
} else } else
bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
bcm43xx_phy_lo_adjust(bcm, is_initializing); bcm43xx_phy_lo_adjust(bcm, is_initializing);
...@@ -2188,12 +2197,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) ...@@ -2188,12 +2197,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
int err = -ENODEV; int err = -ENODEV;
unsigned long flags;
/* We do not want to be preempted while calibrating
* the hardware.
*/
local_irq_save(flags);
switch (phy->type) { switch (phy->type) {
case BCM43xx_PHYTYPE_A: case BCM43xx_PHYTYPE_A:
...@@ -2227,7 +2230,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) ...@@ -2227,7 +2230,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
err = 0; err = 0;
break; break;
} }
local_irq_restore(flags);
if (err) if (err)
printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
......
...@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d) ...@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d)
int err; int err;
u16 txctl; u16 txctl;
bcm43xx_lock_irqonly(bcm, flags); spin_lock_irqsave(&bcm->irq_lock, flags);
if (queue->tx_frozen) if (queue->tx_frozen)
goto out_unlock; goto out_unlock;
...@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d) ...@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d)
continue; continue;
} }
out_unlock: out_unlock:
bcm43xx_unlock_irqonly(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
} }
static void setup_txqueues(struct bcm43xx_pioqueue *queue) static void setup_txqueues(struct bcm43xx_pioqueue *queue)
......
...@@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, ...@@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
GFP_KERNEL); GFP_KERNEL);
if (!sprom) if (!sprom)
return -ENOMEM; return -ENOMEM;
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
err = bcm43xx_sprom_read(bcm, sprom); err = bcm43xx_sprom_read(bcm, sprom);
if (!err) if (!err)
err = sprom2hex(sprom, buf, PAGE_SIZE); err = sprom2hex(sprom, buf, PAGE_SIZE);
mmiowb(); mmiowb();
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
kfree(sprom); kfree(sprom);
return err; return err;
...@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, ...@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
err = hex2sprom(sprom, buf, count); err = hex2sprom(sprom, buf, count);
if (err) if (err)
goto out_kfree; goto out_kfree;
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
spin_lock(&bcm->leds_lock);
err = bcm43xx_sprom_write(bcm, sprom); err = bcm43xx_sprom_write(bcm, sprom);
mmiowb(); mmiowb();
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock(&bcm->leds_lock);
spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
out_kfree: out_kfree:
kfree(sprom); kfree(sprom);
...@@ -170,13 +176,12 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, ...@@ -170,13 +176,12 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
char *buf) char *buf)
{ {
struct bcm43xx_private *bcm = dev_to_bcm(dev); struct bcm43xx_private *bcm = dev_to_bcm(dev);
int err;
ssize_t count = 0; ssize_t count = 0;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
bcm43xx_lock_noirq(bcm); mutex_lock(&bcm->mutex);
switch (bcm43xx_current_radio(bcm)->interfmode) { switch (bcm43xx_current_radio(bcm)->interfmode) {
case BCM43xx_RADIO_INTERFMODE_NONE: case BCM43xx_RADIO_INTERFMODE_NONE:
...@@ -191,11 +196,10 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, ...@@ -191,11 +196,10 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
default: default:
assert(0); assert(0);
} }
err = 0;
bcm43xx_unlock_noirq(bcm); mutex_unlock(&bcm->mutex);
return err ? err : count; return count;
} }
...@@ -229,7 +233,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, ...@@ -229,7 +233,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
return -EINVAL; return -EINVAL;
} }
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
err = bcm43xx_radio_set_interference_mitigation(bcm, mode); err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
if (err) { if (err) {
...@@ -237,7 +242,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, ...@@ -237,7 +242,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
"supported by device\n"); "supported by device\n");
} }
mmiowb(); mmiowb();
bcm43xx_unlock_irqsafe(bcm, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
mutex_unlock(&bcm->mutex);
return err ? err : count; return err ? err : count;
} }
...@@ -251,23 +257,21 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, ...@@ -251,23 +257,21 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
char *buf) char *buf)
{ {
struct bcm43xx_private *bcm = dev_to_bcm(dev); struct bcm43xx_private *bcm = dev_to_bcm(dev);
int err;
ssize_t count; ssize_t count;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
bcm43xx_lock_noirq(bcm); mutex_lock(&bcm->mutex);
if (bcm->short_preamble) if (bcm->short_preamble)
count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
else else
count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
err = 0; mutex_unlock(&bcm->mutex);
bcm43xx_unlock_noirq(bcm);
return err ? err : count; return count;
} }
static ssize_t bcm43xx_attr_preamble_store(struct device *dev, static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
...@@ -276,7 +280,6 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, ...@@ -276,7 +280,6 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
{ {
struct bcm43xx_private *bcm = dev_to_bcm(dev); struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags; unsigned long flags;
int err;
int value; int value;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
...@@ -285,14 +288,15 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, ...@@ -285,14 +288,15 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
value = get_boolean(buf, count); value = get_boolean(buf, count);
if (value < 0) if (value < 0)
return value; return value;
bcm43xx_lock_irqsafe(bcm, flags); mutex_lock(&bcm->mutex);
spin_lock_irqsave(&bcm->irq_lock, flags);
bcm->short_preamble = !!value; bcm->short_preamble = !!value;
err = 0; spin_unlock_irqrestore(&bcm->irq_lock, flags);
bcm43xx_unlock_irqsafe(bcm, flags); mutex_unlock(&bcm->mutex);
return err ? err : count; return count;
} }
static DEVICE_ATTR(shortpreamble, 0644, static DEVICE_ATTR(shortpreamble, 0644,
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment