diff options
author | Samuel Ortiz <samuel.ortiz@intel.com> | 2009-01-23 16:45:14 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:01:34 -0500 |
commit | a8e74e2774cd1aecfef0460de07e6e178df89232 (patch) | |
tree | bccf507738fb8753e7ab16a8de9644e9d99ae07c /drivers/net/wireless/iwlwifi | |
parent | 59606ffa9146538b73bbe1ca1285321cd7474bc0 (diff) |
iwl3945: Use iwlcore TX queue management routines
By adding an additional hw_params (tfd_size) and a new iwl_lib ops (txq_init),
we can now use the iwlcore TX queue management routines.
We had to add a new hw_params because we need to allocate the right DMA buffer
for TFDs, and those have a different sizes depending if you're on 3945 or agn.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 49 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 204 |
8 files changed, 60 insertions, 246 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 22770f44c2fa..2689113f4e60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -1068,8 +1068,8 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
1068 | for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { | 1068 | for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { |
1069 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | 1069 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? |
1070 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 1070 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; |
1071 | rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | 1071 | rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, |
1072 | txq_id); | 1072 | txq_id); |
1073 | if (rc) { | 1073 | if (rc) { |
1074 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | 1074 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); |
1075 | goto error; | 1075 | goto error; |
@@ -1258,7 +1258,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1258 | 1258 | ||
1259 | /* Tx queues */ | 1259 | /* Tx queues */ |
1260 | for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) | 1260 | for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) |
1261 | iwl3945_tx_queue_free(priv, &priv->txq[txq_id]); | 1261 | iwl_tx_queue_free(priv, txq_id); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | 1264 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) |
@@ -2491,6 +2491,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2491 | return -ENOMEM; | 2491 | return -ENOMEM; |
2492 | } | 2492 | } |
2493 | 2493 | ||
2494 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | ||
2494 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; | 2495 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; |
2495 | priv->hw_params.max_pkt_size = 2342; | 2496 | priv->hw_params.max_pkt_size = 2342; |
2496 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 2497 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
@@ -2705,6 +2706,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) | |||
2705 | static struct iwl_lib_ops iwl3945_lib = { | 2706 | static struct iwl_lib_ops iwl3945_lib = { |
2706 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, | 2707 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, |
2707 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, | 2708 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, |
2709 | .txq_init = iwl3945_hw_tx_queue_init, | ||
2708 | .load_ucode = iwl3945_load_bsm, | 2710 | .load_ucode = iwl3945_load_bsm, |
2709 | .apm_ops = { | 2711 | .apm_ops = { |
2710 | .init = iwl3945_apm_init, | 2712 | .init = iwl3945_apm_init, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b2985e25dc83..d7d956db19d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -815,6 +815,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
815 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | 815 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
816 | priv->hw_params.scd_bc_tbls_size = | 816 | priv->hw_params.scd_bc_tbls_size = |
817 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); | 817 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); |
818 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
818 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 819 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
819 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 820 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
820 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; | 821 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; |
@@ -2297,6 +2298,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2297 | .txq_agg_disable = iwl4965_txq_agg_disable, | 2298 | .txq_agg_disable = iwl4965_txq_agg_disable, |
2298 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 2299 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
2299 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 2300 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
2301 | .txq_init = iwl_hw_tx_queue_init, | ||
2300 | .rx_handler_setup = iwl4965_rx_handler_setup, | 2302 | .rx_handler_setup = iwl4965_rx_handler_setup, |
2301 | .setup_deferred_work = iwl4965_setup_deferred_work, | 2303 | .setup_deferred_work = iwl4965_setup_deferred_work, |
2302 | .cancel_deferred_work = iwl4965_cancel_deferred_work, | 2304 | .cancel_deferred_work = iwl4965_cancel_deferred_work, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 04c2585a6341..89d92a8ca157 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -837,6 +837,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
837 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 837 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
838 | priv->hw_params.scd_bc_tbls_size = | 838 | priv->hw_params.scd_bc_tbls_size = |
839 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | 839 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); |
840 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
840 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 841 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
841 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 842 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
842 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 843 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; |
@@ -1494,6 +1495,7 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
1494 | .txq_agg_disable = iwl5000_txq_agg_disable, | 1495 | .txq_agg_disable = iwl5000_txq_agg_disable, |
1495 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 1496 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1496 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 1497 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1498 | .txq_init = iwl_hw_tx_queue_init, | ||
1497 | .rx_handler_setup = iwl5000_rx_handler_setup, | 1499 | .rx_handler_setup = iwl5000_rx_handler_setup, |
1498 | .setup_deferred_work = iwl5000_setup_deferred_work, | 1500 | .setup_deferred_work = iwl5000_setup_deferred_work, |
1499 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1501 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4ce3d6a63d18..5c6b3fe3eedf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -592,6 +592,38 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
592 | return 0; | 592 | return 0; |
593 | } | 593 | } |
594 | 594 | ||
595 | /* | ||
596 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
597 | * given Tx queue, and enable the DMA channel used for that queue. | ||
598 | * | ||
599 | * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
600 | * channels supported in hardware. | ||
601 | */ | ||
602 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
603 | struct iwl_tx_queue *txq) | ||
604 | { | ||
605 | int ret; | ||
606 | unsigned long flags; | ||
607 | int txq_id = txq->q.id; | ||
608 | |||
609 | spin_lock_irqsave(&priv->lock, flags); | ||
610 | ret = iwl_grab_nic_access(priv); | ||
611 | if (ret) { | ||
612 | spin_unlock_irqrestore(&priv->lock, flags); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
617 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
618 | txq->q.dma_addr >> 8); | ||
619 | |||
620 | iwl_release_nic_access(priv); | ||
621 | spin_unlock_irqrestore(&priv->lock, flags); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | |||
595 | /****************************************************************************** | 627 | /****************************************************************************** |
596 | * | 628 | * |
597 | * Misc. internal state and helper functions | 629 | * Misc. internal state and helper functions |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 409caaa31bb1..9a350806a21e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -116,6 +116,8 @@ struct iwl_lib_ops { | |||
116 | u16 len, u8 reset, u8 pad); | 116 | u16 len, u8 reset, u8 pad); |
117 | void (*txq_free_tfd)(struct iwl_priv *priv, | 117 | void (*txq_free_tfd)(struct iwl_priv *priv, |
118 | struct iwl_tx_queue *txq); | 118 | struct iwl_tx_queue *txq); |
119 | int (*txq_init)(struct iwl_priv *priv, | ||
120 | struct iwl_tx_queue *txq); | ||
119 | /* aggregations */ | 121 | /* aggregations */ |
120 | int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, | 122 | int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, |
121 | int sta_id, int tid, u16 ssn_idx); | 123 | int sta_id, int tid, u16 ssn_idx); |
@@ -264,7 +266,12 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
264 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 266 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
265 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | 267 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); |
266 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | 268 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); |
269 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
270 | struct iwl_tx_queue *txq); | ||
267 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 271 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
272 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
273 | int slots_num, u32 txq_id); | ||
274 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | ||
268 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 275 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
269 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 276 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
270 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); | 277 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 78ce4f49c568..5aa22d61e398 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -567,6 +567,7 @@ struct iwl_sensitivity_ranges { | |||
567 | * @max_txq_num: Max # Tx queues supported | 567 | * @max_txq_num: Max # Tx queues supported |
568 | * @dma_chnl_num: Number of Tx DMA/FIFO channels | 568 | * @dma_chnl_num: Number of Tx DMA/FIFO channels |
569 | * @scd_bc_tbls_size: size of scheduler byte count tables | 569 | * @scd_bc_tbls_size: size of scheduler byte count tables |
570 | * @tfd_size: TFD size | ||
570 | * @tx/rx_chains_num: Number of TX/RX chains | 571 | * @tx/rx_chains_num: Number of TX/RX chains |
571 | * @valid_tx/rx_ant: usable antennas | 572 | * @valid_tx/rx_ant: usable antennas |
572 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) | 573 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) |
@@ -587,6 +588,7 @@ struct iwl_hw_params { | |||
587 | u8 max_txq_num; | 588 | u8 max_txq_num; |
588 | u8 dma_chnl_num; | 589 | u8 dma_chnl_num; |
589 | u16 scd_bc_tbls_size; | 590 | u16 scd_bc_tbls_size; |
591 | u32 tfd_size; | ||
590 | u8 tx_chains_num; | 592 | u8 tx_chains_num; |
591 | u8 rx_chains_num; | 593 | u8 rx_chains_num; |
592 | u8 valid_tx_ant; | 594 | u8 valid_tx_ant; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 83e9f32cbd8e..58118c8224cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -131,7 +131,7 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr); | |||
131 | * Free all buffers. | 131 | * Free all buffers. |
132 | * 0-fill, but do not free "txq" descriptor structure. | 132 | * 0-fill, but do not free "txq" descriptor structure. |
133 | */ | 133 | */ |
134 | static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | 134 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) |
135 | { | 135 | { |
136 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 136 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
137 | struct iwl_queue *q = &txq->q; | 137 | struct iwl_queue *q = &txq->q; |
@@ -154,7 +154,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
154 | 154 | ||
155 | /* De-alloc circular buffer of TFDs */ | 155 | /* De-alloc circular buffer of TFDs */ |
156 | if (txq->q.n_bd) | 156 | if (txq->q.n_bd) |
157 | pci_free_consistent(dev, sizeof(struct iwl_tfd) * | 157 | pci_free_consistent(dev, priv->hw_params.tfd_size * |
158 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 158 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
159 | 159 | ||
160 | /* De-alloc array of per-TFD driver data */ | 160 | /* De-alloc array of per-TFD driver data */ |
@@ -164,7 +164,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
164 | /* 0-fill queue descriptor structure */ | 164 | /* 0-fill queue descriptor structure */ |
165 | memset(txq, 0, sizeof(*txq)); | 165 | memset(txq, 0, sizeof(*txq)); |
166 | } | 166 | } |
167 | 167 | EXPORT_SYMBOL(iwl_tx_queue_free); | |
168 | 168 | ||
169 | /** | 169 | /** |
170 | * iwl_cmd_queue_free - Deallocate DMA queue. | 170 | * iwl_cmd_queue_free - Deallocate DMA queue. |
@@ -295,12 +295,12 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
295 | /* Circular buffer of transmit frame descriptors (TFDs), | 295 | /* Circular buffer of transmit frame descriptors (TFDs), |
296 | * shared with device */ | 296 | * shared with device */ |
297 | txq->tfds = pci_alloc_consistent(dev, | 297 | txq->tfds = pci_alloc_consistent(dev, |
298 | sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX, | 298 | priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX, |
299 | &txq->q.dma_addr); | 299 | &txq->q.dma_addr); |
300 | 300 | ||
301 | if (!txq->tfds) { | 301 | if (!txq->tfds) { |
302 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", | 302 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", |
303 | sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX); | 303 | priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX); |
304 | goto error; | 304 | goto error; |
305 | } | 305 | } |
306 | txq->q.id = id; | 306 | txq->q.id = id; |
@@ -314,42 +314,11 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
314 | return -ENOMEM; | 314 | return -ENOMEM; |
315 | } | 315 | } |
316 | 316 | ||
317 | /* | ||
318 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
319 | * given Tx queue, and enable the DMA channel used for that queue. | ||
320 | * | ||
321 | * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
322 | * channels supported in hardware. | ||
323 | */ | ||
324 | static int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
325 | struct iwl_tx_queue *txq) | ||
326 | { | ||
327 | int ret; | ||
328 | unsigned long flags; | ||
329 | int txq_id = txq->q.id; | ||
330 | |||
331 | spin_lock_irqsave(&priv->lock, flags); | ||
332 | ret = iwl_grab_nic_access(priv); | ||
333 | if (ret) { | ||
334 | spin_unlock_irqrestore(&priv->lock, flags); | ||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
339 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
340 | txq->q.dma_addr >> 8); | ||
341 | |||
342 | iwl_release_nic_access(priv); | ||
343 | spin_unlock_irqrestore(&priv->lock, flags); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | /** | 317 | /** |
349 | * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue | 318 | * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue |
350 | */ | 319 | */ |
351 | static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 320 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
352 | int slots_num, u32 txq_id) | 321 | int slots_num, u32 txq_id) |
353 | { | 322 | { |
354 | int i, len; | 323 | int i, len; |
355 | int ret; | 324 | int ret; |
@@ -391,7 +360,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
391 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | 360 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); |
392 | 361 | ||
393 | /* Tell device where to find queue */ | 362 | /* Tell device where to find queue */ |
394 | iwl_hw_tx_queue_init(priv, txq); | 363 | priv->cfg->ops->lib->txq_init(priv, txq); |
395 | 364 | ||
396 | return 0; | 365 | return 0; |
397 | err: | 366 | err: |
@@ -406,6 +375,8 @@ err: | |||
406 | } | 375 | } |
407 | return -ENOMEM; | 376 | return -ENOMEM; |
408 | } | 377 | } |
378 | EXPORT_SYMBOL(iwl_tx_queue_init); | ||
379 | |||
409 | /** | 380 | /** |
410 | * iwl_hw_txq_ctx_free - Free TXQ Context | 381 | * iwl_hw_txq_ctx_free - Free TXQ Context |
411 | * | 382 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bc10e2ae597d..14f95238059a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -93,210 +93,6 @@ struct iwl_mod_params iwl3945_mod_params = { | |||
93 | /* the rest are 0 by default */ | 93 | /* the rest are 0 by default */ |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | ||
97 | * DMA services | ||
98 | * | ||
99 | * Theory of operation | ||
100 | * | ||
101 | * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer | ||
102 | * of buffer descriptors, each of which points to one or more data buffers for | ||
103 | * the device to read from or fill. Driver and device exchange status of each | ||
104 | * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty | ||
105 | * entries in each circular buffer, to protect against confusing empty and full | ||
106 | * queue states. | ||
107 | * | ||
108 | * The device reads or writes the data in the queues via the device's several | ||
109 | * DMA/FIFO channels. Each queue is mapped to a single DMA channel. | ||
110 | * | ||
111 | * For Tx queue, there are low mark and high mark limits. If, after queuing | ||
112 | * the packet for Tx, free space become < low mark, Tx queue stopped. When | ||
113 | * reclaiming packets (on 'tx done IRQ), if free space become > high mark, | ||
114 | * Tx queue resumed. | ||
115 | * | ||
116 | * The 3945 operates with six queues: One receive queue, one transmit queue | ||
117 | * (#4) for sending commands to the device firmware, and four transmit queues | ||
118 | * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. | ||
119 | ***************************************************/ | ||
120 | |||
121 | /** | ||
122 | * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes | ||
123 | */ | ||
124 | static int iwl3945_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | ||
125 | int count, int slots_num, u32 id) | ||
126 | { | ||
127 | q->n_bd = count; | ||
128 | q->n_window = slots_num; | ||
129 | q->id = id; | ||
130 | |||
131 | /* count must be power-of-two size, otherwise iwl_queue_inc_wrap | ||
132 | * and iwl_queue_dec_wrap are broken. */ | ||
133 | BUG_ON(!is_power_of_2(count)); | ||
134 | |||
135 | /* slots_num must be power-of-two size, otherwise | ||
136 | * get_cmd_index is broken. */ | ||
137 | BUG_ON(!is_power_of_2(slots_num)); | ||
138 | |||
139 | q->low_mark = q->n_window / 4; | ||
140 | if (q->low_mark < 4) | ||
141 | q->low_mark = 4; | ||
142 | |||
143 | q->high_mark = q->n_window / 8; | ||
144 | if (q->high_mark < 2) | ||
145 | q->high_mark = 2; | ||
146 | |||
147 | q->write_ptr = q->read_ptr = 0; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue | ||
154 | */ | ||
155 | static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, | ||
156 | struct iwl_tx_queue *txq, u32 id) | ||
157 | { | ||
158 | struct pci_dev *dev = priv->pci_dev; | ||
159 | |||
160 | /* Driver private data, only for Tx (not command) queues, | ||
161 | * not shared with device. */ | ||
162 | if (id != IWL_CMD_QUEUE_NUM) { | ||
163 | txq->txb = kmalloc(sizeof(txq->txb[0]) * | ||
164 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | ||
165 | if (!txq->txb) { | ||
166 | IWL_ERR(priv, "kmalloc for auxiliary BD " | ||
167 | "structures failed\n"); | ||
168 | goto error; | ||
169 | } | ||
170 | } else | ||
171 | txq->txb = NULL; | ||
172 | |||
173 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
174 | * shared with device */ | ||
175 | txq->tfds = pci_alloc_consistent(dev, | ||
176 | sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX, | ||
177 | &txq->q.dma_addr); | ||
178 | |||
179 | if (!txq->tfds) { | ||
180 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", | ||
181 | sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX); | ||
182 | goto error; | ||
183 | } | ||
184 | txq->q.id = id; | ||
185 | |||
186 | return 0; | ||
187 | |||
188 | error: | ||
189 | kfree(txq->txb); | ||
190 | txq->txb = NULL; | ||
191 | |||
192 | return -ENOMEM; | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue | ||
197 | */ | ||
198 | int iwl3945_tx_queue_init(struct iwl_priv *priv, | ||
199 | struct iwl_tx_queue *txq, int slots_num, u32 txq_id) | ||
200 | { | ||
201 | int len, i; | ||
202 | int rc = 0; | ||
203 | |||
204 | /* | ||
205 | * Alloc buffer array for commands (Tx or other types of commands). | ||
206 | * For the command queue (#4), allocate command space + one big | ||
207 | * command for scan, since scan command is very huge; the system will | ||
208 | * not have two scans at the same time, so only one is needed. | ||
209 | * For data Tx queues (all other queues), no super-size command | ||
210 | * space is needed. | ||
211 | */ | ||
212 | len = sizeof(struct iwl_cmd); | ||
213 | for (i = 0; i <= slots_num; i++) { | ||
214 | if (i == slots_num) { | ||
215 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
216 | len += IWL_MAX_SCAN_SIZE; | ||
217 | else | ||
218 | continue; | ||
219 | } | ||
220 | |||
221 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); | ||
222 | if (!txq->cmd[i]) | ||
223 | goto err; | ||
224 | } | ||
225 | |||
226 | /* Alloc driver data array and TFD circular buffer */ | ||
227 | rc = iwl3945_tx_queue_alloc(priv, txq, txq_id); | ||
228 | if (rc) | ||
229 | goto err; | ||
230 | |||
231 | txq->need_update = 0; | ||
232 | |||
233 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | ||
234 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | ||
235 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | ||
236 | |||
237 | /* Initialize queue high/low-water, head/tail indexes */ | ||
238 | iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
239 | |||
240 | /* Tell device where to find queue, enable DMA channel. */ | ||
241 | iwl3945_hw_tx_queue_init(priv, txq); | ||
242 | |||
243 | return 0; | ||
244 | err: | ||
245 | for (i = 0; i < slots_num; i++) { | ||
246 | kfree(txq->cmd[i]); | ||
247 | txq->cmd[i] = NULL; | ||
248 | } | ||
249 | |||
250 | if (txq_id == IWL_CMD_QUEUE_NUM) { | ||
251 | kfree(txq->cmd[slots_num]); | ||
252 | txq->cmd[slots_num] = NULL; | ||
253 | } | ||
254 | return -ENOMEM; | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * iwl3945_tx_queue_free - Deallocate DMA queue. | ||
259 | * @txq: Transmit queue to deallocate. | ||
260 | * | ||
261 | * Empty queue by removing and destroying all BD's. | ||
262 | * Free all buffers. | ||
263 | * 0-fill, but do not free "txq" descriptor structure. | ||
264 | */ | ||
265 | void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
266 | { | ||
267 | struct iwl_queue *q = &txq->q; | ||
268 | struct pci_dev *dev = priv->pci_dev; | ||
269 | int len, i; | ||
270 | |||
271 | if (q->n_bd == 0) | ||
272 | return; | ||
273 | |||
274 | /* first, empty all BD's */ | ||
275 | for (; q->write_ptr != q->read_ptr; | ||
276 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) | ||
277 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
278 | |||
279 | len = sizeof(struct iwl_cmd) * q->n_window; | ||
280 | if (q->id == IWL_CMD_QUEUE_NUM) | ||
281 | len += IWL_MAX_SCAN_SIZE; | ||
282 | |||
283 | /* De-alloc array of command/tx buffers */ | ||
284 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) | ||
285 | kfree(txq->cmd[i]); | ||
286 | |||
287 | /* De-alloc circular buffer of TFDs */ | ||
288 | if (txq->q.n_bd) | ||
289 | pci_free_consistent(dev, sizeof(struct iwl3945_tfd) * | ||
290 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | ||
291 | |||
292 | /* De-alloc array of per-TFD driver data */ | ||
293 | kfree(txq->txb); | ||
294 | txq->txb = NULL; | ||
295 | |||
296 | /* 0-fill queue descriptor structure */ | ||
297 | memset(txq, 0, sizeof(*txq)); | ||
298 | } | ||
299 | |||
300 | /*************** STATION TABLE MANAGEMENT **** | 96 | /*************** STATION TABLE MANAGEMENT **** |
301 | * mac80211 should be examined to determine if sta_info is duplicating | 97 | * mac80211 should be examined to determine if sta_info is duplicating |
302 | * the functionality provided here | 98 | * the functionality provided here |