diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 114 |
1 files changed, 78 insertions, 36 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 8afa39b4b488..842f15653238 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -80,46 +80,103 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
80 | } | 80 | } |
81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | 81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); |
82 | 82 | ||
83 | /* priv->sta_lock must be held */ | ||
83 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 84 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
84 | { | 85 | { |
85 | unsigned long flags; | ||
86 | |||
87 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
88 | 86 | ||
89 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) | 87 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) |
90 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", | 88 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n", |
91 | sta_id); | 89 | sta_id, priv->stations[sta_id].sta.sta.addr); |
92 | 90 | ||
93 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | 91 | if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) { |
94 | IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", | 92 | IWL_DEBUG_ASSOC(priv, |
95 | priv->stations[sta_id].sta.sta.addr); | 93 | "STA id %u addr %pM already present in uCode (according to driver)\n", |
96 | 94 | sta_id, priv->stations[sta_id].sta.sta.addr); | |
97 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 95 | } else { |
96 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
97 | IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", | ||
98 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
99 | } | ||
98 | } | 100 | } |
99 | 101 | ||
100 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 102 | static void iwl_process_add_sta_resp(struct iwl_priv *priv, |
101 | struct iwl_device_cmd *cmd, | 103 | struct iwl_addsta_cmd *addsta, |
102 | struct iwl_rx_packet *pkt) | 104 | struct iwl_rx_packet *pkt, |
105 | bool sync) | ||
103 | { | 106 | { |
104 | struct iwl_addsta_cmd *addsta = | ||
105 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
106 | u8 sta_id = addsta->sta.sta_id; | 107 | u8 sta_id = addsta->sta.sta_id; |
108 | unsigned long flags; | ||
107 | 109 | ||
108 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 110 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
109 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 111 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
110 | pkt->hdr.flags); | 112 | pkt->hdr.flags); |
111 | return; | 113 | return; |
112 | } | 114 | } |
113 | 115 | ||
116 | IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", | ||
117 | sta_id); | ||
118 | |||
119 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
120 | |||
114 | switch (pkt->u.add_sta.status) { | 121 | switch (pkt->u.add_sta.status) { |
115 | case ADD_STA_SUCCESS_MSK: | 122 | case ADD_STA_SUCCESS_MSK: |
123 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
116 | iwl_sta_ucode_activate(priv, sta_id); | 124 | iwl_sta_ucode_activate(priv, sta_id); |
117 | /* fall through */ | 125 | break; |
126 | case ADD_STA_NO_ROOM_IN_TABLE: | ||
127 | IWL_ERR(priv, "Adding station %d failed, no room in table.\n", | ||
128 | sta_id); | ||
129 | break; | ||
130 | case ADD_STA_NO_BLOCK_ACK_RESOURCE: | ||
131 | IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n", | ||
132 | sta_id); | ||
133 | break; | ||
134 | case ADD_STA_MODIFY_NON_EXIST_STA: | ||
135 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | ||
136 | sta_id); | ||
137 | break; | ||
118 | default: | 138 | default: |
119 | IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", | 139 | IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", |
120 | pkt->u.add_sta.status); | 140 | pkt->u.add_sta.status); |
121 | break; | 141 | break; |
122 | } | 142 | } |
143 | |||
144 | IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n", | ||
145 | priv->stations[sta_id].sta.mode == | ||
146 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
147 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
148 | |||
149 | /* | ||
150 | * XXX: The MAC address in the command buffer is often changed from | ||
151 | * the original sent to the device. That is, the MAC address | ||
152 | * written to the command buffer often is not the same MAC adress | ||
153 | * read from the command buffer when the command returns. This | ||
154 | * issue has not yet been resolved and this debugging is left to | ||
155 | * observe the problem. | ||
156 | */ | ||
157 | IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n", | ||
158 | priv->stations[sta_id].sta.mode == | ||
159 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
160 | addsta->sta.addr); | ||
161 | |||
162 | /* | ||
163 | * Determine if we wanted to modify or add a station, | ||
164 | * if adding a station succeeded we have some more initialization | ||
165 | * to do when using station notification. TODO | ||
166 | */ | ||
167 | |||
168 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
169 | } | ||
170 | |||
171 | static void iwl_add_sta_callback(struct iwl_priv *priv, | ||
172 | struct iwl_device_cmd *cmd, | ||
173 | struct iwl_rx_packet *pkt) | ||
174 | { | ||
175 | struct iwl_addsta_cmd *addsta = | ||
176 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
177 | |||
178 | iwl_process_add_sta_resp(priv, addsta, pkt, false); | ||
179 | |||
123 | } | 180 | } |
124 | 181 | ||
125 | int iwl_send_add_sta(struct iwl_priv *priv, | 182 | int iwl_send_add_sta(struct iwl_priv *priv, |
@@ -145,24 +202,9 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
145 | if (ret || (flags & CMD_ASYNC)) | 202 | if (ret || (flags & CMD_ASYNC)) |
146 | return ret; | 203 | return ret; |
147 | 204 | ||
148 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | ||
149 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
150 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | ||
151 | pkt->hdr.flags); | ||
152 | ret = -EIO; | ||
153 | } | ||
154 | |||
155 | if (ret == 0) { | 205 | if (ret == 0) { |
156 | switch (pkt->u.add_sta.status) { | 206 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
157 | case ADD_STA_SUCCESS_MSK: | 207 | iwl_process_add_sta_resp(priv, sta, pkt, true); |
158 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); | ||
159 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
160 | break; | ||
161 | default: | ||
162 | ret = -EIO; | ||
163 | IWL_WARN(priv, "REPLY_ADD_STA failed\n"); | ||
164 | break; | ||
165 | } | ||
166 | } | 208 | } |
167 | iwl_free_pages(priv, cmd.reply_page); | 209 | iwl_free_pages(priv, cmd.reply_page); |
168 | 210 | ||