aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c119
1 files changed, 67 insertions, 52 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index ed666b7e7e41..5b5cf9357dbf 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -211,15 +211,17 @@ struct mwl8k_vif {
211 /* Local MAC address. */ 211 /* Local MAC address. */
212 u8 mac_addr[ETH_ALEN]; 212 u8 mac_addr[ETH_ALEN];
213 213
214 /* Index into station database. Returned by UPDATE_STADB. */
215 u8 peer_id;
216
217 /* Non AMPDU sequence number assigned by driver */ 214 /* Non AMPDU sequence number assigned by driver */
218 u16 seqno; 215 u16 seqno;
219}; 216};
220
221#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) 217#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
222 218
219struct mwl8k_sta {
220 /* Index into station database. Returned by UPDATE_STADB. */
221 u8 peer_id;
222};
223#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
224
223static const struct ieee80211_channel mwl8k_channels[] = { 225static const struct ieee80211_channel mwl8k_channels[] = {
224 { .center_freq = 2412, .hw_value = 1, }, 226 { .center_freq = 2412, .hw_value = 1, },
225 { .center_freq = 2417, .hw_value = 2, }, 227 { .center_freq = 2417, .hw_value = 2, },
@@ -1402,7 +1404,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1402 tx->pkt_phys_addr = cpu_to_le32(dma); 1404 tx->pkt_phys_addr = cpu_to_le32(dma);
1403 tx->pkt_len = cpu_to_le16(skb->len); 1405 tx->pkt_len = cpu_to_le16(skb->len);
1404 tx->rate_info = 0; 1406 tx->rate_info = 0;
1405 tx->peer_id = mwl8k_vif->peer_id; 1407 if (!priv->ap_fw && tx_info->control.sta != NULL)
1408 tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
1409 else
1410 tx->peer_id = 0;
1406 wmb(); 1411 wmb();
1407 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); 1412 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
1408 1413
@@ -2582,14 +2587,6 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode)
2582/* 2587/*
2583 * CMD_UPDATE_STADB. 2588 * CMD_UPDATE_STADB.
2584 */ 2589 */
2585#define MWL8K_STA_DB_ADD_ENTRY 0
2586#define MWL8K_STA_DB_MODIFY_ENTRY 1
2587#define MWL8K_STA_DB_DEL_ENTRY 2
2588#define MWL8K_STA_DB_FLUSH 3
2589
2590/* Peer Entry flags - used to define the type of the peer node */
2591#define MWL8K_PEER_TYPE_ACCESSPOINT 2
2592
2593struct ewc_ht_info { 2590struct ewc_ht_info {
2594 __le16 control1; 2591 __le16 control1;
2595 __le16 control2; 2592 __le16 control2;
@@ -2640,12 +2637,17 @@ struct mwl8k_cmd_update_stadb {
2640 struct peer_capability_info peer_info; 2637 struct peer_capability_info peer_info;
2641} __attribute__((packed)); 2638} __attribute__((packed));
2642 2639
2643static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, 2640#define MWL8K_STA_DB_MODIFY_ENTRY 1
2644 struct ieee80211_vif *vif, __u32 action, u8 *addr) 2641#define MWL8K_STA_DB_DEL_ENTRY 2
2642
2643/* Peer Entry flags - used to define the type of the peer node */
2644#define MWL8K_PEER_TYPE_ACCESSPOINT 2
2645
2646static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
2647 struct ieee80211_vif *vif, u8 *addr)
2645{ 2648{
2646 struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2647 struct mwl8k_cmd_update_stadb *cmd; 2649 struct mwl8k_cmd_update_stadb *cmd;
2648 struct peer_capability_info *peer_info; 2650 struct peer_capability_info *p;
2649 int rc; 2651 int rc;
2650 2652
2651 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2653 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -2654,37 +2656,38 @@ static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw,
2654 2656
2655 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); 2657 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
2656 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2658 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2659 cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY);
2660 memcpy(cmd->peer_addr, addr, ETH_ALEN);
2657 2661
2658 cmd->action = cpu_to_le32(action); 2662 p = &cmd->peer_info;
2659 peer_info = &cmd->peer_info; 2663 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2664 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
2665 memcpy(p->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
2666 p->interop = 1;
2667 p->amsdu_enabled = 0;
2668
2669 rc = mwl8k_post_cmd(hw, &cmd->header);
2670 kfree(cmd);
2671
2672 return rc ? rc : p->station_id;
2673}
2674
2675static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
2676 struct ieee80211_vif *vif, u8 *addr)
2677{
2678 struct mwl8k_cmd_update_stadb *cmd;
2679 int rc;
2680
2681 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2682 if (cmd == NULL)
2683 return -ENOMEM;
2684
2685 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
2686 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2687 cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY);
2660 memcpy(cmd->peer_addr, addr, ETH_ALEN); 2688 memcpy(cmd->peer_addr, addr, ETH_ALEN);
2661 2689
2662 switch (action) { 2690 rc = mwl8k_post_cmd(hw, &cmd->header);
2663 case MWL8K_STA_DB_ADD_ENTRY:
2664 case MWL8K_STA_DB_MODIFY_ENTRY:
2665 /* Build peer_info block */
2666 peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2667 peer_info->basic_caps =
2668 cpu_to_le16(vif->bss_conf.assoc_capability);
2669 memcpy(peer_info->legacy_rates, mwl8k_rateids,
2670 sizeof(mwl8k_rateids));
2671 peer_info->interop = 1;
2672 peer_info->amsdu_enabled = 0;
2673
2674 rc = mwl8k_post_cmd(hw, &cmd->header);
2675 if (rc == 0)
2676 mv_vif->peer_id = peer_info->station_id;
2677
2678 break;
2679
2680 case MWL8K_STA_DB_DEL_ENTRY:
2681 case MWL8K_STA_DB_FLUSH:
2682 default:
2683 rc = mwl8k_post_cmd(hw, &cmd->header);
2684 if (rc == 0)
2685 mv_vif->peer_id = 0;
2686 break;
2687 }
2688 kfree(cmd); 2691 kfree(cmd);
2689 2692
2690 return rc; 2693 return rc;
@@ -3142,11 +3145,11 @@ static void mwl8k_sta_notify_worker(struct work_struct *work)
3142{ 3145{
3143 struct mwl8k_priv *priv = 3146 struct mwl8k_priv *priv =
3144 container_of(work, struct mwl8k_priv, sta_notify_worker); 3147 container_of(work, struct mwl8k_priv, sta_notify_worker);
3148 struct ieee80211_hw *hw = priv->hw;
3145 3149
3146 spin_lock_bh(&priv->sta_notify_list_lock); 3150 spin_lock_bh(&priv->sta_notify_list_lock);
3147 while (!list_empty(&priv->sta_notify_list)) { 3151 while (!list_empty(&priv->sta_notify_list)) {
3148 struct mwl8k_sta_notify_item *s; 3152 struct mwl8k_sta_notify_item *s;
3149 int action;
3150 3153
3151 s = list_entry(priv->sta_notify_list.next, 3154 s = list_entry(priv->sta_notify_list.next,
3152 struct mwl8k_sta_notify_item, list); 3155 struct mwl8k_sta_notify_item, list);
@@ -3154,11 +3157,22 @@ static void mwl8k_sta_notify_worker(struct work_struct *work)
3154 3157
3155 spin_unlock_bh(&priv->sta_notify_list_lock); 3158 spin_unlock_bh(&priv->sta_notify_list_lock);
3156 3159
3157 if (s->cmd == STA_NOTIFY_ADD) 3160 if (s->cmd == STA_NOTIFY_ADD) {
3158 action = MWL8K_STA_DB_MODIFY_ENTRY; 3161 int rc;
3159 else 3162
3160 action = MWL8K_STA_DB_DEL_ENTRY; 3163 rc = mwl8k_cmd_update_stadb_add(hw, s->vif, s->addr);
3161 mwl8k_cmd_update_stadb(priv->hw, s->vif, action, s->addr); 3164 if (rc >= 0) {
3165 struct ieee80211_sta *sta;
3166
3167 rcu_read_lock();
3168 sta = ieee80211_find_sta(s->vif, s->addr);
3169 if (sta != NULL)
3170 MWL8K_STA(sta)->peer_id = rc;
3171 rcu_read_unlock();
3172 }
3173 } else {
3174 mwl8k_cmd_update_stadb_del(hw, s->vif, s->addr);
3175 }
3162 3176
3163 kfree(s); 3177 kfree(s);
3164 3178
@@ -3448,6 +3462,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
3448 /* Set rssi and noise values to dBm */ 3462 /* Set rssi and noise values to dBm */
3449 hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; 3463 hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
3450 hw->vif_data_size = sizeof(struct mwl8k_vif); 3464 hw->vif_data_size = sizeof(struct mwl8k_vif);
3465 hw->sta_data_size = sizeof(struct mwl8k_sta);
3451 priv->vif = NULL; 3466 priv->vif = NULL;
3452 3467
3453 /* Set default radio state and preamble */ 3468 /* Set default radio state and preamble */