aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2010-01-12 07:51:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-12 14:21:23 -0500
commitee0ddf1865954f44ee929d963e2c968eb377f447 (patch)
tree85cbe8d86dad8b53404db76aa78450460b1e258c /drivers/net/wireless/mwl8k.c
parentaa21d0f69a5ca28d33f584b8952cca154115fd26 (diff)
mwl8k: enable multi-BSS AP operation
As follows: - GET_HW_SPEC is now responsible for setting priv->{ap,sta}_macids_supported, which are bitmasks of supported macids for AP and STA mode. (Typically, STA firmware images will support only one macid, #0, in STA mode, and AP firmware images will support macids #0-7, in AP mode.) - Our wiphy ->interfaces_modes is now set based on the non-zero-ness of these two bitmasks. - We main priv->macids_used, a bitmask of which macids are currently in use. ->add_interface() will assign the lowest free macid for this interface type as it is created, or bail out if there are no more free macids to assign. ->delete_interface() will mark the macid as being free again. This enables the multi-BSS code added in the previous commits. 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.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index d8cf43853de1..06dc7a0978a0 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -147,6 +147,8 @@ struct mwl8k_priv {
147 struct ieee80211_supported_band band_50; 147 struct ieee80211_supported_band band_50;
148 struct ieee80211_channel channels_50[4]; 148 struct ieee80211_channel channels_50[4];
149 struct ieee80211_rate rates_50[9]; 149 struct ieee80211_rate rates_50[9];
150 u32 ap_macids_supported;
151 u32 sta_macids_supported;
150 152
151 /* firmware access */ 153 /* firmware access */
152 struct mutex fw_mutex; 154 struct mutex fw_mutex;
@@ -161,6 +163,7 @@ struct mwl8k_priv {
161 struct completion *tx_wait; 163 struct completion *tx_wait;
162 164
163 /* List of interfaces. */ 165 /* List of interfaces. */
166 u32 macids_used;
164 struct list_head vif_list; 167 struct list_head vif_list;
165 168
166 /* power management status cookie from firmware */ 169 /* power management status cookie from firmware */
@@ -1786,6 +1789,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
1786 priv->fw_rev = le32_to_cpu(cmd->fw_rev); 1789 priv->fw_rev = le32_to_cpu(cmd->fw_rev);
1787 priv->hw_rev = cmd->hw_rev; 1790 priv->hw_rev = cmd->hw_rev;
1788 mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); 1791 mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
1792 priv->ap_macids_supported = 0x00000000;
1793 priv->sta_macids_supported = 0x00000001;
1789 } 1794 }
1790 1795
1791 kfree(cmd); 1796 kfree(cmd);
@@ -1840,6 +1845,8 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
1840 priv->fw_rev = le32_to_cpu(cmd->fw_rev); 1845 priv->fw_rev = le32_to_cpu(cmd->fw_rev);
1841 priv->hw_rev = cmd->hw_rev; 1846 priv->hw_rev = cmd->hw_rev;
1842 mwl8k_setup_2ghz_band(hw); 1847 mwl8k_setup_2ghz_band(hw);
1848 priv->ap_macids_supported = 0x000000ff;
1849 priv->sta_macids_supported = 0x00000000;
1843 1850
1844 off = le32_to_cpu(cmd->wcbbase0) & 0xffff; 1851 off = le32_to_cpu(cmd->wcbbase0) & 0xffff;
1845 iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); 1852 iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off);
@@ -2759,16 +2766,33 @@ struct mwl8k_cmd_set_mac_addr {
2759 }; 2766 };
2760} __attribute__((packed)); 2767} __attribute__((packed));
2761 2768
2762#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 2769#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0
2763#define MWL8K_MAC_TYPE_PRIMARY_AP 2 2770#define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1
2771#define MWL8K_MAC_TYPE_PRIMARY_AP 2
2772#define MWL8K_MAC_TYPE_SECONDARY_AP 3
2764 2773
2765static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, 2774static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw,
2766 struct ieee80211_vif *vif, u8 *mac) 2775 struct ieee80211_vif *vif, u8 *mac)
2767{ 2776{
2768 struct mwl8k_priv *priv = hw->priv; 2777 struct mwl8k_priv *priv = hw->priv;
2778 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
2769 struct mwl8k_cmd_set_mac_addr *cmd; 2779 struct mwl8k_cmd_set_mac_addr *cmd;
2780 int mac_type;
2770 int rc; 2781 int rc;
2771 2782
2783 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
2784 if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) {
2785 if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported))
2786 mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT;
2787 else
2788 mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT;
2789 } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) {
2790 if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported))
2791 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
2792 else
2793 mac_type = MWL8K_MAC_TYPE_SECONDARY_AP;
2794 }
2795
2772 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2796 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2773 if (cmd == NULL) 2797 if (cmd == NULL)
2774 return -ENOMEM; 2798 return -ENOMEM;
@@ -2776,7 +2800,7 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw,
2776 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); 2800 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
2777 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2801 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2778 if (priv->ap_fw) { 2802 if (priv->ap_fw) {
2779 cmd->mbss.mac_type = cpu_to_le16(MWL8K_MAC_TYPE_PRIMARY_AP); 2803 cmd->mbss.mac_type = cpu_to_le16(mac_type);
2780 memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); 2804 memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
2781 } else { 2805 } else {
2782 memcpy(cmd->mac_addr, mac, ETH_ALEN); 2806 memcpy(cmd->mac_addr, mac, ETH_ALEN);
@@ -3271,12 +3295,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
3271{ 3295{
3272 struct mwl8k_priv *priv = hw->priv; 3296 struct mwl8k_priv *priv = hw->priv;
3273 struct mwl8k_vif *mwl8k_vif; 3297 struct mwl8k_vif *mwl8k_vif;
3274 3298 u32 macids_supported;
3275 /* 3299 int macid;
3276 * We only support one active interface at a time.
3277 */
3278 if (!list_empty(&priv->vif_list))
3279 return -EBUSY;
3280 3300
3281 /* 3301 /*
3282 * Reject interface creation if sniffer mode is active, as 3302 * Reject interface creation if sniffer mode is active, as
@@ -3290,11 +3310,27 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
3290 return -EINVAL; 3310 return -EINVAL;
3291 } 3311 }
3292 3312
3313
3314 switch (vif->type) {
3315 case NL80211_IFTYPE_AP:
3316 macids_supported = priv->ap_macids_supported;
3317 break;
3318 case NL80211_IFTYPE_STATION:
3319 macids_supported = priv->sta_macids_supported;
3320 break;
3321 default:
3322 return -EINVAL;
3323 }
3324
3325 macid = ffs(macids_supported & ~priv->macids_used);
3326 if (!macid--)
3327 return -EBUSY;
3328
3293 /* Setup driver private area. */ 3329 /* Setup driver private area. */
3294 mwl8k_vif = MWL8K_VIF(vif); 3330 mwl8k_vif = MWL8K_VIF(vif);
3295 memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); 3331 memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
3296 mwl8k_vif->vif = vif; 3332 mwl8k_vif->vif = vif;
3297 mwl8k_vif->macid = 0; 3333 mwl8k_vif->macid = macid;
3298 mwl8k_vif->seqno = 0; 3334 mwl8k_vif->seqno = 0;
3299 3335
3300 /* Set the mac address. */ 3336 /* Set the mac address. */
@@ -3303,6 +3339,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
3303 if (priv->ap_fw) 3339 if (priv->ap_fw)
3304 mwl8k_cmd_set_new_stn_add_self(hw, vif); 3340 mwl8k_cmd_set_new_stn_add_self(hw, vif);
3305 3341
3342 priv->macids_used |= 1 << mwl8k_vif->macid;
3306 list_add_tail(&mwl8k_vif->list, &priv->vif_list); 3343 list_add_tail(&mwl8k_vif->list, &priv->vif_list);
3307 3344
3308 return 0; 3345 return 0;
@@ -3319,6 +3356,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw,
3319 3356
3320 mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); 3357 mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00");
3321 3358
3359 priv->macids_used &= ~(1 << mwl8k_vif->macid);
3322 list_del(&mwl8k_vif->list); 3360 list_del(&mwl8k_vif->list);
3323} 3361}
3324 3362
@@ -4023,6 +4061,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
4023 hw->vif_data_size = sizeof(struct mwl8k_vif); 4061 hw->vif_data_size = sizeof(struct mwl8k_vif);
4024 hw->sta_data_size = sizeof(struct mwl8k_sta); 4062 hw->sta_data_size = sizeof(struct mwl8k_sta);
4025 4063
4064 priv->macids_used = 0;
4026 INIT_LIST_HEAD(&priv->vif_list); 4065 INIT_LIST_HEAD(&priv->vif_list);
4027 4066
4028 /* Set default radio state and preamble */ 4067 /* Set default radio state and preamble */
@@ -4094,12 +4133,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
4094 rc = mwl8k_cmd_get_hw_spec_ap(hw); 4133 rc = mwl8k_cmd_get_hw_spec_ap(hw);
4095 if (!rc) 4134 if (!rc)
4096 rc = mwl8k_cmd_set_hw_spec(hw); 4135 rc = mwl8k_cmd_set_hw_spec(hw);
4097
4098 hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP);
4099 } else { 4136 } else {
4100 rc = mwl8k_cmd_get_hw_spec_sta(hw); 4137 rc = mwl8k_cmd_get_hw_spec_sta(hw);
4101
4102 hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
4103 } 4138 }
4104 if (rc) { 4139 if (rc) {
4105 printk(KERN_ERR "%s: Cannot initialise firmware\n", 4140 printk(KERN_ERR "%s: Cannot initialise firmware\n",
@@ -4107,6 +4142,13 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
4107 goto err_free_irq; 4142 goto err_free_irq;
4108 } 4143 }
4109 4144
4145 hw->wiphy->interface_modes = 0;
4146 if (priv->ap_macids_supported)
4147 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
4148 if (priv->sta_macids_supported)
4149 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
4150
4151
4110 /* Turn radio off */ 4152 /* Turn radio off */
4111 rc = mwl8k_cmd_radio_disable(hw); 4153 rc = mwl8k_cmd_radio_disable(hw);
4112 if (rc) { 4154 if (rc) {