diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2010-01-04 15:58:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-05 17:13:35 -0500 |
commit | 341c97918ab7e84a155ea8b18759425304d213b6 (patch) | |
tree | 084dd6619fff8a38ca70f7c243ec0c65575bc752 /drivers/net/wireless/mwl8k.c | |
parent | a2292d83b5dcb7f378956a124854d2b17fa53aa3 (diff) |
mwl8k: pass GET_HW_SPEC capability bitmask up the stack
This enables HT association and AMPDU in the receive direction for
STA firmware images on hardware that supports it.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 57ced0db910a..23a5a3442623 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -1578,6 +1578,68 @@ struct mwl8k_cmd_get_hw_spec_sta { | |||
1578 | __le32 total_rxd; | 1578 | __le32 total_rxd; |
1579 | } __attribute__((packed)); | 1579 | } __attribute__((packed)); |
1580 | 1580 | ||
1581 | #define MWL8K_CAP_MAX_AMSDU 0x20000000 | ||
1582 | #define MWL8K_CAP_GREENFIELD 0x08000000 | ||
1583 | #define MWL8K_CAP_AMPDU 0x04000000 | ||
1584 | #define MWL8K_CAP_RX_STBC 0x01000000 | ||
1585 | #define MWL8K_CAP_TX_STBC 0x00800000 | ||
1586 | #define MWL8K_CAP_SHORTGI_40MHZ 0x00400000 | ||
1587 | #define MWL8K_CAP_SHORTGI_20MHZ 0x00200000 | ||
1588 | #define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000 | ||
1589 | #define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000 | ||
1590 | #define MWL8K_CAP_DELAY_BA 0x00003000 | ||
1591 | #define MWL8K_CAP_MIMO 0x00000200 | ||
1592 | #define MWL8K_CAP_40MHZ 0x00000100 | ||
1593 | |||
1594 | static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) | ||
1595 | { | ||
1596 | struct mwl8k_priv *priv = hw->priv; | ||
1597 | int rx_streams; | ||
1598 | int tx_streams; | ||
1599 | |||
1600 | priv->band.ht_cap.ht_supported = 1; | ||
1601 | |||
1602 | if (cap & MWL8K_CAP_MAX_AMSDU) | ||
1603 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1604 | if (cap & MWL8K_CAP_GREENFIELD) | ||
1605 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1606 | if (cap & MWL8K_CAP_AMPDU) { | ||
1607 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
1608 | priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
1609 | priv->band.ht_cap.ampdu_density = | ||
1610 | IEEE80211_HT_MPDU_DENSITY_NONE; | ||
1611 | } | ||
1612 | if (cap & MWL8K_CAP_RX_STBC) | ||
1613 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; | ||
1614 | if (cap & MWL8K_CAP_TX_STBC) | ||
1615 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
1616 | if (cap & MWL8K_CAP_SHORTGI_40MHZ) | ||
1617 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
1618 | if (cap & MWL8K_CAP_SHORTGI_20MHZ) | ||
1619 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
1620 | if (cap & MWL8K_CAP_DELAY_BA) | ||
1621 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; | ||
1622 | if (cap & MWL8K_CAP_40MHZ) | ||
1623 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1624 | |||
1625 | rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); | ||
1626 | tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); | ||
1627 | |||
1628 | priv->band.ht_cap.mcs.rx_mask[0] = 0xff; | ||
1629 | if (rx_streams >= 2) | ||
1630 | priv->band.ht_cap.mcs.rx_mask[1] = 0xff; | ||
1631 | if (rx_streams >= 3) | ||
1632 | priv->band.ht_cap.mcs.rx_mask[2] = 0xff; | ||
1633 | priv->band.ht_cap.mcs.rx_mask[4] = 0x01; | ||
1634 | priv->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1635 | |||
1636 | if (rx_streams != tx_streams) { | ||
1637 | priv->band.ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1638 | priv->band.ht_cap.mcs.tx_params |= (tx_streams - 1) << | ||
1639 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
1640 | } | ||
1641 | } | ||
1642 | |||
1581 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | 1643 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) |
1582 | { | 1644 | { |
1583 | struct mwl8k_priv *priv = hw->priv; | 1645 | struct mwl8k_priv *priv = hw->priv; |
@@ -1608,6 +1670,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | |||
1608 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1670 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1609 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1671 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
1610 | priv->hw_rev = cmd->hw_rev; | 1672 | priv->hw_rev = cmd->hw_rev; |
1673 | if (cmd->caps & cpu_to_le32(MWL8K_CAP_MIMO)) | ||
1674 | mwl8k_set_ht_caps(hw, le32_to_cpu(cmd->caps)); | ||
1611 | } | 1675 | } |
1612 | 1676 | ||
1613 | kfree(cmd); | 1677 | kfree(cmd); |