aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
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;