diff options
author | Cahill, Ben M <ben.m.cahill@intel.com> | 2007-11-28 22:09:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:05:23 -0500 |
commit | 6440adb5760a897497c2b1ebdccc32c7944fd57f (patch) | |
tree | f7ab0b2eef45f35b79f6f4e60bccdf67514b5889 /drivers/net/wireless/iwlwifi/iwl4965-base.c | |
parent | 8b6eaea8ec79b111a18a1c60333deb16ba27e6b3 (diff) |
iwlwifi: add comments to iwl*-base.c
Add comments to iwlXXXX-base.c
Signed-off-by: Cahill, Ben M <ben.m.cahill@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 212 |
1 files changed, 179 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 66aa938e316e..43ce645e4a60 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -63,13 +63,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, | |||
63 | ******************************************************************************/ | 63 | ******************************************************************************/ |
64 | 64 | ||
65 | /* module parameters */ | 65 | /* module parameters */ |
66 | static int iwl4965_param_disable_hw_scan; | 66 | static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */ |
67 | static int iwl4965_param_debug; | 67 | static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */ |
68 | static int iwl4965_param_disable; /* def: enable radio */ | 68 | static int iwl4965_param_disable; /* def: enable radio */ |
69 | static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ | 69 | static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ |
70 | int iwl4965_param_hwcrypto; /* def: using software encryption */ | 70 | int iwl4965_param_hwcrypto; /* def: using software encryption */ |
71 | static int iwl4965_param_qos_enable = 1; | 71 | static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */ |
72 | int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; | 72 | int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */ |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * module name, copyright, version, etc. | 75 | * module name, copyright, version, etc. |
@@ -183,17 +183,24 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len) | |||
183 | * | 183 | * |
184 | * Theory of operation | 184 | * Theory of operation |
185 | * | 185 | * |
186 | * A queue is a circular buffers with 'Read' and 'Write' pointers. | 186 | * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer |
187 | * 2 empty entries always kept in the buffer to protect from overflow. | 187 | * of buffer descriptors, each of which points to one or more data buffers for |
188 | * the device to read from or fill. Driver and device exchange status of each | ||
189 | * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty | ||
190 | * entries in each circular buffer, to protect against confusing empty and full | ||
191 | * queue states. | ||
192 | * | ||
193 | * The device reads or writes the data in the queues via the device's several | ||
194 | * DMA/FIFO channels. Each queue is mapped to a single DMA channel. | ||
188 | * | 195 | * |
189 | * For Tx queue, there are low mark and high mark limits. If, after queuing | 196 | * For Tx queue, there are low mark and high mark limits. If, after queuing |
190 | * the packet for Tx, free space become < low mark, Tx queue stopped. When | 197 | * the packet for Tx, free space become < low mark, Tx queue stopped. When |
191 | * reclaiming packets (on 'tx done IRQ), if free space become > high mark, | 198 | * reclaiming packets (on 'tx done IRQ), if free space become > high mark, |
192 | * Tx queue resumed. | 199 | * Tx queue resumed. |
193 | * | 200 | * |
194 | * The IWL operates with six queues, one receive queue in the device's | 201 | * The 4965 operates with up to 17 queues: One receive queue, one transmit |
195 | * sram, one transmit queue for sending commands to the device firmware, | 202 | * queue (#4) for sending commands to the device firmware, and 15 other |
196 | * and four transmit queues for data. | 203 | * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels. |
197 | ***************************************************/ | 204 | ***************************************************/ |
198 | 205 | ||
199 | static int iwl4965_queue_space(const struct iwl4965_queue *q) | 206 | static int iwl4965_queue_space(const struct iwl4965_queue *q) |
@@ -212,13 +219,21 @@ static int iwl4965_queue_space(const struct iwl4965_queue *q) | |||
212 | return s; | 219 | return s; |
213 | } | 220 | } |
214 | 221 | ||
215 | /* XXX: n_bd must be power-of-two size */ | 222 | /** |
223 | * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning | ||
224 | * @index -- current index | ||
225 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
226 | */ | ||
216 | static inline int iwl4965_queue_inc_wrap(int index, int n_bd) | 227 | static inline int iwl4965_queue_inc_wrap(int index, int n_bd) |
217 | { | 228 | { |
218 | return ++index & (n_bd - 1); | 229 | return ++index & (n_bd - 1); |
219 | } | 230 | } |
220 | 231 | ||
221 | /* XXX: n_bd must be power-of-two size */ | 232 | /** |
233 | * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end | ||
234 | * @index -- current index | ||
235 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
236 | */ | ||
222 | static inline int iwl4965_queue_dec_wrap(int index, int n_bd) | 237 | static inline int iwl4965_queue_dec_wrap(int index, int n_bd) |
223 | { | 238 | { |
224 | return --index & (n_bd - 1); | 239 | return --index & (n_bd - 1); |
@@ -233,12 +248,17 @@ static inline int x2_queue_used(const struct iwl4965_queue *q, int i) | |||
233 | 248 | ||
234 | static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge) | 249 | static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge) |
235 | { | 250 | { |
251 | /* This is for scan command, the big buffer at end of command array */ | ||
236 | if (is_huge) | 252 | if (is_huge) |
237 | return q->n_window; | 253 | return q->n_window; /* must be power of 2 */ |
238 | 254 | ||
255 | /* Otherwise, use normal size buffers */ | ||
239 | return index & (q->n_window - 1); | 256 | return index & (q->n_window - 1); |
240 | } | 257 | } |
241 | 258 | ||
259 | /** | ||
260 | * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes | ||
261 | */ | ||
242 | static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q, | 262 | static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q, |
243 | int count, int slots_num, u32 id) | 263 | int count, int slots_num, u32 id) |
244 | { | 264 | { |
@@ -267,11 +287,16 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q | |||
267 | return 0; | 287 | return 0; |
268 | } | 288 | } |
269 | 289 | ||
290 | /** | ||
291 | * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue | ||
292 | */ | ||
270 | static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, | 293 | static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, |
271 | struct iwl4965_tx_queue *txq, u32 id) | 294 | struct iwl4965_tx_queue *txq, u32 id) |
272 | { | 295 | { |
273 | struct pci_dev *dev = priv->pci_dev; | 296 | struct pci_dev *dev = priv->pci_dev; |
274 | 297 | ||
298 | /* Driver private data, only for Tx (not command) queues, | ||
299 | * not shared with device. */ | ||
275 | if (id != IWL_CMD_QUEUE_NUM) { | 300 | if (id != IWL_CMD_QUEUE_NUM) { |
276 | txq->txb = kmalloc(sizeof(txq->txb[0]) * | 301 | txq->txb = kmalloc(sizeof(txq->txb[0]) * |
277 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | 302 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); |
@@ -283,6 +308,8 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, | |||
283 | } else | 308 | } else |
284 | txq->txb = NULL; | 309 | txq->txb = NULL; |
285 | 310 | ||
311 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
312 | * shared with device */ | ||
286 | txq->bd = pci_alloc_consistent(dev, | 313 | txq->bd = pci_alloc_consistent(dev, |
287 | sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX, | 314 | sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX, |
288 | &txq->q.dma_addr); | 315 | &txq->q.dma_addr); |
@@ -320,7 +347,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, | |||
320 | * For the command queue (#4), allocate command space + one big | 347 | * For the command queue (#4), allocate command space + one big |
321 | * command for scan, since scan command is very huge; the system will | 348 | * command for scan, since scan command is very huge; the system will |
322 | * not have two scans at the same time, so only one is needed. | 349 | * not have two scans at the same time, so only one is needed. |
323 | * For normal Tx queues (all other queues), no super-size command | 350 | * For data Tx queues (all other queues), no super-size command |
324 | * space is needed. | 351 | * space is needed. |
325 | */ | 352 | */ |
326 | len = sizeof(struct iwl4965_cmd) * slots_num; | 353 | len = sizeof(struct iwl4965_cmd) * slots_num; |
@@ -357,8 +384,8 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, | |||
357 | * @txq: Transmit queue to deallocate. | 384 | * @txq: Transmit queue to deallocate. |
358 | * | 385 | * |
359 | * Empty queue by removing and destroying all BD's. | 386 | * Empty queue by removing and destroying all BD's. |
360 | * Free all buffers. txq itself is not freed. | 387 | * Free all buffers. |
361 | * | 388 | * 0-fill, but do not free "txq" descriptor structure. |
362 | */ | 389 | */ |
363 | void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) | 390 | void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) |
364 | { | 391 | { |
@@ -378,19 +405,21 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t | |||
378 | if (q->id == IWL_CMD_QUEUE_NUM) | 405 | if (q->id == IWL_CMD_QUEUE_NUM) |
379 | len += IWL_MAX_SCAN_SIZE; | 406 | len += IWL_MAX_SCAN_SIZE; |
380 | 407 | ||
408 | /* De-alloc array of command/tx buffers */ | ||
381 | pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); | 409 | pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); |
382 | 410 | ||
383 | /* free buffers belonging to queue itself */ | 411 | /* De-alloc circular buffer of TFDs */ |
384 | if (txq->q.n_bd) | 412 | if (txq->q.n_bd) |
385 | pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) * | 413 | pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) * |
386 | txq->q.n_bd, txq->bd, txq->q.dma_addr); | 414 | txq->q.n_bd, txq->bd, txq->q.dma_addr); |
387 | 415 | ||
416 | /* De-alloc array of per-TFD driver data */ | ||
388 | if (txq->txb) { | 417 | if (txq->txb) { |
389 | kfree(txq->txb); | 418 | kfree(txq->txb); |
390 | txq->txb = NULL; | 419 | txq->txb = NULL; |
391 | } | 420 | } |
392 | 421 | ||
393 | /* 0 fill whole structure */ | 422 | /* 0-fill queue descriptor structure */ |
394 | memset(txq, 0, sizeof(*txq)); | 423 | memset(txq, 0, sizeof(*txq)); |
395 | } | 424 | } |
396 | 425 | ||
@@ -404,6 +433,11 @@ const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | |||
404 | /**************************************************************/ | 433 | /**************************************************************/ |
405 | 434 | ||
406 | #if 0 /* temporary disable till we add real remove station */ | 435 | #if 0 /* temporary disable till we add real remove station */ |
436 | /** | ||
437 | * iwl4965_remove_station - Remove driver's knowledge of station. | ||
438 | * | ||
439 | * NOTE: This does not remove station from device's station table. | ||
440 | */ | ||
407 | static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) | 441 | static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) |
408 | { | 442 | { |
409 | int index = IWL_INVALID_STATION; | 443 | int index = IWL_INVALID_STATION; |
@@ -441,6 +475,11 @@ out: | |||
441 | } | 475 | } |
442 | #endif | 476 | #endif |
443 | 477 | ||
478 | /** | ||
479 | * iwl4965_clear_stations_table - Clear the driver's station table | ||
480 | * | ||
481 | * NOTE: This does not clear or otherwise alter the device's station table. | ||
482 | */ | ||
444 | static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) | 483 | static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) |
445 | { | 484 | { |
446 | unsigned long flags; | 485 | unsigned long flags; |
@@ -453,6 +492,9 @@ static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) | |||
453 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 492 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
454 | } | 493 | } |
455 | 494 | ||
495 | /** | ||
496 | * iwl4965_add_station_flags - Add station to tables in driver and device | ||
497 | */ | ||
456 | u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_ap, u8 flags) | 498 | u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_ap, u8 flags) |
457 | { | 499 | { |
458 | int i; | 500 | int i; |
@@ -499,6 +541,7 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_a | |||
499 | station->used = 1; | 541 | station->used = 1; |
500 | priv->num_stations++; | 542 | priv->num_stations++; |
501 | 543 | ||
544 | /* Set up the REPLY_ADD_STA command to send to device */ | ||
502 | memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd)); | 545 | memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd)); |
503 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); | 546 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); |
504 | station->sta.mode = 0; | 547 | station->sta.mode = 0; |
@@ -513,6 +556,8 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_a | |||
513 | #endif /*CONFIG_IWL4965_HT*/ | 556 | #endif /*CONFIG_IWL4965_HT*/ |
514 | 557 | ||
515 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 558 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
559 | |||
560 | /* Add station to device's station table */ | ||
516 | iwl4965_send_add_station(priv, &station->sta, flags); | 561 | iwl4965_send_add_station(priv, &station->sta, flags); |
517 | return index; | 562 | return index; |
518 | 563 | ||
@@ -682,7 +727,11 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c | |||
682 | fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); | 727 | fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); |
683 | 728 | ||
684 | txq->need_update = 1; | 729 | txq->need_update = 1; |
730 | |||
731 | /* Set up entry in queue's byte count circular buffer */ | ||
685 | ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); | 732 | ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); |
733 | |||
734 | /* Increment and update queue's write index */ | ||
686 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); | 735 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); |
687 | iwl4965_tx_queue_update_write_ptr(priv, txq); | 736 | iwl4965_tx_queue_update_write_ptr(priv, txq); |
688 | 737 | ||
@@ -848,7 +897,10 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, | |||
848 | { | 897 | { |
849 | u8 sta_id; | 898 | u8 sta_id; |
850 | 899 | ||
900 | /* Add station to device's station table */ | ||
851 | sta_id = iwl4965_add_station_flags(priv, addr, is_ap, 0); | 901 | sta_id = iwl4965_add_station_flags(priv, addr, is_ap, 0); |
902 | |||
903 | /* Set up default rate scaling table in device's station table */ | ||
852 | iwl4965_add_station(priv, addr, is_ap); | 904 | iwl4965_add_station(priv, addr, is_ap); |
853 | 905 | ||
854 | return sta_id; | 906 | return sta_id; |
@@ -1574,7 +1626,7 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac) | |||
1574 | /** | 1626 | /** |
1575 | * iwl4965_eeprom_init - read EEPROM contents | 1627 | * iwl4965_eeprom_init - read EEPROM contents |
1576 | * | 1628 | * |
1577 | * Load the EEPROM from adapter into priv->eeprom | 1629 | * Load the EEPROM contents from adapter into priv->eeprom |
1578 | * | 1630 | * |
1579 | * NOTE: This routine uses the non-debug IO access functions. | 1631 | * NOTE: This routine uses the non-debug IO access functions. |
1580 | */ | 1632 | */ |
@@ -1599,6 +1651,7 @@ int iwl4965_eeprom_init(struct iwl4965_priv *priv) | |||
1599 | return -ENOENT; | 1651 | return -ENOENT; |
1600 | } | 1652 | } |
1601 | 1653 | ||
1654 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
1602 | rc = iwl4965_eeprom_acquire_semaphore(priv); | 1655 | rc = iwl4965_eeprom_acquire_semaphore(priv); |
1603 | if (rc < 0) { | 1656 | if (rc < 0) { |
1604 | IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); | 1657 | IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); |
@@ -2739,6 +2792,11 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, | |||
2739 | cmd->cmd.tx.next_frame_len = 0; | 2792 | cmd->cmd.tx.next_frame_len = 0; |
2740 | } | 2793 | } |
2741 | 2794 | ||
2795 | /** | ||
2796 | * iwl4965_get_sta_id - Find station's index within station table | ||
2797 | * | ||
2798 | * If new IBSS station, create new entry in station table | ||
2799 | */ | ||
2742 | static int iwl4965_get_sta_id(struct iwl4965_priv *priv, | 2800 | static int iwl4965_get_sta_id(struct iwl4965_priv *priv, |
2743 | struct ieee80211_hdr *hdr) | 2801 | struct ieee80211_hdr *hdr) |
2744 | { | 2802 | { |
@@ -2746,16 +2804,15 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, | |||
2746 | u16 fc = le16_to_cpu(hdr->frame_control); | 2804 | u16 fc = le16_to_cpu(hdr->frame_control); |
2747 | DECLARE_MAC_BUF(mac); | 2805 | DECLARE_MAC_BUF(mac); |
2748 | 2806 | ||
2749 | /* If this frame is broadcast or not data then use the broadcast | 2807 | /* If this frame is broadcast or management, use broadcast station id */ |
2750 | * station id */ | ||
2751 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || | 2808 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || |
2752 | is_multicast_ether_addr(hdr->addr1)) | 2809 | is_multicast_ether_addr(hdr->addr1)) |
2753 | return priv->hw_setting.bcast_sta_id; | 2810 | return priv->hw_setting.bcast_sta_id; |
2754 | 2811 | ||
2755 | switch (priv->iw_mode) { | 2812 | switch (priv->iw_mode) { |
2756 | 2813 | ||
2757 | /* If this frame is part of a BSS network (we're a station), then | 2814 | /* If we are a client station in a BSS network, use the special |
2758 | * we use the AP's station id */ | 2815 | * AP station entry (that's the only station we communicate with) */ |
2759 | case IEEE80211_IF_TYPE_STA: | 2816 | case IEEE80211_IF_TYPE_STA: |
2760 | return IWL_AP_ID; | 2817 | return IWL_AP_ID; |
2761 | 2818 | ||
@@ -2766,13 +2823,14 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, | |||
2766 | return sta_id; | 2823 | return sta_id; |
2767 | return priv->hw_setting.bcast_sta_id; | 2824 | return priv->hw_setting.bcast_sta_id; |
2768 | 2825 | ||
2769 | /* If this frame is part of a IBSS network, then we use the | 2826 | /* If this frame is going out to an IBSS network, find the station, |
2770 | * target specific station id */ | 2827 | * or create a new station table entry */ |
2771 | case IEEE80211_IF_TYPE_IBSS: | 2828 | case IEEE80211_IF_TYPE_IBSS: |
2772 | sta_id = iwl4965_hw_find_station(priv, hdr->addr1); | 2829 | sta_id = iwl4965_hw_find_station(priv, hdr->addr1); |
2773 | if (sta_id != IWL_INVALID_STATION) | 2830 | if (sta_id != IWL_INVALID_STATION) |
2774 | return sta_id; | 2831 | return sta_id; |
2775 | 2832 | ||
2833 | /* Create new station table entry */ | ||
2776 | sta_id = iwl4965_add_station_flags(priv, hdr->addr1, 0, CMD_ASYNC); | 2834 | sta_id = iwl4965_add_station_flags(priv, hdr->addr1, 0, CMD_ASYNC); |
2777 | 2835 | ||
2778 | if (sta_id != IWL_INVALID_STATION) | 2836 | if (sta_id != IWL_INVALID_STATION) |
@@ -2854,6 +2912,8 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2854 | spin_unlock_irqrestore(&priv->lock, flags); | 2912 | spin_unlock_irqrestore(&priv->lock, flags); |
2855 | 2913 | ||
2856 | hdr_len = ieee80211_get_hdrlen(fc); | 2914 | hdr_len = ieee80211_get_hdrlen(fc); |
2915 | |||
2916 | /* Find (or create) index into station table for destination station */ | ||
2857 | sta_id = iwl4965_get_sta_id(priv, hdr); | 2917 | sta_id = iwl4965_get_sta_id(priv, hdr); |
2858 | if (sta_id == IWL_INVALID_STATION) { | 2918 | if (sta_id == IWL_INVALID_STATION) { |
2859 | DECLARE_MAC_BUF(mac); | 2919 | DECLARE_MAC_BUF(mac); |
@@ -2882,30 +2942,52 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2882 | #endif /* CONFIG_IWL4965_HT_AGG */ | 2942 | #endif /* CONFIG_IWL4965_HT_AGG */ |
2883 | #endif /* CONFIG_IWL4965_HT */ | 2943 | #endif /* CONFIG_IWL4965_HT */ |
2884 | } | 2944 | } |
2945 | |||
2946 | /* Descriptor for chosen Tx queue */ | ||
2885 | txq = &priv->txq[txq_id]; | 2947 | txq = &priv->txq[txq_id]; |
2886 | q = &txq->q; | 2948 | q = &txq->q; |
2887 | 2949 | ||
2888 | spin_lock_irqsave(&priv->lock, flags); | 2950 | spin_lock_irqsave(&priv->lock, flags); |
2889 | 2951 | ||
2952 | /* Set up first empty TFD within this queue's circular TFD buffer */ | ||
2890 | tfd = &txq->bd[q->write_ptr]; | 2953 | tfd = &txq->bd[q->write_ptr]; |
2891 | memset(tfd, 0, sizeof(*tfd)); | 2954 | memset(tfd, 0, sizeof(*tfd)); |
2892 | control_flags = (u32 *) tfd; | 2955 | control_flags = (u32 *) tfd; |
2893 | idx = get_cmd_index(q, q->write_ptr, 0); | 2956 | idx = get_cmd_index(q, q->write_ptr, 0); |
2894 | 2957 | ||
2958 | /* Set up driver data for this TFD */ | ||
2895 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl4965_tx_info)); | 2959 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl4965_tx_info)); |
2896 | txq->txb[q->write_ptr].skb[0] = skb; | 2960 | txq->txb[q->write_ptr].skb[0] = skb; |
2897 | memcpy(&(txq->txb[q->write_ptr].status.control), | 2961 | memcpy(&(txq->txb[q->write_ptr].status.control), |
2898 | ctl, sizeof(struct ieee80211_tx_control)); | 2962 | ctl, sizeof(struct ieee80211_tx_control)); |
2963 | |||
2964 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
2899 | out_cmd = &txq->cmd[idx]; | 2965 | out_cmd = &txq->cmd[idx]; |
2900 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | 2966 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); |
2901 | memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); | 2967 | memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); |
2968 | |||
2969 | /* | ||
2970 | * Set up the Tx-command (not MAC!) header. | ||
2971 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
2972 | * after Tx, uCode's Tx response will return this value so driver can | ||
2973 | * locate the frame within the tx queue and do post-tx processing. | ||
2974 | */ | ||
2902 | out_cmd->hdr.cmd = REPLY_TX; | 2975 | out_cmd->hdr.cmd = REPLY_TX; |
2903 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | 2976 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | |
2904 | INDEX_TO_SEQ(q->write_ptr))); | 2977 | INDEX_TO_SEQ(q->write_ptr))); |
2905 | /* copy frags header */ | 2978 | |
2979 | /* Copy MAC header from skb into command buffer */ | ||
2906 | memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); | 2980 | memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); |
2907 | 2981 | ||
2908 | /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */ | 2982 | /* |
2983 | * Use the first empty entry in this queue's command buffer array | ||
2984 | * to contain the Tx command and MAC header concatenated together | ||
2985 | * (payload data will be in another buffer). | ||
2986 | * Size of this varies, due to varying MAC header length. | ||
2987 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
2988 | * of the MAC header (device reads on dword boundaries). | ||
2989 | * We'll tell device about this padding later. | ||
2990 | */ | ||
2909 | len = priv->hw_setting.tx_cmd_len + | 2991 | len = priv->hw_setting.tx_cmd_len + |
2910 | sizeof(struct iwl4965_cmd_header) + hdr_len; | 2992 | sizeof(struct iwl4965_cmd_header) + hdr_len; |
2911 | 2993 | ||
@@ -2917,15 +2999,20 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2917 | else | 2999 | else |
2918 | len_org = 0; | 3000 | len_org = 0; |
2919 | 3001 | ||
3002 | /* Physical address of this Tx command's header (not MAC header!), | ||
3003 | * within command buffer array. */ | ||
2920 | txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx + | 3004 | txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx + |
2921 | offsetof(struct iwl4965_cmd, hdr); | 3005 | offsetof(struct iwl4965_cmd, hdr); |
2922 | 3006 | ||
3007 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
3008 | * first entry */ | ||
2923 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); | 3009 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); |
2924 | 3010 | ||
2925 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) | 3011 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) |
2926 | iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); | 3012 | iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); |
2927 | 3013 | ||
2928 | /* 802.11 null functions have no payload... */ | 3014 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
3015 | * if any (802.11 null frames have no payload). */ | ||
2929 | len = skb->len - hdr_len; | 3016 | len = skb->len - hdr_len; |
2930 | if (len) { | 3017 | if (len) { |
2931 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | 3018 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, |
@@ -2933,9 +3020,11 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2933 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); | 3020 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); |
2934 | } | 3021 | } |
2935 | 3022 | ||
3023 | /* Tell 4965 about any 2-byte padding after MAC header */ | ||
2936 | if (len_org) | 3024 | if (len_org) |
2937 | out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | 3025 | out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK; |
2938 | 3026 | ||
3027 | /* Total # bytes to be transmitted */ | ||
2939 | len = (u16)skb->len; | 3028 | len = (u16)skb->len; |
2940 | out_cmd->cmd.tx.len = cpu_to_le16(len); | 3029 | out_cmd->cmd.tx.len = cpu_to_le16(len); |
2941 | 3030 | ||
@@ -2965,8 +3054,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2965 | iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, | 3054 | iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, |
2966 | ieee80211_get_hdrlen(fc)); | 3055 | ieee80211_get_hdrlen(fc)); |
2967 | 3056 | ||
3057 | /* Set up entry for this TFD in Tx byte-count array */ | ||
2968 | iwl4965_tx_queue_update_wr_ptr(priv, txq, len); | 3058 | iwl4965_tx_queue_update_wr_ptr(priv, txq, len); |
2969 | 3059 | ||
3060 | /* Tell device the write index *just past* this latest filled TFD */ | ||
2970 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); | 3061 | q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); |
2971 | rc = iwl4965_tx_queue_update_write_ptr(priv, txq); | 3062 | rc = iwl4965_tx_queue_update_write_ptr(priv, txq); |
2972 | spin_unlock_irqrestore(&priv->lock, flags); | 3063 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -3443,11 +3534,11 @@ static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv, | |||
3443 | } | 3534 | } |
3444 | 3535 | ||
3445 | /** | 3536 | /** |
3446 | * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC. | 3537 | * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd |
3447 | * | 3538 | * |
3448 | * When FW advances 'R' index, all entries between old and | 3539 | * When FW advances 'R' index, all entries between old and new 'R' index |
3449 | * new 'R' index need to be reclaimed. As result, some free space | 3540 | * need to be reclaimed. As result, some free space forms. If there is |
3450 | * forms. If there is enough free space (> low mark), wake Tx queue. | 3541 | * enough free space (> low mark), wake the stack that feeds us. |
3451 | */ | 3542 | */ |
3452 | int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) | 3543 | int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) |
3453 | { | 3544 | { |
@@ -3528,6 +3619,10 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) | |||
3528 | return le32_to_cpu(*scd_ssn) & MAX_SN; | 3619 | return le32_to_cpu(*scd_ssn) & MAX_SN; |
3529 | 3620 | ||
3530 | } | 3621 | } |
3622 | |||
3623 | /** | ||
3624 | * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue | ||
3625 | */ | ||
3531 | static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, | 3626 | static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, |
3532 | struct iwl4965_ht_agg *agg, | 3627 | struct iwl4965_ht_agg *agg, |
3533 | struct iwl4965_tx_resp *tx_resp, | 3628 | struct iwl4965_tx_resp *tx_resp, |
@@ -3542,14 +3637,16 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, | |||
3542 | u16 seq; | 3637 | u16 seq; |
3543 | 3638 | ||
3544 | if (agg->wait_for_ba) | 3639 | if (agg->wait_for_ba) |
3545 | IWL_DEBUG_TX_REPLY("got tx repsons w/o back\n"); | 3640 | IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); |
3546 | 3641 | ||
3547 | agg->frame_count = tx_resp->frame_count; | 3642 | agg->frame_count = tx_resp->frame_count; |
3548 | agg->start_idx = start_idx; | 3643 | agg->start_idx = start_idx; |
3549 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | 3644 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); |
3550 | agg->bitmap0 = agg->bitmap1 = 0; | 3645 | agg->bitmap0 = agg->bitmap1 = 0; |
3551 | 3646 | ||
3647 | /* # frames attempted by Tx command */ | ||
3552 | if (agg->frame_count == 1) { | 3648 | if (agg->frame_count == 1) { |
3649 | /* Only one frame was attempted; no block-ack will arrive */ | ||
3553 | struct iwl4965_tx_queue *txq ; | 3650 | struct iwl4965_tx_queue *txq ; |
3554 | status = le32_to_cpu(frame_status[0]); | 3651 | status = le32_to_cpu(frame_status[0]); |
3555 | 3652 | ||
@@ -3578,9 +3675,11 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, | |||
3578 | 3675 | ||
3579 | agg->wait_for_ba = 0; | 3676 | agg->wait_for_ba = 0; |
3580 | } else { | 3677 | } else { |
3678 | /* Two or more frames were attempted; expect block-ack */ | ||
3581 | u64 bitmap = 0; | 3679 | u64 bitmap = 0; |
3582 | int start = agg->start_idx; | 3680 | int start = agg->start_idx; |
3583 | 3681 | ||
3682 | /* Construct bit-map of pending frames within Tx window */ | ||
3584 | for (i = 0; i < agg->frame_count; i++) { | 3683 | for (i = 0; i < agg->frame_count; i++) { |
3585 | u16 sc; | 3684 | u16 sc; |
3586 | status = le32_to_cpu(frame_status[i]); | 3685 | status = le32_to_cpu(frame_status[i]); |
@@ -3644,6 +3743,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, | |||
3644 | #endif | 3743 | #endif |
3645 | #endif | 3744 | #endif |
3646 | 3745 | ||
3746 | /** | ||
3747 | * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response | ||
3748 | */ | ||
3647 | static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, | 3749 | static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, |
3648 | struct iwl4965_rx_mem_buffer *rxb) | 3750 | struct iwl4965_rx_mem_buffer *rxb) |
3649 | { | 3751 | { |
@@ -4265,6 +4367,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ | |||
4265 | if (q->need_update == 0) | 4367 | if (q->need_update == 0) |
4266 | goto exit_unlock; | 4368 | goto exit_unlock; |
4267 | 4369 | ||
4370 | /* If power-saving is in use, make sure device is awake */ | ||
4268 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 4371 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { |
4269 | reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1); | 4372 | reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1); |
4270 | 4373 | ||
@@ -4278,10 +4381,14 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ | |||
4278 | if (rc) | 4381 | if (rc) |
4279 | goto exit_unlock; | 4382 | goto exit_unlock; |
4280 | 4383 | ||
4384 | /* Device expects a multiple of 8 */ | ||
4281 | iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, | 4385 | iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, |
4282 | q->write & ~0x7); | 4386 | q->write & ~0x7); |
4283 | iwl4965_release_nic_access(priv); | 4387 | iwl4965_release_nic_access(priv); |
4388 | |||
4389 | /* Else device is assumed to be awake */ | ||
4284 | } else | 4390 | } else |
4391 | /* Device expects a multiple of 8 */ | ||
4285 | iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); | 4392 | iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); |
4286 | 4393 | ||
4287 | 4394 | ||
@@ -4324,9 +4431,12 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) | |||
4324 | spin_lock_irqsave(&rxq->lock, flags); | 4431 | spin_lock_irqsave(&rxq->lock, flags); |
4325 | write = rxq->write & ~0x7; | 4432 | write = rxq->write & ~0x7; |
4326 | while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | 4433 | while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) { |
4434 | /* Get next free Rx buffer, remove from free list */ | ||
4327 | element = rxq->rx_free.next; | 4435 | element = rxq->rx_free.next; |
4328 | rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); | 4436 | rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); |
4329 | list_del(element); | 4437 | list_del(element); |
4438 | |||
4439 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
4330 | rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr); | 4440 | rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr); |
4331 | rxq->queue[rxq->write] = rxb; | 4441 | rxq->queue[rxq->write] = rxb; |
4332 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 4442 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
@@ -4339,7 +4449,8 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) | |||
4339 | queue_work(priv->workqueue, &priv->rx_replenish); | 4449 | queue_work(priv->workqueue, &priv->rx_replenish); |
4340 | 4450 | ||
4341 | 4451 | ||
4342 | /* If we've added more space for the firmware to place data, tell it */ | 4452 | /* If we've added more space for the firmware to place data, tell it. |
4453 | * Increment device's write pointer in multiples of 8. */ | ||
4343 | if ((write != (rxq->write & ~0x7)) | 4454 | if ((write != (rxq->write & ~0x7)) |
4344 | || (abs(rxq->write - rxq->read) > 7)) { | 4455 | || (abs(rxq->write - rxq->read) > 7)) { |
4345 | spin_lock_irqsave(&rxq->lock, flags); | 4456 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -4372,6 +4483,8 @@ void iwl4965_rx_replenish(void *data) | |||
4372 | while (!list_empty(&rxq->rx_used)) { | 4483 | while (!list_empty(&rxq->rx_used)) { |
4373 | element = rxq->rx_used.next; | 4484 | element = rxq->rx_used.next; |
4374 | rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); | 4485 | rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); |
4486 | |||
4487 | /* Alloc a new receive buffer */ | ||
4375 | rxb->skb = | 4488 | rxb->skb = |
4376 | alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); | 4489 | alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); |
4377 | if (!rxb->skb) { | 4490 | if (!rxb->skb) { |
@@ -4385,6 +4498,8 @@ void iwl4965_rx_replenish(void *data) | |||
4385 | } | 4498 | } |
4386 | priv->alloc_rxb_skb++; | 4499 | priv->alloc_rxb_skb++; |
4387 | list_del(element); | 4500 | list_del(element); |
4501 | |||
4502 | /* Get physical address of RB/SKB */ | ||
4388 | rxb->dma_addr = | 4503 | rxb->dma_addr = |
4389 | pci_map_single(priv->pci_dev, rxb->skb->data, | 4504 | pci_map_single(priv->pci_dev, rxb->skb->data, |
4390 | IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 4505 | IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
@@ -4429,12 +4544,16 @@ int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv) | |||
4429 | spin_lock_init(&rxq->lock); | 4544 | spin_lock_init(&rxq->lock); |
4430 | INIT_LIST_HEAD(&rxq->rx_free); | 4545 | INIT_LIST_HEAD(&rxq->rx_free); |
4431 | INIT_LIST_HEAD(&rxq->rx_used); | 4546 | INIT_LIST_HEAD(&rxq->rx_used); |
4547 | |||
4548 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | ||
4432 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 4549 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); |
4433 | if (!rxq->bd) | 4550 | if (!rxq->bd) |
4434 | return -ENOMEM; | 4551 | return -ENOMEM; |
4552 | |||
4435 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | 4553 | /* Fill the rx_used queue with _all_ of the Rx buffers */ |
4436 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) | 4554 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) |
4437 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 4555 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
4556 | |||
4438 | /* Set us so that we have processed and used all buffers, but have | 4557 | /* Set us so that we have processed and used all buffers, but have |
4439 | * not restocked the Rx queue with fresh buffers */ | 4558 | * not restocked the Rx queue with fresh buffers */ |
4440 | rxq->read = rxq->write = 0; | 4559 | rxq->read = rxq->write = 0; |
@@ -4566,6 +4685,8 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) | |||
4566 | int reclaim; | 4685 | int reclaim; |
4567 | unsigned long flags; | 4686 | unsigned long flags; |
4568 | 4687 | ||
4688 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | ||
4689 | * buffer that the driver may process (last buffer filled by ucode). */ | ||
4569 | r = iwl4965_hw_get_rx_read(priv); | 4690 | r = iwl4965_hw_get_rx_read(priv); |
4570 | i = rxq->read; | 4691 | i = rxq->read; |
4571 | 4692 | ||
@@ -4649,6 +4770,9 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) | |||
4649 | iwl4965_rx_queue_restock(priv); | 4770 | iwl4965_rx_queue_restock(priv); |
4650 | } | 4771 | } |
4651 | 4772 | ||
4773 | /** | ||
4774 | * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware | ||
4775 | */ | ||
4652 | static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, | 4776 | static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, |
4653 | struct iwl4965_tx_queue *txq) | 4777 | struct iwl4965_tx_queue *txq) |
4654 | { | 4778 | { |
@@ -5282,6 +5406,11 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, | |||
5282 | } | 5406 | } |
5283 | } | 5407 | } |
5284 | 5408 | ||
5409 | /** | ||
5410 | * iwl4965_get_channel_info - Find driver's private channel info | ||
5411 | * | ||
5412 | * Based on band and channel number. | ||
5413 | */ | ||
5285 | const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, | 5414 | const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, |
5286 | int phymode, u16 channel) | 5415 | int phymode, u16 channel) |
5287 | { | 5416 | { |
@@ -5309,6 +5438,9 @@ const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965 | |||
5309 | #define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ | 5438 | #define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ |
5310 | ? # x " " : "") | 5439 | ? # x " " : "") |
5311 | 5440 | ||
5441 | /** | ||
5442 | * iwl4965_init_channel_map - Set up driver's info for all possible channels | ||
5443 | */ | ||
5312 | static int iwl4965_init_channel_map(struct iwl4965_priv *priv) | 5444 | static int iwl4965_init_channel_map(struct iwl4965_priv *priv) |
5313 | { | 5445 | { |
5314 | int eeprom_ch_count = 0; | 5446 | int eeprom_ch_count = 0; |
@@ -5418,6 +5550,7 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) | |||
5418 | } | 5550 | } |
5419 | } | 5551 | } |
5420 | 5552 | ||
5553 | /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ | ||
5421 | for (band = 6; band <= 7; band++) { | 5554 | for (band = 6; band <= 7; band++) { |
5422 | int phymode; | 5555 | int phymode; |
5423 | u8 fat_extension_chan; | 5556 | u8 fat_extension_chan; |
@@ -5425,7 +5558,9 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) | |||
5425 | iwl4965_init_band_reference(priv, band, &eeprom_ch_count, | 5558 | iwl4965_init_band_reference(priv, band, &eeprom_ch_count, |
5426 | &eeprom_ch_info, &eeprom_ch_index); | 5559 | &eeprom_ch_info, &eeprom_ch_index); |
5427 | 5560 | ||
5561 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
5428 | phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A; | 5562 | phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A; |
5563 | |||
5429 | /* Loop through each band adding each of the channels */ | 5564 | /* Loop through each band adding each of the channels */ |
5430 | for (ch = 0; ch < eeprom_ch_count; ch++) { | 5565 | for (ch = 0; ch < eeprom_ch_count; ch++) { |
5431 | 5566 | ||
@@ -5437,11 +5572,13 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) | |||
5437 | else | 5572 | else |
5438 | fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; | 5573 | fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; |
5439 | 5574 | ||
5575 | /* Set up driver's info for lower half */ | ||
5440 | iwl4965_set_fat_chan_info(priv, phymode, | 5576 | iwl4965_set_fat_chan_info(priv, phymode, |
5441 | eeprom_ch_index[ch], | 5577 | eeprom_ch_index[ch], |
5442 | &(eeprom_ch_info[ch]), | 5578 | &(eeprom_ch_info[ch]), |
5443 | fat_extension_chan); | 5579 | fat_extension_chan); |
5444 | 5580 | ||
5581 | /* Set up driver's info for upper half */ | ||
5445 | iwl4965_set_fat_chan_info(priv, phymode, | 5582 | iwl4965_set_fat_chan_info(priv, phymode, |
5446 | (eeprom_ch_index[ch] + 4), | 5583 | (eeprom_ch_index[ch] + 4), |
5447 | &(eeprom_ch_info[ch]), | 5584 | &(eeprom_ch_info[ch]), |
@@ -8951,6 +9088,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8951 | struct ieee80211_hw *hw; | 9088 | struct ieee80211_hw *hw; |
8952 | int i; | 9089 | int i; |
8953 | 9090 | ||
9091 | /* Disabling hardware scan means that mac80211 will perform scans | ||
9092 | * "the hard way", rather than using device's scan. */ | ||
8954 | if (iwl4965_param_disable_hw_scan) { | 9093 | if (iwl4965_param_disable_hw_scan) { |
8955 | IWL_DEBUG_INFO("Disabling hw_scan\n"); | 9094 | IWL_DEBUG_INFO("Disabling hw_scan\n"); |
8956 | iwl4965_hw_ops.hw_scan = NULL; | 9095 | iwl4965_hw_ops.hw_scan = NULL; |
@@ -9002,9 +9141,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
9002 | /* Tell mac80211 our Tx characteristics */ | 9141 | /* Tell mac80211 our Tx characteristics */ |
9003 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; | 9142 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; |
9004 | 9143 | ||
9144 | /* Default value; 4 EDCA QOS priorities */ | ||
9005 | hw->queues = 4; | 9145 | hw->queues = 4; |
9006 | #ifdef CONFIG_IWL4965_HT | 9146 | #ifdef CONFIG_IWL4965_HT |
9007 | #ifdef CONFIG_IWL4965_HT_AGG | 9147 | #ifdef CONFIG_IWL4965_HT_AGG |
9148 | /* Enhanced value; more queues, to support 11n aggregation */ | ||
9008 | hw->queues = 16; | 9149 | hw->queues = 16; |
9009 | #endif /* CONFIG_IWL4965_HT_AGG */ | 9150 | #endif /* CONFIG_IWL4965_HT_AGG */ |
9010 | #endif /* CONFIG_IWL4965_HT */ | 9151 | #endif /* CONFIG_IWL4965_HT */ |
@@ -9028,6 +9169,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
9028 | 9169 | ||
9029 | pci_set_master(pdev); | 9170 | pci_set_master(pdev); |
9030 | 9171 | ||
9172 | /* Clear the driver's (not device's) station table */ | ||
9031 | iwl4965_clear_stations_table(priv); | 9173 | iwl4965_clear_stations_table(priv); |
9032 | 9174 | ||
9033 | priv->data_retry_limit = -1; | 9175 | priv->data_retry_limit = -1; |
@@ -9047,9 +9189,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
9047 | err = pci_request_regions(pdev, DRV_NAME); | 9189 | err = pci_request_regions(pdev, DRV_NAME); |
9048 | if (err) | 9190 | if (err) |
9049 | goto out_pci_disable_device; | 9191 | goto out_pci_disable_device; |
9192 | |||
9050 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 9193 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
9051 | * PCI Tx retries from interfering with C3 CPU state */ | 9194 | * PCI Tx retries from interfering with C3 CPU state */ |
9052 | pci_write_config_byte(pdev, 0x41, 0x00); | 9195 | pci_write_config_byte(pdev, 0x41, 0x00); |
9196 | |||
9053 | priv->hw_base = pci_iomap(pdev, 0, 0); | 9197 | priv->hw_base = pci_iomap(pdev, 0, 0); |
9054 | if (!priv->hw_base) { | 9198 | if (!priv->hw_base) { |
9055 | err = -ENODEV; | 9199 | err = -ENODEV; |
@@ -9062,6 +9206,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
9062 | 9206 | ||
9063 | /* Initialize module parameter values here */ | 9207 | /* Initialize module parameter values here */ |
9064 | 9208 | ||
9209 | /* Disable radio (SW RF KILL) via parameter when loading driver */ | ||
9065 | if (iwl4965_param_disable) { | 9210 | if (iwl4965_param_disable) { |
9066 | set_bit(STATUS_RF_KILL_SW, &priv->status); | 9211 | set_bit(STATUS_RF_KILL_SW, &priv->status); |
9067 | IWL_DEBUG_INFO("Radio disabled.\n"); | 9212 | IWL_DEBUG_INFO("Radio disabled.\n"); |
@@ -9076,6 +9221,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
9076 | priv->valid_antenna = 0x7; /* assume all 3 connected */ | 9221 | priv->valid_antenna = 0x7; /* assume all 3 connected */ |
9077 | priv->ps_mode = IWL_MIMO_PS_NONE; | 9222 | priv->ps_mode = IWL_MIMO_PS_NONE; |
9078 | 9223 | ||
9224 | /* Choose which receivers/antennas to use */ | ||
9079 | iwl4965_set_rxon_chain(priv); | 9225 | iwl4965_set_rxon_chain(priv); |
9080 | 9226 | ||
9081 | printk(KERN_INFO DRV_NAME | 9227 | printk(KERN_INFO DRV_NAME |