aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-03-16 20:47:58 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-03-25 14:18:37 -0400
commite04ed0a5bb62520345c73587d7ebf51e426642ee (patch)
tree66486c421699b3dab4c1a28e71353dbb098a2745
parent741a626627e42812afd957f875c34c89be8a103e (diff)
iwlwifi: move agn common code to iwlagn library file
Multiple iwlagn based devices share the same common functions. Move those functions from iwl-5000.c to iwl-agn-lib.c file. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c394
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c56
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c377
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h14
7 files changed, 464 insertions, 416 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index fec44cf3c0a..a684a72eb6e 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -11,6 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
11obj-$(CONFIG_IWLAGN) += iwlagn.o 11obj-$(CONFIG_IWLAGN) += iwlagn.o
12iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o 12iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
13iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o 13iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
14iwlagn-objs += iwl-agn-lib.o
14 15
15iwlagn-$(CONFIG_IWL4965) += iwl-4965.o 16iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
16iwlagn-$(CONFIG_IWL5000) += iwl-5000.o 17iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 9d211606c04..a99945be6d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -170,9 +170,9 @@ static struct iwl_lib_ops iwl1000_lib = {
170 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, 170 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
171 .txq_free_tfd = iwl_hw_txq_free_tfd, 171 .txq_free_tfd = iwl_hw_txq_free_tfd,
172 .txq_init = iwl_hw_tx_queue_init, 172 .txq_init = iwl_hw_tx_queue_init,
173 .rx_handler_setup = iwl5000_rx_handler_setup, 173 .rx_handler_setup = iwlagn_rx_handler_setup,
174 .setup_deferred_work = iwl5000_setup_deferred_work, 174 .setup_deferred_work = iwlagn_setup_deferred_work,
175 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 175 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
176 .load_ucode = iwlagn_load_ucode, 176 .load_ucode = iwlagn_load_ucode,
177 .dump_nic_event_log = iwl_dump_nic_event_log, 177 .dump_nic_event_log = iwl_dump_nic_event_log,
178 .dump_nic_error_log = iwl_dump_nic_error_log, 178 .dump_nic_error_log = iwl_dump_nic_error_log,
@@ -180,7 +180,7 @@ static struct iwl_lib_ops iwl1000_lib = {
180 .dump_fh = iwl_dump_fh, 180 .dump_fh = iwl_dump_fh,
181 .init_alive_start = iwlagn_init_alive_start, 181 .init_alive_start = iwlagn_init_alive_start,
182 .alive_notify = iwlagn_alive_notify, 182 .alive_notify = iwlagn_alive_notify,
183 .send_tx_power = iwl5000_send_tx_power, 183 .send_tx_power = iwlagn_send_tx_power,
184 .update_chain_flags = iwl_update_chain_flags, 184 .update_chain_flags = iwl_update_chain_flags,
185 .apm_ops = { 185 .apm_ops = {
186 .init = iwl_apm_init, 186 .init = iwl_apm_init,
@@ -190,25 +190,25 @@ static struct iwl_lib_ops iwl1000_lib = {
190 }, 190 },
191 .eeprom_ops = { 191 .eeprom_ops = {
192 .regulatory_bands = { 192 .regulatory_bands = {
193 EEPROM_5000_REG_BAND_1_CHANNELS, 193 EEPROM_REG_BAND_1_CHANNELS,
194 EEPROM_5000_REG_BAND_2_CHANNELS, 194 EEPROM_REG_BAND_2_CHANNELS,
195 EEPROM_5000_REG_BAND_3_CHANNELS, 195 EEPROM_REG_BAND_3_CHANNELS,
196 EEPROM_5000_REG_BAND_4_CHANNELS, 196 EEPROM_REG_BAND_4_CHANNELS,
197 EEPROM_5000_REG_BAND_5_CHANNELS, 197 EEPROM_REG_BAND_5_CHANNELS,
198 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 198 EEPROM_REG_BAND_24_HT40_CHANNELS,
199 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 199 EEPROM_REG_BAND_52_HT40_CHANNELS
200 }, 200 },
201 .verify_signature = iwlcore_eeprom_verify_signature, 201 .verify_signature = iwlcore_eeprom_verify_signature,
202 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 202 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
203 .release_semaphore = iwlcore_eeprom_release_semaphore, 203 .release_semaphore = iwlcore_eeprom_release_semaphore,
204 .calib_version = iwl5000_eeprom_calib_version, 204 .calib_version = iwlagn_eeprom_calib_version,
205 .query_addr = iwl5000_eeprom_query_addr, 205 .query_addr = iwlagn_eeprom_query_addr,
206 }, 206 },
207 .post_associate = iwl_post_associate, 207 .post_associate = iwl_post_associate,
208 .isr = iwl_isr_ict, 208 .isr = iwl_isr_ict,
209 .config_ap = iwl_config_ap, 209 .config_ap = iwl_config_ap,
210 .temp_ops = { 210 .temp_ops = {
211 .temperature = iwl5000_temperature, 211 .temperature = iwlagn_temperature,
212 .set_ct_kill = iwl1000_set_ct_threshold, 212 .set_ct_kill = iwl1000_set_ct_threshold,
213 }, 213 },
214 .add_bcast_station = iwl_add_bcast_station, 214 .add_bcast_station = iwl_add_bcast_station,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 9128ccd8dfa..4d3dda1beb2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -47,7 +47,6 @@
47#include "iwl-agn-led.h" 47#include "iwl-agn-led.h"
48#include "iwl-agn-hw.h" 48#include "iwl-agn-hw.h"
49#include "iwl-5000-hw.h" 49#include "iwl-5000-hw.h"
50#include "iwl-6000-hw.h"
51 50
52/* Highest firmware API version supported */ 51/* Highest firmware API version supported */
53#define IWL5000_UCODE_API_MAX 2 52#define IWL5000_UCODE_API_MAX 2
@@ -99,60 +98,6 @@ void iwl5000_nic_config(struct iwl_priv *priv)
99 spin_unlock_irqrestore(&priv->lock, flags); 98 spin_unlock_irqrestore(&priv->lock, flags);
100} 99}
101 100
102
103/*
104 * EEPROM
105 */
106static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
107{
108 u16 offset = 0;
109
110 if ((address & INDIRECT_ADDRESS) == 0)
111 return address;
112
113 switch (address & INDIRECT_TYPE_MSK) {
114 case INDIRECT_HOST:
115 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST);
116 break;
117 case INDIRECT_GENERAL:
118 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL);
119 break;
120 case INDIRECT_REGULATORY:
121 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY);
122 break;
123 case INDIRECT_CALIBRATION:
124 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION);
125 break;
126 case INDIRECT_PROCESS_ADJST:
127 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST);
128 break;
129 case INDIRECT_OTHERS:
130 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
131 break;
132 default:
133 IWL_ERR(priv, "illegal indirect type: 0x%X\n",
134 address & INDIRECT_TYPE_MSK);
135 break;
136 }
137
138 /* translate the offset from words to byte */
139 return (address & ADDRESS_MSK) + (offset << 1);
140}
141
142u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
143{
144 struct iwl_eeprom_calib_hdr {
145 u8 version;
146 u8 pa_type;
147 u16 voltage;
148 } *hdr;
149
150 hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
151 EEPROM_5000_CALIB_ALL);
152 return hdr->version;
153
154}
155
156static struct iwl_sensitivity_ranges iwl5000_sensitivity = { 101static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
157 .min_nrg_cck = 95, 102 .min_nrg_cck = 95,
158 .max_nrg_cck = 0, /* not used, set to 0 */ 103 .max_nrg_cck = 0, /* not used, set to 0 */
@@ -204,14 +149,6 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
204 .nrg_th_cca = 62, 149 .nrg_th_cca = 62,
205}; 150};
206 151
207const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
208 size_t offset)
209{
210 u32 address = eeprom_indirect_address(priv, offset);
211 BUG_ON(address >= priv->cfg->eeprom_size);
212 return &priv->eeprom[address];
213}
214
215static void iwl5150_set_ct_threshold(struct iwl_priv *priv) 152static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
216{ 153{
217 const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; 154 const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
@@ -285,283 +222,6 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
285 return 0; 222 return 0;
286} 223}
287 224
288static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
289{
290 return le32_to_cpup((__le32 *)&tx_resp->status +
291 tx_resp->frame_count) & MAX_SN;
292}
293
294static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
295 struct iwl_ht_agg *agg,
296 struct iwl5000_tx_resp *tx_resp,
297 int txq_id, u16 start_idx)
298{
299 u16 status;
300 struct agg_tx_status *frame_status = &tx_resp->status;
301 struct ieee80211_tx_info *info = NULL;
302 struct ieee80211_hdr *hdr = NULL;
303 u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
304 int i, sh, idx;
305 u16 seq;
306
307 if (agg->wait_for_ba)
308 IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
309
310 agg->frame_count = tx_resp->frame_count;
311 agg->start_idx = start_idx;
312 agg->rate_n_flags = rate_n_flags;
313 agg->bitmap = 0;
314
315 /* # frames attempted by Tx command */
316 if (agg->frame_count == 1) {
317 /* Only one frame was attempted; no block-ack will arrive */
318 status = le16_to_cpu(frame_status[0].status);
319 idx = start_idx;
320
321 /* FIXME: code repetition */
322 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
323 agg->frame_count, agg->start_idx, idx);
324
325 info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
326 info->status.rates[0].count = tx_resp->failure_frame + 1;
327 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
328 info->flags |= iwl_tx_status_to_mac80211(status);
329 iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
330
331 /* FIXME: code repetition end */
332
333 IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
334 status & 0xff, tx_resp->failure_frame);
335 IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
336
337 agg->wait_for_ba = 0;
338 } else {
339 /* Two or more frames were attempted; expect block-ack */
340 u64 bitmap = 0;
341 int start = agg->start_idx;
342
343 /* Construct bit-map of pending frames within Tx window */
344 for (i = 0; i < agg->frame_count; i++) {
345 u16 sc;
346 status = le16_to_cpu(frame_status[i].status);
347 seq = le16_to_cpu(frame_status[i].sequence);
348 idx = SEQ_TO_INDEX(seq);
349 txq_id = SEQ_TO_QUEUE(seq);
350
351 if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
352 AGG_TX_STATE_ABORT_MSK))
353 continue;
354
355 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
356 agg->frame_count, txq_id, idx);
357
358 hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
359 if (!hdr) {
360 IWL_ERR(priv,
361 "BUG_ON idx doesn't point to valid skb"
362 " idx=%d, txq_id=%d\n", idx, txq_id);
363 return -1;
364 }
365
366 sc = le16_to_cpu(hdr->seq_ctrl);
367 if (idx != (SEQ_TO_SN(sc) & 0xff)) {
368 IWL_ERR(priv,
369 "BUG_ON idx doesn't match seq control"
370 " idx=%d, seq_idx=%d, seq=%d\n",
371 idx, SEQ_TO_SN(sc),
372 hdr->seq_ctrl);
373 return -1;
374 }
375
376 IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
377 i, idx, SEQ_TO_SN(sc));
378
379 sh = idx - start;
380 if (sh > 64) {
381 sh = (start - idx) + 0xff;
382 bitmap = bitmap << sh;
383 sh = 0;
384 start = idx;
385 } else if (sh < -64)
386 sh = 0xff - (start - idx);
387 else if (sh < 0) {
388 sh = start - idx;
389 start = idx;
390 bitmap = bitmap << sh;
391 sh = 0;
392 }
393 bitmap |= 1ULL << sh;
394 IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
395 start, (unsigned long long)bitmap);
396 }
397
398 agg->bitmap = bitmap;
399 agg->start_idx = start;
400 IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
401 agg->frame_count, agg->start_idx,
402 (unsigned long long)agg->bitmap);
403
404 if (bitmap)
405 agg->wait_for_ba = 1;
406 }
407 return 0;
408}
409
410static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
411 struct iwl_rx_mem_buffer *rxb)
412{
413 struct iwl_rx_packet *pkt = rxb_addr(rxb);
414 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
415 int txq_id = SEQ_TO_QUEUE(sequence);
416 int index = SEQ_TO_INDEX(sequence);
417 struct iwl_tx_queue *txq = &priv->txq[txq_id];
418 struct ieee80211_tx_info *info;
419 struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
420 u32 status = le16_to_cpu(tx_resp->status.status);
421 int tid;
422 int sta_id;
423 int freed;
424
425 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
426 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
427 "is out of range [0-%d] %d %d\n", txq_id,
428 index, txq->q.n_bd, txq->q.write_ptr,
429 txq->q.read_ptr);
430 return;
431 }
432
433 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
434 memset(&info->status, 0, sizeof(info->status));
435
436 tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
437 sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
438
439 if (txq->sched_retry) {
440 const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
441 struct iwl_ht_agg *agg = NULL;
442
443 agg = &priv->stations[sta_id].tid[tid].agg;
444
445 iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
446
447 /* check if BAR is needed */
448 if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
449 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
450
451 if (txq->q.read_ptr != (scd_ssn & 0xff)) {
452 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
453 IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim "
454 "scd_ssn=%d idx=%d txq=%d swq=%d\n",
455 scd_ssn , index, txq_id, txq->swq_id);
456
457 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
458 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
459
460 if (priv->mac80211_registered &&
461 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
462 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
463 if (agg->state == IWL_AGG_OFF)
464 iwl_wake_queue(priv, txq_id);
465 else
466 iwl_wake_queue(priv, txq->swq_id);
467 }
468 }
469 } else {
470 BUG_ON(txq_id != txq->swq_id);
471
472 info->status.rates[0].count = tx_resp->failure_frame + 1;
473 info->flags |= iwl_tx_status_to_mac80211(status);
474 iwl_hwrate_to_tx_control(priv,
475 le32_to_cpu(tx_resp->rate_n_flags),
476 info);
477
478 IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
479 "0x%x retries %d\n",
480 txq_id,
481 iwl_get_tx_fail_reason(status), status,
482 le32_to_cpu(tx_resp->rate_n_flags),
483 tx_resp->failure_frame);
484
485 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
486 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
487
488 if (priv->mac80211_registered &&
489 (iwl_queue_space(&txq->q) > txq->q.low_mark))
490 iwl_wake_queue(priv, txq_id);
491 }
492
493 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
494
495 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
496 IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");
497}
498
499void iwl5000_setup_deferred_work(struct iwl_priv *priv)
500{
501 /* in 5000 the tx power calibration is done in uCode */
502 priv->disable_tx_power_cal = 1;
503}
504
505void iwl5000_rx_handler_setup(struct iwl_priv *priv)
506{
507 /* init calibration handlers */
508 priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
509 iwlagn_rx_calib_result;
510 priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
511 iwlagn_rx_calib_complete;
512 priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx;
513}
514
515
516int iwl5000_hw_valid_rtc_data_addr(u32 addr)
517{
518 return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
519 (addr < IWLAGN_RTC_DATA_UPPER_BOUND);
520}
521
522int iwl5000_send_tx_power(struct iwl_priv *priv)
523{
524 struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
525 u8 tx_ant_cfg_cmd;
526
527 /* half dBm need to multiply */
528 tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
529
530 if (priv->tx_power_lmt_in_half_dbm &&
531 priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) {
532 /*
533 * For the newer devices which using enhanced/extend tx power
534 * table in EEPROM, the format is in half dBm. driver need to
535 * convert to dBm format before report to mac80211.
536 * By doing so, there is a possibility of 1/2 dBm resolution
537 * lost. driver will perform "round-up" operation before
538 * reporting, but it will cause 1/2 dBm tx power over the
539 * regulatory limit. Perform the checking here, if the
540 * "tx_power_user_lmt" is higher than EEPROM value (in
541 * half-dBm format), lower the tx power based on EEPROM
542 */
543 tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
544 }
545 tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
546 tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
547
548 if (IWL_UCODE_API(priv->ucode_ver) == 1)
549 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
550 else
551 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
552
553 return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
554 sizeof(tx_power_cmd), &tx_power_cmd,
555 NULL);
556}
557
558void iwl5000_temperature(struct iwl_priv *priv)
559{
560 /* store temperature from statistics (in Celsius) */
561 priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
562 iwl_tt_handler(priv);
563}
564
565static void iwl5150_temperature(struct iwl_priv *priv) 225static void iwl5150_temperature(struct iwl_priv *priv)
566{ 226{
567 u32 vt = 0; 227 u32 vt = 0;
@@ -616,9 +276,9 @@ struct iwl_lib_ops iwl5000_lib = {
616 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, 276 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
617 .txq_free_tfd = iwl_hw_txq_free_tfd, 277 .txq_free_tfd = iwl_hw_txq_free_tfd,
618 .txq_init = iwl_hw_tx_queue_init, 278 .txq_init = iwl_hw_tx_queue_init,
619 .rx_handler_setup = iwl5000_rx_handler_setup, 279 .rx_handler_setup = iwlagn_rx_handler_setup,
620 .setup_deferred_work = iwl5000_setup_deferred_work, 280 .setup_deferred_work = iwlagn_setup_deferred_work,
621 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 281 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
622 .dump_nic_event_log = iwl_dump_nic_event_log, 282 .dump_nic_event_log = iwl_dump_nic_event_log,
623 .dump_nic_error_log = iwl_dump_nic_error_log, 283 .dump_nic_error_log = iwl_dump_nic_error_log,
624 .dump_csr = iwl_dump_csr, 284 .dump_csr = iwl_dump_csr,
@@ -626,7 +286,7 @@ struct iwl_lib_ops iwl5000_lib = {
626 .load_ucode = iwlagn_load_ucode, 286 .load_ucode = iwlagn_load_ucode,
627 .init_alive_start = iwlagn_init_alive_start, 287 .init_alive_start = iwlagn_init_alive_start,
628 .alive_notify = iwlagn_alive_notify, 288 .alive_notify = iwlagn_alive_notify,
629 .send_tx_power = iwl5000_send_tx_power, 289 .send_tx_power = iwlagn_send_tx_power,
630 .update_chain_flags = iwl_update_chain_flags, 290 .update_chain_flags = iwl_update_chain_flags,
631 .set_channel_switch = iwl5000_hw_channel_switch, 291 .set_channel_switch = iwl5000_hw_channel_switch,
632 .apm_ops = { 292 .apm_ops = {
@@ -637,25 +297,25 @@ struct iwl_lib_ops iwl5000_lib = {
637 }, 297 },
638 .eeprom_ops = { 298 .eeprom_ops = {
639 .regulatory_bands = { 299 .regulatory_bands = {
640 EEPROM_5000_REG_BAND_1_CHANNELS, 300 EEPROM_REG_BAND_1_CHANNELS,
641 EEPROM_5000_REG_BAND_2_CHANNELS, 301 EEPROM_REG_BAND_2_CHANNELS,
642 EEPROM_5000_REG_BAND_3_CHANNELS, 302 EEPROM_REG_BAND_3_CHANNELS,
643 EEPROM_5000_REG_BAND_4_CHANNELS, 303 EEPROM_REG_BAND_4_CHANNELS,
644 EEPROM_5000_REG_BAND_5_CHANNELS, 304 EEPROM_REG_BAND_5_CHANNELS,
645 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 305 EEPROM_REG_BAND_24_HT40_CHANNELS,
646 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 306 EEPROM_REG_BAND_52_HT40_CHANNELS
647 }, 307 },
648 .verify_signature = iwlcore_eeprom_verify_signature, 308 .verify_signature = iwlcore_eeprom_verify_signature,
649 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 309 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
650 .release_semaphore = iwlcore_eeprom_release_semaphore, 310 .release_semaphore = iwlcore_eeprom_release_semaphore,
651 .calib_version = iwl5000_eeprom_calib_version, 311 .calib_version = iwlagn_eeprom_calib_version,
652 .query_addr = iwl5000_eeprom_query_addr, 312 .query_addr = iwlagn_eeprom_query_addr,
653 }, 313 },
654 .post_associate = iwl_post_associate, 314 .post_associate = iwl_post_associate,
655 .isr = iwl_isr_ict, 315 .isr = iwl_isr_ict,
656 .config_ap = iwl_config_ap, 316 .config_ap = iwl_config_ap,
657 .temp_ops = { 317 .temp_ops = {
658 .temperature = iwl5000_temperature, 318 .temperature = iwlagn_temperature,
659 .set_ct_kill = iwl5000_set_ct_threshold, 319 .set_ct_kill = iwl5000_set_ct_threshold,
660 }, 320 },
661 .add_bcast_station = iwl_add_bcast_station, 321 .add_bcast_station = iwl_add_bcast_station,
@@ -674,16 +334,16 @@ static struct iwl_lib_ops iwl5150_lib = {
674 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, 334 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
675 .txq_free_tfd = iwl_hw_txq_free_tfd, 335 .txq_free_tfd = iwl_hw_txq_free_tfd,
676 .txq_init = iwl_hw_tx_queue_init, 336 .txq_init = iwl_hw_tx_queue_init,
677 .rx_handler_setup = iwl5000_rx_handler_setup, 337 .rx_handler_setup = iwlagn_rx_handler_setup,
678 .setup_deferred_work = iwl5000_setup_deferred_work, 338 .setup_deferred_work = iwlagn_setup_deferred_work,
679 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 339 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
680 .dump_nic_event_log = iwl_dump_nic_event_log, 340 .dump_nic_event_log = iwl_dump_nic_event_log,
681 .dump_nic_error_log = iwl_dump_nic_error_log, 341 .dump_nic_error_log = iwl_dump_nic_error_log,
682 .dump_csr = iwl_dump_csr, 342 .dump_csr = iwl_dump_csr,
683 .load_ucode = iwlagn_load_ucode, 343 .load_ucode = iwlagn_load_ucode,
684 .init_alive_start = iwlagn_init_alive_start, 344 .init_alive_start = iwlagn_init_alive_start,
685 .alive_notify = iwlagn_alive_notify, 345 .alive_notify = iwlagn_alive_notify,
686 .send_tx_power = iwl5000_send_tx_power, 346 .send_tx_power = iwlagn_send_tx_power,
687 .update_chain_flags = iwl_update_chain_flags, 347 .update_chain_flags = iwl_update_chain_flags,
688 .set_channel_switch = iwl5000_hw_channel_switch, 348 .set_channel_switch = iwl5000_hw_channel_switch,
689 .apm_ops = { 349 .apm_ops = {
@@ -694,19 +354,19 @@ static struct iwl_lib_ops iwl5150_lib = {
694 }, 354 },
695 .eeprom_ops = { 355 .eeprom_ops = {
696 .regulatory_bands = { 356 .regulatory_bands = {
697 EEPROM_5000_REG_BAND_1_CHANNELS, 357 EEPROM_REG_BAND_1_CHANNELS,
698 EEPROM_5000_REG_BAND_2_CHANNELS, 358 EEPROM_REG_BAND_2_CHANNELS,
699 EEPROM_5000_REG_BAND_3_CHANNELS, 359 EEPROM_REG_BAND_3_CHANNELS,
700 EEPROM_5000_REG_BAND_4_CHANNELS, 360 EEPROM_REG_BAND_4_CHANNELS,
701 EEPROM_5000_REG_BAND_5_CHANNELS, 361 EEPROM_REG_BAND_5_CHANNELS,
702 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 362 EEPROM_REG_BAND_24_HT40_CHANNELS,
703 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 363 EEPROM_REG_BAND_52_HT40_CHANNELS
704 }, 364 },
705 .verify_signature = iwlcore_eeprom_verify_signature, 365 .verify_signature = iwlcore_eeprom_verify_signature,
706 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 366 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
707 .release_semaphore = iwlcore_eeprom_release_semaphore, 367 .release_semaphore = iwlcore_eeprom_release_semaphore,
708 .calib_version = iwl5000_eeprom_calib_version, 368 .calib_version = iwlagn_eeprom_calib_version,
709 .query_addr = iwl5000_eeprom_query_addr, 369 .query_addr = iwlagn_eeprom_query_addr,
710 }, 370 },
711 .post_associate = iwl_post_associate, 371 .post_associate = iwl_post_associate,
712 .isr = iwl_isr_ict, 372 .isr = iwl_isr_ict,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 96f4fa6e0e2..92b407f89d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -234,9 +234,9 @@ static struct iwl_lib_ops iwl6000_lib = {
234 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, 234 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
235 .txq_free_tfd = iwl_hw_txq_free_tfd, 235 .txq_free_tfd = iwl_hw_txq_free_tfd,
236 .txq_init = iwl_hw_tx_queue_init, 236 .txq_init = iwl_hw_tx_queue_init,
237 .rx_handler_setup = iwl5000_rx_handler_setup, 237 .rx_handler_setup = iwlagn_rx_handler_setup,
238 .setup_deferred_work = iwl5000_setup_deferred_work, 238 .setup_deferred_work = iwlagn_setup_deferred_work,
239 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 239 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
240 .load_ucode = iwlagn_load_ucode, 240 .load_ucode = iwlagn_load_ucode,
241 .dump_nic_event_log = iwl_dump_nic_event_log, 241 .dump_nic_event_log = iwl_dump_nic_event_log,
242 .dump_nic_error_log = iwl_dump_nic_error_log, 242 .dump_nic_error_log = iwl_dump_nic_error_log,
@@ -244,7 +244,7 @@ static struct iwl_lib_ops iwl6000_lib = {
244 .dump_fh = iwl_dump_fh, 244 .dump_fh = iwl_dump_fh,
245 .init_alive_start = iwlagn_init_alive_start, 245 .init_alive_start = iwlagn_init_alive_start,
246 .alive_notify = iwlagn_alive_notify, 246 .alive_notify = iwlagn_alive_notify,
247 .send_tx_power = iwl5000_send_tx_power, 247 .send_tx_power = iwlagn_send_tx_power,
248 .update_chain_flags = iwl_update_chain_flags, 248 .update_chain_flags = iwl_update_chain_flags,
249 .set_channel_switch = iwl6000_hw_channel_switch, 249 .set_channel_switch = iwl6000_hw_channel_switch,
250 .apm_ops = { 250 .apm_ops = {
@@ -255,26 +255,26 @@ static struct iwl_lib_ops iwl6000_lib = {
255 }, 255 },
256 .eeprom_ops = { 256 .eeprom_ops = {
257 .regulatory_bands = { 257 .regulatory_bands = {
258 EEPROM_5000_REG_BAND_1_CHANNELS, 258 EEPROM_REG_BAND_1_CHANNELS,
259 EEPROM_5000_REG_BAND_2_CHANNELS, 259 EEPROM_REG_BAND_2_CHANNELS,
260 EEPROM_5000_REG_BAND_3_CHANNELS, 260 EEPROM_REG_BAND_3_CHANNELS,
261 EEPROM_5000_REG_BAND_4_CHANNELS, 261 EEPROM_REG_BAND_4_CHANNELS,
262 EEPROM_5000_REG_BAND_5_CHANNELS, 262 EEPROM_REG_BAND_5_CHANNELS,
263 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 263 EEPROM_REG_BAND_24_HT40_CHANNELS,
264 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 264 EEPROM_REG_BAND_52_HT40_CHANNELS
265 }, 265 },
266 .verify_signature = iwlcore_eeprom_verify_signature, 266 .verify_signature = iwlcore_eeprom_verify_signature,
267 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 267 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
268 .release_semaphore = iwlcore_eeprom_release_semaphore, 268 .release_semaphore = iwlcore_eeprom_release_semaphore,
269 .calib_version = iwl5000_eeprom_calib_version, 269 .calib_version = iwlagn_eeprom_calib_version,
270 .query_addr = iwl5000_eeprom_query_addr, 270 .query_addr = iwlagn_eeprom_query_addr,
271 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, 271 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
272 }, 272 },
273 .post_associate = iwl_post_associate, 273 .post_associate = iwl_post_associate,
274 .isr = iwl_isr_ict, 274 .isr = iwl_isr_ict,
275 .config_ap = iwl_config_ap, 275 .config_ap = iwl_config_ap,
276 .temp_ops = { 276 .temp_ops = {
277 .temperature = iwl5000_temperature, 277 .temperature = iwlagn_temperature,
278 .set_ct_kill = iwl6000_set_ct_threshold, 278 .set_ct_kill = iwl6000_set_ct_threshold,
279 }, 279 },
280 .add_bcast_station = iwl_add_bcast_station, 280 .add_bcast_station = iwl_add_bcast_station,
@@ -301,9 +301,9 @@ static struct iwl_lib_ops iwl6050_lib = {
301 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, 301 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
302 .txq_free_tfd = iwl_hw_txq_free_tfd, 302 .txq_free_tfd = iwl_hw_txq_free_tfd,
303 .txq_init = iwl_hw_tx_queue_init, 303 .txq_init = iwl_hw_tx_queue_init,
304 .rx_handler_setup = iwl5000_rx_handler_setup, 304 .rx_handler_setup = iwlagn_rx_handler_setup,
305 .setup_deferred_work = iwl5000_setup_deferred_work, 305 .setup_deferred_work = iwlagn_setup_deferred_work,
306 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 306 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
307 .load_ucode = iwlagn_load_ucode, 307 .load_ucode = iwlagn_load_ucode,
308 .dump_nic_event_log = iwl_dump_nic_event_log, 308 .dump_nic_event_log = iwl_dump_nic_event_log,
309 .dump_nic_error_log = iwl_dump_nic_error_log, 309 .dump_nic_error_log = iwl_dump_nic_error_log,
@@ -311,7 +311,7 @@ static struct iwl_lib_ops iwl6050_lib = {
311 .dump_fh = iwl_dump_fh, 311 .dump_fh = iwl_dump_fh,
312 .init_alive_start = iwlagn_init_alive_start, 312 .init_alive_start = iwlagn_init_alive_start,
313 .alive_notify = iwlagn_alive_notify, 313 .alive_notify = iwlagn_alive_notify,
314 .send_tx_power = iwl5000_send_tx_power, 314 .send_tx_power = iwlagn_send_tx_power,
315 .update_chain_flags = iwl_update_chain_flags, 315 .update_chain_flags = iwl_update_chain_flags,
316 .set_channel_switch = iwl6000_hw_channel_switch, 316 .set_channel_switch = iwl6000_hw_channel_switch,
317 .apm_ops = { 317 .apm_ops = {
@@ -322,26 +322,26 @@ static struct iwl_lib_ops iwl6050_lib = {
322 }, 322 },
323 .eeprom_ops = { 323 .eeprom_ops = {
324 .regulatory_bands = { 324 .regulatory_bands = {
325 EEPROM_5000_REG_BAND_1_CHANNELS, 325 EEPROM_REG_BAND_1_CHANNELS,
326 EEPROM_5000_REG_BAND_2_CHANNELS, 326 EEPROM_REG_BAND_2_CHANNELS,
327 EEPROM_5000_REG_BAND_3_CHANNELS, 327 EEPROM_REG_BAND_3_CHANNELS,
328 EEPROM_5000_REG_BAND_4_CHANNELS, 328 EEPROM_REG_BAND_4_CHANNELS,
329 EEPROM_5000_REG_BAND_5_CHANNELS, 329 EEPROM_REG_BAND_5_CHANNELS,
330 EEPROM_5000_REG_BAND_24_HT40_CHANNELS, 330 EEPROM_REG_BAND_24_HT40_CHANNELS,
331 EEPROM_5000_REG_BAND_52_HT40_CHANNELS 331 EEPROM_REG_BAND_52_HT40_CHANNELS
332 }, 332 },
333 .verify_signature = iwlcore_eeprom_verify_signature, 333 .verify_signature = iwlcore_eeprom_verify_signature,
334 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 334 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
335 .release_semaphore = iwlcore_eeprom_release_semaphore, 335 .release_semaphore = iwlcore_eeprom_release_semaphore,
336 .calib_version = iwl5000_eeprom_calib_version, 336 .calib_version = iwlagn_eeprom_calib_version,
337 .query_addr = iwl5000_eeprom_query_addr, 337 .query_addr = iwlagn_eeprom_query_addr,
338 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, 338 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
339 }, 339 },
340 .post_associate = iwl_post_associate, 340 .post_associate = iwl_post_associate,
341 .isr = iwl_isr_ict, 341 .isr = iwl_isr_ict,
342 .config_ap = iwl_config_ap, 342 .config_ap = iwl_config_ap,
343 .temp_ops = { 343 .temp_ops = {
344 .temperature = iwl5000_temperature, 344 .temperature = iwlagn_temperature,
345 .set_ct_kill = iwl6000_set_ct_threshold, 345 .set_ct_kill = iwl6000_set_ct_threshold,
346 .set_calib_version = iwl6050_set_calib_version, 346 .set_calib_version = iwl6050_set_calib_version,
347 }, 347 },
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
new file mode 100644
index 00000000000..e4c0726601a
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -0,0 +1,377 @@
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/sched.h>
34
35#include "iwl-dev.h"
36#include "iwl-core.h"
37#include "iwl-io.h"
38#include "iwl-helpers.h"
39#include "iwl-agn-hw.h"
40#include "iwl-agn.h"
41
42static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
43{
44 return le32_to_cpup((__le32 *)&tx_resp->status +
45 tx_resp->frame_count) & MAX_SN;
46}
47
48static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
49 struct iwl_ht_agg *agg,
50 struct iwl5000_tx_resp *tx_resp,
51 int txq_id, u16 start_idx)
52{
53 u16 status;
54 struct agg_tx_status *frame_status = &tx_resp->status;
55 struct ieee80211_tx_info *info = NULL;
56 struct ieee80211_hdr *hdr = NULL;
57 u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
58 int i, sh, idx;
59 u16 seq;
60
61 if (agg->wait_for_ba)
62 IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
63
64 agg->frame_count = tx_resp->frame_count;
65 agg->start_idx = start_idx;
66 agg->rate_n_flags = rate_n_flags;
67 agg->bitmap = 0;
68
69 /* # frames attempted by Tx command */
70 if (agg->frame_count == 1) {
71 /* Only one frame was attempted; no block-ack will arrive */
72 status = le16_to_cpu(frame_status[0].status);
73 idx = start_idx;
74
75 /* FIXME: code repetition */
76 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
77 agg->frame_count, agg->start_idx, idx);
78
79 info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
80 info->status.rates[0].count = tx_resp->failure_frame + 1;
81 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
82 info->flags |= iwl_tx_status_to_mac80211(status);
83 iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
84
85 /* FIXME: code repetition end */
86
87 IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
88 status & 0xff, tx_resp->failure_frame);
89 IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
90
91 agg->wait_for_ba = 0;
92 } else {
93 /* Two or more frames were attempted; expect block-ack */
94 u64 bitmap = 0;
95 int start = agg->start_idx;
96
97 /* Construct bit-map of pending frames within Tx window */
98 for (i = 0; i < agg->frame_count; i++) {
99 u16 sc;
100 status = le16_to_cpu(frame_status[i].status);
101 seq = le16_to_cpu(frame_status[i].sequence);
102 idx = SEQ_TO_INDEX(seq);
103 txq_id = SEQ_TO_QUEUE(seq);
104
105 if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
106 AGG_TX_STATE_ABORT_MSK))
107 continue;
108
109 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
110 agg->frame_count, txq_id, idx);
111
112 hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
113 if (!hdr) {
114 IWL_ERR(priv,
115 "BUG_ON idx doesn't point to valid skb"
116 " idx=%d, txq_id=%d\n", idx, txq_id);
117 return -1;
118 }
119
120 sc = le16_to_cpu(hdr->seq_ctrl);
121 if (idx != (SEQ_TO_SN(sc) & 0xff)) {
122 IWL_ERR(priv,
123 "BUG_ON idx doesn't match seq control"
124 " idx=%d, seq_idx=%d, seq=%d\n",
125 idx, SEQ_TO_SN(sc),
126 hdr->seq_ctrl);
127 return -1;
128 }
129
130 IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
131 i, idx, SEQ_TO_SN(sc));
132
133 sh = idx - start;
134 if (sh > 64) {
135 sh = (start - idx) + 0xff;
136 bitmap = bitmap << sh;
137 sh = 0;
138 start = idx;
139 } else if (sh < -64)
140 sh = 0xff - (start - idx);
141 else if (sh < 0) {
142 sh = start - idx;
143 start = idx;
144 bitmap = bitmap << sh;
145 sh = 0;
146 }
147 bitmap |= 1ULL << sh;
148 IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
149 start, (unsigned long long)bitmap);
150 }
151
152 agg->bitmap = bitmap;
153 agg->start_idx = start;
154 IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
155 agg->frame_count, agg->start_idx,
156 (unsigned long long)agg->bitmap);
157
158 if (bitmap)
159 agg->wait_for_ba = 1;
160 }
161 return 0;
162}
163
164static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
165 struct iwl_rx_mem_buffer *rxb)
166{
167 struct iwl_rx_packet *pkt = rxb_addr(rxb);
168 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
169 int txq_id = SEQ_TO_QUEUE(sequence);
170 int index = SEQ_TO_INDEX(sequence);
171 struct iwl_tx_queue *txq = &priv->txq[txq_id];
172 struct ieee80211_tx_info *info;
173 struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
174 u32 status = le16_to_cpu(tx_resp->status.status);
175 int tid;
176 int sta_id;
177 int freed;
178
179 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
180 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
181 "is out of range [0-%d] %d %d\n", txq_id,
182 index, txq->q.n_bd, txq->q.write_ptr,
183 txq->q.read_ptr);
184 return;
185 }
186
187 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
188 memset(&info->status, 0, sizeof(info->status));
189
190 tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
191 sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
192
193 if (txq->sched_retry) {
194 const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
195 struct iwl_ht_agg *agg = NULL;
196
197 agg = &priv->stations[sta_id].tid[tid].agg;
198
199 iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
200
201 /* check if BAR is needed */
202 if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
203 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
204
205 if (txq->q.read_ptr != (scd_ssn & 0xff)) {
206 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
207 IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim "
208 "scd_ssn=%d idx=%d txq=%d swq=%d\n",
209 scd_ssn , index, txq_id, txq->swq_id);
210
211 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
212 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
213
214 if (priv->mac80211_registered &&
215 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
216 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
217 if (agg->state == IWL_AGG_OFF)
218 iwl_wake_queue(priv, txq_id);
219 else
220 iwl_wake_queue(priv, txq->swq_id);
221 }
222 }
223 } else {
224 BUG_ON(txq_id != txq->swq_id);
225
226 info->status.rates[0].count = tx_resp->failure_frame + 1;
227 info->flags |= iwl_tx_status_to_mac80211(status);
228 iwl_hwrate_to_tx_control(priv,
229 le32_to_cpu(tx_resp->rate_n_flags),
230 info);
231
232 IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
233 "0x%x retries %d\n",
234 txq_id,
235 iwl_get_tx_fail_reason(status), status,
236 le32_to_cpu(tx_resp->rate_n_flags),
237 tx_resp->failure_frame);
238
239 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
240 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
241
242 if (priv->mac80211_registered &&
243 (iwl_queue_space(&txq->q) > txq->q.low_mark))
244 iwl_wake_queue(priv, txq_id);
245 }
246
247 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
248
249 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
250 IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");
251}
252
253void iwlagn_rx_handler_setup(struct iwl_priv *priv)
254{
255 /* init calibration handlers */
256 priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
257 iwlagn_rx_calib_result;
258 priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
259 iwlagn_rx_calib_complete;
260 priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
261}
262
263void iwlagn_setup_deferred_work(struct iwl_priv *priv)
264{
265 /* in agn, the tx power calibration is done in uCode */
266 priv->disable_tx_power_cal = 1;
267}
268
269int iwlagn_hw_valid_rtc_data_addr(u32 addr)
270{
271 return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
272 (addr < IWLAGN_RTC_DATA_UPPER_BOUND);
273}
274
275int iwlagn_send_tx_power(struct iwl_priv *priv)
276{
277 struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
278 u8 tx_ant_cfg_cmd;
279
280 /* half dBm need to multiply */
281 tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
282
283 if (priv->tx_power_lmt_in_half_dbm &&
284 priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) {
285 /*
286 * For the newer devices which using enhanced/extend tx power
287 * table in EEPROM, the format is in half dBm. driver need to
288 * convert to dBm format before report to mac80211.
289 * By doing so, there is a possibility of 1/2 dBm resolution
290 * lost. driver will perform "round-up" operation before
291 * reporting, but it will cause 1/2 dBm tx power over the
292 * regulatory limit. Perform the checking here, if the
293 * "tx_power_user_lmt" is higher than EEPROM value (in
294 * half-dBm format), lower the tx power based on EEPROM
295 */
296 tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
297 }
298 tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
299 tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
300
301 if (IWL_UCODE_API(priv->ucode_ver) == 1)
302 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
303 else
304 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
305
306 return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
307 sizeof(tx_power_cmd), &tx_power_cmd,
308 NULL);
309}
310
311void iwlagn_temperature(struct iwl_priv *priv)
312{
313 /* store temperature from statistics (in Celsius) */
314 priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
315 iwl_tt_handler(priv);
316}
317
318u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
319{
320 struct iwl_eeprom_calib_hdr {
321 u8 version;
322 u8 pa_type;
323 u16 voltage;
324 } *hdr;
325
326 hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
327 EEPROM_5000_CALIB_ALL);
328 return hdr->version;
329
330}
331
332/*
333 * EEPROM
334 */
335static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
336{
337 u16 offset = 0;
338
339 if ((address & INDIRECT_ADDRESS) == 0)
340 return address;
341
342 switch (address & INDIRECT_TYPE_MSK) {
343 case INDIRECT_HOST:
344 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST);
345 break;
346 case INDIRECT_GENERAL:
347 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL);
348 break;
349 case INDIRECT_REGULATORY:
350 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY);
351 break;
352 case INDIRECT_CALIBRATION:
353 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION);
354 break;
355 case INDIRECT_PROCESS_ADJST:
356 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST);
357 break;
358 case INDIRECT_OTHERS:
359 offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
360 break;
361 default:
362 IWL_ERR(priv, "illegal indirect type: 0x%X\n",
363 address & INDIRECT_TYPE_MSK);
364 break;
365 }
366
367 /* translate the offset from words to byte */
368 return (address & ADDRESS_MSK) + (offset << 1);
369}
370
371const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
372 size_t offset)
373{
374 u32 address = eeprom_indirect_address(priv, offset);
375 BUG_ON(address >= priv->cfg->eeprom_size);
376 return &priv->eeprom[address];
377}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 9b667656982..aa49e667097 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -103,4 +103,14 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv,
103void iwlagn_init_alive_start(struct iwl_priv *priv); 103void iwlagn_init_alive_start(struct iwl_priv *priv);
104int iwlagn_alive_notify(struct iwl_priv *priv); 104int iwlagn_alive_notify(struct iwl_priv *priv);
105 105
106/* lib */
107void iwlagn_rx_handler_setup(struct iwl_priv *priv);
108void iwlagn_setup_deferred_work(struct iwl_priv *priv);
109int iwlagn_hw_valid_rtc_data_addr(u32 addr);
110int iwlagn_send_tx_power(struct iwl_priv *priv);
111void iwlagn_temperature(struct iwl_priv *priv);
112u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
113const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
114 size_t offset);
115
106#endif /* __iwl_agn_h__ */ 116#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 4e1ba824dc5..907a30a97d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -188,19 +188,19 @@ struct iwl_eeprom_enhanced_txpwr {
188/* 5000 regulatory - indirect access */ 188/* 5000 regulatory - indirect access */
189#define EEPROM_5000_REG_SKU_ID ((0x02)\ 189#define EEPROM_5000_REG_SKU_ID ((0x02)\
190 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ 190 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */
191#define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ 191#define EEPROM_REG_BAND_1_CHANNELS ((0x08)\
192 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ 192 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */
193#define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ 193#define EEPROM_REG_BAND_2_CHANNELS ((0x26)\
194 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ 194 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */
195#define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ 195#define EEPROM_REG_BAND_3_CHANNELS ((0x42)\
196 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ 196 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
197#define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ 197#define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\
198 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ 198 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
199#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ 199#define EEPROM_REG_BAND_5_CHANNELS ((0x74)\
200 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ 200 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */
201#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ 201#define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\
202 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ 202 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
203#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ 203#define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\
204 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ 204 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
205 205
206/* 6000 and up regulatory tx power - indirect access */ 206/* 6000 and up regulatory tx power - indirect access */