aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c250
1 files changed, 49 insertions, 201 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3ecc3198d9bf..e027f99f18a5 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,164 +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 = sizeof(*tx_beacon_cmd) + frame_size; 188 cmd.len[0] = sizeof(*tx_beacon_cmd);
193 cmd.data = tx_beacon_cmd; 189 cmd.data[0] = tx_beacon_cmd;
194 190 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
195 err = iwl_send_cmd_sync(priv, &cmd); 191 cmd.len[1] = frame_size;
196 192 cmd.data[1] = priv->beacon_skb->data;
197 /* Free temporary storage */ 193 cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
198 kfree(tx_beacon_cmd);
199
200 return err;
201}
202
203static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
204{
205 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
206 194
207 dma_addr_t addr = get_unaligned_le32(&tb->lo); 195 return iwl_send_cmd_sync(priv, &cmd);
208 if (sizeof(dma_addr_t) > sizeof(u32))
209 addr |=
210 ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
211
212 return addr;
213}
214
215static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
216{
217 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
218
219 return le16_to_cpu(tb->hi_n_len) >> 4;
220}
221
222static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
223 dma_addr_t addr, u16 len)
224{
225 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
226 u16 hi_n_len = len << 4;
227
228 put_unaligned_le32(addr, &tb->lo);
229 if (sizeof(dma_addr_t) > sizeof(u32))
230 hi_n_len |= ((addr >> 16) >> 16) & 0xF;
231
232 tb->hi_n_len = cpu_to_le16(hi_n_len);
233
234 tfd->num_tbs = idx + 1;
235}
236
237static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
238{
239 return tfd->num_tbs & 0x1f;
240}
241
242/**
243 * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
244 * @priv - driver private data
245 * @txq - tx queue
246 *
247 * Does NOT advance any TFD circular buffer read/write indexes
248 * Does NOT free the TFD itself (which is within circular buffer)
249 */
250void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
251{
252 struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
253 struct iwl_tfd *tfd;
254 struct pci_dev *dev = priv->pci_dev;
255 int index = txq->q.read_ptr;
256 int i;
257 int num_tbs;
258
259 tfd = &tfd_tmp[index];
260
261 /* Sanity check on number of chunks */
262 num_tbs = iwl_tfd_get_num_tbs(tfd);
263
264 if (num_tbs >= IWL_NUM_OF_TBS) {
265 IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
266 /* @todo issue fatal error, it is quite serious situation */
267 return;
268 }
269
270 /* Unmap tx_cmd */
271 if (num_tbs)
272 pci_unmap_single(dev,
273 dma_unmap_addr(&txq->meta[index], mapping),
274 dma_unmap_len(&txq->meta[index], len),
275 PCI_DMA_BIDIRECTIONAL);
276
277 /* Unmap chunks, if any. */
278 for (i = 1; i < num_tbs; i++)
279 pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
280 iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
281
282 /* free SKB */
283 if (txq->txb) {
284 struct sk_buff *skb;
285
286 skb = txq->txb[txq->q.read_ptr].skb;
287
288 /* can be called from irqs-disabled context */
289 if (skb) {
290 dev_kfree_skb_any(skb);
291 txq->txb[txq->q.read_ptr].skb = NULL;
292 }
293 }
294}
295
296int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
297 struct iwl_tx_queue *txq,
298 dma_addr_t addr, u16 len,
299 u8 reset, u8 pad)
300{
301 struct iwl_queue *q;
302 struct iwl_tfd *tfd, *tfd_tmp;
303 u32 num_tbs;
304
305 q = &txq->q;
306 tfd_tmp = (struct iwl_tfd *)txq->tfds;
307 tfd = &tfd_tmp[q->write_ptr];
308
309 if (reset)
310 memset(tfd, 0, sizeof(*tfd));
311
312 num_tbs = iwl_tfd_get_num_tbs(tfd);
313
314 /* Each TFD can point to a maximum 20 Tx buffers */
315 if (num_tbs >= IWL_NUM_OF_TBS) {
316 IWL_ERR(priv, "Error can not send more than %d chunks\n",
317 IWL_NUM_OF_TBS);
318 return -EINVAL;
319 }
320
321 if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
322 return -EINVAL;
323
324 if (unlikely(addr & ~IWL_TX_DMA_MASK))
325 IWL_ERR(priv, "Unaligned address = %llx\n",
326 (unsigned long long)addr);
327
328 iwl_tfd_set_tb(tfd, num_tbs, addr, len);
329
330 return 0;
331}
332
333/*
334 * Tell nic where to find circular buffer of Tx Frame Descriptors for
335 * given Tx queue, and enable the DMA channel used for that queue.
336 *
337 * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
338 * channels supported in hardware.
339 */
340int iwl_hw_tx_queue_init(struct iwl_priv *priv,
341 struct iwl_tx_queue *txq)
342{
343 int txq_id = txq->q.id;
344
345 /* Circular buffer (TFD queue in DRAM) physical base address */
346 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
347 txq->q.dma_addr >> 8);
348
349 return 0;
350} 196}
351 197
352static void iwl_bg_beacon_update(struct work_struct *work) 198static void iwl_bg_beacon_update(struct work_struct *work)
@@ -1776,10 +1622,7 @@ static const char *desc_lookup(u32 num)
1776 1622
1777void iwl_dump_nic_error_log(struct iwl_priv *priv) 1623void iwl_dump_nic_error_log(struct iwl_priv *priv)
1778{ 1624{
1779 u32 data2, line; 1625 u32 base;
1780 u32 desc, time, count, base, data1;
1781 u32 blink1, blink2, ilink1, ilink2;
1782 u32 pc, hcmd;
1783 struct iwl_error_event_table table; 1626 struct iwl_error_event_table table;
1784 1627
1785 base = priv->device_pointers.error_event_table; 1628 base = priv->device_pointers.error_event_table;
@@ -1802,37 +1645,40 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1802 1645
1803 iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); 1646 iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
1804 1647
1805 count = table.valid; 1648 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
1806
1807 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
1808 IWL_ERR(priv, "Start IWL Error Log Dump:\n"); 1649 IWL_ERR(priv, "Start IWL Error Log Dump:\n");
1809 IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", 1650 IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
1810 priv->status, count); 1651 priv->status, table.valid);
1811 } 1652 }
1812 1653
1813 desc = table.error_id; 1654 priv->isr_stats.err_code = table.error_id;
1814 priv->isr_stats.err_code = desc; 1655
1815 pc = table.pc; 1656 trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
1816 blink1 = table.blink1; 1657 table.data1, table.data2, table.line,
1817 blink2 = table.blink2; 1658 table.blink1, table.blink2, table.ilink1,
1818 ilink1 = table.ilink1; 1659 table.ilink2, table.bcon_time, table.gp1,
1819 ilink2 = table.ilink2; 1660 table.gp2, table.gp3, table.ucode_ver,
1820 data1 = table.data1; 1661 table.hw_ver, table.brd_ver);
1821 data2 = table.data2; 1662 IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
1822 line = table.line; 1663 desc_lookup(table.error_id));
1823 time = table.tsf_low; 1664 IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
1824 hcmd = table.hcmd; 1665 IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
1825 1666 IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
1826 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, 1667 IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
1827 blink1, blink2, ilink1, ilink2); 1668 IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
1828 1669 IWL_ERR(priv, "0x%08X | data1\n", table.data1);
1829 IWL_ERR(priv, "Desc Time " 1670 IWL_ERR(priv, "0x%08X | data2\n", table.data2);
1830 "data1 data2 line\n"); 1671 IWL_ERR(priv, "0x%08X | line\n", table.line);
1831 IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n", 1672 IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
1832 desc_lookup(desc), desc, time, data1, data2, line); 1673 IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
1833 IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); 1674 IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
1834 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", 1675 IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
1835 pc, blink1, blink2, ilink1, ilink2, hcmd); 1676 IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
1677 IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
1678 IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
1679 IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
1680 IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
1681 IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
1836} 1682}
1837 1683
1838#define EVENT_START_OFFSET (4 * sizeof(u32)) 1684#define EVENT_START_OFFSET (4 * sizeof(u32))
@@ -2114,8 +1960,8 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
2114 struct iwl_calib_cfg_cmd calib_cfg_cmd; 1960 struct iwl_calib_cfg_cmd calib_cfg_cmd;
2115 struct iwl_host_cmd cmd = { 1961 struct iwl_host_cmd cmd = {
2116 .id = CALIBRATION_CFG_CMD, 1962 .id = CALIBRATION_CFG_CMD,
2117 .len = sizeof(struct iwl_calib_cfg_cmd), 1963 .len = { sizeof(struct iwl_calib_cfg_cmd), },
2118 .data = &calib_cfg_cmd, 1964 .data = { &calib_cfg_cmd, },
2119 }; 1965 };
2120 1966
2121 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); 1967 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
@@ -3395,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
3395 iwlcore_free_geos(priv); 3241 iwlcore_free_geos(priv);
3396 iwl_free_channel_map(priv); 3242 iwl_free_channel_map(priv);
3397 kfree(priv->scan_cmd); 3243 kfree(priv->scan_cmd);
3244 kfree(priv->beacon_cmd);
3398} 3245}
3399 3246
3400struct ieee80211_ops iwlagn_hw_ops = { 3247struct ieee80211_ops iwlagn_hw_ops = {
@@ -3812,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3812 */ 3659 */
3813 set_bit(STATUS_EXIT_PENDING, &priv->status); 3660 set_bit(STATUS_EXIT_PENDING, &priv->status);
3814 3661
3662 iwl_testmode_cleanup(priv);
3815 iwl_leds_exit(priv); 3663 iwl_leds_exit(priv);
3816 3664
3817 if (priv->mac80211_registered) { 3665 if (priv->mac80211_registered) {