diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-commands.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 46 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-devtrace.h | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sv-open.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 231 |
8 files changed, 180 insertions, 152 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 30e11c7c4144..d39efcce8ba7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -87,7 +87,6 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
87 | 87 | ||
88 | struct iwl_host_cmd hcmd = { | 88 | struct iwl_host_cmd hcmd = { |
89 | .id = REPLY_PHY_CALIBRATION_CMD, | 89 | .id = REPLY_PHY_CALIBRATION_CMD, |
90 | .flags = CMD_SIZE_HUGE, | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | for (i = 0; i < IWL_CALIB_MAX; i++) { | 92 | for (i = 0; i < IWL_CALIB_MAX; i++) { |
@@ -95,6 +94,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
95 | priv->calib_results[i].buf) { | 94 | priv->calib_results[i].buf) { |
96 | hcmd.len[0] = priv->calib_results[i].buf_len; | 95 | hcmd.len[0] = priv->calib_results[i].buf_len; |
97 | hcmd.data[0] = priv->calib_results[i].buf; | 96 | hcmd.data[0] = priv->calib_results[i].buf; |
97 | hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
98 | ret = iwl_send_cmd_sync(priv, &hcmd); | 98 | ret = iwl_send_cmd_sync(priv, &hcmd); |
99 | if (ret) { | 99 | if (ret) { |
100 | IWL_ERR(priv, "Error %d iteration %d\n", | 100 | IWL_ERR(priv, "Error %d iteration %d\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 576f45e9ab9f..f803fb62f8bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1141,7 +1141,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1141 | struct iwl_host_cmd cmd = { | 1141 | struct iwl_host_cmd cmd = { |
1142 | .id = REPLY_SCAN_CMD, | 1142 | .id = REPLY_SCAN_CMD, |
1143 | .len = { sizeof(struct iwl_scan_cmd), }, | 1143 | .len = { sizeof(struct iwl_scan_cmd), }, |
1144 | .flags = CMD_SIZE_HUGE, | ||
1145 | }; | 1144 | }; |
1146 | struct iwl_scan_cmd *scan; | 1145 | struct iwl_scan_cmd *scan; |
1147 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 1146 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
@@ -1428,6 +1427,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1428 | cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + | 1427 | cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + |
1429 | scan->channel_count * sizeof(struct iwl_scan_channel); | 1428 | scan->channel_count * sizeof(struct iwl_scan_channel); |
1430 | cmd.data[0] = scan; | 1429 | cmd.data[0] = scan; |
1430 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
1431 | scan->len = cpu_to_le16(cmd.len[0]); | 1431 | scan->len = cpu_to_le16(cmd.len[0]); |
1432 | 1432 | ||
1433 | /* set scan bit here for PAN params */ | 1433 | /* set scan bit here for PAN params */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2bb08d7e0674..675b9a644a0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
134 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 134 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
135 | struct iwl_host_cmd cmd = { | 135 | struct iwl_host_cmd cmd = { |
136 | .id = REPLY_TX_BEACON, | 136 | .id = REPLY_TX_BEACON, |
137 | .flags = CMD_SIZE_HUGE, | ||
138 | }; | 137 | }; |
139 | u32 frame_size; | 138 | u32 frame_size; |
140 | u32 rate_flags; | 139 | u32 rate_flags; |
141 | u32 rate; | 140 | u32 rate; |
142 | int err; | ||
143 | 141 | ||
144 | /* | 142 | /* |
145 | * We have to set up the TX command, the TX Beacon command, and the | 143 | * We have to set up the TX command, the TX Beacon command, and the |
@@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
156 | if (WARN_ON(!priv->beacon_skb)) | 154 | if (WARN_ON(!priv->beacon_skb)) |
157 | return -EINVAL; | 155 | return -EINVAL; |
158 | 156 | ||
159 | /* Allocate beacon memory */ | 157 | /* Allocate beacon command */ |
160 | tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, | 158 | if (!priv->beacon_cmd) |
161 | GFP_KERNEL); | 159 | priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL); |
160 | tx_beacon_cmd = priv->beacon_cmd; | ||
162 | if (!tx_beacon_cmd) | 161 | if (!tx_beacon_cmd) |
163 | return -ENOMEM; | 162 | return -ENOMEM; |
164 | 163 | ||
165 | frame_size = priv->beacon_skb->len; | 164 | frame_size = priv->beacon_skb->len; |
166 | 165 | ||
167 | /* Set up TX beacon contents */ | ||
168 | memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); | ||
169 | |||
170 | /* Set up TX command fields */ | 166 | /* Set up TX command fields */ |
171 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 167 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
172 | tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; | 168 | tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; |
@@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
175 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | 171 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; |
176 | 172 | ||
177 | /* Set up TX beacon command fields */ | 173 | /* Set up TX beacon command fields */ |
178 | iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, | 174 | iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data, |
179 | frame_size); | 175 | frame_size); |
180 | 176 | ||
181 | /* Set up packet rate and flags */ | 177 | /* Set up packet rate and flags */ |
@@ -189,15 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
189 | rate_flags); | 185 | rate_flags); |
190 | 186 | ||
191 | /* Submit command */ | 187 | /* Submit command */ |
192 | cmd.len[0] = sizeof(*tx_beacon_cmd) + frame_size; | 188 | cmd.len[0] = sizeof(*tx_beacon_cmd); |
193 | cmd.data[0] = tx_beacon_cmd; | 189 | cmd.data[0] = tx_beacon_cmd; |
190 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
191 | cmd.len[1] = frame_size; | ||
192 | cmd.data[1] = priv->beacon_skb->data; | ||
193 | cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; | ||
194 | 194 | ||
195 | err = iwl_send_cmd_sync(priv, &cmd); | 195 | return iwl_send_cmd_sync(priv, &cmd); |
196 | |||
197 | /* Free temporary storage */ | ||
198 | kfree(tx_beacon_cmd); | ||
199 | |||
200 | return err; | ||
201 | } | 196 | } |
202 | 197 | ||
203 | static void iwl_bg_beacon_update(struct work_struct *work) | 198 | static void iwl_bg_beacon_update(struct work_struct *work) |
@@ -3246,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3246 | iwlcore_free_geos(priv); | 3241 | iwlcore_free_geos(priv); |
3247 | iwl_free_channel_map(priv); | 3242 | iwl_free_channel_map(priv); |
3248 | kfree(priv->scan_cmd); | 3243 | kfree(priv->scan_cmd); |
3244 | kfree(priv->beacon_cmd); | ||
3249 | } | 3245 | } |
3250 | 3246 | ||
3251 | struct ieee80211_ops iwlagn_hw_ops = { | 3247 | struct ieee80211_ops iwlagn_hw_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 5fdad6532118..6ee5f1aa555c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -205,7 +205,6 @@ enum { | |||
205 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) | 205 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) |
206 | #define SEQ_TO_INDEX(s) ((s) & 0xff) | 206 | #define SEQ_TO_INDEX(s) ((s) & 0xff) |
207 | #define INDEX_TO_SEQ(i) ((i) & 0xff) | 207 | #define INDEX_TO_SEQ(i) ((i) & 0xff) |
208 | #define SEQ_HUGE_FRAME cpu_to_le16(0x4000) | ||
209 | #define SEQ_RX_FRAME cpu_to_le16(0x8000) | 208 | #define SEQ_RX_FRAME cpu_to_le16(0x8000) |
210 | 209 | ||
211 | /** | 210 | /** |
@@ -234,9 +233,7 @@ struct iwl_cmd_header { | |||
234 | * | 233 | * |
235 | * 0:7 tfd index - position within TX queue | 234 | * 0:7 tfd index - position within TX queue |
236 | * 8:12 TX queue id | 235 | * 8:12 TX queue id |
237 | * 13 reserved | 236 | * 13:14 reserved |
238 | * 14 huge - driver sets this to indicate command is in the | ||
239 | * 'huge' storage at the end of the command buffers | ||
240 | * 15 unsolicited RX or uCode-originated notification | 237 | * 15 unsolicited RX or uCode-originated notification |
241 | */ | 238 | */ |
242 | __le16 sequence; | 239 | __le16 sequence; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 38254bdfabbb..3e3b8b8939d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -110,8 +110,6 @@ struct iwl_cmd_meta { | |||
110 | struct iwl_device_cmd *cmd, | 110 | struct iwl_device_cmd *cmd, |
111 | struct iwl_rx_packet *pkt); | 111 | struct iwl_rx_packet *pkt); |
112 | 112 | ||
113 | /* The CMD_SIZE_HUGE flag bit indicates that the command | ||
114 | * structure is stored at the end of the shared queue memory. */ | ||
115 | u32 flags; | 113 | u32 flags; |
116 | 114 | ||
117 | DEFINE_DMA_UNMAP_ADDR(mapping); | 115 | DEFINE_DMA_UNMAP_ADDR(mapping); |
@@ -121,7 +119,23 @@ struct iwl_cmd_meta { | |||
121 | /* | 119 | /* |
122 | * Generic queue structure | 120 | * Generic queue structure |
123 | * | 121 | * |
124 | * Contains common data for Rx and Tx queues | 122 | * Contains common data for Rx and Tx queues. |
123 | * | ||
124 | * Note the difference between n_bd and n_window: the hardware | ||
125 | * always assumes 256 descriptors, so n_bd is always 256 (unless | ||
126 | * there might be HW changes in the future). For the normal TX | ||
127 | * queues, n_window, which is the size of the software queue data | ||
128 | * is also 256; however, for the command queue, n_window is only | ||
129 | * 32 since we don't need so many commands pending. Since the HW | ||
130 | * still uses 256 BDs for DMA though, n_bd stays 256. As a result, | ||
131 | * the software buffers (in the variables @meta, @txb in struct | ||
132 | * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds | ||
133 | * in the same struct) have 256. | ||
134 | * This means that we end up with the following: | ||
135 | * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | | ||
136 | * SW entries: | 0 | ... | 31 | | ||
137 | * where N is a number between 0 and 7. This means that the SW | ||
138 | * data is a window overlayed over the HW queue. | ||
125 | */ | 139 | */ |
126 | struct iwl_queue { | 140 | struct iwl_queue { |
127 | int n_bd; /* number of BDs in this queue */ | 141 | int n_bd; /* number of BDs in this queue */ |
@@ -163,7 +177,7 @@ struct iwl_tx_info { | |||
163 | 177 | ||
164 | struct iwl_tx_queue { | 178 | struct iwl_tx_queue { |
165 | struct iwl_queue q; | 179 | struct iwl_queue q; |
166 | void *tfds; | 180 | struct iwl_tfd *tfds; |
167 | struct iwl_device_cmd **cmd; | 181 | struct iwl_device_cmd **cmd; |
168 | struct iwl_cmd_meta *meta; | 182 | struct iwl_cmd_meta *meta; |
169 | struct iwl_tx_info *txb; | 183 | struct iwl_tx_info *txb; |
@@ -245,7 +259,6 @@ enum { | |||
245 | CMD_SYNC = 0, | 259 | CMD_SYNC = 0, |
246 | CMD_SIZE_NORMAL = 0, | 260 | CMD_SIZE_NORMAL = 0, |
247 | CMD_NO_SKB = 0, | 261 | CMD_NO_SKB = 0, |
248 | CMD_SIZE_HUGE = (1 << 0), | ||
249 | CMD_ASYNC = (1 << 1), | 262 | CMD_ASYNC = (1 << 1), |
250 | CMD_WANT_SKB = (1 << 2), | 263 | CMD_WANT_SKB = (1 << 2), |
251 | CMD_MAPPED = (1 << 3), | 264 | CMD_MAPPED = (1 << 3), |
@@ -257,8 +270,8 @@ enum { | |||
257 | * struct iwl_device_cmd | 270 | * struct iwl_device_cmd |
258 | * | 271 | * |
259 | * For allocation of the command and tx queues, this establishes the overall | 272 | * For allocation of the command and tx queues, this establishes the overall |
260 | * size of the largest command we send to uCode, except for a scan command | 273 | * size of the largest command we send to uCode, except for commands that |
261 | * (which is relatively huge; space is allocated separately). | 274 | * aren't fully copied and use other TFD space. |
262 | */ | 275 | */ |
263 | struct iwl_device_cmd { | 276 | struct iwl_device_cmd { |
264 | struct iwl_cmd_header hdr; /* uCode API */ | 277 | struct iwl_cmd_header hdr; /* uCode API */ |
@@ -275,7 +288,11 @@ struct iwl_device_cmd { | |||
275 | 288 | ||
276 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) | 289 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) |
277 | 290 | ||
278 | #define IWL_MAX_CMD_TFDS 1 | 291 | #define IWL_MAX_CMD_TFDS 2 |
292 | |||
293 | enum iwl_hcmd_dataflag { | ||
294 | IWL_HCMD_DFL_NOCOPY = BIT(0), | ||
295 | }; | ||
279 | 296 | ||
280 | struct iwl_host_cmd { | 297 | struct iwl_host_cmd { |
281 | const void *data[IWL_MAX_CMD_TFDS]; | 298 | const void *data[IWL_MAX_CMD_TFDS]; |
@@ -285,6 +302,7 @@ struct iwl_host_cmd { | |||
285 | struct iwl_rx_packet *pkt); | 302 | struct iwl_rx_packet *pkt); |
286 | u32 flags; | 303 | u32 flags; |
287 | u16 len[IWL_MAX_CMD_TFDS]; | 304 | u16 len[IWL_MAX_CMD_TFDS]; |
305 | u8 dataflags[IWL_MAX_CMD_TFDS]; | ||
288 | u8 id; | 306 | u8 id; |
289 | }; | 307 | }; |
290 | 308 | ||
@@ -687,17 +705,8 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i) | |||
687 | } | 705 | } |
688 | 706 | ||
689 | 707 | ||
690 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | 708 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) |
691 | { | 709 | { |
692 | /* | ||
693 | * This is for init calibration result and scan command which | ||
694 | * required buffer > TFD_MAX_PAYLOAD_SIZE, | ||
695 | * the big buffer at end of command array | ||
696 | */ | ||
697 | if (is_huge) | ||
698 | return q->n_window; /* must be power of 2 */ | ||
699 | |||
700 | /* Otherwise, use normal size buffers */ | ||
701 | return index & (q->n_window - 1); | 710 | return index & (q->n_window - 1); |
702 | } | 711 | } |
703 | 712 | ||
@@ -1451,6 +1460,7 @@ struct iwl_priv { | |||
1451 | struct work_struct beacon_update; | 1460 | struct work_struct beacon_update; |
1452 | struct iwl_rxon_context *beacon_ctx; | 1461 | struct iwl_rxon_context *beacon_ctx; |
1453 | struct sk_buff *beacon_skb; | 1462 | struct sk_buff *beacon_skb; |
1463 | void *beacon_cmd; | ||
1454 | 1464 | ||
1455 | struct work_struct tt_work; | 1465 | struct work_struct tt_work; |
1456 | struct work_struct ct_enter; | 1466 | struct work_struct ct_enter; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index f00172cb8a6d..fc131867c10b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -137,20 +137,27 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, | |||
137 | #define TRACE_SYSTEM iwlwifi | 137 | #define TRACE_SYSTEM iwlwifi |
138 | 138 | ||
139 | TRACE_EVENT(iwlwifi_dev_hcmd, | 139 | TRACE_EVENT(iwlwifi_dev_hcmd, |
140 | TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), | 140 | TP_PROTO(struct iwl_priv *priv, u32 flags, |
141 | TP_ARGS(priv, hcmd, len, flags), | 141 | const void *hcmd0, size_t len0, |
142 | const void *hcmd1, size_t len1, | ||
143 | const void *hcmd2, size_t len2), | ||
144 | TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2), | ||
142 | TP_STRUCT__entry( | 145 | TP_STRUCT__entry( |
143 | PRIV_ENTRY | 146 | PRIV_ENTRY |
144 | __dynamic_array(u8, hcmd, len) | 147 | __dynamic_array(u8, hcmd0, len0) |
148 | __dynamic_array(u8, hcmd1, len1) | ||
149 | __dynamic_array(u8, hcmd2, len2) | ||
145 | __field(u32, flags) | 150 | __field(u32, flags) |
146 | ), | 151 | ), |
147 | TP_fast_assign( | 152 | TP_fast_assign( |
148 | PRIV_ASSIGN; | 153 | PRIV_ASSIGN; |
149 | memcpy(__get_dynamic_array(hcmd), hcmd, len); | 154 | memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); |
155 | memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); | ||
156 | memcpy(__get_dynamic_array(hcmd2), hcmd2, len2); | ||
150 | __entry->flags = flags; | 157 | __entry->flags = flags; |
151 | ), | 158 | ), |
152 | TP_printk("[%p] hcmd %#.2x (%ssync)", | 159 | TP_printk("[%p] hcmd %#.2x (%ssync)", |
153 | __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], | 160 | __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0], |
154 | __entry->flags & CMD_ASYNC ? "a" : "") | 161 | __entry->flags & CMD_ASYNC ? "a" : "") |
155 | ); | 162 | ); |
156 | 163 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 01a8ec9cd6b2..dd2904aa9be2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c | |||
@@ -200,6 +200,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) | |||
200 | cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); | 200 | cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); |
201 | cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | 201 | cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); |
202 | cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | 202 | cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); |
203 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
203 | IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," | 204 | IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," |
204 | " len %d\n", cmd.id, cmd.flags, cmd.len[0]); | 205 | " len %d\n", cmd.id, cmd.flags, cmd.len[0]); |
205 | /* ok, let's submit the command to ucode */ | 206 | /* ok, let's submit the command to ucode */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a47558f0ee3d..2f6b38cfcc13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -125,25 +125,13 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) | |||
125 | return tfd->num_tbs & 0x1f; | 125 | return tfd->num_tbs & 0x1f; |
126 | } | 126 | } |
127 | 127 | ||
128 | /** | 128 | static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, |
129 | * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | 129 | struct iwl_tfd *tfd) |
130 | * @priv - driver private data | ||
131 | * @txq - tx queue | ||
132 | * | ||
133 | * Does NOT advance any TFD circular buffer read/write indexes | ||
134 | * Does NOT free the TFD itself (which is within circular buffer) | ||
135 | */ | ||
136 | void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
137 | { | 130 | { |
138 | struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; | ||
139 | struct iwl_tfd *tfd; | ||
140 | struct pci_dev *dev = priv->pci_dev; | 131 | struct pci_dev *dev = priv->pci_dev; |
141 | int index = txq->q.read_ptr; | ||
142 | int i; | 132 | int i; |
143 | int num_tbs; | 133 | int num_tbs; |
144 | 134 | ||
145 | tfd = &tfd_tmp[index]; | ||
146 | |||
147 | /* Sanity check on number of chunks */ | 135 | /* Sanity check on number of chunks */ |
148 | num_tbs = iwl_tfd_get_num_tbs(tfd); | 136 | num_tbs = iwl_tfd_get_num_tbs(tfd); |
149 | 137 | ||
@@ -156,14 +144,30 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
156 | /* Unmap tx_cmd */ | 144 | /* Unmap tx_cmd */ |
157 | if (num_tbs) | 145 | if (num_tbs) |
158 | pci_unmap_single(dev, | 146 | pci_unmap_single(dev, |
159 | dma_unmap_addr(&txq->meta[index], mapping), | 147 | dma_unmap_addr(meta, mapping), |
160 | dma_unmap_len(&txq->meta[index], len), | 148 | dma_unmap_len(meta, len), |
161 | PCI_DMA_BIDIRECTIONAL); | 149 | PCI_DMA_BIDIRECTIONAL); |
162 | 150 | ||
163 | /* Unmap chunks, if any. */ | 151 | /* Unmap chunks, if any. */ |
164 | for (i = 1; i < num_tbs; i++) | 152 | for (i = 1; i < num_tbs; i++) |
165 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | 153 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), |
166 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | 154 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); |
155 | } | ||
156 | |||
157 | /** | ||
158 | * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | ||
159 | * @priv - driver private data | ||
160 | * @txq - tx queue | ||
161 | * | ||
162 | * Does NOT advance any TFD circular buffer read/write indexes | ||
163 | * Does NOT free the TFD itself (which is within circular buffer) | ||
164 | */ | ||
165 | void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
166 | { | ||
167 | struct iwl_tfd *tfd_tmp = txq->tfds; | ||
168 | int index = txq->q.read_ptr; | ||
169 | |||
170 | iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]); | ||
167 | 171 | ||
168 | /* free SKB */ | 172 | /* free SKB */ |
169 | if (txq->txb) { | 173 | if (txq->txb) { |
@@ -189,7 +193,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
189 | u32 num_tbs; | 193 | u32 num_tbs; |
190 | 194 | ||
191 | q = &txq->q; | 195 | q = &txq->q; |
192 | tfd_tmp = (struct iwl_tfd *)txq->tfds; | 196 | tfd_tmp = txq->tfds; |
193 | tfd = &tfd_tmp[q->write_ptr]; | 197 | tfd = &tfd_tmp[q->write_ptr]; |
194 | 198 | ||
195 | if (reset) | 199 | if (reset) |
@@ -303,7 +307,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) | |||
303 | return; | 307 | return; |
304 | 308 | ||
305 | while (q->read_ptr != q->write_ptr) { | 309 | while (q->read_ptr != q->write_ptr) { |
306 | i = get_cmd_index(q, q->read_ptr, 0); | 310 | i = get_cmd_index(q, q->read_ptr); |
307 | 311 | ||
308 | if (txq->meta[i].flags & CMD_MAPPED) { | 312 | if (txq->meta[i].flags & CMD_MAPPED) { |
309 | pci_unmap_single(priv->pci_dev, | 313 | pci_unmap_single(priv->pci_dev, |
@@ -315,15 +319,6 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) | |||
315 | 319 | ||
316 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 320 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
317 | } | 321 | } |
318 | |||
319 | i = q->n_window; | ||
320 | if (txq->meta[i].flags & CMD_MAPPED) { | ||
321 | pci_unmap_single(priv->pci_dev, | ||
322 | dma_unmap_addr(&txq->meta[i], mapping), | ||
323 | dma_unmap_len(&txq->meta[i], len), | ||
324 | PCI_DMA_BIDIRECTIONAL); | ||
325 | txq->meta[i].flags = 0; | ||
326 | } | ||
327 | } | 322 | } |
328 | 323 | ||
329 | /** | 324 | /** |
@@ -343,7 +338,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
343 | iwl_cmd_queue_unmap(priv); | 338 | iwl_cmd_queue_unmap(priv); |
344 | 339 | ||
345 | /* De-alloc array of command/tx buffers */ | 340 | /* De-alloc array of command/tx buffers */ |
346 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 341 | for (i = 0; i < TFD_CMD_SLOTS; i++) |
347 | kfree(txq->cmd[i]); | 342 | kfree(txq->cmd[i]); |
348 | 343 | ||
349 | /* De-alloc circular buffer of TFDs */ | 344 | /* De-alloc circular buffer of TFDs */ |
@@ -483,33 +478,17 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
483 | { | 478 | { |
484 | int i, len; | 479 | int i, len; |
485 | int ret; | 480 | int ret; |
486 | int actual_slots = slots_num; | ||
487 | |||
488 | /* | ||
489 | * Alloc buffer array for commands (Tx or other types of commands). | ||
490 | * For the command queue (#4/#9), allocate command space + one big | ||
491 | * command for scan, since scan command is very huge; the system will | ||
492 | * not have two scans at the same time, so only one is needed. | ||
493 | * For normal Tx queues (all other queues), no super-size command | ||
494 | * space is needed. | ||
495 | */ | ||
496 | if (txq_id == priv->cmd_queue) | ||
497 | actual_slots++; | ||
498 | 481 | ||
499 | txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, | 482 | txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num, |
500 | GFP_KERNEL); | 483 | GFP_KERNEL); |
501 | txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots, | 484 | txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num, |
502 | GFP_KERNEL); | 485 | GFP_KERNEL); |
503 | 486 | ||
504 | if (!txq->meta || !txq->cmd) | 487 | if (!txq->meta || !txq->cmd) |
505 | goto out_free_arrays; | 488 | goto out_free_arrays; |
506 | 489 | ||
507 | len = sizeof(struct iwl_device_cmd); | 490 | len = sizeof(struct iwl_device_cmd); |
508 | for (i = 0; i < actual_slots; i++) { | 491 | for (i = 0; i < slots_num; i++) { |
509 | /* only happens for cmd queue */ | ||
510 | if (i == slots_num) | ||
511 | len = IWL_MAX_CMD_SIZE; | ||
512 | |||
513 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); | 492 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); |
514 | if (!txq->cmd[i]) | 493 | if (!txq->cmd[i]) |
515 | goto err; | 494 | goto err; |
@@ -544,7 +523,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
544 | 523 | ||
545 | return 0; | 524 | return 0; |
546 | err: | 525 | err: |
547 | for (i = 0; i < actual_slots; i++) | 526 | for (i = 0; i < slots_num; i++) |
548 | kfree(txq->cmd[i]); | 527 | kfree(txq->cmd[i]); |
549 | out_free_arrays: | 528 | out_free_arrays: |
550 | kfree(txq->meta); | 529 | kfree(txq->meta); |
@@ -592,23 +571,44 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
592 | dma_addr_t phys_addr; | 571 | dma_addr_t phys_addr; |
593 | unsigned long flags; | 572 | unsigned long flags; |
594 | u32 idx; | 573 | u32 idx; |
595 | u16 fix_size; | 574 | u16 copy_size, cmd_size; |
596 | bool is_ct_kill = false; | 575 | bool is_ct_kill = false; |
576 | bool had_nocopy = false; | ||
577 | int i; | ||
578 | u8 *cmd_dest; | ||
579 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING | ||
580 | const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {}; | ||
581 | int trace_lens[IWL_MAX_CMD_TFDS + 1] = {}; | ||
582 | int trace_idx; | ||
583 | #endif | ||
597 | 584 | ||
598 | fix_size = (u16)(cmd->len[0] + sizeof(out_cmd->hdr)); | 585 | copy_size = sizeof(out_cmd->hdr); |
586 | cmd_size = sizeof(out_cmd->hdr); | ||
587 | |||
588 | /* need one for the header if the first is NOCOPY */ | ||
589 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); | ||
590 | |||
591 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | ||
592 | if (!cmd->len[i]) | ||
593 | continue; | ||
594 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { | ||
595 | had_nocopy = true; | ||
596 | } else { | ||
597 | /* NOCOPY must not be followed by normal! */ | ||
598 | if (WARN_ON(had_nocopy)) | ||
599 | return -EINVAL; | ||
600 | copy_size += cmd->len[i]; | ||
601 | } | ||
602 | cmd_size += cmd->len[i]; | ||
603 | } | ||
599 | 604 | ||
600 | /* | 605 | /* |
601 | * If any of the command structures end up being larger than | 606 | * If any of the command structures end up being larger than |
602 | * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then | 607 | * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically |
603 | * we will need to increase the size of the TFD entries | 608 | * allocated into separate TFDs, then we will need to |
604 | * Also, check to see if command buffer should not exceed the size | 609 | * increase the size of the buffers. |
605 | * of device_cmd and max_cmd_size. | ||
606 | */ | 610 | */ |
607 | if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && | 611 | if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) |
608 | !(cmd->flags & CMD_SIZE_HUGE))) | ||
609 | return -EINVAL; | ||
610 | |||
611 | if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) | ||
612 | return -EINVAL; | 612 | return -EINVAL; |
613 | 613 | ||
614 | if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { | 614 | if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { |
@@ -617,14 +617,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
617 | return -EIO; | 617 | return -EIO; |
618 | } | 618 | } |
619 | 619 | ||
620 | /* | ||
621 | * As we only have a single huge buffer, check that the command | ||
622 | * is synchronous (otherwise buffers could end up being reused). | ||
623 | */ | ||
624 | |||
625 | if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) | ||
626 | return -EINVAL; | ||
627 | |||
628 | spin_lock_irqsave(&priv->hcmd_lock, flags); | 620 | spin_lock_irqsave(&priv->hcmd_lock, flags); |
629 | 621 | ||
630 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 622 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
@@ -639,7 +631,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
639 | return -ENOSPC; | 631 | return -ENOSPC; |
640 | } | 632 | } |
641 | 633 | ||
642 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); | 634 | idx = get_cmd_index(q, q->write_ptr); |
643 | out_cmd = txq->cmd[idx]; | 635 | out_cmd = txq->cmd[idx]; |
644 | out_meta = &txq->meta[idx]; | 636 | out_meta = &txq->meta[idx]; |
645 | 637 | ||
@@ -654,55 +646,84 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
654 | if (cmd->flags & CMD_ASYNC) | 646 | if (cmd->flags & CMD_ASYNC) |
655 | out_meta->callback = cmd->callback; | 647 | out_meta->callback = cmd->callback; |
656 | 648 | ||
657 | out_cmd->hdr.cmd = cmd->id; | 649 | /* set up the header */ |
658 | memcpy(&out_cmd->cmd.payload, cmd->data[0], cmd->len[0]); | ||
659 | |||
660 | /* At this point, the out_cmd now has all of the incoming cmd | ||
661 | * information */ | ||
662 | 650 | ||
651 | out_cmd->hdr.cmd = cmd->id; | ||
663 | out_cmd->hdr.flags = 0; | 652 | out_cmd->hdr.flags = 0; |
664 | out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | | 653 | out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | |
665 | INDEX_TO_SEQ(q->write_ptr)); | 654 | INDEX_TO_SEQ(q->write_ptr)); |
666 | if (cmd->flags & CMD_SIZE_HUGE) | 655 | |
667 | out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; | 656 | /* and copy the data that needs to be copied */ |
668 | 657 | ||
669 | #ifdef CONFIG_IWLWIFI_DEBUG | 658 | cmd_dest = &out_cmd->cmd.payload[0]; |
670 | switch (out_cmd->hdr.cmd) { | 659 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
671 | case REPLY_TX_LINK_QUALITY_CMD: | 660 | if (!cmd->len[i]) |
672 | case SENSITIVITY_CMD: | 661 | continue; |
673 | IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " | 662 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) |
674 | "%d bytes at %d[%d]:%d\n", | 663 | break; |
675 | get_cmd_string(out_cmd->hdr.cmd), | 664 | memcpy(cmd_dest, cmd->data[i], cmd->len[i]); |
676 | out_cmd->hdr.cmd, | 665 | cmd_dest += cmd->len[i]; |
677 | le16_to_cpu(out_cmd->hdr.sequence), fix_size, | ||
678 | q->write_ptr, idx, priv->cmd_queue); | ||
679 | break; | ||
680 | default: | ||
681 | IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " | ||
682 | "%d bytes at %d[%d]:%d\n", | ||
683 | get_cmd_string(out_cmd->hdr.cmd), | ||
684 | out_cmd->hdr.cmd, | ||
685 | le16_to_cpu(out_cmd->hdr.sequence), fix_size, | ||
686 | q->write_ptr, idx, priv->cmd_queue); | ||
687 | } | 666 | } |
688 | #endif | 667 | |
668 | IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " | ||
669 | "%d bytes at %d[%d]:%d\n", | ||
670 | get_cmd_string(out_cmd->hdr.cmd), | ||
671 | out_cmd->hdr.cmd, | ||
672 | le16_to_cpu(out_cmd->hdr.sequence), cmd_size, | ||
673 | q->write_ptr, idx, priv->cmd_queue); | ||
674 | |||
689 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, | 675 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, |
690 | fix_size, PCI_DMA_BIDIRECTIONAL); | 676 | copy_size, PCI_DMA_BIDIRECTIONAL); |
691 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { | 677 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { |
692 | idx = -ENOMEM; | 678 | idx = -ENOMEM; |
693 | goto out; | 679 | goto out; |
694 | } | 680 | } |
695 | 681 | ||
696 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 682 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
697 | dma_unmap_len_set(out_meta, len, fix_size); | 683 | dma_unmap_len_set(out_meta, len, copy_size); |
684 | |||
685 | iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); | ||
686 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING | ||
687 | trace_bufs[0] = &out_cmd->hdr; | ||
688 | trace_lens[0] = copy_size; | ||
689 | trace_idx = 1; | ||
690 | #endif | ||
691 | |||
692 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | ||
693 | if (!cmd->len[i]) | ||
694 | continue; | ||
695 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | ||
696 | continue; | ||
697 | phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], | ||
698 | cmd->len[i], PCI_DMA_TODEVICE); | ||
699 | if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { | ||
700 | iwlagn_unmap_tfd(priv, out_meta, | ||
701 | &txq->tfds[q->write_ptr]); | ||
702 | idx = -ENOMEM; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
706 | iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, | ||
707 | cmd->len[i], 0); | ||
708 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING | ||
709 | trace_bufs[trace_idx] = cmd->data[i]; | ||
710 | trace_lens[trace_idx] = cmd->len[i]; | ||
711 | trace_idx++; | ||
712 | #endif | ||
713 | } | ||
698 | 714 | ||
699 | out_meta->flags = cmd->flags | CMD_MAPPED; | 715 | out_meta->flags = cmd->flags | CMD_MAPPED; |
700 | 716 | ||
701 | txq->need_update = 1; | 717 | txq->need_update = 1; |
702 | 718 | ||
703 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 719 | /* check that tracing gets all possible blocks */ |
704 | 720 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); | |
705 | iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1); | 721 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING |
722 | trace_iwlwifi_dev_hcmd(priv, cmd->flags, | ||
723 | trace_bufs[0], trace_lens[0], | ||
724 | trace_bufs[1], trace_lens[1], | ||
725 | trace_bufs[2], trace_lens[2]); | ||
726 | #endif | ||
706 | 727 | ||
707 | /* Increment and update queue's write index */ | 728 | /* Increment and update queue's write index */ |
708 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 729 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
@@ -761,7 +782,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
761 | int txq_id = SEQ_TO_QUEUE(sequence); | 782 | int txq_id = SEQ_TO_QUEUE(sequence); |
762 | int index = SEQ_TO_INDEX(sequence); | 783 | int index = SEQ_TO_INDEX(sequence); |
763 | int cmd_index; | 784 | int cmd_index; |
764 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | ||
765 | struct iwl_device_cmd *cmd; | 785 | struct iwl_device_cmd *cmd; |
766 | struct iwl_cmd_meta *meta; | 786 | struct iwl_cmd_meta *meta; |
767 | struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; | 787 | struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; |
@@ -779,14 +799,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
779 | return; | 799 | return; |
780 | } | 800 | } |
781 | 801 | ||
782 | cmd_index = get_cmd_index(&txq->q, index, huge); | 802 | cmd_index = get_cmd_index(&txq->q, index); |
783 | cmd = txq->cmd[cmd_index]; | 803 | cmd = txq->cmd[cmd_index]; |
784 | meta = &txq->meta[cmd_index]; | 804 | meta = &txq->meta[cmd_index]; |
785 | 805 | ||
786 | pci_unmap_single(priv->pci_dev, | 806 | iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]); |
787 | dma_unmap_addr(meta, mapping), | ||
788 | dma_unmap_len(meta, len), | ||
789 | PCI_DMA_BIDIRECTIONAL); | ||
790 | 807 | ||
791 | /* Input error checking is done when commands are added to queue. */ | 808 | /* Input error checking is done when commands are added to queue. */ |
792 | if (meta->flags & CMD_WANT_SKB) { | 809 | if (meta->flags & CMD_WANT_SKB) { |