summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2015-06-11 06:53:45 -0400
committerKalle Valo <kvalo@codeaurora.org>2015-06-15 06:13:50 -0400
commited8e0ed53b317f72df907298fb653a976b083dc4 (patch)
treebed2f51fe75130f23362f5b246b872c2b66ecc81
parentf7a40873d2fa04d7e87bd829074da9b0f32a33ed (diff)
rt2800: fix assigning same WCID for different stations
On some hardware reading WCID entries table results getting 0xff numbers, no matter of value written there before. This cause assigning the same WCID for different stations and makes not possible to connect to more than one station. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c57
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c16
3 files changed, 28 insertions, 55 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index ebd5625d13f1..95c1d7c0a2f3 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2961,6 +2961,15 @@ enum rt2800_eeprom_word {
2961#define BCN_TBTT_OFFSET 64 2961#define BCN_TBTT_OFFSET 64
2962 2962
2963/* 2963/*
2964 * Hardware has 255 WCID table entries. First 32 entries are reserved for
2965 * shared keys. Since parts of the pairwise key table might be shared with
2966 * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
2967 */
2968#define WCID_START 33
2969#define WCID_END 222
2970#define STA_IDS_SIZE (WCID_END - WCID_START + 2)
2971
2972/*
2964 * RT2800 driver data structure 2973 * RT2800 driver data structure
2965 */ 2974 */
2966struct rt2800_drv_data { 2975struct rt2800_drv_data {
@@ -2971,6 +2980,7 @@ struct rt2800_drv_data {
2971 u8 txmixer_gain_24g; 2980 u8 txmixer_gain_24g;
2972 u8 txmixer_gain_5g; 2981 u8 txmixer_gain_5g;
2973 unsigned int tbtt_tick; 2982 unsigned int tbtt_tick;
2983 DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
2974}; 2984};
2975 2985
2976#endif /* RT2800_H */ 2986#endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index dfeca8355b22..c7843769ab71 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1381,38 +1381,6 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
1381} 1381}
1382EXPORT_SYMBOL_GPL(rt2800_config_shared_key); 1382EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
1383 1383
1384static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
1385{
1386 struct mac_wcid_entry wcid_entry;
1387 int idx;
1388 u32 offset;
1389
1390 /*
1391 * Search for the first free WCID entry and return the corresponding
1392 * index.
1393 *
1394 * Make sure the WCID starts _after_ the last possible shared key
1395 * entry (>32).
1396 *
1397 * Since parts of the pairwise key table might be shared with
1398 * the beacon frame buffers 6 & 7 we should only write into the
1399 * first 222 entries.
1400 */
1401 for (idx = 33; idx <= 222; idx++) {
1402 offset = MAC_WCID_ENTRY(idx);
1403 rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
1404 sizeof(wcid_entry));
1405 if (is_broadcast_ether_addr(wcid_entry.mac))
1406 return idx;
1407 }
1408
1409 /*
1410 * Use -1 to indicate that we don't have any more space in the WCID
1411 * table.
1412 */
1413 return -1;
1414}
1415
1416int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, 1384int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
1417 struct rt2x00lib_crypto *crypto, 1385 struct rt2x00lib_crypto *crypto,
1418 struct ieee80211_key_conf *key) 1386 struct ieee80211_key_conf *key)
@@ -1425,7 +1393,7 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
1425 * Allow key configuration only for STAs that are 1393 * Allow key configuration only for STAs that are
1426 * known by the hw. 1394 * known by the hw.
1427 */ 1395 */
1428 if (crypto->wcid < 0) 1396 if (crypto->wcid > WCID_END)
1429 return -ENOSPC; 1397 return -ENOSPC;
1430 key->hw_key_idx = crypto->wcid; 1398 key->hw_key_idx = crypto->wcid;
1431 1399
@@ -1455,11 +1423,13 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
1455{ 1423{
1456 int wcid; 1424 int wcid;
1457 struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); 1425 struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
1426 struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
1458 1427
1459 /* 1428 /*
1460 * Find next free WCID. 1429 * Search for the first free WCID entry and return the corresponding
1430 * index.
1461 */ 1431 */
1462 wcid = rt2800_find_wcid(rt2x00dev); 1432 wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START;
1463 1433
1464 /* 1434 /*
1465 * Store selected wcid even if it is invalid so that we can 1435 * Store selected wcid even if it is invalid so that we can
@@ -1471,9 +1441,11 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
1471 * No space left in the device, however, we can still communicate 1441 * No space left in the device, however, we can still communicate
1472 * with the STA -> No error. 1442 * with the STA -> No error.
1473 */ 1443 */
1474 if (wcid < 0) 1444 if (wcid > WCID_END)
1475 return 0; 1445 return 0;
1476 1446
1447 __set_bit(wcid - WCID_START, drv_data->sta_ids);
1448
1477 /* 1449 /*
1478 * Clean up WCID attributes and write STA address to the device. 1450 * Clean up WCID attributes and write STA address to the device.
1479 */ 1451 */
@@ -1487,11 +1459,16 @@ EXPORT_SYMBOL_GPL(rt2800_sta_add);
1487 1459
1488int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) 1460int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
1489{ 1461{
1462 struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
1463
1464 if (wcid > WCID_END)
1465 return 0;
1490 /* 1466 /*
1491 * Remove WCID entry, no need to clean the attributes as they will 1467 * Remove WCID entry, no need to clean the attributes as they will
1492 * get renewed when the WCID is reused. 1468 * get renewed when the WCID is reused.
1493 */ 1469 */
1494 rt2800_config_wcid(rt2x00dev, NULL, wcid); 1470 rt2800_config_wcid(rt2x00dev, NULL, wcid);
1471 __clear_bit(wcid - WCID_START, drv_data->sta_ids);
1495 1472
1496 return 0; 1473 return 0;
1497} 1474}
@@ -7970,11 +7947,11 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
7970 /* 7947 /*
7971 * Don't allow aggregation for stations the hardware isn't aware 7948 * Don't allow aggregation for stations the hardware isn't aware
7972 * of because tx status reports for frames to an unknown station 7949 * of because tx status reports for frames to an unknown station
7973 * always contain wcid=255 and thus we can't distinguish between 7950 * always contain wcid=WCID_END+1 and thus we can't distinguish
7974 * multiple stations which leads to unwanted situations when the 7951 * between multiple stations which leads to unwanted situations
7975 * hw reorders frames due to aggregation. 7952 * when the hw reorders frames due to aggregation.
7976 */ 7953 */
7977 if (sta_priv->wcid < 0) 7954 if (sta_priv->wcid > WCID_END)
7978 return 1; 7955 return 1;
7979 7956
7980 switch (action) { 7957 switch (action) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 1b8a459a412b..3c26ee65a415 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -535,16 +535,8 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
535 struct ieee80211_sta *sta) 535 struct ieee80211_sta *sta)
536{ 536{
537 struct rt2x00_dev *rt2x00dev = hw->priv; 537 struct rt2x00_dev *rt2x00dev = hw->priv;
538 struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
539 538
540 /* 539 return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta);
541 * If there's no space left in the device table store
542 * -1 as wcid but tell mac80211 everything went ok.
543 */
544 if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
545 sta_priv->wcid = -1;
546
547 return 0;
548} 540}
549EXPORT_SYMBOL_GPL(rt2x00mac_sta_add); 541EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
550 542
@@ -554,12 +546,6 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
554 struct rt2x00_dev *rt2x00dev = hw->priv; 546 struct rt2x00_dev *rt2x00dev = hw->priv;
555 struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); 547 struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
556 548
557 /*
558 * If we never sent the STA to the device no need to clean it up.
559 */
560 if (sta_priv->wcid < 0)
561 return 0;
562
563 return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid); 549 return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
564} 550}
565EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); 551EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);