aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-04-05 09:05:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:44 -0400
commit5042c5070daaa6a3c033e4510439e3ac02a1df60 (patch)
tree84048d9e1bb06cc41fd7605abddd3da90992c7c9 /drivers/net/wireless/b43/main.c
parentc97a4ccc1fad35d3d183900af29c171b6d56b7f9 (diff)
b43: Fix PHY TX control words in SHM
This fixes the initialization of the PHY TX control words in shared memory. These control words are used for management frames like beacons. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c199
1 files changed, 116 insertions, 83 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index ec28a6ef42be..1aa0f727174b 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1281,22 +1281,107 @@ static void b43_write_template_common(struct b43_wldev *dev,
1281 size + sizeof(struct b43_plcp_hdr6)); 1281 size + sizeof(struct b43_plcp_hdr6));
1282} 1282}
1283 1283
1284/* Check if the use of the antenna that ieee80211 told us to
1285 * use is possible. This will fall back to DEFAULT.
1286 * "antenna_nr" is the antenna identifier we got from ieee80211. */
1287u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
1288 u8 antenna_nr)
1289{
1290 u8 antenna_mask;
1291
1292 if (antenna_nr == 0) {
1293 /* Zero means "use default antenna". That's always OK. */
1294 return 0;
1295 }
1296
1297 /* Get the mask of available antennas. */
1298 if (dev->phy.gmode)
1299 antenna_mask = dev->dev->bus->sprom.ant_available_bg;
1300 else
1301 antenna_mask = dev->dev->bus->sprom.ant_available_a;
1302
1303 if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
1304 /* This antenna is not available. Fall back to default. */
1305 return 0;
1306 }
1307
1308 return antenna_nr;
1309}
1310
1311static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
1312{
1313 antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
1314 switch (antenna) {
1315 case 0: /* default/diversity */
1316 return B43_ANTENNA_DEFAULT;
1317 case 1: /* Antenna 0 */
1318 return B43_ANTENNA0;
1319 case 2: /* Antenna 1 */
1320 return B43_ANTENNA1;
1321 case 3: /* Antenna 2 */
1322 return B43_ANTENNA2;
1323 case 4: /* Antenna 3 */
1324 return B43_ANTENNA3;
1325 default:
1326 return B43_ANTENNA_DEFAULT;
1327 }
1328}
1329
1330/* Convert a b43 antenna number value to the PHY TX control value. */
1331static u16 b43_antenna_to_phyctl(int antenna)
1332{
1333 switch (antenna) {
1334 case B43_ANTENNA0:
1335 return B43_TXH_PHY_ANT0;
1336 case B43_ANTENNA1:
1337 return B43_TXH_PHY_ANT1;
1338 case B43_ANTENNA2:
1339 return B43_TXH_PHY_ANT2;
1340 case B43_ANTENNA3:
1341 return B43_TXH_PHY_ANT3;
1342 case B43_ANTENNA_AUTO:
1343 return B43_TXH_PHY_ANT01AUTO;
1344 }
1345 B43_WARN_ON(1);
1346 return 0;
1347}
1348
1284static void b43_write_beacon_template(struct b43_wldev *dev, 1349static void b43_write_beacon_template(struct b43_wldev *dev,
1285 u16 ram_offset, 1350 u16 ram_offset,
1286 u16 shm_size_offset, u8 rate) 1351 u16 shm_size_offset)
1287{ 1352{
1288 unsigned int i, len, variable_len; 1353 unsigned int i, len, variable_len;
1289 const struct ieee80211_mgmt *bcn; 1354 const struct ieee80211_mgmt *bcn;
1290 const u8 *ie; 1355 const u8 *ie;
1291 bool tim_found = 0; 1356 bool tim_found = 0;
1357 unsigned int rate;
1358 u16 ctl;
1359 int antenna;
1292 1360
1293 bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); 1361 bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
1294 len = min((size_t) dev->wl->current_beacon->len, 1362 len = min((size_t) dev->wl->current_beacon->len,
1295 0x200 - sizeof(struct b43_plcp_hdr6)); 1363 0x200 - sizeof(struct b43_plcp_hdr6));
1364 rate = dev->wl->beacon_txctl.tx_rate->hw_value;
1296 1365
1297 b43_write_template_common(dev, (const u8 *)bcn, 1366 b43_write_template_common(dev, (const u8 *)bcn,
1298 len, ram_offset, shm_size_offset, rate); 1367 len, ram_offset, shm_size_offset, rate);
1299 1368
1369 /* Write the PHY TX control parameters. */
1370 antenna = b43_antenna_from_ieee80211(dev,
1371 dev->wl->beacon_txctl.antenna_sel_tx);
1372 antenna = b43_antenna_to_phyctl(antenna);
1373 ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
1374 /* We can't send beacons with short preamble. Would get PHY errors. */
1375 ctl &= ~B43_TXH_PHY_SHORTPRMBL;
1376 ctl &= ~B43_TXH_PHY_ANT;
1377 ctl &= ~B43_TXH_PHY_ENC;
1378 ctl |= antenna;
1379 if (b43_is_cck_rate(rate))
1380 ctl |= B43_TXH_PHY_ENC_CCK;
1381 else
1382 ctl |= B43_TXH_PHY_ENC_OFDM;
1383 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
1384
1300 /* Find the position of the TIM and the DTIM_period value 1385 /* Find the position of the TIM and the DTIM_period value
1301 * and write them to SHM. */ 1386 * and write them to SHM. */
1302 ie = bcn->u.beacon.variable; 1387 ie = bcn->u.beacon.variable;
@@ -1474,8 +1559,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
1474 1559
1475 if (!beacon0_valid) { 1560 if (!beacon0_valid) {
1476 if (!wl->beacon0_uploaded) { 1561 if (!wl->beacon0_uploaded) {
1477 b43_write_beacon_template(dev, 0x68, 0x18, 1562 b43_write_beacon_template(dev, 0x68, 0x18);
1478 B43_CCK_RATE_1MB);
1479 b43_write_probe_resp_template(dev, 0x268, 0x4A, 1563 b43_write_probe_resp_template(dev, 0x268, 0x4A,
1480 &__b43_ratetable[3]); 1564 &__b43_ratetable[3]);
1481 wl->beacon0_uploaded = 1; 1565 wl->beacon0_uploaded = 1;
@@ -1485,8 +1569,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
1485 b43_write32(dev, B43_MMIO_MACCMD, cmd); 1569 b43_write32(dev, B43_MMIO_MACCMD, cmd);
1486 } else if (!beacon1_valid) { 1570 } else if (!beacon1_valid) {
1487 if (!wl->beacon1_uploaded) { 1571 if (!wl->beacon1_uploaded) {
1488 b43_write_beacon_template(dev, 0x468, 0x1A, 1572 b43_write_beacon_template(dev, 0x468, 0x1A);
1489 B43_CCK_RATE_1MB);
1490 wl->beacon1_uploaded = 1; 1573 wl->beacon1_uploaded = 1;
1491 } 1574 }
1492 cmd = b43_read32(dev, B43_MMIO_MACCMD); 1575 cmd = b43_read32(dev, B43_MMIO_MACCMD);
@@ -1519,7 +1602,8 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
1519 1602
1520/* Asynchronously update the packet templates in template RAM. 1603/* Asynchronously update the packet templates in template RAM.
1521 * Locking: Requires wl->irq_lock to be locked. */ 1604 * Locking: Requires wl->irq_lock to be locked. */
1522static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) 1605static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
1606 const struct ieee80211_tx_control *txctl)
1523{ 1607{
1524 /* This is the top half of the ansynchronous beacon update. 1608 /* This is the top half of the ansynchronous beacon update.
1525 * The bottom half is the beacon IRQ. 1609 * The bottom half is the beacon IRQ.
@@ -1530,6 +1614,7 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
1530 if (wl->current_beacon) 1614 if (wl->current_beacon)
1531 dev_kfree_skb_any(wl->current_beacon); 1615 dev_kfree_skb_any(wl->current_beacon);
1532 wl->current_beacon = beacon; 1616 wl->current_beacon = beacon;
1617 memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl));
1533 wl->beacon0_uploaded = 0; 1618 wl->beacon0_uploaded = 0;
1534 wl->beacon1_uploaded = 0; 1619 wl->beacon1_uploaded = 0;
1535 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); 1620 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
@@ -2363,38 +2448,28 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
2363 } 2448 }
2364} 2449}
2365 2450
2451/* Set the default values for the PHY TX Control Words. */
2452static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
2453{
2454 u16 ctl = 0;
2455
2456 ctl |= B43_TXH_PHY_ENC_CCK;
2457 ctl |= B43_TXH_PHY_ANT01AUTO;
2458 ctl |= B43_TXH_PHY_TXPWR;
2459
2460 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
2461 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl);
2462 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl);
2463}
2464
2366/* Set the TX-Antenna for management frames sent by firmware. */ 2465/* Set the TX-Antenna for management frames sent by firmware. */
2367static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) 2466static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
2368{ 2467{
2369 u16 ant = 0; 2468 u16 ant;
2370 u16 tmp; 2469 u16 tmp;
2371 2470
2372 switch (antenna) { 2471 ant = b43_antenna_to_phyctl(antenna);
2373 case B43_ANTENNA0:
2374 ant |= B43_TXH_PHY_ANT0;
2375 break;
2376 case B43_ANTENNA1:
2377 ant |= B43_TXH_PHY_ANT1;
2378 break;
2379 case B43_ANTENNA2:
2380 ant |= B43_TXH_PHY_ANT2;
2381 break;
2382 case B43_ANTENNA3:
2383 ant |= B43_TXH_PHY_ANT3;
2384 break;
2385 case B43_ANTENNA_AUTO:
2386 ant |= B43_TXH_PHY_ANT01AUTO;
2387 break;
2388 default:
2389 B43_WARN_ON(1);
2390 }
2391
2392 /* FIXME We also need to set the other flags of the PHY control field somewhere. */
2393 2472
2394 /* For Beacons */
2395 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
2396 tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
2397 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
2398 /* For ACK/CTS */ 2473 /* For ACK/CTS */
2399 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL); 2474 tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
2400 tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; 2475 tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
@@ -3112,52 +3187,6 @@ init_failure:
3112 return err; 3187 return err;
3113} 3188}
3114 3189
3115/* Check if the use of the antenna that ieee80211 told us to
3116 * use is possible. This will fall back to DEFAULT.
3117 * "antenna_nr" is the antenna identifier we got from ieee80211. */
3118u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
3119 u8 antenna_nr)
3120{
3121 u8 antenna_mask;
3122
3123 if (antenna_nr == 0) {
3124 /* Zero means "use default antenna". That's always OK. */
3125 return 0;
3126 }
3127
3128 /* Get the mask of available antennas. */
3129 if (dev->phy.gmode)
3130 antenna_mask = dev->dev->bus->sprom.ant_available_bg;
3131 else
3132 antenna_mask = dev->dev->bus->sprom.ant_available_a;
3133
3134 if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
3135 /* This antenna is not available. Fall back to default. */
3136 return 0;
3137 }
3138
3139 return antenna_nr;
3140}
3141
3142static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
3143{
3144 antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
3145 switch (antenna) {
3146 case 0: /* default/diversity */
3147 return B43_ANTENNA_DEFAULT;
3148 case 1: /* Antenna 0 */
3149 return B43_ANTENNA0;
3150 case 2: /* Antenna 1 */
3151 return B43_ANTENNA1;
3152 case 3: /* Antenna 2 */
3153 return B43_ANTENNA2;
3154 case 4: /* Antenna 3 */
3155 return B43_ANTENNA3;
3156 default:
3157 return B43_ANTENNA_DEFAULT;
3158 }
3159}
3160
3161static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 3190static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3162{ 3191{
3163 struct b43_wl *wl = hw_to_b43_wl(hw); 3192 struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3405,8 +3434,10 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
3405 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { 3434 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
3406 B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); 3435 B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
3407 b43_set_ssid(dev, conf->ssid, conf->ssid_len); 3436 b43_set_ssid(dev, conf->ssid, conf->ssid_len);
3408 if (conf->beacon) 3437 if (conf->beacon) {
3409 b43_update_templates(wl, conf->beacon); 3438 b43_update_templates(wl, conf->beacon,
3439 conf->beacon_control);
3440 }
3410 } 3441 }
3411 b43_write_mac_bssid_templates(dev); 3442 b43_write_mac_bssid_templates(dev);
3412 } 3443 }
@@ -3877,6 +3908,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
3877 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1); 3908 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
3878 3909
3879 b43_rate_memory_init(dev); 3910 b43_rate_memory_init(dev);
3911 b43_set_phytxctl_defaults(dev);
3880 3912
3881 /* Minimum Contention Window */ 3913 /* Minimum Contention Window */
3882 if (phy->type == B43_PHYTYPE_B) { 3914 if (phy->type == B43_PHYTYPE_B) {
@@ -4087,16 +4119,17 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
4087 struct b43_wl *wl = hw_to_b43_wl(hw); 4119 struct b43_wl *wl = hw_to_b43_wl(hw);
4088 struct sk_buff *beacon; 4120 struct sk_buff *beacon;
4089 unsigned long flags; 4121 unsigned long flags;
4122 struct ieee80211_tx_control txctl;
4090 4123
4091 /* We could modify the existing beacon and set the aid bit in 4124 /* We could modify the existing beacon and set the aid bit in
4092 * the TIM field, but that would probably require resizing and 4125 * the TIM field, but that would probably require resizing and
4093 * moving of data within the beacon template. 4126 * moving of data within the beacon template.
4094 * Simply request a new beacon and let mac80211 do the hard work. */ 4127 * Simply request a new beacon and let mac80211 do the hard work. */
4095 beacon = ieee80211_beacon_get(hw, wl->vif, NULL); 4128 beacon = ieee80211_beacon_get(hw, wl->vif, &txctl);
4096 if (unlikely(!beacon)) 4129 if (unlikely(!beacon))
4097 return -ENOMEM; 4130 return -ENOMEM;
4098 spin_lock_irqsave(&wl->irq_lock, flags); 4131 spin_lock_irqsave(&wl->irq_lock, flags);
4099 b43_update_templates(wl, beacon); 4132 b43_update_templates(wl, beacon, &txctl);
4100 spin_unlock_irqrestore(&wl->irq_lock, flags); 4133 spin_unlock_irqrestore(&wl->irq_lock, flags);
4101 4134
4102 return 0; 4135 return 0;
@@ -4110,7 +4143,7 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
4110 unsigned long flags; 4143 unsigned long flags;
4111 4144
4112 spin_lock_irqsave(&wl->irq_lock, flags); 4145 spin_lock_irqsave(&wl->irq_lock, flags);
4113 b43_update_templates(wl, beacon); 4146 b43_update_templates(wl, beacon, ctl);
4114 spin_unlock_irqrestore(&wl->irq_lock, flags); 4147 spin_unlock_irqrestore(&wl->irq_lock, flags);
4115 4148
4116 return 0; 4149 return 0;