diff options
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 11 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 59 |
3 files changed, 60 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 112149e9b31e..894bcb8b8b37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
| @@ -307,10 +307,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
| 307 | 307 | ||
| 308 | spin_unlock_irqrestore(&priv->lock, flags); | 308 | spin_unlock_irqrestore(&priv->lock, flags); |
| 309 | 309 | ||
| 310 | /* Allocate and init all Tx and Command queues */ | 310 | /* Allocate or reset and init all Tx and Command queues */ |
| 311 | ret = iwl_txq_ctx_reset(priv); | 311 | if (!priv->txq) { |
| 312 | if (ret) | 312 | ret = iwl_txq_ctx_alloc(priv); |
| 313 | return ret; | 313 | if (ret) |
| 314 | return ret; | ||
| 315 | } else | ||
| 316 | iwl_txq_ctx_reset(priv); | ||
| 314 | 317 | ||
| 315 | set_bit(STATUS_INIT, &priv->status); | 318 | set_bit(STATUS_INIT, &priv->status); |
| 316 | 319 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ef7739f9e8e..732590f5fe30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
| @@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
| 442 | /***************************************************** | 442 | /***************************************************** |
| 443 | * TX | 443 | * TX |
| 444 | ******************************************************/ | 444 | ******************************************************/ |
| 445 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
| 446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
| 446 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 447 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
| 448 | struct iwl_tx_queue *txq, | 449 | struct iwl_tx_queue *txq, |
| @@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
| 456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
| 458 | int slots_num, u32 txq_id); | 459 | int slots_num, u32 txq_id); |
| 460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 461 | int slots_num, u32 txq_id); | ||
| 459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
| 460 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
| 461 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 6aa309032f4e..343d81ad2653 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -433,6 +433,26 @@ out_free_arrays: | |||
| 433 | } | 433 | } |
| 434 | EXPORT_SYMBOL(iwl_tx_queue_init); | 434 | EXPORT_SYMBOL(iwl_tx_queue_init); |
| 435 | 435 | ||
| 436 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 437 | int slots_num, u32 txq_id) | ||
| 438 | { | ||
| 439 | int actual_slots = slots_num; | ||
| 440 | |||
| 441 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
| 442 | actual_slots++; | ||
| 443 | |||
| 444 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
| 445 | |||
| 446 | txq->need_update = 0; | ||
| 447 | |||
| 448 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
| 449 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
| 450 | |||
| 451 | /* Tell device where to find queue */ | ||
| 452 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
| 453 | } | ||
| 454 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
| 455 | |||
| 436 | /** | 456 | /** |
| 437 | * iwl_hw_txq_ctx_free - Free TXQ Context | 457 | * iwl_hw_txq_ctx_free - Free TXQ Context |
| 438 | * | 458 | * |
| @@ -444,8 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 444 | 464 | ||
| 445 | /* Tx queues */ | 465 | /* Tx queues */ |
| 446 | if (priv->txq) { | 466 | if (priv->txq) { |
| 447 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | 467 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
| 448 | txq_id++) | ||
| 449 | if (txq_id == IWL_CMD_QUEUE_NUM) | 468 | if (txq_id == IWL_CMD_QUEUE_NUM) |
| 450 | iwl_cmd_queue_free(priv); | 469 | iwl_cmd_queue_free(priv); |
| 451 | else | 470 | else |
| @@ -461,15 +480,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 461 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 480 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
| 462 | 481 | ||
| 463 | /** | 482 | /** |
| 464 | * iwl_txq_ctx_reset - Reset TX queue context | 483 | * iwl_txq_ctx_alloc - allocate TX queue context |
| 465 | * Destroys all DMA structures and initialize them again | 484 | * Allocate all Tx DMA structures and initialize them |
| 466 | * | 485 | * |
| 467 | * @param priv | 486 | * @param priv |
| 468 | * @return error code | 487 | * @return error code |
| 469 | */ | 488 | */ |
| 470 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 489 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) |
| 471 | { | 490 | { |
| 472 | int ret = 0; | 491 | int ret; |
| 473 | int txq_id, slots_num; | 492 | int txq_id, slots_num; |
| 474 | unsigned long flags; | 493 | unsigned long flags; |
| 475 | 494 | ||
| @@ -527,8 +546,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
| 527 | return ret; | 546 | return ret; |
| 528 | } | 547 | } |
| 529 | 548 | ||
| 549 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
| 550 | { | ||
| 551 | int txq_id, slots_num; | ||
| 552 | unsigned long flags; | ||
| 553 | |||
| 554 | spin_lock_irqsave(&priv->lock, flags); | ||
| 555 | |||
| 556 | /* Turn off all Tx DMA fifos */ | ||
| 557 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
| 558 | |||
| 559 | /* Tell NIC where to find the "keep warm" buffer */ | ||
| 560 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
| 561 | |||
| 562 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 563 | |||
| 564 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
| 565 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
| 566 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
| 567 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
| 568 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 530 | /** | 572 | /** |
| 531 | * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | 573 | * iwl_txq_ctx_stop - Stop all Tx DMA channels |
| 532 | */ | 574 | */ |
| 533 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 575 | void iwl_txq_ctx_stop(struct iwl_priv *priv) |
| 534 | { | 576 | { |
| @@ -548,9 +590,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) | |||
| 548 | 1000); | 590 | 1000); |
| 549 | } | 591 | } |
| 550 | spin_unlock_irqrestore(&priv->lock, flags); | 592 | spin_unlock_irqrestore(&priv->lock, flags); |
| 551 | |||
| 552 | /* Deallocate memory for all Tx queues */ | ||
| 553 | iwl_hw_txq_ctx_free(priv); | ||
| 554 | } | 593 | } |
| 555 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 594 | EXPORT_SYMBOL(iwl_txq_ctx_stop); |
| 556 | 595 | ||
