Commit 10ceaac958b0b04d6939ec114b7182d78d2a0027
Committed by
Greg Kroah-Hartman
1 parent
d93089df1b
Exists in
master
and in
7 other branches
ath6kl: iw dev wlan0 link implementation
implementing the cfg ops that gets called when iw dev wlan0 link is issued by user. The ops that needs to be implemented is get_station. kvalo: check the mac address, remove signal_pending(), use ARRAY_SIZE() and fix style issues Signed-off-by: Naveen Singh <nsingh@atheros.com> Signed-off-by: Kalle Valo <kalle.valo@atheros.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 1 changed file with 146 additions and 0 deletions Side-by-side Diff
drivers/staging/ath6kl/os/linux/cfg80211.c
... | ... | @@ -1461,6 +1461,151 @@ |
1461 | 1461 | WLAN_CIPHER_SUITE_CCMP, |
1462 | 1462 | }; |
1463 | 1463 | |
1464 | +bool is_rate_legacy(s32 rate) | |
1465 | +{ | |
1466 | + static const s32 legacy[] = { 1000, 2000, 5500, 11000, | |
1467 | + 6000, 9000, 12000, 18000, 24000, | |
1468 | + 36000, 48000, 54000 }; | |
1469 | + u8 i; | |
1470 | + | |
1471 | + for (i = 0; i < ARRAY_SIZE(legacy); i++) { | |
1472 | + if (rate == legacy[i]) | |
1473 | + return true; | |
1474 | + } | |
1475 | + | |
1476 | + return false; | |
1477 | +} | |
1478 | + | |
1479 | +bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi) | |
1480 | +{ | |
1481 | + static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000, | |
1482 | + 52000, 58500, 65000, 72200 }; | |
1483 | + u8 i; | |
1484 | + | |
1485 | + for (i = 0; i < ARRAY_SIZE(ht20); i++) { | |
1486 | + if (rate == ht20[i]) { | |
1487 | + if (i == ARRAY_SIZE(ht20) - 1) | |
1488 | + /* last rate uses sgi */ | |
1489 | + *sgi = true; | |
1490 | + else | |
1491 | + *sgi = false; | |
1492 | + | |
1493 | + *mcs = i; | |
1494 | + return true; | |
1495 | + } | |
1496 | + } | |
1497 | + return false; | |
1498 | +} | |
1499 | + | |
1500 | +bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) | |
1501 | +{ | |
1502 | + static const s32 ht40[] = { 13500, 27000, 40500, 54000, | |
1503 | + 81000, 108000, 121500, 135000, | |
1504 | + 150000 }; | |
1505 | + u8 i; | |
1506 | + | |
1507 | + for (i = 0; i < ARRAY_SIZE(ht40); i++) { | |
1508 | + if (rate == ht40[i]) { | |
1509 | + if (i == ARRAY_SIZE(ht40) - 1) | |
1510 | + /* last rate uses sgi */ | |
1511 | + *sgi = true; | |
1512 | + else | |
1513 | + *sgi = false; | |
1514 | + | |
1515 | + *mcs = i; | |
1516 | + return true; | |
1517 | + } | |
1518 | + } | |
1519 | + | |
1520 | + return false; | |
1521 | +} | |
1522 | + | |
1523 | +static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev, | |
1524 | + u8 *mac, struct station_info *sinfo) | |
1525 | +{ | |
1526 | + struct ar6_softc *ar = ar6k_priv(dev); | |
1527 | + long left; | |
1528 | + bool sgi; | |
1529 | + s32 rate; | |
1530 | + int ret; | |
1531 | + u8 mcs; | |
1532 | + | |
1533 | + if (memcmp(mac, ar->arBssid, ETH_ALEN) != 0) | |
1534 | + return -ENOENT; | |
1535 | + | |
1536 | + if (down_interruptible(&ar->arSem)) | |
1537 | + return -EBUSY; | |
1538 | + | |
1539 | + ar->statsUpdatePending = true; | |
1540 | + | |
1541 | + ret = wmi_get_stats_cmd(ar->arWmi); | |
1542 | + | |
1543 | + if (ret != 0) { | |
1544 | + up(&ar->arSem); | |
1545 | + return -EIO; | |
1546 | + } | |
1547 | + | |
1548 | + left = wait_event_interruptible_timeout(arEvent, | |
1549 | + ar->statsUpdatePending == false, | |
1550 | + wmitimeout * HZ); | |
1551 | + | |
1552 | + up(&ar->arSem); | |
1553 | + | |
1554 | + if (left == 0) | |
1555 | + return -ETIMEDOUT; | |
1556 | + else if (left < 0) | |
1557 | + return left; | |
1558 | + | |
1559 | + if (ar->arTargetStats.rx_bytes) { | |
1560 | + sinfo->rx_bytes = ar->arTargetStats.rx_bytes; | |
1561 | + sinfo->filled |= STATION_INFO_RX_BYTES; | |
1562 | + sinfo->rx_packets = ar->arTargetStats.rx_packets; | |
1563 | + sinfo->filled |= STATION_INFO_RX_PACKETS; | |
1564 | + } | |
1565 | + | |
1566 | + if (ar->arTargetStats.tx_bytes) { | |
1567 | + sinfo->tx_bytes = ar->arTargetStats.tx_bytes; | |
1568 | + sinfo->filled |= STATION_INFO_TX_BYTES; | |
1569 | + sinfo->tx_packets = ar->arTargetStats.tx_packets; | |
1570 | + sinfo->filled |= STATION_INFO_TX_PACKETS; | |
1571 | + } | |
1572 | + | |
1573 | + sinfo->signal = ar->arTargetStats.cs_rssi; | |
1574 | + sinfo->filled |= STATION_INFO_SIGNAL; | |
1575 | + | |
1576 | + rate = ar->arTargetStats.tx_unicast_rate; | |
1577 | + | |
1578 | + if (is_rate_legacy(rate)) { | |
1579 | + sinfo->txrate.legacy = rate / 100; | |
1580 | + } else if (is_rate_ht20(rate, &mcs, &sgi)) { | |
1581 | + if (sgi) { | |
1582 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | |
1583 | + sinfo->txrate.mcs = mcs - 1; | |
1584 | + } else { | |
1585 | + sinfo->txrate.mcs = mcs; | |
1586 | + } | |
1587 | + | |
1588 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | |
1589 | + } else if (is_rate_ht40(rate, &mcs, &sgi)) { | |
1590 | + if (sgi) { | |
1591 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | |
1592 | + sinfo->txrate.mcs = mcs - 1; | |
1593 | + } else { | |
1594 | + sinfo->txrate.mcs = mcs; | |
1595 | + } | |
1596 | + | |
1597 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | |
1598 | + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | |
1599 | + } else { | |
1600 | + WARN(1, "invalid rate: %d", rate); | |
1601 | + return 0; | |
1602 | + } | |
1603 | + | |
1604 | + sinfo->filled |= STATION_INFO_TX_BITRATE; | |
1605 | + | |
1606 | + return 0; | |
1607 | +} | |
1608 | + | |
1464 | 1609 | static struct |
1465 | 1610 | cfg80211_ops ar6k_cfg80211_ops = { |
1466 | 1611 | .change_virtual_intf = ar6k_cfg80211_change_iface, |
... | ... | @@ -1481,6 +1626,7 @@ |
1481 | 1626 | .set_power_mgmt = ar6k_cfg80211_set_power_mgmt, |
1482 | 1627 | .join_ibss = ar6k_cfg80211_join_ibss, |
1483 | 1628 | .leave_ibss = ar6k_cfg80211_leave_ibss, |
1629 | + .get_station = ar6k_get_station, | |
1484 | 1630 | }; |
1485 | 1631 | |
1486 | 1632 | struct wireless_dev * |