From 1c014420583564ac09e3b67006f2e7050861e66b Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Thu, 17 Apr 2008 19:41:02 +0200 Subject: mac80211: Replace ieee80211_tx_control->key_idx with ieee80211_key_conf The hw_key_idx inside the ieee80211_key_conf structure does not provide all the information drivers might need to perform hardware encryption. This is in particular true for rt2x00 who needs to know the key algorithm and whether it is a shared or pairwise key. By passing the ieee80211_key_conf pointer it assures us that drivers can make full use of all information that it should know about a particular key. Additionally this patch updates all drivers to grab the hw_key_idx from the ieee80211_key_conf structure. v2: Removed bogus u16 cast v3: Add warning about ieee80211_tx_control pointers v4: Update warning about ieee80211_tx_control pointers Signed-off-by: Ivo van Doorn Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 19aefbfb2c9..88491947a20 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -235,7 +235,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, plcp_fragment_len = fragment_len + FCS_LEN; if (use_encryption) { - u8 key_idx = (u16) (txctl->key_idx); + u8 key_idx = txctl->hw_key->hw_key_idx; struct b43_key *key; int wlhdr_len; size_t iv_len; -- cgit v1.2.3 From f5eda47f45e90dfa38e25d569b9ac84ba94f8301 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 20 Apr 2008 16:03:32 +0200 Subject: b43: Rewrite LO calibration algorithm This patch distributes the Local Oscillator calibration bursts over time, so that calibration only happens when it's actually needed. Currently we periodically perform a recalibration of the whole table. The table is huge and this takes lots of time. Additionally only small bits of the table are actually needed at a given time. So instead of maintaining a huge table with all possible calibration values, we create dynamic calibration settings that a) We only calibrate when they are actually needed. b) Are cached for some time until they expire. So a recalibration might happen if we need a calibration setting that's not cached, or if the active calibration setting expires. Currently the expire timeout is set to 30 seconds. We may raise that in future. This patch reduces overall memory consumption by nuking the huge static calibration tables. This patch has been tested on several 4306, 4311 and 4318 flavours. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 77 ++-- drivers/net/wireless/b43/debugfs.h | 1 + drivers/net/wireless/b43/lo.c | 721 +++++++++++++------------------------ drivers/net/wireless/b43/lo.h | 115 +++--- drivers/net/wireless/b43/main.c | 26 +- drivers/net/wireless/b43/main.h | 3 + drivers/net/wireless/b43/phy.c | 123 ++----- drivers/net/wireless/b43/phy.h | 16 +- 8 files changed, 396 insertions(+), 686 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 7fca2ebc747..210e2789c1c 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -270,24 +270,22 @@ static int restart_write_file(struct b43_wldev *dev, return err; } -static ssize_t append_lo_table(ssize_t count, char *buf, const size_t bufsize, - struct b43_loctl table[B43_NR_BB][B43_NR_RF]) +static unsigned long calc_expire_secs(unsigned long now, + unsigned long time, + unsigned long expire) { - unsigned int i, j; - struct b43_loctl *ctl; - - for (i = 0; i < B43_NR_BB; i++) { - for (j = 0; j < B43_NR_RF; j++) { - ctl = &(table[i][j]); - fappend("(bbatt %2u, rfatt %2u) -> " - "(I %+3d, Q %+3d, Used: %d, Calibrated: %d)\n", - i, j, ctl->i, ctl->q, - ctl->used, - b43_loctl_is_calibrated(ctl)); - } + expire = time + expire; + + if (time_after(now, expire)) + return 0; /* expired */ + if (expire < now) { + /* jiffies wrapped */ + expire -= MAX_JIFFY_OFFSET; + now -= MAX_JIFFY_OFFSET; } + B43_WARN_ON(expire < now); - return count; + return (expire - now) / HZ; } static ssize_t loctls_read_file(struct b43_wldev *dev, @@ -296,27 +294,45 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, ssize_t count = 0; struct b43_txpower_lo_control *lo; int i, err = 0; + struct b43_lo_calib *cal; + unsigned long now = jiffies; + struct b43_phy *phy = &dev->phy; - if (dev->phy.type != B43_PHYTYPE_G) { + if (phy->type != B43_PHYTYPE_G) { fappend("Device is not a G-PHY\n"); err = -ENODEV; goto out; } - lo = dev->phy.lo_control; + lo = phy->lo_control; fappend("-- Local Oscillator calibration data --\n\n"); - fappend("Measured: %d, Rebuild: %d, HW-power-control: %d\n", - lo->lo_measured, - lo->rebuild, + fappend("HW-power-control enabled: %d\n", dev->phy.hardware_power_control); - fappend("TX Bias: 0x%02X, TX Magn: 0x%02X\n", - lo->tx_bias, lo->tx_magn); - fappend("Power Vector: 0x%08X%08X\n", + fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n", + lo->tx_bias, lo->tx_magn, + calc_expire_secs(now, lo->txctl_measured_time, + B43_LO_TXCTL_EXPIRE)); + fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n", (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL)); - fappend("\nControl table WITH PADMIX:\n"); - count = append_lo_table(count, buf, bufsize, lo->with_padmix); - fappend("\nControl table WITHOUT PADMIX:\n"); - count = append_lo_table(count, buf, bufsize, lo->no_padmix); + (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL), + calc_expire_secs(now, lo->pwr_vec_read_time, + B43_LO_PWRVEC_EXPIRE)); + + fappend("\nCalibrated settings:\n"); + list_for_each_entry(cal, &lo->calib_list, list) { + bool active; + + active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && + b43_compare_rfatt(&cal->rfatt, &phy->rfatt)); + fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " + "(expires in %lu sec)%s\n", + cal->bbatt.att, + cal->rfatt.att, cal->rfatt.with_padmix, + cal->ctl.i, cal->ctl.q, + calc_expire_secs(now, cal->calib_time, + B43_LO_CALIB_EXPIRE), + active ? " ACTIVE" : ""); + } + fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); for (i = 0; i < lo->rfatt_list.len; i++) { fappend("%u(%d), ", @@ -351,7 +367,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, struct b43_dfs_file *dfile; ssize_t uninitialized_var(ret); char *buf; - const size_t bufsize = 1024 * 128; + const size_t bufsize = 1024 * 16; /* 16 kiB buffer */ const size_t buforder = get_order(bufsize); int err = 0; @@ -380,8 +396,6 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, err = -ENOMEM; goto out_unlock; } - /* Sparse warns about the following memset, because it has a big - * size value. That warning is bogus, so I will ignore it. --mb */ memset(buf, 0, bufsize); if (dfops->take_irqlock) { spin_lock_irq(&dev->wl->irq_lock); @@ -523,6 +537,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); + add_dyn_dbg("debug_lo", B43_DBG_LO, 0); #undef add_dyn_dbg } diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 6eebe858db5..c75cff4151d 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -10,6 +10,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ B43_DBG_DMAVERBOSE, B43_DBG_PWORK_FAST, B43_DBG_PWORK_STOP, + B43_DBG_LO, __B43_NR_DYNDBG, }; diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index d890f366a23..4edee6da2b8 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -36,10 +36,22 @@ #include -/* Define to 1 to always calibrate all possible LO control pairs. - * This is a workaround until we fix the partial LO calibration optimization. */ -#define B43_CALIB_ALL_LOCTLS 1 +static struct b43_lo_calib * b43_find_lo_calib(struct b43_txpower_lo_control *lo, + const struct b43_bbatt *bbatt, + const struct b43_rfatt *rfatt) +{ + struct b43_lo_calib *c; + + list_for_each_entry(c, &lo->calib_list, list) { + if (!b43_compare_bbatt(&c->bbatt, bbatt)) + continue; + if (!b43_compare_rfatt(&c->rfatt, rfatt)) + continue; + return c; + } + return NULL; +} /* Write the LocalOscillator Control (adjust) value-pair. */ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) @@ -64,183 +76,6 @@ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) b43_phy_write(dev, reg, value); } -static int assert_rfatt_and_bbatt(const struct b43_rfatt *rfatt, - const struct b43_bbatt *bbatt, - struct b43_wldev *dev) -{ - int err = 0; - - /* Check the attenuation values against the LO control array sizes. */ - if (unlikely(rfatt->att >= B43_NR_RF)) { - b43err(dev->wl, "rfatt(%u) >= size of LO array\n", rfatt->att); - err = -EINVAL; - } - if (unlikely(bbatt->att >= B43_NR_BB)) { - b43err(dev->wl, "bbatt(%u) >= size of LO array\n", bbatt->att); - err = -EINVAL; - } - - return err; -} - -#if !B43_CALIB_ALL_LOCTLS -static -struct b43_loctl *b43_get_lo_g_ctl_nopadmix(struct b43_wldev *dev, - const struct b43_rfatt *rfatt, - const struct b43_bbatt *bbatt) -{ - struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; - - if (assert_rfatt_and_bbatt(rfatt, bbatt, dev)) - return &(lo->no_padmix[0][0]); /* Just prevent a crash */ - return &(lo->no_padmix[bbatt->att][rfatt->att]); -} -#endif /* !B43_CALIB_ALL_LOCTLS */ - -struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev, - const struct b43_rfatt *rfatt, - const struct b43_bbatt *bbatt) -{ - struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; - - if (assert_rfatt_and_bbatt(rfatt, bbatt, dev)) - return &(lo->no_padmix[0][0]); /* Just prevent a crash */ - if (rfatt->with_padmix) - return &(lo->with_padmix[bbatt->att][rfatt->att]); - return &(lo->no_padmix[bbatt->att][rfatt->att]); -} - -/* Call a function for every possible LO control value-pair. */ -static void b43_call_for_each_loctl(struct b43_wldev *dev, - void (*func) (struct b43_wldev *, - struct b43_loctl *)) -{ - struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *ctl = phy->lo_control; - int i, j; - - for (i = 0; i < B43_NR_BB; i++) { - for (j = 0; j < B43_NR_RF; j++) - func(dev, &(ctl->with_padmix[i][j])); - } - for (i = 0; i < B43_NR_BB; i++) { - for (j = 0; j < B43_NR_RF; j++) - func(dev, &(ctl->no_padmix[i][j])); - } -} - -static u16 lo_b_r15_loop(struct b43_wldev *dev) -{ - int i; - u16 ret = 0; - - for (i = 0; i < 10; i++) { - b43_phy_write(dev, 0x0015, 0xAFA0); - udelay(1); - b43_phy_write(dev, 0x0015, 0xEFA0); - udelay(10); - b43_phy_write(dev, 0x0015, 0xFFA0); - udelay(40); - ret += b43_phy_read(dev, 0x002C); - } - - return ret; -} - -void b43_lo_b_measure(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 regstack[12] = { 0 }; - u16 mls; - u16 fval; - int i, j; - - regstack[0] = b43_phy_read(dev, 0x0015); - regstack[1] = b43_radio_read16(dev, 0x0052) & 0xFFF0; - - if (phy->radio_ver == 0x2053) { - regstack[2] = b43_phy_read(dev, 0x000A); - regstack[3] = b43_phy_read(dev, 0x002A); - regstack[4] = b43_phy_read(dev, 0x0035); - regstack[5] = b43_phy_read(dev, 0x0003); - regstack[6] = b43_phy_read(dev, 0x0001); - regstack[7] = b43_phy_read(dev, 0x0030); - - regstack[8] = b43_radio_read16(dev, 0x0043); - regstack[9] = b43_radio_read16(dev, 0x007A); - regstack[10] = b43_read16(dev, 0x03EC); - regstack[11] = b43_radio_read16(dev, 0x0052) & 0x00F0; - - b43_phy_write(dev, 0x0030, 0x00FF); - b43_write16(dev, 0x03EC, 0x3F3F); - b43_phy_write(dev, 0x0035, regstack[4] & 0xFF7F); - b43_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0); - } - b43_phy_write(dev, 0x0015, 0xB000); - b43_phy_write(dev, 0x002B, 0x0004); - - if (phy->radio_ver == 0x2053) { - b43_phy_write(dev, 0x002B, 0x0203); - b43_phy_write(dev, 0x002A, 0x08A3); - } - - phy->minlowsig[0] = 0xFFFF; - - for (i = 0; i < 4; i++) { - b43_radio_write16(dev, 0x0052, regstack[1] | i); - lo_b_r15_loop(dev); - } - for (i = 0; i < 10; i++) { - b43_radio_write16(dev, 0x0052, regstack[1] | i); - mls = lo_b_r15_loop(dev) / 10; - if (mls < phy->minlowsig[0]) { - phy->minlowsig[0] = mls; - phy->minlowsigpos[0] = i; - } - } - b43_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]); - - phy->minlowsig[1] = 0xFFFF; - - for (i = -4; i < 5; i += 2) { - for (j = -4; j < 5; j += 2) { - if (j < 0) - fval = (0x0100 * i) + j + 0x0100; - else - fval = (0x0100 * i) + j; - b43_phy_write(dev, 0x002F, fval); - mls = lo_b_r15_loop(dev) / 10; - if (mls < phy->minlowsig[1]) { - phy->minlowsig[1] = mls; - phy->minlowsigpos[1] = fval; - } - } - } - phy->minlowsigpos[1] += 0x0101; - - b43_phy_write(dev, 0x002F, phy->minlowsigpos[1]); - if (phy->radio_ver == 0x2053) { - b43_phy_write(dev, 0x000A, regstack[2]); - b43_phy_write(dev, 0x002A, regstack[3]); - b43_phy_write(dev, 0x0035, regstack[4]); - b43_phy_write(dev, 0x0003, regstack[5]); - b43_phy_write(dev, 0x0001, regstack[6]); - b43_phy_write(dev, 0x0030, regstack[7]); - - b43_radio_write16(dev, 0x0043, regstack[8]); - b43_radio_write16(dev, 0x007A, regstack[9]); - - b43_radio_write16(dev, 0x0052, - (b43_radio_read16(dev, 0x0052) & 0x000F) - | regstack[11]); - - b43_write16(dev, 0x03EC, regstack[10]); - } - b43_phy_write(dev, 0x0015, regstack[0]); -} - static u16 lo_measure_feedthrough(struct b43_wldev *dev, u16 lna, u16 pga, u16 trsw_rx) { @@ -438,48 +273,26 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) & 0xFFF0); /* TX bias == 0 */ } + lo->txctl_measured_time = jiffies; } static void lo_read_power_vector(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; - u16 i; + int i; u64 tmp; u64 power_vector = 0; - int rf_offset, bb_offset; - struct b43_loctl *loctl; for (i = 0; i < 8; i += 2) { tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); - /* Clear the top byte. We get holes in the bitmap... */ - tmp &= 0xFF; power_vector |= (tmp << (i * 8)); /* Clear the vector on the device. */ b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); } - if (power_vector) lo->power_vector = power_vector; - power_vector = lo->power_vector; - - for (i = 0; i < 64; i++) { - if (power_vector & ((u64) 1ULL << i)) { - /* Now figure out which b43_loctl corresponds - * to this bit. - */ - rf_offset = i / lo->rfatt_list.len; - bb_offset = i % lo->rfatt_list.len; //FIXME? - loctl = - b43_get_lo_g_ctl(dev, - &lo->rfatt_list.list[rf_offset], - &lo->bbatt_list.list[bb_offset]); - /* And mark it as "used", as the device told us - * through the bitmap it is using it. - */ - loctl->used = 1; - } - } + lo->pwr_vec_read_time = jiffies; } /* 802.11/LO/GPHY/MeasuringGains */ @@ -609,8 +422,6 @@ static void lo_measure_setup(struct b43_wldev *dev, b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); } - if (!lo->rebuild && b43_has_hardware_pctl(phy)) - lo_read_power_vector(dev); if (phy->rev >= 2) { sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); sav->phy_analogoverval = @@ -691,8 +502,12 @@ static void lo_measure_setup(struct b43_wldev *dev, b43_radio_read16(dev, 0x51); /* dummy read */ if (phy->type == B43_PHYTYPE_G) b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); - if (lo->rebuild) + + /* Re-measure the txctl values, if needed. */ + if (time_before(lo->txctl_measured_time, + jiffies - B43_LO_TXCTL_EXPIRE)) lo_measure_txctl_values(dev); + if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); } else { @@ -707,7 +522,6 @@ static void lo_measure_restore(struct b43_wldev *dev, struct lo_g_saved_values *sav) { struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; u16 tmp; if (phy->rev >= 2) { @@ -722,14 +536,6 @@ static void lo_measure_restore(struct b43_wldev *dev, tmp = (phy->pga_gain | 0xEFA0); b43_phy_write(dev, B43_PHY_PGACTL, tmp); } - if (b43_has_hardware_pctl(phy)) { - b43_gphy_dc_lt_init(dev); - } else { - if (lo->rebuild) - b43_lo_g_adjust_to(dev, 3, 2, 0); - else - b43_lo_g_adjust(dev); - } if (phy->type == B43_PHYTYPE_G) { if (phy->rev >= 3) b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); @@ -793,7 +599,6 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, struct b43_lo_g_statemachine *d) { struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_loctl test_loctl; struct b43_loctl orig_loctl; struct b43_loctl prev_loctl = { @@ -852,7 +657,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, found_lower = 1; d->lowest_feedth = feedth; if ((d->nr_measured < 2) && - (!has_loopback_gain(phy) || lo->rebuild)) + !has_loopback_gain(phy)) break; } } @@ -874,7 +679,6 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, int *max_rx_gain) { struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_lo_g_statemachine d; u16 feedth; int found_lower; @@ -883,18 +687,18 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, d.nr_measured = 0; d.state_val_multiplier = 1; - if (has_loopback_gain(phy) && !lo->rebuild) + if (has_loopback_gain(phy)) d.state_val_multiplier = 3; memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); - if (has_loopback_gain(phy) && lo->rebuild) + if (has_loopback_gain(phy)) max_repeat = 4; do { b43_lo_write(dev, &d.min_loctl); feedth = lo_measure_feedthrough(dev, phy->lna_gain, phy->pga_gain, phy->trsw_rx_gain); - if (!lo->rebuild && feedth < 0x258) { + if (feedth < 0x258) { if (feedth >= 0x12C) *max_rx_gain += 6; else @@ -944,278 +748,188 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, } while (++repeat_cnt < max_repeat); } -#if B43_CALIB_ALL_LOCTLS -static const struct b43_rfatt b43_full_rfatt_list_items[] = { - { .att = 0, .with_padmix = 0, }, - { .att = 1, .with_padmix = 0, }, - { .att = 2, .with_padmix = 0, }, - { .att = 3, .with_padmix = 0, }, - { .att = 4, .with_padmix = 0, }, - { .att = 5, .with_padmix = 0, }, - { .att = 6, .with_padmix = 0, }, - { .att = 7, .with_padmix = 0, }, - { .att = 8, .with_padmix = 0, }, - { .att = 9, .with_padmix = 0, }, - { .att = 10, .with_padmix = 0, }, - { .att = 11, .with_padmix = 0, }, - { .att = 12, .with_padmix = 0, }, - { .att = 13, .with_padmix = 0, }, - { .att = 14, .with_padmix = 0, }, - { .att = 15, .with_padmix = 0, }, - { .att = 0, .with_padmix = 1, }, - { .att = 1, .with_padmix = 1, }, - { .att = 2, .with_padmix = 1, }, - { .att = 3, .with_padmix = 1, }, - { .att = 4, .with_padmix = 1, }, - { .att = 5, .with_padmix = 1, }, - { .att = 6, .with_padmix = 1, }, - { .att = 7, .with_padmix = 1, }, - { .att = 8, .with_padmix = 1, }, - { .att = 9, .with_padmix = 1, }, - { .att = 10, .with_padmix = 1, }, - { .att = 11, .with_padmix = 1, }, - { .att = 12, .with_padmix = 1, }, - { .att = 13, .with_padmix = 1, }, - { .att = 14, .with_padmix = 1, }, - { .att = 15, .with_padmix = 1, }, -}; -static const struct b43_rfatt_list b43_full_rfatt_list = { - .list = b43_full_rfatt_list_items, - .len = ARRAY_SIZE(b43_full_rfatt_list_items), -}; - -static const struct b43_bbatt b43_full_bbatt_list_items[] = { - { .att = 0, }, - { .att = 1, }, - { .att = 2, }, - { .att = 3, }, - { .att = 4, }, - { .att = 5, }, - { .att = 6, }, - { .att = 7, }, - { .att = 8, }, - { .att = 9, }, - { .att = 10, }, - { .att = 11, }, -}; -static const struct b43_bbatt_list b43_full_bbatt_list = { - .list = b43_full_bbatt_list_items, - .len = ARRAY_SIZE(b43_full_bbatt_list_items), -}; -#endif /* B43_CALIB_ALL_LOCTLS */ - -static void lo_measure(struct b43_wldev *dev) +static +struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, + const struct b43_bbatt *bbatt, + const struct b43_rfatt *rfatt) { struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_loctl loctl = { .i = 0, .q = 0, }; - struct b43_loctl *ploctl; int max_rx_gain; - int rfidx, bbidx; - const struct b43_bbatt_list *bbatt_list; - const struct b43_rfatt_list *rfatt_list; - + struct b43_lo_calib *cal; + struct lo_g_saved_values uninitialized_var(saved_regs); /* Values from the "TXCTL Register and Value Table" */ u16 txctl_reg; u16 txctl_value; u16 pad_mix_gain; - bbatt_list = &lo->bbatt_list; - rfatt_list = &lo->rfatt_list; -#if B43_CALIB_ALL_LOCTLS - bbatt_list = &b43_full_bbatt_list; - rfatt_list = &b43_full_rfatt_list; -#endif + saved_regs.old_channel = phy->channel; + b43_mac_suspend(dev); + lo_measure_setup(dev, &saved_regs); txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); - for (rfidx = 0; rfidx < rfatt_list->len; rfidx++) { - - b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) - & 0xFFF0) | - rfatt_list->list[rfidx].att); - b43_radio_write16(dev, txctl_reg, - (b43_radio_read16(dev, txctl_reg) - & ~txctl_value) - | (rfatt_list->list[rfidx].with_padmix ? - txctl_value : 0)); - - for (bbidx = 0; bbidx < bbatt_list->len; bbidx++) { - if (lo->rebuild) { -#if B43_CALIB_ALL_LOCTLS - ploctl = b43_get_lo_g_ctl(dev, - &rfatt_list->list[rfidx], - &bbatt_list->list[bbidx]); -#else - ploctl = b43_get_lo_g_ctl_nopadmix(dev, - &rfatt_list-> - list[rfidx], - &bbatt_list-> - list[bbidx]); -#endif - } else { - ploctl = b43_get_lo_g_ctl(dev, - &rfatt_list->list[rfidx], - &bbatt_list->list[bbidx]); - if (!ploctl->used) - continue; - } - memcpy(&loctl, ploctl, sizeof(loctl)); - loctl.i = 0; - loctl.q = 0; - - max_rx_gain = rfatt_list->list[rfidx].att * 2; - max_rx_gain += bbatt_list->list[bbidx].att / 2; - if (rfatt_list->list[rfidx].with_padmix) - max_rx_gain -= pad_mix_gain; - if (has_loopback_gain(phy)) - max_rx_gain += phy->max_lb_gain; - lo_measure_gain_values(dev, max_rx_gain, - has_loopback_gain(phy)); - - b43_phy_set_baseband_attenuation(dev, - bbatt_list->list[bbidx].att); - lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); - if (phy->type == B43_PHYTYPE_B) { - loctl.i++; - loctl.q++; - } - b43_loctl_set_calibrated(&loctl, 1); - memcpy(ploctl, &loctl, sizeof(loctl)); - } - } -} - -#if B43_DEBUG -static void do_validate_loctl(struct b43_wldev *dev, struct b43_loctl *control) -{ - const int is_initializing = (b43_status(dev) == B43_STAT_UNINIT); - int i = control->i; - int q = control->q; + b43_radio_write16(dev, 0x43, + (b43_radio_read16(dev, 0x43) & 0xFFF0) + | rfatt->att); + b43_radio_write16(dev, txctl_reg, + (b43_radio_read16(dev, txctl_reg) & ~txctl_value) + | (rfatt->with_padmix) ? txctl_value : 0); - if (b43_loctl_is_calibrated(control)) { - if ((abs(i) > 16) || (abs(q) > 16)) - goto error; - } else { - if (control->used) - goto error; - if (dev->phy.lo_control->rebuild) { - control->i = 0; - control->q = 0; - if ((i != B43_LOCTL_POISON) || - (q != B43_LOCTL_POISON)) - goto error; - } + max_rx_gain = rfatt->att * 2; + max_rx_gain += bbatt->att / 2; + if (rfatt->with_padmix) + max_rx_gain -= pad_mix_gain; + if (has_loopback_gain(phy)) + max_rx_gain += phy->max_lb_gain; + lo_measure_gain_values(dev, max_rx_gain, + has_loopback_gain(phy)); + + b43_phy_set_baseband_attenuation(dev, bbatt->att); + lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); + + lo_measure_restore(dev, &saved_regs); + b43_mac_enable(dev); + + if (b43_debug(dev, B43_DBG_LO)) { + b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) " + "=> I=%d Q=%d\n", + bbatt->att, rfatt->att, rfatt->with_padmix, + loctl.i, loctl.q); } - if (is_initializing && control->used) - goto error; - - return; -error: - b43err(dev->wl, "LO control pair validation failed " - "(I: %d, Q: %d, used %u, calib: %u, initing: %d)\n", - i, q, control->used, - b43_loctl_is_calibrated(control), - is_initializing); -} -static void validate_all_loctls(struct b43_wldev *dev) -{ - b43_call_for_each_loctl(dev, do_validate_loctl); -} - -static void do_reset_calib(struct b43_wldev *dev, struct b43_loctl *control) -{ - if (dev->phy.lo_control->rebuild || - control->used) { - b43_loctl_set_calibrated(control, 0); - control->i = B43_LOCTL_POISON; - control->q = B43_LOCTL_POISON; + cal = kmalloc(sizeof(*cal), GFP_KERNEL); + if (!cal) { + b43warn(dev->wl, "LO calib: out of memory\n"); + return NULL; } + memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); + memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); + memcpy(&cal->ctl, &loctl, sizeof(loctl)); + cal->calib_time = jiffies; + INIT_LIST_HEAD(&cal->list); + + return cal; } -static void reset_all_loctl_calibration_states(struct b43_wldev *dev) +/* Get a calibrated LO setting for the given attenuation values. + * Might return a NULL pointer under OOM! */ +static +struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, + const struct b43_bbatt *bbatt, + const struct b43_rfatt *rfatt) { - b43_call_for_each_loctl(dev, do_reset_calib); + struct b43_txpower_lo_control *lo = dev->phy.lo_control; + struct b43_lo_calib *c; + + c = b43_find_lo_calib(lo, bbatt, rfatt); + if (c) + return c; + /* Not in the list of calibrated LO settings. + * Calibrate it now. */ + c = b43_calibrate_lo_setting(dev, bbatt, rfatt); + if (!c) + return NULL; + list_add(&c->list, &lo->calib_list); + + return c; } -#else /* B43_DEBUG */ -static inline void validate_all_loctls(struct b43_wldev *dev) { } -static inline void reset_all_loctl_calibration_states(struct b43_wldev *dev) { } -#endif /* B43_DEBUG */ - -void b43_lo_g_measure(struct b43_wldev *dev) +void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) { struct b43_phy *phy = &dev->phy; - struct lo_g_saved_values uninitialized_var(sav); - - B43_WARN_ON((phy->type != B43_PHYTYPE_B) && - (phy->type != B43_PHYTYPE_G)); - - sav.old_channel = phy->channel; - lo_measure_setup(dev, &sav); - reset_all_loctl_calibration_states(dev); - lo_measure(dev); - lo_measure_restore(dev, &sav); - - validate_all_loctls(dev); + struct b43_txpower_lo_control *lo = phy->lo_control; + int i; + int rf_offset, bb_offset; + const struct b43_rfatt *rfatt; + const struct b43_bbatt *bbatt; + u64 power_vector; + bool table_changed = 0; - phy->lo_control->lo_measured = 1; - phy->lo_control->rebuild = 0; -} + BUILD_BUG_ON(B43_DC_LT_SIZE != 32); + B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64); -#if B43_DEBUG -static void validate_loctl_calibration(struct b43_wldev *dev, - struct b43_loctl *loctl, - struct b43_rfatt *rfatt, - struct b43_bbatt *bbatt) -{ - if (b43_loctl_is_calibrated(loctl)) - return; - if (!dev->phy.lo_control->lo_measured) { - /* On init we set the attenuation values before we - * calibrated the LO. I guess that's OK. */ - return; + power_vector = lo->power_vector; + if (!update_all && !power_vector) + return; /* Nothing to do. */ + + /* Suspend the MAC now to avoid continuous suspend/enable + * cycles in the loop. */ + b43_mac_suspend(dev); + + for (i = 0; i < B43_DC_LT_SIZE * 2; i++) { + struct b43_lo_calib *cal; + int idx; + u16 val; + + if (!update_all && !(power_vector & (((u64)1ULL) << i))) + continue; + /* Update the table entry for this power_vector bit. + * The table rows are RFatt entries and columns are BBatt. */ + bb_offset = i / lo->rfatt_list.len; + rf_offset = i % lo->rfatt_list.len; + bbatt = &(lo->bbatt_list.list[bb_offset]); + rfatt = &(lo->rfatt_list.list[rf_offset]); + + cal = b43_calibrate_lo_setting(dev, bbatt, rfatt); + if (!cal) { + b43warn(dev->wl, "LO: Could not " + "calibrate DC table entry\n"); + continue; + } + /*FIXME: Is Q really in the low nibble? */ + val = (u8)(cal->ctl.q); + val |= ((u8)(cal->ctl.i)) << 4; + kfree(cal); + + /* Get the index into the hardware DC LT. */ + idx = i / 2; + /* Change the table in memory. */ + if (i % 2) { + /* Change the high byte. */ + lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF) + | ((val & 0x00FF) << 8); + } else { + /* Change the low byte. */ + lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00) + | (val & 0x00FF); + } + table_changed = 1; } - b43err(dev->wl, "Adjusting Local Oscillator to an uncalibrated " - "control pair: rfatt=%u,%spadmix bbatt=%u\n", - rfatt->att, - (rfatt->with_padmix) ? "" : "no-", - bbatt->att); -} -#else -static inline void validate_loctl_calibration(struct b43_wldev *dev, - struct b43_loctl *loctl, - struct b43_rfatt *rfatt, - struct b43_bbatt *bbatt) -{ + if (table_changed) { + /* The table changed in memory. Update the hardware table. */ + for (i = 0; i < B43_DC_LT_SIZE; i++) + b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]); + } + b43_mac_enable(dev); } -#endif -static inline void fixup_rfatt_for_txcontrol(struct b43_rfatt *rf, - u8 tx_control) +/* Fixup the RF attenuation value for the case where we are + * using the PAD mixer. */ +static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) { - if (tx_control & B43_TXCTL_TXMIX) { - if (rf->att < 5) - rf->att = 4; - } + if (!rf->with_padmix) + return; + if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) + rf->att = 4; } void b43_lo_g_adjust(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; + struct b43_lo_calib *cal; struct b43_rfatt rf; - struct b43_loctl *loctl; memcpy(&rf, &phy->rfatt, sizeof(rf)); - fixup_rfatt_for_txcontrol(&rf, phy->tx_control); + b43_lo_fixup_rfatt(&rf); - loctl = b43_get_lo_g_ctl(dev, &rf, &phy->bbatt); - validate_loctl_calibration(dev, loctl, &rf, &phy->bbatt); - b43_lo_write(dev, loctl); + cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf); + if (!cal) + return; + b43_lo_write(dev, &cal->ctl); } void b43_lo_g_adjust_to(struct b43_wldev *dev, @@ -1223,39 +937,102 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev, { struct b43_rfatt rf; struct b43_bbatt bb; - struct b43_loctl *loctl; + struct b43_lo_calib *cal; memset(&rf, 0, sizeof(rf)); memset(&bb, 0, sizeof(bb)); rf.att = rfatt; bb.att = bbatt; - fixup_rfatt_for_txcontrol(&rf, tx_control); - loctl = b43_get_lo_g_ctl(dev, &rf, &bb); - validate_loctl_calibration(dev, loctl, &rf, &bb); - b43_lo_write(dev, loctl); + b43_lo_fixup_rfatt(&rf); + cal = b43_get_calib_lo_settings(dev, &bb, &rf); + if (!cal) + return; + b43_lo_write(dev, &cal->ctl); } -static void do_mark_unused(struct b43_wldev *dev, struct b43_loctl *control) +/* Periodic LO maintanance work */ +void b43_lo_g_maintanance_work(struct b43_wldev *dev) { - control->used = 0; + struct b43_phy *phy = &dev->phy; + struct b43_txpower_lo_control *lo = phy->lo_control; + unsigned long now; + unsigned long expire; + struct b43_lo_calib *cal, *tmp; + bool current_item_expired = 0; + bool hwpctl; + + if (!lo) + return; + now = jiffies; + hwpctl = b43_has_hardware_pctl(phy); + + if (hwpctl) { + /* Read the power vector and update it, if needed. */ + expire = now - B43_LO_PWRVEC_EXPIRE; + if (time_before(lo->pwr_vec_read_time, expire)) { + lo_read_power_vector(dev); + b43_gphy_dc_lt_init(dev, 0); + } + //FIXME Recalc the whole DC table from time to time? + } + + if (hwpctl) + return; + /* Search for expired LO settings. Remove them. + * Recalibrate the current setting, if expired. */ + expire = now - B43_LO_CALIB_EXPIRE; + list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { + if (!time_before(cal->calib_time, expire)) + continue; + /* This item expired. */ + if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && + b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) { + B43_WARN_ON(current_item_expired); + current_item_expired = 1; + } + if (b43_debug(dev, B43_DBG_LO)) { + b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), " + "I=%d, Q=%d expired\n", + cal->bbatt.att, cal->rfatt.att, + cal->rfatt.with_padmix, + cal->ctl.i, cal->ctl.q); + } + list_del(&cal->list); + kfree(cal); + } + if (current_item_expired || unlikely(list_empty(&lo->calib_list))) { + /* Recalibrate currently used LO setting. */ + if (b43_debug(dev, B43_DBG_LO)) + b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); + cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt); + if (cal) { + list_add(&cal->list, &lo->calib_list); + b43_lo_write(dev, &cal->ctl); + } else + b43warn(dev->wl, "Failed to recalibrate current LO setting\n"); + } } -void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev) +void b43_lo_g_cleanup(struct b43_wldev *dev) { - struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; + struct b43_txpower_lo_control *lo = dev->phy.lo_control; + struct b43_lo_calib *cal, *tmp; - b43_call_for_each_loctl(dev, do_mark_unused); - lo->rebuild = 1; + if (!lo) + return; + list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { + list_del(&cal->list); + kfree(cal); + } } -void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev) +/* LO Initialization */ +void b43_lo_g_init(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - struct b43_rfatt rf; - memcpy(&rf, &phy->rfatt, sizeof(rf)); - fixup_rfatt_for_txcontrol(&rf, phy->tx_control); - - b43_get_lo_g_ctl(dev, &rf, &phy->bbatt)->used = 1; + if (b43_has_hardware_pctl(phy)) { + lo_read_power_vector(dev); + b43_gphy_dc_lt_init(dev, 1); + } } diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h index 455615d1f8c..1da321cabc1 100644 --- a/drivers/net/wireless/b43/lo.h +++ b/drivers/net/wireless/b43/lo.h @@ -10,82 +10,63 @@ struct b43_loctl { /* Control values. */ s8 i; s8 q; - /* "Used by hardware" flag. */ - bool used; -#ifdef CONFIG_B43_DEBUG - /* Is this lo-control-array entry calibrated? */ - bool calibrated; -#endif }; - /* Debugging: Poison value for i and q values. */ #define B43_LOCTL_POISON 111 -/* loctl->calibrated debugging mechanism */ -#ifdef CONFIG_B43_DEBUG -static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, - bool calibrated) -{ - loctl->calibrated = calibrated; -} -static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) -{ - return loctl->calibrated; -} -#else -static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, - bool calibrated) -{ -} -static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) -{ - return 1; -} -#endif - -/* TX Power LO Control Array. - * Value-pairs to adjust the LocalOscillator are stored - * in this structure. - * There are two different set of values. One for "Flag is Set" - * and one for "Flag is Unset". - * By "Flag" the flag in struct b43_rfatt is meant. - * The Value arrays are two-dimensional. The first index - * is the baseband attenuation and the second index - * is the radio attenuation. - * Use b43_get_lo_g_ctl() to retrieve a value from the lists. - */ +/* This struct holds calibrated LO settings for a set of + * Baseband and RF attenuation settings. */ +struct b43_lo_calib { + /* The set of attenuation values this set of LO + * control values is calibrated for. */ + struct b43_bbatt bbatt; + struct b43_rfatt rfatt; + /* The set of control values for the LO. */ + struct b43_loctl ctl; + /* The time when these settings were calibrated (in jiffies) */ + unsigned long calib_time; + /* List. */ + struct list_head list; +}; + +/* Size of the DC Lookup Table in 16bit words. */ +#define B43_DC_LT_SIZE 32 + +/* Local Oscillator calibration information */ struct b43_txpower_lo_control { -#define B43_NR_BB 12 -#define B43_NR_RF 16 - /* LO Control values, with PAD Mixer */ - struct b43_loctl with_padmix[B43_NR_BB][B43_NR_RF]; - /* LO Control values, without PAD Mixer */ - struct b43_loctl no_padmix[B43_NR_BB][B43_NR_RF]; - - /* Flag to indicate a complete rebuild of the two tables above - * to the LO measuring code. */ - bool rebuild; - - /* Lists of valid RF and BB attenuation values for this device. */ + /* Lists of RF and BB attenuation values for this device. + * Used for building hardware power control tables. */ struct b43_rfatt_list rfatt_list; struct b43_bbatt_list bbatt_list; + /* The DC Lookup Table is cached in memory here. + * Note that this is only used for Hardware Power Control. */ + u16 dc_lt[B43_DC_LT_SIZE]; + + /* List of calibrated control values (struct b43_lo_calib). */ + struct list_head calib_list; + /* Last time the power vector was read (jiffies). */ + unsigned long pwr_vec_read_time; + /* Last time the txctl values were measured (jiffies). */ + unsigned long txctl_measured_time; + /* Current TX Bias value */ u8 tx_bias; /* Current TX Magnification Value (if used by the device) */ u8 tx_magn; - /* GPHY LO is measured. */ - bool lo_measured; - /* Saved device PowerVector */ u64 power_vector; }; -/* Measure the BPHY Local Oscillator. */ -void b43_lo_b_measure(struct b43_wldev *dev); -/* Measure the BPHY/GPHY Local Oscillator. */ -void b43_lo_g_measure(struct b43_wldev *dev); +/* Calibration expire timeouts. + * Timeouts must be multiple of 15 seconds. To make sure + * the item really expired when the 15 second timer hits, we + * subtract two additional seconds from the timeout. */ +#define B43_LO_CALIB_EXPIRE (HZ * (30 - 2)) +#define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2)) +#define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4)) + /* Adjust the Local Oscillator to the saved attenuation * and txctl values. @@ -95,18 +76,10 @@ void b43_lo_g_adjust(struct b43_wldev *dev); void b43_lo_g_adjust_to(struct b43_wldev *dev, u16 rfatt, u16 bbatt, u16 tx_control); -/* Mark all possible b43_lo_g_ctl as "unused" */ -void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev); -/* Mark the b43_lo_g_ctl corresponding to the current - * attenuation values as used. - */ -void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev); +void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all); -/* Get a reference to a LO Control value pair in the - * TX Power LO Control Array. - */ -struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev, - const struct b43_rfatt *rfatt, - const struct b43_bbatt *bbatt); +void b43_lo_g_maintanance_work(struct b43_wldev *dev); +void b43_lo_g_cleanup(struct b43_wldev *dev); +void b43_lo_g_init(struct b43_wldev *dev); #endif /* B43_LO_H_ */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8fdba9415c0..e3d8555d4a9 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2308,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) } /* http://bcm-specs.sipsolutions.net/EnableMac */ -static void b43_mac_enable(struct b43_wldev *dev) +void b43_mac_enable(struct b43_wldev *dev) { dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); @@ -2331,7 +2331,7 @@ static void b43_mac_enable(struct b43_wldev *dev) } /* http://bcm-specs.sipsolutions.net/SuspendMAC */ -static void b43_mac_suspend(struct b43_wldev *dev) +void b43_mac_suspend(struct b43_wldev *dev) { int i; u32 tmp; @@ -2503,6 +2503,7 @@ static void b43_chip_exit(struct b43_wldev *dev) { b43_radio_turn_off(dev, 1); b43_gpio_cleanup(dev); + b43_lo_g_cleanup(dev); /* firmware is released later */ } @@ -2609,28 +2610,12 @@ err_gpio_clean: return err; } -static void b43_periodic_every120sec(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->type != B43_PHYTYPE_G || phy->rev < 2) - return; - - b43_mac_suspend(dev); - b43_lo_g_measure(dev); - b43_mac_enable(dev); - if (b43_has_hardware_pctl(phy)) - b43_lo_g_ctl_mark_all_unused(dev); -} - static void b43_periodic_every60sec(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; if (phy->type != B43_PHYTYPE_G) return; - if (!b43_has_hardware_pctl(phy)) - b43_lo_g_ctl_mark_all_unused(dev); if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { b43_mac_suspend(dev); b43_calc_nrssi_slope(dev); @@ -2682,6 +2667,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) } } b43_phy_xmitpower(dev); //FIXME: unless scanning? + b43_lo_g_maintanance_work(dev); //TODO for APHY (temperature?) atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); @@ -2693,8 +2679,6 @@ static void do_periodic_work(struct b43_wldev *dev) unsigned int state; state = dev->periodic_state; - if (state % 8 == 0) - b43_periodic_every120sec(dev); if (state % 4 == 0) b43_periodic_every60sec(dev); if (state % 2 == 0) @@ -3668,8 +3652,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev, lo = phy->lo_control; if (lo) { memset(lo, 0, sizeof(*(phy->lo_control))); - lo->rebuild = 1; lo->tx_bias = 0xFF; + INIT_LIST_HEAD(&lo->calib_list); } phy->max_lb_gain = 0; phy->trsw_rx_gain = 0; diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 5230aeca78b..dad23c42b42 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -114,4 +114,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason); #define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); +void b43_mac_suspend(struct b43_wldev *dev); +void b43_mac_enable(struct b43_wldev *dev); + #endif /* B43_MAIN_H_ */ diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index de024dc0371..fd1f301748c 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -145,8 +145,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, {.att = 9,.with_padmix = 1,}, }; - if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) || - (phy->type == B43_PHYTYPE_G && phy->rev < 6)) { + if (!b43_has_hardware_pctl(phy)) { /* Software pctl */ list->list = rfatt_0; list->len = ARRAY_SIZE(rfatt_0); @@ -158,7 +157,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, /* Hardware pctl */ list->list = rfatt_1; list->len = ARRAY_SIZE(rfatt_1); - list->min_val = 2; + list->min_val = 0; list->max_val = 14; return; } @@ -346,6 +345,7 @@ void b43_set_txpower_g(struct b43_wldev *dev, /* Save the values for later */ phy->tx_control = tx_control; memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); + phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX); memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); if (b43_debug(dev, B43_DBG_XMITPOWER)) { @@ -559,11 +559,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) u16 tmp; u8 rf, bb; - if (!lo->lo_measured) { - b43_phy_write(dev, 0x3FF, 0); - return; - } - for (rf = 0; rf < lo->rfatt_list.len; rf++) { for (bb = 0; bb < lo->bbatt_list.len; bb++) { if (nr_written >= 0x40) @@ -581,42 +576,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) } } -/* GPHY_DC_Lookup_Table */ -void b43_gphy_dc_lt_init(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_txpower_lo_control *lo = phy->lo_control; - struct b43_loctl *loctl0; - struct b43_loctl *loctl1; - int i; - int rf_offset, bb_offset; - u16 tmp; - - for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) { - rf_offset = i / lo->rfatt_list.len; - bb_offset = i % lo->rfatt_list.len; - - loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset], - &lo->bbatt_list.list[bb_offset]); - if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) { - rf_offset = (i + 1) / lo->rfatt_list.len; - bb_offset = (i + 1) % lo->rfatt_list.len; - - loctl1 = - b43_get_lo_g_ctl(dev, - &lo->rfatt_list.list[rf_offset], - &lo->bbatt_list.list[bb_offset]); - } else - loctl1 = loctl0; - - tmp = ((u16) loctl0->q & 0xF); - tmp |= ((u16) loctl0->i & 0xF) << 4; - tmp |= ((u16) loctl1->q & 0xF) << 8; - tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME? - b43_phy_write(dev, 0x3A0 + (i / 2), tmp); - } -} - static void hardware_pctl_init_aphy(struct b43_wldev *dev) { //TODO @@ -643,7 +602,7 @@ static void hardware_pctl_init_gphy(struct b43_wldev *dev) b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) & 0xFFBF); - b43_gphy_dc_lt_init(dev); + b43_gphy_dc_lt_init(dev, 1); } /* HardwarePowerControl init for A and G PHY */ @@ -967,7 +926,7 @@ static void b43_phy_initb2(struct b43_wldev *dev) b43_phy_write(dev, 0x0032, 0x00CA); b43_phy_write(dev, 0x0032, 0x00CC); b43_phy_write(dev, 0x0035, 0x07C2); - b43_lo_b_measure(dev); +//XXX won't trigger b43_lo_b_measure(dev); b43_phy_write(dev, 0x0026, 0xCC00); if (phy->radio_ver != 0x2050) b43_phy_write(dev, 0x0026, 0xCE00); @@ -1017,7 +976,7 @@ static void b43_phy_initb4(struct b43_wldev *dev) b43_phy_write(dev, 0x0032, 0x00E0); b43_phy_write(dev, 0x0035, 0x07C2); - b43_lo_b_measure(dev); +//XXX won't trigger b43_lo_b_measure(dev); b43_phy_write(dev, 0x0026, 0xCC00); if (phy->radio_ver == 0x2050) @@ -1259,19 +1218,9 @@ static void b43_phy_initb6(struct b43_wldev *dev) b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) | 0x0004); } - if (phy->type == B43_PHYTYPE_B) { - b43_write16(dev, 0x03E6, 0x8140); - b43_phy_write(dev, 0x0016, 0x0410); - b43_phy_write(dev, 0x0017, 0x0820); - b43_phy_write(dev, 0x0062, 0x0007); - b43_radio_init2050(dev); - b43_lo_g_measure(dev); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { - b43_calc_nrssi_slope(dev); - b43_calc_nrssi_threshold(dev); - } - b43_phy_init_pctl(dev); - } else if (phy->type == B43_PHYTYPE_G) + if (phy->type == B43_PHYTYPE_B) + B43_WARN_ON(1); + else if (phy->type == B43_PHYTYPE_G) b43_write16(dev, 0x03E6, 0x0); } @@ -1534,34 +1483,31 @@ static void b43_phy_initg(struct b43_wldev *dev) else b43_radio_write16(dev, 0x0078, phy->initval); } - if (phy->lo_control->tx_bias == 0xFF) { - b43_lo_g_measure(dev); + b43_lo_g_init(dev); + if (has_tx_magnification(phy)) { + b43_radio_write16(dev, 0x52, + (b43_radio_read16(dev, 0x52) & 0xFF00) + | phy->lo_control->tx_bias | phy-> + lo_control->tx_magn); } else { - if (has_tx_magnification(phy)) { - b43_radio_write16(dev, 0x52, - (b43_radio_read16(dev, 0x52) & 0xFF00) - | phy->lo_control->tx_bias | phy-> - lo_control->tx_magn); - } else { - b43_radio_write16(dev, 0x52, - (b43_radio_read16(dev, 0x52) & 0xFFF0) - | phy->lo_control->tx_bias); - } - if (phy->rev >= 6) { - b43_phy_write(dev, B43_PHY_CCK(0x36), - (b43_phy_read(dev, B43_PHY_CCK(0x36)) - & 0x0FFF) | (phy->lo_control-> - tx_bias << 12)); - } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); - else - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); - if (phy->rev < 2) - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); - else - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); + b43_radio_write16(dev, 0x52, + (b43_radio_read16(dev, 0x52) & 0xFFF0) + | phy->lo_control->tx_bias); } + if (phy->rev >= 6) { + b43_phy_write(dev, B43_PHY_CCK(0x36), + (b43_phy_read(dev, B43_PHY_CCK(0x36)) + & 0x0FFF) | (phy->lo_control-> + tx_bias << 12)); + } + if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) + b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); + else + b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); + if (phy->rev < 2) + b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); + else + b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); if (phy->gmode || phy->rev >= 2) { b43_lo_g_adjust(dev); b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); @@ -1821,10 +1767,8 @@ void b43_phy_xmitpower(struct b43_wldev *dev) bbatt_delta -= 4 * rfatt_delta; /* So do we finally need to adjust something? */ - if ((rfatt_delta == 0) && (bbatt_delta == 0)) { - b43_lo_g_ctl_mark_cur_used(dev); + if ((rfatt_delta == 0) && (bbatt_delta == 0)) return; - } /* Calculate the new attenuation values. */ bbatt = phy->bbatt.att; @@ -1870,7 +1814,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev) b43_radio_lock(dev); b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); - b43_lo_g_ctl_mark_cur_used(dev); b43_radio_unlock(dev); b43_phy_unlock(dev); break; diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h index 6d165d82217..4aab1090352 100644 --- a/drivers/net/wireless/b43/phy.h +++ b/drivers/net/wireless/b43/phy.h @@ -225,7 +225,6 @@ int b43_phy_init(struct b43_wldev *dev); void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); void b43_phy_xmitpower(struct b43_wldev *dev); -void b43_gphy_dc_lt_init(struct b43_wldev *dev); /* Returns the boolean whether the board has HardwarePowerControl */ bool b43_has_hardware_pctl(struct b43_phy *phy); @@ -252,6 +251,14 @@ struct b43_rfatt_list { u8 max_val; }; +/* Returns true, if the values are the same. */ +static inline bool b43_compare_rfatt(const struct b43_rfatt *a, + const struct b43_rfatt *b) +{ + return ((a->att == b->att) && + (a->with_padmix == b->with_padmix)); +} + /* Baseband Attenuation */ struct b43_bbatt { u8 att; /* Attenuation value */ @@ -265,6 +272,13 @@ struct b43_bbatt_list { u8 max_val; }; +/* Returns true, if the values are the same. */ +static inline bool b43_compare_bbatt(const struct b43_bbatt *a, + const struct b43_bbatt *b) +{ + return (a->att == b->att); +} + /* tx_control bits. */ #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ -- cgit v1.2.3 From f4440e8a47e216adfe32d96a35bef6d13d498b58 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 20 Apr 2008 16:23:26 +0200 Subject: b43: Remove some dead code This patch removes some dead code from the driver. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/lo.c | 6 +- drivers/net/wireless/b43/phy.c | 121 ----------------------------------------- 2 files changed, 2 insertions(+), 125 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 4edee6da2b8..4ce1e356120 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -58,7 +58,6 @@ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) { struct b43_phy *phy = &dev->phy; u16 value; - u16 reg; if (B43_DEBUG) { if (unlikely(abs(control->i) > 16 || abs(control->q) > 16)) { @@ -68,12 +67,11 @@ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) return; } } + B43_WARN_ON(phy->type != B43_PHYTYPE_G); value = (u8) (control->q); value |= ((u8) (control->i)) << 8; - - reg = (phy->type == B43_PHYTYPE_B) ? 0x002F : B43_PHY_LO_CTL; - b43_phy_write(dev, reg, value); + b43_phy_write(dev, B43_PHY_LO_CTL, value); } static u16 lo_measure_feedthrough(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index fd1f301748c..8b3c24da8db 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -890,109 +890,6 @@ static void b43_phy_inita(struct b43_wldev *dev) } } -static void b43_phy_initb2(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 offset, val; - - b43_write16(dev, 0x03EC, 0x3F22); - b43_phy_write(dev, 0x0020, 0x301C); - b43_phy_write(dev, 0x0026, 0x0000); - b43_phy_write(dev, 0x0030, 0x00C6); - b43_phy_write(dev, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - b43_phy_write(dev, offset, val); - val -= 0x0202; - } - b43_phy_write(dev, 0x03E4, 0x3000); - b43_radio_selectchannel(dev, phy->channel, 0); - if (phy->radio_ver != 0x2050) { - b43_radio_write16(dev, 0x0075, 0x0080); - b43_radio_write16(dev, 0x0079, 0x0081); - } - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x0050, 0x0023); - if (phy->radio_ver == 0x2050) { - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x005A, 0x0070); - b43_radio_write16(dev, 0x005B, 0x007B); - b43_radio_write16(dev, 0x005C, 0x00B0); - b43_radio_write16(dev, 0x007A, 0x000F); - b43_phy_write(dev, 0x0038, 0x0677); - b43_radio_init2050(dev); - } - b43_phy_write(dev, 0x0014, 0x0080); - b43_phy_write(dev, 0x0032, 0x00CA); - b43_phy_write(dev, 0x0032, 0x00CC); - b43_phy_write(dev, 0x0035, 0x07C2); -//XXX won't trigger b43_lo_b_measure(dev); - b43_phy_write(dev, 0x0026, 0xCC00); - if (phy->radio_ver != 0x2050) - b43_phy_write(dev, 0x0026, 0xCE00); - b43_write16(dev, B43_MMIO_CHANNEL_EXT, 0x1000); - b43_phy_write(dev, 0x002A, 0x88A3); - if (phy->radio_ver != 0x2050) - b43_phy_write(dev, 0x002A, 0x88C2); - b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); - b43_phy_init_pctl(dev); -} - -static void b43_phy_initb4(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 offset, val; - - b43_write16(dev, 0x03EC, 0x3F22); - b43_phy_write(dev, 0x0020, 0x301C); - b43_phy_write(dev, 0x0026, 0x0000); - b43_phy_write(dev, 0x0030, 0x00C6); - b43_phy_write(dev, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - b43_phy_write(dev, offset, val); - val -= 0x0202; - } - b43_phy_write(dev, 0x03E4, 0x3000); - b43_radio_selectchannel(dev, phy->channel, 0); - if (phy->radio_ver != 0x2050) { - b43_radio_write16(dev, 0x0075, 0x0080); - b43_radio_write16(dev, 0x0079, 0x0081); - } - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x0050, 0x0023); - if (phy->radio_ver == 0x2050) { - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x005A, 0x0070); - b43_radio_write16(dev, 0x005B, 0x007B); - b43_radio_write16(dev, 0x005C, 0x00B0); - b43_radio_write16(dev, 0x007A, 0x000F); - b43_phy_write(dev, 0x0038, 0x0677); - b43_radio_init2050(dev); - } - b43_phy_write(dev, 0x0014, 0x0080); - b43_phy_write(dev, 0x0032, 0x00CA); - if (phy->radio_ver == 0x2050) - b43_phy_write(dev, 0x0032, 0x00E0); - b43_phy_write(dev, 0x0035, 0x07C2); - -//XXX won't trigger b43_lo_b_measure(dev); - - b43_phy_write(dev, 0x0026, 0xCC00); - if (phy->radio_ver == 0x2050) - b43_phy_write(dev, 0x0026, 0xCE00); - b43_write16(dev, B43_MMIO_CHANNEL_EXT, 0x1100); - b43_phy_write(dev, 0x002A, 0x88A3); - if (phy->radio_ver == 0x2050) - b43_phy_write(dev, 0x002A, 0x88C2); - b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { - b43_calc_nrssi_slope(dev); - b43_calc_nrssi_threshold(dev); - } - b43_phy_init_pctl(dev); -} - static void b43_phy_initb5(struct b43_wldev *dev) { struct ssb_bus *bus = dev->dev->bus; @@ -1950,24 +1847,6 @@ int b43_phy_init(struct b43_wldev *dev) else unsupported = 1; break; - case B43_PHYTYPE_B: - switch (phy->rev) { - case 2: - b43_phy_initb2(dev); - break; - case 4: - b43_phy_initb4(dev); - break; - case 5: - b43_phy_initb5(dev); - break; - case 6: - b43_phy_initb6(dev); - break; - default: - unsupported = 1; - } - break; case B43_PHYTYPE_G: b43_phy_initg(dev); break; -- cgit v1.2.3 From e40ac414c0130358f9eb068f4993a37f013621be Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 25 Apr 2008 21:10:54 +0200 Subject: b43: Don't disable IRQs in mac_suspend This patch removes the IRQ-disable from mac_suspend. The main advantage of this is to get rid of the IRQ-sync call in mac_suspend. We need to remove the MAC suspend bit from the IRQ service mask, as otherwise the IRQ handler would race with us. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 3 +-- drivers/net/wireless/b43/main.c | 13 ------------- 2 files changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 37783cdd301..7d034df250b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -410,8 +410,7 @@ enum { #define B43_IRQ_TIMEOUT 0x80000000 #define B43_IRQ_ALL 0xFFFFFFFF -#define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \ - B43_IRQ_TBTT_INDI | \ +#define B43_IRQ_MASKTEMPLATE (B43_IRQ_TBTT_INDI | \ B43_IRQ_ATIM_END | \ B43_IRQ_PMQ | \ B43_IRQ_MAC_TXERR | \ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e3d8555d4a9..cf546e367d3 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2322,11 +2322,6 @@ void b43_mac_enable(struct b43_wldev *dev) b43_read32(dev, B43_MMIO_MACCTL); b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); b43_power_saving_ctl_bits(dev, 0); - - /* Re-enable IRQs. */ - spin_lock_irq(&dev->wl->irq_lock); - b43_interrupt_enable(dev, dev->irq_savedstate); - spin_unlock_irq(&dev->wl->irq_lock); } } @@ -2340,14 +2335,6 @@ void b43_mac_suspend(struct b43_wldev *dev) B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { - /* Mask IRQs before suspending MAC. Otherwise - * the MAC stays busy and won't suspend. */ - spin_lock_irq(&dev->wl->irq_lock); - tmp = b43_interrupt_disable(dev, B43_IRQ_ALL); - spin_unlock_irq(&dev->wl->irq_lock); - b43_synchronize_irq(dev); - dev->irq_savedstate = tmp; - b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) -- cgit v1.2.3 From 57ffc589a92424f9def74fe0d49b2f7763ff07fd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 29 Apr 2008 17:18:59 +0200 Subject: mac80211: clean up get_tx_stats callback The callback takes a ieee80211_tx_queue_stats with a contained array of ieee80211_tx_queue_stats_data, remove the former, rename the latter to ieee80211_tx_queue_stats and make tx_stats() take the array directly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 8 +++----- drivers/net/wireless/b43/pio.c | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 6dcbb3c87e7..f50e2014ffb 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1427,18 +1427,16 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev, { const int nr_queues = dev->wl->hw->queues; struct b43_dmaring *ring; - struct ieee80211_tx_queue_stats_data *data; unsigned long flags; int i; for (i = 0; i < nr_queues; i++) { - data = &(stats->data[i]); ring = select_ring_by_priority(dev, i); spin_lock_irqsave(&ring->lock, flags); - data->len = ring->used_slots / SLOTS_PER_PACKET; - data->limit = ring->nr_slots / SLOTS_PER_PACKET; - data->count = ring->nr_tx_packets; + stats[i].len = ring->used_slots / SLOTS_PER_PACKET; + stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET; + stats[i].count = ring->nr_tx_packets; spin_unlock_irqrestore(&ring->lock, flags); } } diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index fcacafb0434..08c8a087f30 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -611,18 +611,16 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev, { const int nr_queues = dev->wl->hw->queues; struct b43_pio_txqueue *q; - struct ieee80211_tx_queue_stats_data *data; unsigned long flags; int i; for (i = 0; i < nr_queues; i++) { - data = &(stats->data[i]); q = select_queue_by_priority(dev, i); spin_lock_irqsave(&q->lock, flags); - data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; - data->limit = B43_PIO_MAX_NR_TXPACKETS; - data->count = q->nr_tx_packets; + stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; + stats[i].limit = B43_PIO_MAX_NR_TXPACKETS; + stats[i].count = q->nr_tx_packets; spin_unlock_irqrestore(&q->lock, flags); } } -- cgit v1.2.3 From e100bb64bf7cdeae7f742a65ee1985649a7fd1b4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 30 Apr 2008 18:51:21 +0200 Subject: mac80211: QoS related cleanups This * makes the queue number passed to drivers a u16 (as it will be with skb_get_queue_mapping) * removes the useless queue number defines * splits hw->queues into hw->queues/ampdu_queues * removes the debugfs files for per-queue counters * removes some dead QoS code * removes the beacon queue configuration for IBSS so that the drivers now never get a queue number bigger than (hw->queues + hw->ampdu_queues - 1) for tx and only in the range 0..hw->queues-1 for conf_tx. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cf546e367d3..c6e79a15d3c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2996,8 +2996,7 @@ static void b43_qos_update_work(struct work_struct *work) mutex_unlock(&wl->mutex); } -static int b43_op_conf_tx(struct ieee80211_hw *hw, - int _queue, +static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, const struct ieee80211_tx_queue_params *params) { struct b43_wl *wl = hw_to_b43_wl(hw); -- cgit v1.2.3 From cdbf0846e2dd5f122f3910d0e2a305fab337744b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Fri, 2 May 2008 13:47:48 -0700 Subject: b43: replace limit_value macro with clamp_val kernel-provided clamp_val is identical, delete the private limit_value helper. Signed-off-by: Harvey Harrison Cc: Michael Buesch Cc: "John W. Linville" Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 16 ---------------- drivers/net/wireless/b43/lo.c | 4 ++-- drivers/net/wireless/b43/main.c | 8 ++++---- drivers/net/wireless/b43/phy.c | 24 ++++++++++++------------ 4 files changed, 18 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 7d034df250b..0c2bc061e8f 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -939,22 +939,6 @@ static inline bool __b43_warn_on_dummy(bool x) { return x; } # define B43_WARN_ON(x) __b43_warn_on_dummy(unlikely(!!(x))) #endif -/** Limit a value between two limits */ -#ifdef limit_value -# undef limit_value -#endif -#define limit_value(value, min, max) \ - ({ \ - typeof(value) __value = (value); \ - typeof(value) __min = (min); \ - typeof(value) __max = (max); \ - if (__value < __min) \ - __value = __min; \ - else if (__value > __max) \ - __value = __max; \ - __value; \ - }) - /* Convert an integer to a Q5.2 value */ #define INT_TO_Q52(i) ((i) << 2) /* Convert a Q5.2 value to an integer (precision loss!) */ diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 4ce1e356120..9c854d6aae3 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -199,7 +199,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) if (lb_gain > 10) { radio_pctl_reg = 0; pga = abs(10 - lb_gain) / 6; - pga = limit_value(pga, 0, 15); + pga = clamp_val(pga, 0, 15); } else { int cmp_val; int tmp; @@ -321,7 +321,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev, phy->lna_lod_gain = 1; trsw_rx_gain -= 8; } - trsw_rx_gain = limit_value(trsw_rx_gain, 0, 0x2D); + trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); phy->pga_gain = trsw_rx_gain / 3; if (phy->pga_gain >= 5) { phy->pga_gain -= 5; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c6e79a15d3c..7c23aa8705c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1182,10 +1182,10 @@ static void handle_irq_noise(struct b43_wldev *dev) /* Get the noise samples. */ B43_WARN_ON(dev->noisecalc.nr_samples >= 8); i = dev->noisecalc.nr_samples; - noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); + noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); + noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); + noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); + noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]]; dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]]; dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]]; diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 8b3c24da8db..6378c266549 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -1415,7 +1415,7 @@ static void b43_phy_initg(struct b43_wldev *dev) * the value 0x7FFFFFFF here. I think that is some weird * compiler optimization in the original driver. * Essentially, what we do here is resetting all NRSSI LT - * entries to -32 (see the limit_value() in nrssi_hw_update()) + * entries to -32 (see the clamp_val() in nrssi_hw_update()) */ b43_nrssi_hw_update(dev, 0xFFFF); //FIXME? b43_calc_nrssi_threshold(dev); @@ -1477,13 +1477,13 @@ static s8 b43_phy_estimate_power_out(struct b43_wldev *dev, s8 tssi) switch (phy->type) { case B43_PHYTYPE_A: tmp += 0x80; - tmp = limit_value(tmp, 0x00, 0xFF); + tmp = clamp_val(tmp, 0x00, 0xFF); dbm = phy->tssi2dbm[tmp]; //TODO: There's a FIXME on the specs break; case B43_PHYTYPE_B: case B43_PHYTYPE_G: - tmp = limit_value(tmp, 0x00, 0x3F); + tmp = clamp_val(tmp, 0x00, 0x3F); dbm = phy->tssi2dbm[tmp]; break; default: @@ -1542,8 +1542,8 @@ void b43_put_attenuation_into_ranges(struct b43_wldev *dev, break; } - *_rfatt = limit_value(rfatt, rf_min, rf_max); - *_bbatt = limit_value(bbatt, bb_min, bb_max); + *_rfatt = clamp_val(rfatt, rf_min, rf_max); + *_bbatt = clamp_val(bbatt, bb_min, bb_max); } /* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ @@ -1638,7 +1638,7 @@ void b43_phy_xmitpower(struct b43_wldev *dev) /* Get desired power (in Q5.2) */ desired_pwr = INT_TO_Q52(phy->power_level); /* And limit it. max_pwr already is Q5.2 */ - desired_pwr = limit_value(desired_pwr, 0, max_pwr); + desired_pwr = clamp_val(desired_pwr, 0, max_pwr); if (b43_debug(dev, B43_DBG_XMITPOWER)) { b43dbg(dev->wl, "Current TX power output: " Q52_FMT @@ -1748,7 +1748,7 @@ static inline f = q; i++; } while (delta >= 2); - entry[index] = limit_value(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128); + entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128); return 0; } @@ -2274,7 +2274,7 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) for (i = 0; i < 64; i++) { tmp = b43_nrssi_hw_read(dev, i); tmp -= val; - tmp = limit_value(tmp, -32, 31); + tmp = clamp_val(tmp, -32, 31); b43_nrssi_hw_write(dev, i, tmp); } } @@ -2291,7 +2291,7 @@ void b43_nrssi_mem_update(struct b43_wldev *dev) tmp = (i - delta) * phy->nrssislope; tmp /= 0x10000; tmp += 0x3A; - tmp = limit_value(tmp, 0, 0x3F); + tmp = clamp_val(tmp, 0, 0x3F); phy->nrssi_lt[i] = tmp; } } @@ -2728,7 +2728,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev) } else threshold = phy->nrssi[1] - 5; - threshold = limit_value(threshold, 0, 0x3E); + threshold = clamp_val(threshold, 0, 0x3E); b43_phy_read(dev, 0x0020); /* dummy read */ b43_phy_write(dev, 0x0020, (((u16) threshold) << 8) | 0x001C); @@ -2779,7 +2779,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev) else a += 32; a = a >> 6; - a = limit_value(a, -31, 31); + a = clamp_val(a, -31, 31); b = b * (phy->nrssi[1] - phy->nrssi[0]); b += (phy->nrssi[0] << 6); @@ -2788,7 +2788,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev) else b += 32; b = b >> 6; - b = limit_value(b, -31, 31); + b = clamp_val(b, -31, 31); tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000; tmp_u16 |= ((u32) b & 0x0000003F); -- cgit v1.2.3 From 566bfe5a8bcde13188a356f77666f8115813cf31 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 8 May 2008 19:15:40 +0200 Subject: mac80211: use hardware flags for signal/noise units trying to clean up the signal/noise code. the previous code in mac80211 had confusing names for the related variables, did not have much definition of what units of signal and noise were provided and used implicit mechanisms from the wireless extensions. this patch introduces hardware capability flags to let the hardware specify clearly if it can provide signal and noise level values and which units it can provide. this also anticipates possible new units like RCPI in the future. for signal: IEEE80211_HW_SIGNAL_UNSPEC - unspecified, unknown, hw specific IEEE80211_HW_SIGNAL_DB - dB difference to unspecified reference point IEEE80211_HW_SIGNAL_DBM - dBm, difference to 1mW for noise we currently only have dBm: IEEE80211_HW_NOISE_DBM - dBm, difference to 1mW if IEEE80211_HW_SIGNAL_UNSPEC or IEEE80211_HW_SIGNAL_DB is used the driver has to provide the maximum value (max_signal) it reports in order for applications to make sense of the signal values. i tried my best to find out for each driver what it can provide and update it but i'm not sure (?) for some of them and used the more conservative guess in doubt. this can be fixed easily after this patch has been merged by changing the hardware flags of the driver. DRIVER SIGNAL MAX NOISE QUAL ----------------------------------------------------------------- adm8211 unspec(?) 100 n/a missing at76_usb unspec(?) (?) unused missing ath5k dBm dBm percent rssi b43legacy dBm dBm percent jssi(?) b43 dBm dBm percent jssi(?) iwl-3945 dBm dBm percent snr+more iwl-4965 dBm dBm percent snr+more p54 unspec 127 n/a missing rt2x00 dBm n/a percent rssi+tx/rx frame success rt2400 dBm n/a rt2500pci dBm n/a rt2500usb dBm n/a rt61pci dBm n/a rt73usb dBm n/a rtl8180 unspec(?) 65 n/a (?) rtl8187 unspec(?) 65 (?) noise(?) zd1211 dB(?) 100 n/a percent drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 8 ++++---- drivers/net/wireless/b43/xmit.c | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7c23aa8705c..fc23ba5309b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4466,10 +4466,10 @@ static int b43_wireless_init(struct ssb_device *dev) /* fill hw info */ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_RX_INCLUDES_FCS; - hw->max_signal = 100; - hw->max_rssi = -110; - hw->max_noise = -110; + IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + hw->queues = b43_modparam_qos ? 4 : 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 88491947a20..afce9338d83 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -581,12 +581,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) // and also find out what the maximum possible value is. // Fill status.ssi and status.signal fields. } else { - status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi, + status.signal = b43_rssi_postprocess(dev, rxhdr->jssi, (phystat0 & B43_RX_PHYST0_OFDM), (phystat0 & B43_RX_PHYST0_GAINCTL), (phystat3 & B43_RX_PHYST3_TRSTATE)); - /* the next line looks wrong, but is what mac80211 wants */ - status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; + status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; } if (phystat0 & B43_RX_PHYST0_OFDM) -- cgit v1.2.3 From 7a1d65235da829e6dc8938b82c991e40e278fc50 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 10 May 2008 11:12:31 +0200 Subject: b43: nphy.c remove duplicated include Remove duplicated include in drivers/net/wireless/b43/nphy.c Signed-off-by: Huang Weiyi Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/nphy.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c index 8695eb22347..644eed993be 100644 --- a/drivers/net/wireless/b43/nphy.c +++ b/drivers/net/wireless/b43/nphy.c @@ -29,8 +29,6 @@ #include "nphy.h" #include "tables_nphy.h" -#include - void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO -- cgit v1.2.3 From 6dcdc19e4ba4e6a9ccd733fdb745ad062cf3ea0a Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 13 May 2008 18:13:35 -0700 Subject: b43: use the bitrev helpers rather than rolling a private one The 4-bit reversal flip_4bit is replaced with the bitrev helper bitrev8 and a 4-bit shift. The B43_WARN is moved to the location where a register is read from for checking there. The other caller explicitly passes an array index which is guaranteed to be within range and so a B43_WARN is not added there. Signed-off-by: Harvey Harrison Reviewed-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 6378c266549..305d4cd6fd0 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "b43.h" #include "phy.h" @@ -83,25 +84,9 @@ const u8 b43_radio_channel_codes_bg[] = { 72, 84, }; +#define bitrev4(tmp) (bitrev8(tmp) >> 4) static void b43_phy_initg(struct b43_wldev *dev); -/* Reverse the bits of a 4bit value. - * Example: 1101 is flipped 1011 - */ -static u16 flip_4bit(u16 value) -{ - u16 flipped = 0x0000; - - B43_WARN_ON(value & ~0x000F); - - flipped |= (value & 0x0001) << 3; - flipped |= (value & 0x0002) << 1; - flipped |= (value & 0x0004) >> 1; - flipped |= (value & 0x0008) >> 3; - - return flipped; -} - static void generate_rfatt_list(struct b43_wldev *dev, struct b43_rfatt_list *list) { @@ -2891,13 +2876,13 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode) } radio_stacksave(0x0078); tmp = (b43_radio_read16(dev, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); + B43_WARN_ON(tmp > 15); + flipped = bitrev4(tmp); if (flipped < 10 && flipped >= 8) flipped = 7; else if (flipped >= 10) flipped -= 3; - flipped = flip_4bit(flipped); - flipped = (flipped << 1) | 0x0020; + flipped = (bitrev4(flipped) << 1) | 0x0020; b43_radio_write16(dev, 0x0078, flipped); b43_calc_nrssi_threshold(dev); @@ -3530,7 +3515,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev) tmp1 >>= 9; for (i = 0; i < 16; i++) { - radio78 = ((flip_4bit(i) << 1) | 0x20); + radio78 = (bitrev4(i) << 1) | 0x0020; b43_radio_write16(dev, 0x78, radio78); udelay(10); for (j = 0; j < 16; j++) { -- cgit v1.2.3 From 36d6825b91bc492b65b6333c369cd96a2fc8c903 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 May 2008 12:55:26 +0200 Subject: mac80211: let drivers wake but not start queues Having drivers start queues is just confusing, their ->start() callback can block and do whatever is necessary, so let mac80211 start queues and have drivers wake queues when necessary (to get packets flowing again right away.) Signed-off-by: Johannes Berg Acked-by: David S. Miller Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index fc23ba5309b..9445a604a96 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3497,7 +3497,6 @@ static int b43_wireless_core_start(struct b43_wldev *dev) /* Start data flow (TX/RX). */ b43_mac_enable(dev); b43_interrupt_enable(dev, dev->irq_savedstate); - ieee80211_start_queues(dev->wl->hw); /* Start maintainance work */ b43_periodic_tasks_setup(dev); -- cgit v1.2.3 From 2e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 May 2008 12:55:27 +0200 Subject: mac80211: use rate index in TX control This patch modifies struct ieee80211_tx_control to give band info and the rate index (instead of rate pointers) to drivers. This mostly serves to reduce the TX control structure size to make it fit into skb->cb so that the fragmentation code can put it there and we can think about passing it to drivers that way in the future. The rt2x00 driver update was done by Ivo, thanks. Signed-off-by: Ivo van Doorn Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43/xmit.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9445a604a96..e428645352b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1372,7 +1372,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev, bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len = min((size_t) dev->wl->current_beacon->len, 0x200 - sizeof(struct b43_plcp_hdr6)); - rate = dev->wl->beacon_txctl.tx_rate->hw_value; + rate = ieee80211_get_tx_rate(dev->wl->hw, &dev->wl->beacon_txctl)->hw_value; b43_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index afce9338d83..9b682a3cf5e 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -201,13 +201,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, u32 mac_ctl = 0; u16 phy_ctl = 0; u8 extra_ft = 0; + struct ieee80211_rate *txrate; memset(txhdr, 0, sizeof(*txhdr)); - WARN_ON(!txctl->tx_rate); - rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB; + txrate = ieee80211_get_tx_rate(dev->wl->hw, txctl); + rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; rate_ofdm = b43_is_ofdm_rate(rate); - fbrate = txctl->alt_retry_rate ? : txctl->tx_rate; + fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : txrate; rate_fb = fbrate->hw_value; rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); @@ -336,9 +337,11 @@ int b43_generate_txhdr(struct b43_wldev *dev, int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; struct b43_plcp_hdr6 *plcp; + struct ieee80211_rate *rts_cts_rate; - WARN_ON(!txctl->rts_cts_rate); - rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB; + rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl); + + rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); -- cgit v1.2.3 From e039fa4a4195ac4ee895e6f3d1334beed63256fe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 May 2008 12:55:29 +0200 Subject: mac80211: move TX info into skb->cb This patch converts mac80211 and all drivers to have transmit information and status in skb->cb rather than allocating extra memory for it and copying all the data around. To make it fit, a union is used where only data that is necessary for all steps is kept outside of the union. A number of fixes were done by Ivo, as well as the rt2x00 part of this patch. Signed-off-by: Ivo van Doorn Signed-off-by: Johannes Berg Acked-by: David S. Miller Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 - drivers/net/wireless/b43/dma.c | 45 ++++++++++++++++++-------------- drivers/net/wireless/b43/dma.h | 3 +-- drivers/net/wireless/b43/main.c | 33 +++++++++-------------- drivers/net/wireless/b43/pio.c | 36 +++++++++++++------------ drivers/net/wireless/b43/pio.h | 8 ++---- drivers/net/wireless/b43/xmit.c | 58 ++++++++++++++++++++--------------------- drivers/net/wireless/b43/xmit.h | 4 +-- 8 files changed, 90 insertions(+), 98 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 0c2bc061e8f..aa493830a82 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -733,7 +733,6 @@ struct b43_wl { /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ struct sk_buff *current_beacon; - struct ieee80211_tx_control beacon_txctl; bool beacon0_uploaded; bool beacon1_uploaded; struct work_struct beacon_update_trigger; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index f50e2014ffb..aced9866d81 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1131,10 +1131,10 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) } static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff *skb, - struct ieee80211_tx_control *ctl) + struct sk_buff *skb) { const struct b43_dma_ops *ops = ring->ops; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *header; int slot, old_top_slot, old_used_slots; int err; @@ -1158,7 +1158,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, header = &(ring->txhdr_cache[slot * hdrsize]); cookie = generate_cookie(ring, slot); err = b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, ctl, cookie); + skb->data, skb->len, info, cookie); if (unlikely(err)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; @@ -1180,7 +1180,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring, desc = ops->idx2desc(ring, slot, &meta); memset(meta, 0, sizeof(*meta)); - memcpy(&meta->txstat.control, ctl, sizeof(*ctl)); meta->skb = skb; meta->is_last_fragment = 1; @@ -1210,7 +1209,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1); - if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { /* Tell the firmware about the cookie of the last * mcast frame, so it can clear the more-data bit in it. */ b43_shm_write16(ring->dev, B43_SHM_SHARED, @@ -1281,16 +1280,16 @@ static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev, return ring; } -int b43_dma_tx(struct b43_wldev *dev, - struct sk_buff *skb, struct ieee80211_tx_control *ctl) +int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) { struct b43_dmaring *ring; struct ieee80211_hdr *hdr; int err = 0; unsigned long flags; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); hdr = (struct ieee80211_hdr *)skb->data; - if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { /* The multicast ring will be sent after the DTIM */ ring = dev->dma.tx_ring_mcast; /* Set the more-data bit. Ucode will clear it on @@ -1298,7 +1297,7 @@ int b43_dma_tx(struct b43_wldev *dev, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); } else { /* Decide by priority where to put this frame. */ - ring = select_ring_by_priority(dev, ctl->queue); + ring = select_ring_by_priority(dev, info->queue); } spin_lock_irqsave(&ring->lock, flags); @@ -1316,9 +1315,9 @@ int b43_dma_tx(struct b43_wldev *dev, /* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The queue to ring mapping is * static, so we don't need to store it per frame. */ - ring->queue_prio = ctl->queue; + ring->queue_prio = info->queue; - err = dma_tx_fragment(ring, skb, ctl); + err = dma_tx_fragment(ring, skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ @@ -1334,7 +1333,7 @@ int b43_dma_tx(struct b43_wldev *dev, if ((free_slots(ring) < SLOTS_PER_PACKET) || should_inject_overflow(ring)) { /* This TX ring is full. */ - ieee80211_stop_queue(dev->wl->hw, ctl->queue); + ieee80211_stop_queue(dev->wl->hw, info->queue); ring->stopped = 1; if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); @@ -1377,13 +1376,19 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, b43_txhdr_size(dev), 1); if (meta->is_last_fragment) { - B43_WARN_ON(!meta->skb); - /* Call back to inform the ieee80211 subsystem about the - * status of the transmission. - * Some fields of txstat are already filled in dma_tx(). + struct ieee80211_tx_info *info; + + BUG_ON(!meta->skb); + + info = IEEE80211_SKB_CB(meta->skb); + + memset(&info->status, 0, sizeof(info->status)); + + /* + * Call back to inform the ieee80211 subsystem about + * the status of the transmission. */ - frame_succeed = b43_fill_txstatus_report( - &(meta->txstat), status); + frame_succeed = b43_fill_txstatus_report(info, status); #ifdef CONFIG_B43_DEBUG if (frame_succeed) ring->nr_succeed_tx_packets++; @@ -1391,8 +1396,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, ring->nr_failed_tx_packets++; ring->nr_total_packet_tries += status->frame_count; #endif /* DEBUG */ - ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, - &(meta->txstat)); + ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); + /* skb is freed by ieee80211_tx_status_irqsafe() */ meta->skb = NULL; } else { diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 20acf885dba..d1eb5c0848a 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -181,7 +181,6 @@ struct b43_dmadesc_meta { dma_addr_t dmaaddr; /* ieee80211 TX status. Only used once per 802.11 frag. */ bool is_last_fragment; - struct ieee80211_tx_status txstat; }; struct b43_dmaring; @@ -285,7 +284,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev, struct ieee80211_tx_queue_stats *stats); int b43_dma_tx(struct b43_wldev *dev, - struct sk_buff *skb, struct ieee80211_tx_control *ctl); + struct sk_buff *skb); void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e428645352b..3622d76de1e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1368,18 +1368,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev, unsigned int rate; u16 ctl; int antenna; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len = min((size_t) dev->wl->current_beacon->len, 0x200 - sizeof(struct b43_plcp_hdr6)); - rate = ieee80211_get_tx_rate(dev->wl->hw, &dev->wl->beacon_txctl)->hw_value; + rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; b43_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); /* Write the PHY TX control parameters. */ - antenna = b43_antenna_from_ieee80211(dev, - dev->wl->beacon_txctl.antenna_sel_tx); + antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); antenna = b43_antenna_to_phyctl(antenna); ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); /* We can't send beacons with short preamble. Would get PHY errors. */ @@ -1613,8 +1613,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ -static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon, - const struct ieee80211_tx_control *txctl) +static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) { /* This is the top half of the ansynchronous beacon update. * The bottom half is the beacon IRQ. @@ -1625,7 +1624,6 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon, if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; - memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl)); wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); @@ -2813,8 +2811,7 @@ static int b43_rng_init(struct b43_wl *wl) } static int b43_op_tx(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ieee80211_tx_control *ctl) + struct sk_buff *skb) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; @@ -2836,9 +2833,9 @@ static int b43_op_tx(struct ieee80211_hw *hw, err = -ENODEV; if (likely(b43_status(dev) >= B43_STAT_STARTED)) { if (b43_using_pio_transfers(dev)) - err = b43_pio_tx(dev, skb, ctl); + err = b43_pio_tx(dev, skb); else - err = b43_dma_tx(dev, skb, ctl); + err = b43_dma_tx(dev, skb); } read_unlock_irqrestore(&wl->tx_lock, flags); @@ -3429,10 +3426,8 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); b43_set_ssid(dev, conf->ssid, conf->ssid_len); - if (conf->beacon) { - b43_update_templates(wl, conf->beacon, - conf->beacon_control); - } + if (conf->beacon) + b43_update_templates(wl, conf->beacon); } b43_write_mac_bssid_templates(dev); } @@ -4118,31 +4113,29 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) struct b43_wl *wl = hw_to_b43_wl(hw); struct sk_buff *beacon; unsigned long flags; - struct ieee80211_tx_control txctl; /* We could modify the existing beacon and set the aid bit in * the TIM field, but that would probably require resizing and * moving of data within the beacon template. * Simply request a new beacon and let mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(hw, wl->vif, &txctl); + beacon = ieee80211_beacon_get(hw, wl->vif); if (unlikely(!beacon)) return -ENOMEM; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon, &txctl); + b43_update_templates(wl, beacon); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; } static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *beacon, - struct ieee80211_tx_control *ctl) + struct sk_buff *beacon) { struct b43_wl *wl = hw_to_b43_wl(hw); unsigned long flags; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon, ctl); + b43_update_templates(wl, beacon); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 08c8a087f30..284786a94e7 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -446,29 +446,27 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, } static int pio_tx_frame(struct b43_pio_txqueue *q, - struct sk_buff *skb, - struct ieee80211_tx_control *ctl) + struct sk_buff *skb) { struct b43_pio_txpacket *pack; struct b43_txhdr txhdr; u16 cookie; int err; unsigned int hdrlen; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); B43_WARN_ON(list_empty(&q->packets_list)); pack = list_entry(q->packets_list.next, struct b43_pio_txpacket, list); - memset(&pack->txstat, 0, sizeof(pack->txstat)); - memcpy(&pack->txstat.control, ctl, sizeof(*ctl)); cookie = generate_cookie(q, pack); hdrlen = b43_txhdr_size(q->dev); err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, - skb->len, ctl, cookie); + skb->len, info, cookie); if (err) return err; - if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { /* Tell the firmware about the cookie of the last * mcast frame, so it can clear the more-data bit in it. */ b43_shm_write16(q->dev, B43_SHM_SHARED, @@ -492,17 +490,18 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, return 0; } -int b43_pio_tx(struct b43_wldev *dev, - struct sk_buff *skb, struct ieee80211_tx_control *ctl) +int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) { struct b43_pio_txqueue *q; struct ieee80211_hdr *hdr; unsigned long flags; unsigned int hdrlen, total_len; int err = 0; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); hdr = (struct ieee80211_hdr *)skb->data; - if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { /* The multicast queue will be sent after the DTIM. */ q = dev->pio.tx_queue_mcast; /* Set the frame More-Data bit. Ucode will clear it @@ -510,7 +509,7 @@ int b43_pio_tx(struct b43_wldev *dev, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); } else { /* Decide by priority where to put this frame. */ - q = select_queue_by_priority(dev, ctl->queue); + q = select_queue_by_priority(dev, info->queue); } spin_lock_irqsave(&q->lock, flags); @@ -533,7 +532,7 @@ int b43_pio_tx(struct b43_wldev *dev, if (total_len > (q->buffer_size - q->buffer_used)) { /* Not enough memory on the queue. */ err = -EBUSY; - ieee80211_stop_queue(dev->wl->hw, ctl->queue); + ieee80211_stop_queue(dev->wl->hw, info->queue); q->stopped = 1; goto out_unlock; } @@ -541,9 +540,9 @@ int b43_pio_tx(struct b43_wldev *dev, /* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The mac80211-queue to b43-queue * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = ctl->queue; + q->queue_prio = info->queue; - err = pio_tx_frame(q, skb, ctl); + err = pio_tx_frame(q, skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ @@ -561,7 +560,7 @@ int b43_pio_tx(struct b43_wldev *dev, if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || (q->free_packet_slots == 0)) { /* The queue is full. */ - ieee80211_stop_queue(dev->wl->hw, ctl->queue); + ieee80211_stop_queue(dev->wl->hw, info->queue); q->stopped = 1; } @@ -578,6 +577,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, struct b43_pio_txqueue *q; struct b43_pio_txpacket *pack = NULL; unsigned int total_len; + struct ieee80211_tx_info *info; q = parse_cookie(dev, status->cookie, &pack); if (unlikely(!q)) @@ -586,15 +586,17 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, spin_lock(&q->lock); /* IRQs are already disabled. */ - b43_fill_txstatus_report(&(pack->txstat), status); + info = (void *)pack->skb; + memset(&info->status, 0, sizeof(info->status)); + + b43_fill_txstatus_report(info, status); total_len = pack->skb->len + b43_txhdr_size(dev); total_len = roundup(total_len, 4); q->buffer_used -= total_len; q->free_packet_slots += 1; - ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb, - &(pack->txstat)); + ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); pack->skb = NULL; list_add(&pack->list, &q->packets_list); diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index e2ec676cc9e..6c174c91ca2 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h @@ -62,8 +62,6 @@ struct b43_pio_txpacket { struct b43_pio_txqueue *queue; /* The TX data packet. */ struct sk_buff *skb; - /* The status meta data. */ - struct ieee80211_tx_status txstat; /* Index in the (struct b43_pio_txqueue)->packets array. */ u8 index; @@ -167,8 +165,7 @@ int b43_pio_init(struct b43_wldev *dev); void b43_pio_stop(struct b43_wldev *dev); void b43_pio_free(struct b43_wldev *dev); -int b43_pio_tx(struct b43_wldev *dev, - struct sk_buff *skb, struct ieee80211_tx_control *ctl); +int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); void b43_pio_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); void b43_pio_get_tx_stats(struct b43_wldev *dev, @@ -193,8 +190,7 @@ static inline void b43_pio_stop(struct b43_wldev *dev) { } static inline int b43_pio_tx(struct b43_wldev *dev, - struct sk_buff *skb, - struct ieee80211_tx_control *ctl) + struct sk_buff *skb) { return 0; } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 9b682a3cf5e..f9e1cff2aec 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -185,14 +185,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 *_txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, + const struct ieee80211_tx_info *info, u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; const struct b43_phy *phy = &dev->phy; const struct ieee80211_hdr *wlhdr = (const struct ieee80211_hdr *)fragment_data; - int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); + int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)); u16 fctl = le16_to_cpu(wlhdr->frame_control); struct ieee80211_rate *fbrate; u8 rate, rate_fb; @@ -205,10 +205,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, memset(txhdr, 0, sizeof(*txhdr)); - txrate = ieee80211_get_tx_rate(dev->wl->hw, txctl); + txrate = ieee80211_get_tx_rate(dev->wl->hw, info); rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; rate_ofdm = b43_is_ofdm_rate(rate); - fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : txrate; + fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate; rate_fb = fbrate->hw_value; rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); @@ -228,15 +228,13 @@ int b43_generate_txhdr(struct b43_wldev *dev, * use the original dur_id field. */ txhdr->dur_fb = wlhdr->duration_id; } else { - txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, - txctl->vif, - fragment_len, - fbrate); + txhdr->dur_fb = ieee80211_generic_frame_duration( + dev->wl->hw, info->control.vif, fragment_len, fbrate); } plcp_fragment_len = fragment_len + FCS_LEN; if (use_encryption) { - u8 key_idx = txctl->hw_key->hw_key_idx; + u8 key_idx = info->control.hw_key->hw_key_idx; struct b43_key *key; int wlhdr_len; size_t iv_len; @@ -254,7 +252,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, } /* Hardware appends ICV. */ - plcp_fragment_len += txctl->icv_len; + plcp_fragment_len += info->control.icv_len; key_idx = b43_kidx_to_fw(dev, key_idx); mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & @@ -262,7 +260,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & B43_TXH_MAC_KEYALG; wlhdr_len = ieee80211_get_hdrlen(fctl); - iv_len = min((size_t) txctl->iv_len, + iv_len = min((size_t) info->control.iv_len, ARRAY_SIZE(txhdr->iv)); memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); } @@ -293,10 +291,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; - switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { + switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { case 0: /* Default */ phy_ctl |= B43_TXH_PHY_ANT01AUTO; break; @@ -317,21 +315,21 @@ int b43_generate_txhdr(struct b43_wldev *dev, } /* MAC control */ - if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK)) + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) mac_ctl |= B43_TXH_MAC_HWSEQ; - if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43_TXH_MAC_STMSDU; if (phy->type == B43_PHYTYPE_A) mac_ctl |= B43_TXH_MAC_5GHZ; - if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) + if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) mac_ctl |= B43_TXH_MAC_LONGFRAME; /* Generate the RTS or CTS-to-self frame */ - if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) || - (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) { + if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || + (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; @@ -339,14 +337,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, struct b43_plcp_hdr6 *plcp; struct ieee80211_rate *rts_cts_rate; - rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl); + rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { + if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { struct ieee80211_cts *cts; if (b43_is_old_txhdr_format(dev)) { @@ -356,9 +354,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, cts = (struct ieee80211_cts *) (txhdr->new_format.rts_frame); } - ieee80211_ctstoself_get(dev->wl->hw, txctl->vif, + ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, - txctl, cts); + info, cts); mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { @@ -371,9 +369,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts = (struct ieee80211_rts *) (txhdr->new_format.rts_frame); } - ieee80211_rts_get(dev->wl->hw, txctl->vif, + ieee80211_rts_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, - txctl, rts); + info, rts); mac_ctl |= B43_TXH_MAC_SENDRTS; len = sizeof(struct ieee80211_rts); } @@ -687,27 +685,27 @@ void b43_handle_txstatus(struct b43_wldev *dev, /* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was * successfully transmitted. */ -bool b43_fill_txstatus_report(struct ieee80211_tx_status *report, +bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, const struct b43_txstatus *status) { bool frame_success = 1; if (status->acked) { /* The frame was ACKed. */ - report->flags |= IEEE80211_TX_STATUS_ACK; + report->flags |= IEEE80211_TX_STAT_ACK; } else { /* The frame was not ACKed... */ - if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { + if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ...but we expected an ACK. */ frame_success = 0; - report->excessive_retries = 1; + report->status.excessive_retries = 1; } } if (status->frame_count == 0) { /* The frame was not transmitted at all. */ - report->retry_count = 0; + report->status.retry_count = 0; } else - report->retry_count = status->frame_count - 1; + report->status.retry_count = status->frame_count - 1; return frame_success; } diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index b05f44e0d62..0215faf4754 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 * txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, u16 cookie); + const struct ieee80211_tx_info *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { @@ -294,7 +294,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); void b43_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); -bool b43_fill_txstatus_report(struct ieee80211_tx_status *report, +bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, const struct b43_txstatus *status); void b43_tx_suspend(struct b43_wldev *dev); -- cgit v1.2.3 From e93048825face354ecb0cb3ac00190c764a44f45 Mon Sep 17 00:00:00 2001 From: "Larry.Finger@lwfinger.net" Date: Thu, 15 May 2008 14:07:36 -0500 Subject: b43: Fix typo in firmware file name for 802.11 cores with rev 13 When the patch for the BCM4311 rev 2 was prepared, I misread the specs and coded the wrong file name for the initvals firmware. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3622d76de1e..ff5dce67faa 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1958,7 +1958,7 @@ static int b43_request_firmware(struct b43_wldev *dev) if ((rev >= 5) && (rev <= 10)) filename = "b0g0initvals5"; else if (rev >= 13) - filename = "lp0initvals13"; + filename = "b0g0initvals13"; else goto err_no_initvals; break; -- cgit v1.2.3 From e2530083609148a7835b54c431f6b8956407c1f6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 17 May 2008 00:57:14 +0200 Subject: mac80211: use multi-queue master netdevice This patch updates mac80211 and drivers to be multi-queue aware and use that instead of the internal queue mapping. Also does a number of cleanups in various pieces of the code that fall out and reduces internal mac80211 state size. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 7 ++++--- drivers/net/wireless/b43/pio.c | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index aced9866d81..b4eadd908be 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1297,7 +1297,8 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); } else { /* Decide by priority where to put this frame. */ - ring = select_ring_by_priority(dev, info->queue); + ring = select_ring_by_priority( + dev, skb_get_queue_mapping(skb)); } spin_lock_irqsave(&ring->lock, flags); @@ -1315,7 +1316,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) /* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The queue to ring mapping is * static, so we don't need to store it per frame. */ - ring->queue_prio = info->queue; + ring->queue_prio = skb_get_queue_mapping(skb); err = dma_tx_fragment(ring, skb); if (unlikely(err == -ENOKEY)) { @@ -1333,7 +1334,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) if ((free_slots(ring) < SLOTS_PER_PACKET) || should_inject_overflow(ring)) { /* This TX ring is full. */ - ieee80211_stop_queue(dev->wl->hw, info->queue); + ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); ring->stopped = 1; if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 284786a94e7..8b1555d95f1 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -509,7 +509,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); } else { /* Decide by priority where to put this frame. */ - q = select_queue_by_priority(dev, info->queue); + q = select_queue_by_priority(dev, skb_get_queue_mapping(skb)); } spin_lock_irqsave(&q->lock, flags); @@ -532,7 +532,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) if (total_len > (q->buffer_size - q->buffer_used)) { /* Not enough memory on the queue. */ err = -EBUSY; - ieee80211_stop_queue(dev->wl->hw, info->queue); + ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); q->stopped = 1; goto out_unlock; } @@ -540,7 +540,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) /* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The mac80211-queue to b43-queue * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = info->queue; + q->queue_prio = skb_get_queue_mapping(skb); err = pio_tx_frame(q, skb); if (unlikely(err == -ENOKEY)) { @@ -560,7 +560,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || (q->free_packet_slots == 0)) { /* The queue is full. */ - ieee80211_stop_queue(dev->wl->hw, info->queue); + ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); q->stopped = 1; } -- cgit v1.2.3 From e48b0eeb0ab508021b654a45f332b30cac2163b9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 17 May 2008 22:44:35 +0200 Subject: b43: Add hooks for firmware debugging This patch adds some hooks for firmware debugging. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 9 +++++ drivers/net/wireless/b43/main.c | 79 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index aa493830a82..00468594b45 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -422,6 +422,12 @@ enum { B43_IRQ_RFKILL | \ B43_IRQ_TX_OK) +/* Debug-IRQ reasons. */ +#define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */ +#define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */ +#define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */ +#define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */ + /* Device specific rate values. * The actual values defined here are (rate_in_mbps * 2). * Some code depends on this. Don't change it. */ @@ -765,6 +771,9 @@ struct b43_firmware { u16 rev; /* Firmware patchlevel */ u16 patch; + + /* Set to true, if we are using an opensource firmware. */ + bool opensource; }; /* Device (802.11 core) initialization status. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ff5dce67faa..656a1f04ad6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1664,7 +1664,64 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) static void handle_irq_ucode_debug(struct b43_wldev *dev) { - //TODO + unsigned int i, cnt; + u16 reason; + __le16 *buf; + + /* The proprietary firmware doesn't have this IRQ. */ + if (!dev->fw.opensource) + return; + + /* Microcode register 63 contains the debug-IRQ reason. */ + reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 63); + switch (reason) { + case B43_DEBUGIRQ_PANIC: + /* The reason for the panic is in register 3. */ + reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 3); + b43err(dev->wl, "Whoopsy, the microcode panic'ed! Reason: %u\n", + reason); + b43_controller_restart(dev, "Microcode panic"); + break; + case B43_DEBUGIRQ_DUMP_SHM: + if (!B43_DEBUG) + break; /* Only with driver debugging enabled. */ + buf = kmalloc(4096, GFP_ATOMIC); + if (!buf) { + b43dbg(dev->wl, "SHM-dump: Failed to allocate memory\n"); + goto out; + } + for (i = 0; i < 4096; i += 2) { + u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, i); + buf[i / 2] = cpu_to_le16(tmp); + } + b43info(dev->wl, "Shared memory dump:\n"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, + 16, 2, buf, 4096, 1); + kfree(buf); + break; + case B43_DEBUGIRQ_DUMP_REGS: + if (!B43_DEBUG) + break; /* Only with driver debugging enabled. */ + b43info(dev->wl, "Microcode register dump:\n"); + for (i = 0, cnt = 0; i < 64; i++) { + u16 tmp = b43_shm_read16(dev, B43_SHM_SCRATCH, i); + if (cnt == 0) + printk(KERN_INFO); + printk("r%02u: 0x%04X ", i, tmp); + cnt++; + if (cnt == 6) { + printk("\n"); + cnt = 0; + } + } + printk("\n"); + break; + default: + b43dbg(dev->wl, "Debug-IRQ triggered for unknown reason: %u\n", + reason); + } +out: + b43_shm_write16(dev, B43_SHM_SCRATCH, 63, B43_DEBUGIRQ_ACK); } /* Interrupt handler bottom-half */ @@ -2122,14 +2179,22 @@ static int b43_upload_microcode(struct b43_wldev *dev) err = -EOPNOTSUPP; goto error; } - b43info(dev->wl, "Loading firmware version %u.%u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", - fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); - dev->fw.rev = fwrev; dev->fw.patch = fwpatch; + dev->fw.opensource = (fwdate == 0xFFFF); + + if (dev->fw.opensource) { + /* Patchlevel info is encoded in the "time" field. */ + dev->fw.patch = fwtime; + b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n", + dev->fw.rev, dev->fw.patch); + } else { + b43info(dev->wl, "Loading firmware version %u.%u " + "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", + fwrev, fwpatch, + (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, + (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + } if (b43_is_old_txhdr_format(dev)) { b43warn(dev->wl, "You are using an old firmware image. " -- cgit v1.2.3 From 6821783271aaf541504ff8a138184fcc83fa282b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 17 May 2008 23:43:57 +0200 Subject: b43: Allow running without PCM firmware This patch adds code to allow running the device without PCM firmware loaded. Without PCM firmware we don't have hardware accelerated crypto on devices with a core rev <= 10. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 4 ++++ drivers/net/wireless/b43/main.c | 47 +++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 00468594b45..f588dfa9c1d 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -774,6 +774,10 @@ struct b43_firmware { /* Set to true, if we are using an opensource firmware. */ bool opensource; + /* Set to true, if the core needs a PCM firmware, but + * we failed to load one. This is always false for + * core rev > 10, as these don't need PCM firmware. */ + bool pcm_request_failed; }; /* Device (802.11 core) initialization status. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 656a1f04ad6..6011747bb3b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1908,7 +1908,8 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) static int do_request_fw(struct b43_wldev *dev, const char *name, - struct b43_firmware_file *fw) + struct b43_firmware_file *fw, + bool silent) { char path[sizeof(modparam_fwpostfix) + 32]; const struct firmware *blob; @@ -1932,9 +1933,15 @@ static int do_request_fw(struct b43_wldev *dev, "b43%s/%s.fw", modparam_fwpostfix, name); err = request_firmware(&blob, path, dev->dev->dev); - if (err) { - b43err(dev->wl, "Firmware file \"%s\" not found " - "or load failed.\n", path); + if (err == -ENOENT) { + if (!silent) { + b43err(dev->wl, "Firmware file \"%s\" not found\n", + path); + } + return err; + } else if (err) { + b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n", + path, err); return err; } if (blob->size < sizeof(struct b43_fw_header)) @@ -1985,7 +1992,7 @@ static int b43_request_firmware(struct b43_wldev *dev) filename = "ucode13"; else goto err_no_ucode; - err = do_request_fw(dev, filename, &fw->ucode); + err = do_request_fw(dev, filename, &fw->ucode, 0); if (err) goto err_load; @@ -1996,8 +2003,13 @@ static int b43_request_firmware(struct b43_wldev *dev) filename = NULL; else goto err_no_pcm; - err = do_request_fw(dev, filename, &fw->pcm); - if (err) + fw->pcm_request_failed = 0; + err = do_request_fw(dev, filename, &fw->pcm, 1); + if (err == -ENOENT) { + /* We did not find a PCM file? Not fatal, but + * core rev <= 10 must do without hwcrypto then. */ + fw->pcm_request_failed = 1; + } else if (err) goto err_load; /* Get initvals */ @@ -2028,7 +2040,7 @@ static int b43_request_firmware(struct b43_wldev *dev) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals); + err = do_request_fw(dev, filename, &fw->initvals, 0); if (err) goto err_load; @@ -2062,7 +2074,7 @@ static int b43_request_firmware(struct b43_wldev *dev) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals_band); + err = do_request_fw(dev, filename, &fw->initvals_band, 0); if (err) goto err_load; @@ -2186,14 +2198,20 @@ static int b43_upload_microcode(struct b43_wldev *dev) if (dev->fw.opensource) { /* Patchlevel info is encoded in the "time" field. */ dev->fw.patch = fwtime; - b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n", - dev->fw.rev, dev->fw.patch); + b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n", + dev->fw.rev, dev->fw.patch, + dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : ""); } else { b43info(dev->wl, "Loading firmware version %u.%u " "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + if (dev->fw.pcm_request_failed) { + b43warn(dev->wl, "No \"pcm5.fw\" firmware file found. " + "Hardware accelerated cryptography is disabled.\n"); + b43_print_fw_helptext(dev->wl, 0); + } } if (b43_is_old_txhdr_format(dev)) { @@ -3358,6 +3376,13 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) goto out_unlock; + if (dev->fw.pcm_request_failed) { + /* We don't have firmware for the crypto engine. + * Must use software-crypto. */ + err = -EOPNOTSUPP; + goto out_unlock; + } + err = -EINVAL; switch (key->alg) { case ALG_WEP: -- cgit v1.2.3 From afa83e239af58a93eddd10a7a43ac5618884db15 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 19 May 2008 23:51:37 +0200 Subject: b43: Add panic reason code that doesn't trigger restart Add a firmware panic reason code that doesn't trigger a restart. This is useful for firmware debugging and avoiding endless restart loops. We can use FWPANIC_DIE to halt the firmware at a well defined point. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 9 +++++++++ drivers/net/wireless/b43/main.c | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f588dfa9c1d..f0041750355 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -422,12 +422,21 @@ enum { B43_IRQ_RFKILL | \ B43_IRQ_TX_OK) +/* The firmware register to fetch the debug-IRQ reason from. */ +#define B43_DEBUGIRQ_REASON_REG 63 /* Debug-IRQ reasons. */ #define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */ #define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */ #define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */ #define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */ +/* The firmware register to fetch the panic reason from. */ +#define B43_FWPANIC_REASON_REG 3 +/* Firmware panic reason codes */ +#define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ +#define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ + + /* Device specific rate values. * The actual values defined here are (rate_in_mbps * 2). * Some code depends on this. Don't change it. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6011747bb3b..e1dfb407467 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1662,6 +1662,30 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } +static void b43_handle_firmware_panic(struct b43_wldev *dev) +{ + u16 reason; + + /* Read the register that contains the reason code for the panic. */ + reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_FWPANIC_REASON_REG); + b43err(dev->wl, "Whoopsy, firmware panic! Reason: %u\n", reason); + + switch (reason) { + default: + b43dbg(dev->wl, "The panic reason is unknown.\n"); + /* fallthrough */ + case B43_FWPANIC_DIE: + /* Do not restart the controller or firmware. + * The device is nonfunctional from now on. + * Restarting would result in this panic to trigger again, + * so we avoid that recursion. */ + break; + case B43_FWPANIC_RESTART: + b43_controller_restart(dev, "Microcode panic"); + break; + } +} + static void handle_irq_ucode_debug(struct b43_wldev *dev) { unsigned int i, cnt; @@ -1672,15 +1696,12 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev) if (!dev->fw.opensource) return; - /* Microcode register 63 contains the debug-IRQ reason. */ - reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 63); + /* Read the register that contains the reason code for this IRQ. */ + reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG); + switch (reason) { case B43_DEBUGIRQ_PANIC: - /* The reason for the panic is in register 3. */ - reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 3); - b43err(dev->wl, "Whoopsy, the microcode panic'ed! Reason: %u\n", - reason); - b43_controller_restart(dev, "Microcode panic"); + b43_handle_firmware_panic(dev); break; case B43_DEBUGIRQ_DUMP_SHM: if (!B43_DEBUG) @@ -1721,7 +1742,9 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev) reason); } out: - b43_shm_write16(dev, B43_SHM_SCRATCH, 63, B43_DEBUGIRQ_ACK); + /* Acknowledge the debug-IRQ, so the firmware can continue. */ + b43_shm_write16(dev, B43_SHM_SCRATCH, + B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK); } /* Interrupt handler bottom-half */ -- cgit v1.2.3 From 53c068566dde708cb28a4dfc06ae3d7fd7434397 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 20 May 2008 00:24:36 +0200 Subject: b43: Add firmware markers support This adds support for firmware markers. With firmware markers it's easily possible to check whether the firmware runs some codepath or not. The driver will throw a message when the firmware executes a MARKER(x). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 5 +++++ drivers/net/wireless/b43/main.c | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f0041750355..e919189919b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -428,8 +428,13 @@ enum { #define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */ #define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */ #define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */ +#define B43_DEBUGIRQ_MARKER 3 /* A "marker" was thrown by the firmware. */ #define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */ +/* The firmware register that contains the "marker" line. */ +#define B43_MARKER_ID_REG 2 +#define B43_MARKER_LINE_REG 3 + /* The firmware register to fetch the panic reason from. */ #define B43_FWPANIC_REASON_REG 3 /* Firmware panic reason codes */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e1dfb407467..cbb317bb348 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1689,7 +1689,7 @@ static void b43_handle_firmware_panic(struct b43_wldev *dev) static void handle_irq_ucode_debug(struct b43_wldev *dev) { unsigned int i, cnt; - u16 reason; + u16 reason, marker_id, marker_line; __le16 *buf; /* The proprietary firmware doesn't have this IRQ. */ @@ -1737,6 +1737,17 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev) } printk("\n"); break; + case B43_DEBUGIRQ_MARKER: + if (!B43_DEBUG) + break; /* Only with driver debugging enabled. */ + marker_id = b43_shm_read16(dev, B43_SHM_SCRATCH, + B43_MARKER_ID_REG); + marker_line = b43_shm_read16(dev, B43_SHM_SCRATCH, + B43_MARKER_LINE_REG); + b43info(dev->wl, "The firmware just executed the MARKER(%u) " + "at line number %u\n", + marker_id, marker_line); + break; default: b43dbg(dev->wl, "Debug-IRQ triggered for unknown reason: %u\n", reason); -- cgit v1.2.3 From 04dea136b06ddd58879c9272b9f66ff060962317 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 20 May 2008 12:10:49 +0200 Subject: b43: enable mesh This patch enables b43 to do mesh networking, tested against my zd1211rw dongle. Signed-off-by: Johannes Berg Reviewed-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cbb317bb348..f9c14c66434 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1430,11 +1430,17 @@ static void b43_write_beacon_template(struct b43_wldev *dev, i += ie_len + 2; } if (!tim_found) { - b43warn(dev->wl, "Did not find a valid TIM IE in " - "the beacon template packet. AP or IBSS operation " - "may be broken.\n"); - } else - b43dbg(dev->wl, "Updated beacon template\n"); + /* + * If ucode wants to modify TIM do it behind the beacon, this + * will happen, for example, when doing mesh networking. + */ + b43_shm_write16(dev, B43_SHM_SHARED, + B43_SHM_SH_TIMBPOS, + len + sizeof(struct b43_plcp_hdr6)); + b43_shm_write16(dev, B43_SHM_SHARED, + B43_SHM_SH_DTIMPER, 0); + } + b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); } static void b43_write_probe_resp_plcp(struct b43_wldev *dev, @@ -1549,7 +1555,8 @@ static void handle_irq_beacon(struct b43_wldev *dev) struct b43_wl *wl = dev->wl; u32 cmd, beacon0_valid, beacon1_valid; - if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) + if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) && + !b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) return; /* This is the bottom half of the asynchronous beacon update. */ @@ -2491,7 +2498,8 @@ static void b43_adjust_opmode(struct b43_wldev *dev) ctl &= ~B43_MACCTL_BEACPROMISC; ctl |= B43_MACCTL_INFRA; - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) + if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || + b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) ctl |= B43_MACCTL_AP; else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) ctl &= ~B43_MACCTL_INFRA; @@ -3358,8 +3366,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); b43_set_rx_antenna(dev, antenna); - /* Update templates for AP mode. */ - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) + /* Update templates for AP/mesh mode. */ + if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || + b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) b43_set_beacon_int(dev, conf->beacon_int); if (!!conf->radio_enabled != phy->radio_on) { @@ -3547,8 +3556,9 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, else memset(wl->bssid, 0, ETH_ALEN); if (b43_status(dev) >= B43_STAT_INITIALIZED) { - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { - B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); + if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || + b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { + B43_WARN_ON(conf->type != wl->if_type); b43_set_ssid(dev, conf->ssid, conf->ssid_len); if (conf->beacon) b43_update_templates(wl, conf->beacon); @@ -4088,6 +4098,7 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ if (conf->type != IEEE80211_IF_TYPE_AP && + conf->type != IEEE80211_IF_TYPE_MESH_POINT && conf->type != IEEE80211_IF_TYPE_STA && conf->type != IEEE80211_IF_TYPE_WDS && conf->type != IEEE80211_IF_TYPE_IBSS) -- cgit v1.2.3 From f37d923422b61884a75a2a64865ed03ca5ccfc6d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sat, 14 Jun 2008 23:33:39 -0700 Subject: b43: use frame control helpers Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index f9e1cff2aec..bf6f6c1ed4c 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -193,7 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, const struct ieee80211_hdr *wlhdr = (const struct ieee80211_hdr *)fragment_data; int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)); - u16 fctl = le16_to_cpu(wlhdr->frame_control); + __le16 fctl = wlhdr->frame_control; struct ieee80211_rate *fbrate; u8 rate, rate_fb; int rate_ofdm, rate_fb_ofdm; @@ -259,7 +259,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, B43_TXH_MAC_KEYIDX; mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & B43_TXH_MAC_KEYALG; - wlhdr_len = ieee80211_get_hdrlen(fctl); + wlhdr_len = ieee80211_hdrlen(fctl); iv_len = min((size_t) info->control.iv_len, ARRAY_SIZE(txhdr->iv)); memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); @@ -317,8 +317,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; - if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && - ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) + if (!ieee80211_is_pspoll(fctl)) mac_ctl |= B43_TXH_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43_TXH_MAC_STMSDU; @@ -509,7 +508,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) struct b43_plcp_hdr6 *plcp; struct ieee80211_hdr *wlhdr; const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; - u16 fctl; + __le16 fctl; u16 phystat0, phystat3, chanstat, mactime; u32 macstat; u16 chanid; @@ -549,7 +548,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) goto drop; } wlhdr = (struct ieee80211_hdr *)(skb->data); - fctl = le16_to_cpu(wlhdr->frame_control); + fctl = wlhdr->frame_control; if (macstat & B43_RX_MAC_DEC) { unsigned int keyidx; @@ -564,7 +563,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) B43_WARN_ON(keyidx >= dev->max_nr_keys); if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { - wlhdr_len = ieee80211_get_hdrlen(fctl); + wlhdr_len = ieee80211_hdrlen(fctl); if (unlikely(skb->len < (wlhdr_len + 3))) { b43dbg(dev->wl, "RX: Packet size underrun (3)\n"); @@ -604,9 +603,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) * of timestamp, i.e. about 65 milliseconds after the PHY received * the first symbol. */ - if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) - == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || - dev->wl->radiotap_enabled) { + if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { u16 low_mactime_now; b43_tsf_read(dev, &status.mactime); -- cgit v1.2.3 From 8bd463f4f913db12a1b7374f84304631289a1e0b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 19 Jun 2008 00:35:49 +0200 Subject: b43: Add debugfs files for MMIO register access This adds debugfs files for reading and writing arbitrary wireless core registers. This is useful for debugging. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 124 +++++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/debugfs.h | 9 +++ 2 files changed, 133 insertions(+) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 210e2789c1c..9cdd9eca082 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -74,6 +74,115 @@ struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev, } while (0) +/* The biggest MMIO address that we allow access to from the debugfs files. */ +#define B43_MAX_MMIO_ACCESS (0xF00 - 1) + +static ssize_t mmio16read__read_file(struct b43_wldev *dev, + char *buf, size_t bufsize) +{ + ssize_t count = 0; + unsigned int addr; + u16 val; + + addr = dev->dfsentry->mmio16read_next; + if (addr > B43_MAX_MMIO_ACCESS) + return -EDESTADDRREQ; + + val = b43_read16(dev, addr); + fappend("0x%04X\n", val); + + return count; +} + +static int mmio16read__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int addr; + int res; + + res = sscanf(buf, "0x%X", &addr); + if (res != 1) + return -EINVAL; + if (addr > B43_MAX_MMIO_ACCESS) + return -EADDRNOTAVAIL; + + dev->dfsentry->mmio16read_next = addr; + + return 0; +} + +static int mmio16write__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int addr, val; + int res; + + res = sscanf(buf, "0x%X = 0x%X", &addr, &val); + if (res != 2) + return -EINVAL; + if (addr > B43_MAX_MMIO_ACCESS) + return -EADDRNOTAVAIL; + if (val > 0xFFFF) + return -E2BIG; + + b43_write16(dev, addr, val); + + return 0; +} + +static ssize_t mmio32read__read_file(struct b43_wldev *dev, + char *buf, size_t bufsize) +{ + ssize_t count = 0; + unsigned int addr; + u32 val; + + addr = dev->dfsentry->mmio32read_next; + if (addr > B43_MAX_MMIO_ACCESS) + return -EDESTADDRREQ; + + val = b43_read32(dev, addr); + fappend("0x%08X\n", val); + + return count; +} + +static int mmio32read__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int addr; + int res; + + res = sscanf(buf, "0x%X", &addr); + if (res != 1) + return -EINVAL; + if (addr > B43_MAX_MMIO_ACCESS) + return -EADDRNOTAVAIL; + + dev->dfsentry->mmio32read_next = addr; + + return 0; +} + +static int mmio32write__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int addr, val; + int res; + + res = sscanf(buf, "0x%X = 0x%X", &addr, &val); + if (res != 2) + return -EINVAL; + if (addr > B43_MAX_MMIO_ACCESS) + return -EADDRNOTAVAIL; + if (val > 0xFFFFFFFF) + return -E2BIG; + + b43_write32(dev, addr, val); + + return 0; +} + /* wl->irq_lock is locked */ static ssize_t tsf_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) @@ -496,6 +605,10 @@ out_unlock: .take_irqlock = _take_irqlock, \ } +B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); +B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); +B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); +B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1); B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1); @@ -584,6 +697,9 @@ void b43_debugfs_add_device(struct b43_wldev *dev) return; } + e->mmio16read_next = 0xFFFF; /* invalid address */ + e->mmio32read_next = 0xFFFF; /* invalid address */ + #define ADD_FILE(name, mode) \ do { \ struct dentry *d; \ @@ -596,6 +712,10 @@ void b43_debugfs_add_device(struct b43_wldev *dev) } while (0) + ADD_FILE(mmio16read, 0600); + ADD_FILE(mmio16write, 0200); + ADD_FILE(mmio32read, 0600); + ADD_FILE(mmio32write, 0200); ADD_FILE(tsf, 0600); ADD_FILE(ucode_regs, 0400); ADD_FILE(shm, 0400); @@ -620,6 +740,10 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) return; b43_remove_dynamic_debug(dev); + debugfs_remove(e->file_mmio16read.dentry); + debugfs_remove(e->file_mmio16write.dentry); + debugfs_remove(e->file_mmio32read.dentry); + debugfs_remove(e->file_mmio32write.dentry); debugfs_remove(e->file_tsf.dentry); debugfs_remove(e->file_ucode_regs.dentry); debugfs_remove(e->file_shm.dentry); diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index c75cff4151d..d6848696cee 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -36,6 +36,10 @@ struct b43_dfsentry { struct b43_wldev *dev; struct dentry *subdir; + struct b43_dfs_file file_mmio16read; + struct b43_dfs_file file_mmio16write; + struct b43_dfs_file file_mmio32read; + struct b43_dfs_file file_mmio32write; struct b43_dfs_file file_tsf; struct b43_dfs_file file_ucode_regs; struct b43_dfs_file file_shm; @@ -46,6 +50,11 @@ struct b43_dfsentry { struct b43_txstatus_log txstatlog; + /* The cached address for the next mmio16read file read */ + u16 mmio16read_next; + /* The cached address for the next mmio32read file read */ + u16 mmio32read_next; + /* Enabled/Disabled list for the dynamic debugging features. */ u32 dyn_debug[__B43_NR_DYNDBG]; /* Dentries for the dynamic debugging entries. */ -- cgit v1.2.3 From 6bbc321a96d4d3533eb136b981baba6c8248d635 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 19 Jun 2008 19:33:51 +0200 Subject: b43: Add debugfs files for random SHM access This adds debugfs files for random SHM access. This is needed in order to implement firmware and driver debugging scripts in userspace. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 178 +++++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/debugfs.h | 11 +++ drivers/net/wireless/b43/main.c | 58 ++++++++---- drivers/net/wireless/b43/main.h | 4 + 4 files changed, 234 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 9cdd9eca082..dd40ad826c7 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -74,6 +74,168 @@ struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev, } while (0) +/* The biggest address values for SHM access from the debugfs files. */ +#define B43_MAX_SHM_ROUTING 4 +#define B43_MAX_SHM_ADDR 0xFFFF + +static ssize_t shm16read__read_file(struct b43_wldev *dev, + char *buf, size_t bufsize) +{ + ssize_t count = 0; + unsigned int routing, addr; + u16 val; + + routing = dev->dfsentry->shm16read_routing_next; + addr = dev->dfsentry->shm16read_addr_next; + if ((routing > B43_MAX_SHM_ROUTING) || + (addr > B43_MAX_SHM_ADDR)) + return -EDESTADDRREQ; + + val = b43_shm_read16(dev, routing, addr); + fappend("0x%04X\n", val); + + return count; +} + +static int shm16read__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int routing, addr; + int res; + + res = sscanf(buf, "0x%X 0x%X", &routing, &addr); + if (res != 2) + return -EINVAL; + if (routing > B43_MAX_SHM_ROUTING) + return -EADDRNOTAVAIL; + if (addr > B43_MAX_SHM_ADDR) + return -EADDRNOTAVAIL; + if (routing == B43_SHM_SHARED) { + if ((addr % 2) != 0) + return -EADDRNOTAVAIL; + } + + dev->dfsentry->shm16read_routing_next = routing; + dev->dfsentry->shm16read_addr_next = addr; + + return 0; +} + +static int shm16write__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int routing, addr, mask, set; + u16 val; + int res; + unsigned long flags; + + res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", + &routing, &addr, &mask, &set); + if (res != 4) + return -EINVAL; + if (routing > B43_MAX_SHM_ROUTING) + return -EADDRNOTAVAIL; + if (addr > B43_MAX_SHM_ADDR) + return -EADDRNOTAVAIL; + if (routing == B43_SHM_SHARED) { + if ((addr % 2) != 0) + return -EADDRNOTAVAIL; + } + if ((mask > 0xFFFF) || (set > 0xFFFF)) + return -E2BIG; + + spin_lock_irqsave(&dev->wl->shm_lock, flags); + if (mask == 0) + val = 0; + else + val = __b43_shm_read16(dev, routing, addr); + val &= mask; + val |= set; + __b43_shm_write16(dev, routing, addr, val); + spin_unlock_irqrestore(&dev->wl->shm_lock, flags); + + return 0; +} + +static ssize_t shm32read__read_file(struct b43_wldev *dev, + char *buf, size_t bufsize) +{ + ssize_t count = 0; + unsigned int routing, addr; + u32 val; + + routing = dev->dfsentry->shm32read_routing_next; + addr = dev->dfsentry->shm32read_addr_next; + if ((routing > B43_MAX_SHM_ROUTING) || + (addr > B43_MAX_SHM_ADDR)) + return -EDESTADDRREQ; + + val = b43_shm_read32(dev, routing, addr); + fappend("0x%08X\n", val); + + return count; +} + +static int shm32read__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int routing, addr; + int res; + + res = sscanf(buf, "0x%X 0x%X", &routing, &addr); + if (res != 2) + return -EINVAL; + if (routing > B43_MAX_SHM_ROUTING) + return -EADDRNOTAVAIL; + if (addr > B43_MAX_SHM_ADDR) + return -EADDRNOTAVAIL; + if (routing == B43_SHM_SHARED) { + if ((addr % 2) != 0) + return -EADDRNOTAVAIL; + } + + dev->dfsentry->shm32read_routing_next = routing; + dev->dfsentry->shm32read_addr_next = addr; + + return 0; +} + +static int shm32write__write_file(struct b43_wldev *dev, + const char *buf, size_t count) +{ + unsigned int routing, addr, mask, set; + u32 val; + int res; + unsigned long flags; + + res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", + &routing, &addr, &mask, &set); + if (res != 4) + return -EINVAL; + if (routing > B43_MAX_SHM_ROUTING) + return -EADDRNOTAVAIL; + if (addr > B43_MAX_SHM_ADDR) + return -EADDRNOTAVAIL; + if (routing == B43_SHM_SHARED) { + if ((addr % 2) != 0) + return -EADDRNOTAVAIL; + } + if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) + return -E2BIG; + + spin_lock_irqsave(&dev->wl->shm_lock, flags); + if (mask == 0) + val = 0; + else + val = __b43_shm_read32(dev, routing, addr); + val &= mask; + val |= set; + __b43_shm_write32(dev, routing, addr, val); + spin_unlock_irqrestore(&dev->wl->shm_lock, flags); + + return 0; +} + /* The biggest MMIO address that we allow access to from the debugfs files. */ #define B43_MAX_MMIO_ACCESS (0xF00 - 1) @@ -605,6 +767,10 @@ out_unlock: .take_irqlock = _take_irqlock, \ } +B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); +B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); +B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); +B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); @@ -699,6 +865,10 @@ void b43_debugfs_add_device(struct b43_wldev *dev) e->mmio16read_next = 0xFFFF; /* invalid address */ e->mmio32read_next = 0xFFFF; /* invalid address */ + e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */ + e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */ + e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */ + e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */ #define ADD_FILE(name, mode) \ do { \ @@ -712,6 +882,10 @@ void b43_debugfs_add_device(struct b43_wldev *dev) } while (0) + ADD_FILE(shm16read, 0600); + ADD_FILE(shm16write, 0200); + ADD_FILE(shm32read, 0600); + ADD_FILE(shm32write, 0200); ADD_FILE(mmio16read, 0600); ADD_FILE(mmio16write, 0200); ADD_FILE(mmio32read, 0600); @@ -740,6 +914,10 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) return; b43_remove_dynamic_debug(dev); + debugfs_remove(e->file_shm16read.dentry); + debugfs_remove(e->file_shm16write.dentry); + debugfs_remove(e->file_shm32read.dentry); + debugfs_remove(e->file_shm32write.dentry); debugfs_remove(e->file_mmio16read.dentry); debugfs_remove(e->file_mmio16write.dentry); debugfs_remove(e->file_mmio32read.dentry); diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index d6848696cee..f06f7bc1edc 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -36,6 +36,10 @@ struct b43_dfsentry { struct b43_wldev *dev; struct dentry *subdir; + struct b43_dfs_file file_shm16read; + struct b43_dfs_file file_shm16write; + struct b43_dfs_file file_shm32read; + struct b43_dfs_file file_shm32write; struct b43_dfs_file file_mmio16read; struct b43_dfs_file file_mmio16write; struct b43_dfs_file file_mmio32read; @@ -55,6 +59,13 @@ struct b43_dfsentry { /* The cached address for the next mmio32read file read */ u16 mmio32read_next; + /* The cached address for the next shm16read file read */ + u32 shm16read_routing_next; + u32 shm16read_addr_next; + /* The cached address for the next shm32read file read */ + u32 shm32read_routing_next; + u32 shm32read_addr_next; + /* Enabled/Disabled list for the dynamic debugging features. */ u32 dyn_debug[__B43_NR_DYNDBG]; /* Dentries for the dynamic debugging entries. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7bca8e98151..69272b9bdb6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -373,13 +373,10 @@ static inline void b43_shm_control_word(struct b43_wldev *dev, b43_write32(dev, B43_MMIO_SHM_CONTROL, control); } -u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) +u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) { - struct b43_wl *wl = dev->wl; - unsigned long flags; u32 ret; - spin_lock_irqsave(&wl->shm_lock, flags); if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -397,18 +394,26 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) b43_shm_control_word(dev, routing, offset); ret = b43_read32(dev, B43_MMIO_SHM_DATA); out: - spin_unlock_irqrestore(&wl->shm_lock, flags); - return ret; } -u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) +u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) { struct b43_wl *wl = dev->wl; unsigned long flags; - u16 ret; + u32 ret; spin_lock_irqsave(&wl->shm_lock, flags); + ret = __b43_shm_read32(dev, routing, offset); + spin_unlock_irqrestore(&wl->shm_lock, flags); + + return ret; +} + +u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) +{ + u16 ret; + if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -423,17 +428,24 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) b43_shm_control_word(dev, routing, offset); ret = b43_read16(dev, B43_MMIO_SHM_DATA); out: - spin_unlock_irqrestore(&wl->shm_lock, flags); - return ret; } -void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) +u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) { struct b43_wl *wl = dev->wl; unsigned long flags; + u16 ret; spin_lock_irqsave(&wl->shm_lock, flags); + ret = __b43_shm_read16(dev, routing, offset); + spin_unlock_irqrestore(&wl->shm_lock, flags); + + return ret; +} + +void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) +{ if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -443,35 +455,47 @@ void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) (value >> 16) & 0xffff); b43_shm_control_word(dev, routing, (offset >> 2) + 1); b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); - goto out; + return; } offset >>= 2; } b43_shm_control_word(dev, routing, offset); b43_write32(dev, B43_MMIO_SHM_DATA, value); -out: - spin_unlock_irqrestore(&wl->shm_lock, flags); } -void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) +void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) { struct b43_wl *wl = dev->wl; unsigned long flags; spin_lock_irqsave(&wl->shm_lock, flags); + __b43_shm_write32(dev, routing, offset, value); + spin_unlock_irqrestore(&wl->shm_lock, flags); +} + +void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) +{ if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { /* Unaligned access */ b43_shm_control_word(dev, routing, offset >> 2); b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); - goto out; + return; } offset >>= 2; } b43_shm_control_word(dev, routing, offset); b43_write16(dev, B43_MMIO_SHM_DATA, value); -out: +} + +void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) +{ + struct b43_wl *wl = dev->wl; + unsigned long flags; + + spin_lock_irqsave(&wl->shm_lock, flags); + __b43_shm_write16(dev, routing, offset, value); spin_unlock_irqrestore(&wl->shm_lock, flags); } diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index dad23c42b42..f871a252cb5 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -95,9 +95,13 @@ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf); void b43_tsf_write(struct b43_wldev *dev, u64 tsf); u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); +u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); +u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); +void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); +void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); u64 b43_hf_read(struct b43_wldev *dev); void b43_hf_write(struct b43_wldev *dev, u64 value); -- cgit v1.2.3 From efa275822b50ab942c79ba26f053f9a0cd220e9e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 19 Jun 2008 19:38:32 +0200 Subject: b43: Add mask/set capability to debugfs MMIO interface This adds an atomic mask/set capability to the debugfs MMIO interface. This is needed to support mask and/or set operations from the userspace debugging tools. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index dd40ad826c7..cfe8e202e4c 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -267,6 +267,8 @@ static int mmio16read__write_file(struct b43_wldev *dev, return -EINVAL; if (addr > B43_MAX_MMIO_ACCESS) return -EADDRNOTAVAIL; + if ((addr % 2) != 0) + return -EINVAL; dev->dfsentry->mmio16read_next = addr; @@ -276,17 +278,26 @@ static int mmio16read__write_file(struct b43_wldev *dev, static int mmio16write__write_file(struct b43_wldev *dev, const char *buf, size_t count) { - unsigned int addr, val; + unsigned int addr, mask, set; int res; + u16 val; - res = sscanf(buf, "0x%X = 0x%X", &addr, &val); - if (res != 2) + res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); + if (res != 3) return -EINVAL; if (addr > B43_MAX_MMIO_ACCESS) return -EADDRNOTAVAIL; - if (val > 0xFFFF) + if ((mask > 0xFFFF) || (set > 0xFFFF)) return -E2BIG; + if ((addr % 2) != 0) + return -EINVAL; + if (mask == 0) + val = 0; + else + val = b43_read16(dev, addr); + val &= mask; + val |= set; b43_write16(dev, addr, val); return 0; @@ -320,6 +331,8 @@ static int mmio32read__write_file(struct b43_wldev *dev, return -EINVAL; if (addr > B43_MAX_MMIO_ACCESS) return -EADDRNOTAVAIL; + if ((addr % 4) != 0) + return -EINVAL; dev->dfsentry->mmio32read_next = addr; @@ -329,17 +342,26 @@ static int mmio32read__write_file(struct b43_wldev *dev, static int mmio32write__write_file(struct b43_wldev *dev, const char *buf, size_t count) { - unsigned int addr, val; + unsigned int addr, mask, set; int res; + u32 val; - res = sscanf(buf, "0x%X = 0x%X", &addr, &val); - if (res != 2) + res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); + if (res != 3) return -EINVAL; if (addr > B43_MAX_MMIO_ACCESS) return -EADDRNOTAVAIL; - if (val > 0xFFFFFFFF) + if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) return -E2BIG; + if ((addr % 4) != 0) + return -EINVAL; + if (mask == 0) + val = 0; + else + val = b43_read32(dev, addr); + val &= mask; + val |= set; b43_write32(dev, addr, val); return 0; -- cgit v1.2.3 From 9965183a78ad5303b9154184a0f4056844e8baae Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Jun 2008 01:01:50 +0200 Subject: b43: Remove "shm" and "ucode_regs" debugfs files We don't need these two dump-files anymore, as we can easily do this in userspace now. Use b43-fwdump from the b43-tools repository to dump microcode registers. Use "b43-fwdump -s" to dump SHM (or use -S to do a binary dump) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 42 -------------------------------------- drivers/net/wireless/b43/debugfs.h | 2 -- 2 files changed, 44 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index cfe8e202e4c..24854c3e89c 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -395,42 +395,6 @@ static int tsf_write_file(struct b43_wldev *dev, return 0; } -/* wl->irq_lock is locked */ -static ssize_t ucode_regs_read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - int i; - - for (i = 0; i < 64; i++) { - fappend("r%d = 0x%04x\n", i, - b43_shm_read16(dev, B43_SHM_SCRATCH, i)); - } - - return count; -} - -/* wl->irq_lock is locked */ -static ssize_t shm_read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - int i; - u16 tmp; - __le16 *le16buf = (__le16 *)buf; - - for (i = 0; i < 0x1000; i++) { - if (bufsize < sizeof(tmp)) - break; - tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i); - le16buf[i] = cpu_to_le16(tmp); - count += sizeof(tmp); - bufsize -= sizeof(tmp); - } - - return count; -} - static ssize_t txstat_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) { @@ -798,8 +762,6 @@ B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); -B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1); -B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1); B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); @@ -913,8 +875,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) ADD_FILE(mmio32read, 0600); ADD_FILE(mmio32write, 0200); ADD_FILE(tsf, 0600); - ADD_FILE(ucode_regs, 0400); - ADD_FILE(shm, 0400); ADD_FILE(txstat, 0400); ADD_FILE(txpower_g, 0600); ADD_FILE(restart, 0200); @@ -945,8 +905,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) debugfs_remove(e->file_mmio32read.dentry); debugfs_remove(e->file_mmio32write.dentry); debugfs_remove(e->file_tsf.dentry); - debugfs_remove(e->file_ucode_regs.dentry); - debugfs_remove(e->file_shm.dentry); debugfs_remove(e->file_txstat.dentry); debugfs_remove(e->file_txpower_g.dentry); debugfs_remove(e->file_restart.dentry); diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index f06f7bc1edc..132c81f2f98 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -45,8 +45,6 @@ struct b43_dfsentry { struct b43_dfs_file file_mmio32read; struct b43_dfs_file file_mmio32write; struct b43_dfs_file file_tsf; - struct b43_dfs_file file_ucode_regs; - struct b43_dfs_file file_shm; struct b43_dfs_file file_txstat; struct b43_dfs_file file_txpower_g; struct b43_dfs_file file_restart; -- cgit v1.2.3 From f225763a7d6c92c4932dbd528437997078496fcc Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Jun 2008 11:50:29 +0200 Subject: ssb, b43, b43legacy, b44: Rewrite SSB DMA API This is a rewrite of the DMA API for SSB devices. This is needed, because the old (non-existing) "API" made too many bad assumptions on the API of the host-bus (PCI). This introduces an almost complete SSB-DMA-API that maps to the lowlevel bus-API based on the bustype. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 65 +++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 30 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8a09a1db08d..098f886976f 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -328,11 +328,11 @@ static inline dma_addr_t dmaaddr; if (tx) { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, - buf, len, DMA_TO_DEVICE); + dmaaddr = ssb_dma_map_single(ring->dev->dev, + buf, len, DMA_TO_DEVICE); } else { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, - buf, len, DMA_FROM_DEVICE); + dmaaddr = ssb_dma_map_single(ring->dev->dev, + buf, len, DMA_FROM_DEVICE); } return dmaaddr; @@ -343,11 +343,11 @@ static inline dma_addr_t addr, size_t len, int tx) { if (tx) { - dma_unmap_single(ring->dev->dev->dma_dev, - addr, len, DMA_TO_DEVICE); + ssb_dma_unmap_single(ring->dev->dev, + addr, len, DMA_TO_DEVICE); } else { - dma_unmap_single(ring->dev->dev->dma_dev, - addr, len, DMA_FROM_DEVICE); + ssb_dma_unmap_single(ring->dev->dev, + addr, len, DMA_FROM_DEVICE); } } @@ -356,8 +356,8 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_cpu(ring->dev->dev->dma_dev, - addr, len, DMA_FROM_DEVICE); + ssb_dma_sync_single_for_cpu(ring->dev->dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -365,8 +365,8 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_device(ring->dev->dev->dma_dev, - addr, len, DMA_FROM_DEVICE); + ssb_dma_sync_single_for_device(ring->dev->dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -381,7 +381,6 @@ static inline static int alloc_ringmemory(struct b43_dmaring *ring) { - struct device *dma_dev = ring->dev->dev->dma_dev; gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K @@ -392,11 +391,14 @@ static int alloc_ringmemory(struct b43_dmaring *ring) * For unknown reasons - possibly a hardware error - the BCM4311 rev * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, * which accounts for the GFP_DMA flag below. + * + * The flags here must match the flags in free_ringmemory below! */ if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); + ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, + B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; @@ -408,10 +410,13 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - struct device *dma_dev = ring->dev->dev->dma_dev; + gfp_t flags = GFP_KERNEL; + + if (ring->type == B43_DMA_64BIT) + flags |= GFP_DMA; - dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase); + ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase, flags); } /* Reset the RX DMA channel */ @@ -518,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, size_t buffersize, bool dma_to_device) { - if (unlikely(dma_mapping_error(addr))) + if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) return 1; switch (ring->type) { @@ -844,10 +849,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = dma_map_single(dev->dev->dma_dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = ssb_dma_map_single(dev->dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -859,10 +864,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = dma_map_single(dev->dev->dma_dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = ssb_dma_map_single(dev->dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -873,9 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } } - dma_unmap_single(dev->dev->dma_dev, - dma_test, b43_txhdr_size(dev), - DMA_TO_DEVICE); + ssb_dma_unmap_single(dev->dev, + dma_test, b43_txhdr_size(dev), + DMA_TO_DEVICE); } err = alloc_ringmemory(ring); -- cgit v1.2.3 From 9b839a7453dc7a25dbd367486017648182df541f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Jun 2008 17:44:02 +0200 Subject: b43: Add simple firmware watchdog This adds a simple firmware watchdog for the opensource firmware. This will check every 15 seconds, if the firmware zeroed out the watchdog register. The firmware will do this in its eventloop. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 2 ++ drivers/net/wireless/b43/main.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 532365f5ece..edcdfa36645 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -441,6 +441,8 @@ enum { #define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ #define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ +/* The firmware register that contains the watchdog counter. */ +#define B43_WATCHDOG_REG 1 /* Device specific rate values. * The actual values defined here are (rate_in_mbps * 2). diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 69272b9bdb6..c14d522d69e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2807,6 +2807,21 @@ static void b43_periodic_every30sec(struct b43_wldev *dev) static void b43_periodic_every15sec(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; + u16 wdr; + + if (dev->fw.opensource) { + /* Check if the firmware is still alive. + * It will reset the watchdog counter to 0 in its idle loop. */ + wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG); + if (unlikely(wdr)) { + b43err(dev->wl, "Firmware watchdog: The firmware died!\n"); + b43_controller_restart(dev, "Firmware watchdog"); + return; + } else { + b43_shm_write16(dev, B43_SHM_SCRATCH, + B43_WATCHDOG_REG, 1); + } + } if (phy->type == B43_PHYTYPE_G) { //TODO: update_aci_moving_average -- cgit v1.2.3 From 923fd7036ff04381b265037469c79a2e7d0d6b67 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Jun 2008 18:02:08 +0200 Subject: b43: Add debugfs firmware debugging knob This adds a firmware debugging knob to debugfs. With this knob it's possible to enable advanced runtime firmware checks. For now it only implements one sanity check for the mac-suspend. In future there'll probably be more. If CONFIG_B43_DEBUG is disabled, these checks will collapse to nothing. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 1 + drivers/net/wireless/b43/debugfs.h | 1 + drivers/net/wireless/b43/main.c | 13 +++++++++++++ 3 files changed, 15 insertions(+) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 24854c3e89c..29851bc1101 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -801,6 +801,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); add_dyn_dbg("debug_lo", B43_DBG_LO, 0); + add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); #undef add_dyn_dbg } diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 132c81f2f98..22ffd02ba55 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -11,6 +11,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ B43_DBG_PWORK_FAST, B43_DBG_PWORK_STOP, B43_DBG_LO, + B43_DBG_FIRMWARE, __B43_NR_DYNDBG, }; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c14d522d69e..82cca19137f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2487,6 +2487,19 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) /* http://bcm-specs.sipsolutions.net/EnableMac */ void b43_mac_enable(struct b43_wldev *dev) { + if (b43_debug(dev, B43_DBG_FIRMWARE)) { + u16 fwstate; + + fwstate = b43_shm_read16(dev, B43_SHM_SHARED, + B43_SHM_SH_UCODESTAT); + if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) && + (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) { + b43err(dev->wl, "b43_mac_enable(): The firmware " + "should be suspended, but current state is %u\n", + fwstate); + } + } + dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { -- cgit v1.2.3 From 14a7dd6f6c1e0b361a37b6df52d4dc2ea36757d2 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 24 Jun 2008 12:22:05 +0200 Subject: b43: Fix PIO skb clobber This fixes a clobber of the skb that was introduced by the tx_control->cb conversion patches. This bug causes a crash when the skb destructor is invoked. That happens on skb_orphan or skb_kfree. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/pio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 8b1555d95f1..40159126759 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -586,7 +586,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, spin_lock(&q->lock); /* IRQs are already disabled. */ - info = (void *)pack->skb; + info = IEEE80211_SKB_CB(pack->skb); memset(&info->status, 0, sizeof(info->status)); b43_fill_txstatus_report(info, status); -- cgit v1.2.3 From ff28bd94e307c67abb1bccda5d3a9018bd798e08 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 27 Jun 2008 10:27:47 -0400 Subject: wireless: remove RFKILL_STATE_HARD_BLOCKED warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/b43/rfkill.o drivers/net/wireless/b43/rfkill.c: In function ‘b43_rfkill_soft_toggle’: drivers/net/wireless/b43/rfkill.c:90: warning: enumeration value ‘RFKILL_STATE_HARD_BLOCKED’ not handled in switch CC [M] drivers/net/wireless/b43legacy/rfkill.o drivers/net/wireless/b43legacy/rfkill.c: In function ‘b43legacy_rfkill_soft_toggle’: drivers/net/wireless/b43legacy/rfkill.c:92: warning: enumeration value ‘RFKILL_STATE_HARD_BLOCKED’ not handled in switch CC [M] drivers/net/wireless/iwlwifi/iwl-rfkill.o drivers/net/wireless/iwlwifi/iwl-rfkill.c: In function ‘iwl_rfkill_soft_rf_kill’: drivers/net/wireless/iwlwifi/iwl-rfkill.c:56: warning: enumeration value ‘RFKILL_STATE_HARD_BLOCKED’ not handled in switch Also handle RFKILL_STATE_{ON,OFF} -> RFKILL_STATE_{UNBLOCKED,SOFT_BLOCKED} conversion since I'm already here... Signed-off-by: John W. Linville --- drivers/net/wireless/b43/rfkill.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 11f53cb1139..4cca203992e 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -88,7 +88,7 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) goto out_unlock; err = 0; switch (state) { - case RFKILL_STATE_ON: + case RFKILL_STATE_UNBLOCKED: if (!dev->radio_hw_enable) { /* No luck. We can't toggle the hardware RF-kill * button from software. */ @@ -98,10 +98,13 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) if (!dev->phy.radio_on) b43_radio_turn_on(dev); break; - case RFKILL_STATE_OFF: + case RFKILL_STATE_SOFT_BLOCKED: if (dev->phy.radio_on) b43_radio_turn_off(dev, 0); break; + default: + b43warn(wl, "Received unexpected rfkill state %d.\n", state); + break; } out_unlock: mutex_unlock(&wl->mutex); -- cgit v1.2.3 From f97d1f489d8b44a2c6e8529af855e5e0a2ceaf1e Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Sat, 28 Jun 2008 14:20:40 +0200 Subject: b43/b43legacy: use RFKILL_STATE_UNBLOCKED instead of RFKILL_STATE_ON This patch removes the usage RFKILL_STATE_ON and uses RFKILL_STATE_UNBLOCKED instead. Signed-off-by: Adel Gadllah Signed-off-by: John W. Linville --- drivers/net/wireless/b43/rfkill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 4cca203992e..34ae125d538 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -135,7 +135,7 @@ void b43_rfkill_init(struct b43_wldev *dev) snprintf(rfk->name, sizeof(rfk->name), "b43-%s", wiphy_name(wl->hw->wiphy)); rfk->rfkill->name = rfk->name; - rfk->rfkill->state = RFKILL_STATE_ON; + rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; rfk->rfkill->data = dev; rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; rfk->rfkill->user_claim_unsupported = 1; -- cgit v1.2.3 From bc19d6e0b74ef03a3baf035412c95192b54dfc6f Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Sun, 29 Jun 2008 19:20:21 +0200 Subject: b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support This patch sets the rfkill state to RFKILL_STATE_HARD_BLOCKED when the radio is killed by the hardware switch. Signed-off-by: Adel Gadllah Signed-off-by: John W. Linville --- drivers/net/wireless/b43/rfkill.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 34ae125d538..fec5645944a 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -43,6 +43,23 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) return 0; } +/* Update the rfkill state */ +static void b43_rfkill_update_state(struct b43_wldev *dev) +{ + struct b43_rfkill *rfk = &(dev->wl->rfkill); + + if (!dev->radio_hw_enable) { + rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; + return; + } + + if (!dev->phy.radio_on) + rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; + else + rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; + +} + /* The poll callback for the hardware button. */ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) { @@ -60,6 +77,7 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; report_change = 1; + b43_rfkill_update_state(dev); b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); } -- cgit v1.2.3 From 9d139c810a2aa17365cc548d0cd2a189d8433c65 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2008 14:40:37 +0200 Subject: mac80211: revamp beacon configuration This patch changes mac80211's beacon configuration handling to never pass skbs to the driver directly but rather always require the driver to use ieee80211_beacon_get(). Additionally, it introduces "change flags" on the config_interface() call to enable drivers to figure out what is changing. Finally, it removes the beacon_update() driver callback in favour of having IBSS beacon delivered by ieee80211_beacon_get() as well. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 48 +++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9d2eb273b72..381dbd33dfc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ -static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) +static void b43_update_templates(struct b43_wl *wl) { + struct sk_buff *beacon; + /* This is the top half of the ansynchronous beacon update. * The bottom half is the beacon IRQ. * Beacon update must be asynchronous to avoid sending an * invalid beacon. This can happen for example, if the firmware * transmits a beacon while we are updating it. */ + /* We could modify the existing beacon and set the aid bit in + * the TIM field, but that would probably require resizing and + * moving of data within the beacon template. + * Simply request a new beacon and let mac80211 do the hard work. */ + beacon = ieee80211_beacon_get(wl->hw, wl->vif); + if (unlikely(!beacon)) + return; + if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; @@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, if (b43_status(dev) >= B43_STAT_INITIALIZED) { if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { - B43_WARN_ON(conf->type != wl->if_type); - b43_set_ssid(dev, conf->ssid, conf->ssid_len); - if (conf->beacon) - b43_update_templates(wl, conf->beacon); + B43_WARN_ON(vif->type != wl->if_type); + if (conf->changed & IEEE80211_IFCC_SSID) + b43_set_ssid(dev, conf->ssid, conf->ssid_len); + if (conf->changed & IEEE80211_IFCC_BEACON) + b43_update_templates(wl); + } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { + if (conf->changed & IEEE80211_IFCC_BEACON) + b43_update_templates(wl); } b43_write_mac_bssid_templates(dev); } @@ -4334,33 +4348,12 @@ out_unlock: } static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct sk_buff *beacon; - unsigned long flags; - - /* We could modify the existing beacon and set the aid bit in - * the TIM field, but that would probably require resizing and - * moving of data within the beacon template. - * Simply request a new beacon and let mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(hw, wl->vif); - if (unlikely(!beacon)) - return -ENOMEM; - spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return 0; -} - -static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *beacon) { struct b43_wl *wl = hw_to_b43_wl(hw); unsigned long flags; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); + b43_update_templates(wl); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; @@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw_ops = { .stop = b43_op_stop, .set_retry_limit = b43_op_set_retry_limit, .set_tim = b43_op_beacon_set_tim, - .beacon_update = b43_op_ibss_beacon_update, .sta_notify = b43_op_sta_notify, }; -- cgit v1.2.3 From f591fa5dbbbeaebd95c9c019b3a536a327fb79de Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2008 11:21:26 +0200 Subject: mac80211: fix TX sequence numbers This patch makes mac80211 assign proper sequence numbers to QoS-data frames. It also removes the old sequence number code because we noticed that only the driver or hardware can assign sequence numbers to non-QoS-data and especially management frames in a race-free manner because beacons aren't passed through mac80211's TX path. This patch also adds temporary code to the rt2x00 drivers to not break them completely, that code will have to be reworked for proper sequence numbers on beacons. It also moves sequence number assignment down in the TX path so no sequence numbers are assigned to frames that are dropped. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index bf6f6c1ed4c..8d54502222a 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -317,7 +317,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; - if (!ieee80211_is_pspoll(fctl)) + /* use hardware sequence counter as the non-TID counter */ + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) mac_ctl |= B43_TXH_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43_TXH_MAC_STMSDU; -- cgit v1.2.3 From 0b57664cf2393bc1eff594ff7e5ff26533843fe6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Jul 2008 02:08:24 -0700 Subject: wireless: fix warnings from QoS patch When I removed the special "default" meaning from the QoS parameters, I forgot to update drivers and this lead to warnings because some drivers were checking for the special values and putting in defaults. This fixes that by removing the default special-casing completely. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/wireless/b43/main.c | 47 ++++++----------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless/b43') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 381dbd33dfc..e78319aa47c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3073,53 +3073,20 @@ static void b43_qos_params_upload(struct b43_wldev *dev, u16 shm_offset) { u16 params[B43_NR_QOSPARAMS]; - int cw_min, cw_max, aifs, bslots, tmp; + int bslots, tmp; unsigned int i; - const u16 aCWmin = 0x0001; - const u16 aCWmax = 0x03FF; - - /* Calculate the default values for the parameters, if needed. */ - switch (shm_offset) { - case B43_QOS_VOICE: - aifs = (p->aifs == -1) ? 2 : p->aifs; - cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min; - cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max; - break; - case B43_QOS_VIDEO: - aifs = (p->aifs == -1) ? 2 : p->aifs; - cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min; - cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max; - break; - case B43_QOS_BESTEFFORT: - aifs = (p->aifs == -1) ? 3 : p->aifs; - cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; - cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; - break; - case B43_QOS_BACKGROUND: - aifs = (p->aifs == -1) ? 7 : p->aifs; - cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; - cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; - break; - default: - B43_WARN_ON(1); - return; - } - if (cw_min <= 0) - cw_min = aCWmin; - if (cw_max <= 0) - cw_max = aCWmin; - bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min; + bslots = b43_read16(dev, B43_MMIO_RNG) & p->cw_min; memset(¶ms, 0, sizeof(params)); params[B43_QOSPARAM_TXOP] = p->txop * 32; - params[B43_QOSPARAM_CWMIN] = cw_min; - params[B43_QOSPARAM_CWMAX] = cw_max; - params[B43_QOSPARAM_CWCUR] = cw_min; - params[B43_QOSPARAM_AIFS] = aifs; + params[B43_QOSPARAM_CWMIN] = p->cw_min; + params[B43_QOSPARAM_CWMAX] = p->cw_max; + params[B43_QOSPARAM_CWCUR] = p->cw_min; + params[B43_QOSPARAM_AIFS] = p->aifs; params[B43_QOSPARAM_BSLOTS] = bslots; - params[B43_QOSPARAM_REGGAP] = bslots + aifs; + params[B43_QOSPARAM_REGGAP] = bslots + p->aifs; for (i = 0; i < ARRAY_SIZE(params); i++) { if (i == B43_QOSPARAM_STATUS) { -- cgit v1.2.3