aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c231
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
203static void iwl_bg_beacon_update(struct work_struct *work) 198static 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
3251struct ieee80211_ops iwlagn_hw_ops = { 3247struct 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 */
126struct iwl_queue { 140struct 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
164struct iwl_tx_queue { 178struct 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 */
263struct iwl_device_cmd { 276struct 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
293enum iwl_hcmd_dataflag {
294 IWL_HCMD_DFL_NOCOPY = BIT(0),
295};
279 296
280struct iwl_host_cmd { 297struct 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
690static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) 708static 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
139TRACE_EVENT(iwlwifi_dev_hcmd, 139TRACE_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/** 128static 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 */
136void 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 */
165void 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;
546err: 525err:
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]);
549out_free_arrays: 528out_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) {