diff options
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 76 |
4 files changed, 59 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1d793c093f1..56dbc8144a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
| @@ -939,8 +939,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
| 939 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | 939 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
| 940 | 940 | ||
| 941 | if (txq_id != IWL_CMD_QUEUE_NUM) { | 941 | if (txq_id != IWL_CMD_QUEUE_NUM) { |
| 942 | sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id; | 942 | sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; |
| 943 | sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl; | 943 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; |
| 944 | 944 | ||
| 945 | switch (sec_ctl & TX_CMD_SEC_MSK) { | 945 | switch (sec_ctl & TX_CMD_SEC_MSK) { |
| 946 | case TX_CMD_SEC_CCM: | 946 | case TX_CMD_SEC_CCM: |
| @@ -979,7 +979,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
| 979 | u8 sta = 0; | 979 | u8 sta = 0; |
| 980 | 980 | ||
| 981 | if (txq_id != IWL_CMD_QUEUE_NUM) | 981 | if (txq_id != IWL_CMD_QUEUE_NUM) |
| 982 | sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id; | 982 | sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id; |
| 983 | 983 | ||
| 984 | shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. | 984 | shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. |
| 985 | val = cpu_to_le16(1 | (sta << 12)); | 985 | val = cpu_to_le16(1 | (sta << 12)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 848786ab791..c19db438306 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
| @@ -135,8 +135,7 @@ struct iwl_tx_info { | |||
| 135 | struct iwl_tx_queue { | 135 | struct iwl_tx_queue { |
| 136 | struct iwl_queue q; | 136 | struct iwl_queue q; |
| 137 | struct iwl_tfd_frame *bd; | 137 | struct iwl_tfd_frame *bd; |
| 138 | struct iwl_cmd *cmd; | 138 | struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; |
| 139 | dma_addr_t dma_addr_cmd; | ||
| 140 | struct iwl_tx_info *txb; | 139 | struct iwl_tx_info *txb; |
| 141 | int need_update; | 140 | int need_update; |
| 142 | int sched_retry; | 141 | int sched_retry; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8fa991b7202..6512834bb91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
| @@ -228,7 +228,7 @@ cancel: | |||
| 228 | * TX cmd queue. Otherwise in case the cmd comes | 228 | * TX cmd queue. Otherwise in case the cmd comes |
| 229 | * in later, it will possibly set an invalid | 229 | * in later, it will possibly set an invalid |
| 230 | * address (cmd->meta.source). */ | 230 | * address (cmd->meta.source). */ |
| 231 | qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; | 231 | qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; |
| 232 | qcmd->meta.flags &= ~CMD_WANT_SKB; | 232 | qcmd->meta.flags &= ~CMD_WANT_SKB; |
| 233 | } | 233 | } |
| 234 | fail: | 234 | fail: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 39f19ebee97..aa98c76d819 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -208,11 +208,12 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr); | |||
| 208 | * Free all buffers. | 208 | * Free all buffers. |
| 209 | * 0-fill, but do not free "txq" descriptor structure. | 209 | * 0-fill, but do not free "txq" descriptor structure. |
| 210 | */ | 210 | */ |
| 211 | static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) | 211 | static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) |
| 212 | { | 212 | { |
| 213 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
| 213 | struct iwl_queue *q = &txq->q; | 214 | struct iwl_queue *q = &txq->q; |
| 214 | struct pci_dev *dev = priv->pci_dev; | 215 | struct pci_dev *dev = priv->pci_dev; |
| 215 | int len; | 216 | int i, slots_num, len; |
| 216 | 217 | ||
| 217 | if (q->n_bd == 0) | 218 | if (q->n_bd == 0) |
| 218 | return; | 219 | return; |
| @@ -227,7 +228,12 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
| 227 | len += IWL_MAX_SCAN_SIZE; | 228 | len += IWL_MAX_SCAN_SIZE; |
| 228 | 229 | ||
| 229 | /* De-alloc array of command/tx buffers */ | 230 | /* De-alloc array of command/tx buffers */ |
| 230 | pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); | 231 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? |
| 232 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
| 233 | for (i = 0; i < slots_num; i++) | ||
| 234 | kfree(txq->cmd[i]); | ||
| 235 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
| 236 | kfree(txq->cmd[slots_num]); | ||
| 231 | 237 | ||
| 232 | /* De-alloc circular buffer of TFDs */ | 238 | /* De-alloc circular buffer of TFDs */ |
| 233 | if (txq->q.n_bd) | 239 | if (txq->q.n_bd) |
| @@ -400,8 +406,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, | |||
| 400 | struct iwl_tx_queue *txq, | 406 | struct iwl_tx_queue *txq, |
| 401 | int slots_num, u32 txq_id) | 407 | int slots_num, u32 txq_id) |
| 402 | { | 408 | { |
| 403 | struct pci_dev *dev = priv->pci_dev; | 409 | int i, len; |
| 404 | int len; | ||
| 405 | int rc = 0; | 410 | int rc = 0; |
| 406 | 411 | ||
| 407 | /* | 412 | /* |
| @@ -412,17 +417,25 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, | |||
| 412 | * For normal Tx queues (all other queues), no super-size command | 417 | * For normal Tx queues (all other queues), no super-size command |
| 413 | * space is needed. | 418 | * space is needed. |
| 414 | */ | 419 | */ |
| 415 | len = sizeof(struct iwl_cmd) * slots_num; | 420 | len = sizeof(struct iwl_cmd); |
| 416 | if (txq_id == IWL_CMD_QUEUE_NUM) | 421 | for (i = 0; i <= slots_num; i++) { |
| 417 | len += IWL_MAX_SCAN_SIZE; | 422 | if (i == slots_num) { |
| 418 | txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); | 423 | if (txq_id == IWL_CMD_QUEUE_NUM) |
| 419 | if (!txq->cmd) | 424 | len += IWL_MAX_SCAN_SIZE; |
| 420 | return -ENOMEM; | 425 | else |
| 426 | continue; | ||
| 427 | } | ||
| 428 | |||
| 429 | txq->cmd[i] = kmalloc(len, GFP_KERNEL | GFP_DMA); | ||
| 430 | if (!txq->cmd[i]) | ||
| 431 | return -ENOMEM; | ||
| 432 | } | ||
| 421 | 433 | ||
| 422 | /* Alloc driver data array and TFD circular buffer */ | 434 | /* Alloc driver data array and TFD circular buffer */ |
| 423 | rc = iwl_tx_queue_alloc(priv, txq, txq_id); | 435 | rc = iwl_tx_queue_alloc(priv, txq, txq_id); |
| 424 | if (rc) { | 436 | if (rc) { |
| 425 | pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); | 437 | for (i = 0; i < slots_num; i++) |
| 438 | kfree(txq->cmd[i]); | ||
| 426 | 439 | ||
| 427 | return -ENOMEM; | 440 | return -ENOMEM; |
| 428 | } | 441 | } |
| @@ -451,7 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 451 | 464 | ||
| 452 | /* Tx queues */ | 465 | /* Tx queues */ |
| 453 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 466 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
| 454 | iwl_tx_queue_free(priv, &priv->txq[txq_id]); | 467 | iwl_tx_queue_free(priv, txq_id); |
| 455 | 468 | ||
| 456 | /* Keep-warm buffer */ | 469 | /* Keep-warm buffer */ |
| 457 | iwl_kw_free(priv); | 470 | iwl_kw_free(priv); |
| @@ -859,7 +872,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
| 859 | txq->txb[q->write_ptr].skb[0] = skb; | 872 | txq->txb[q->write_ptr].skb[0] = skb; |
| 860 | 873 | ||
| 861 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 874 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
| 862 | out_cmd = &txq->cmd[idx]; | 875 | out_cmd = txq->cmd[idx]; |
| 863 | tx_cmd = &out_cmd->cmd.tx; | 876 | tx_cmd = &out_cmd->cmd.tx; |
| 864 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | 877 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); |
| 865 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | 878 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); |
| @@ -899,8 +912,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
| 899 | 912 | ||
| 900 | /* Physical address of this Tx command's header (not MAC header!), | 913 | /* Physical address of this Tx command's header (not MAC header!), |
| 901 | * within command buffer array. */ | 914 | * within command buffer array. */ |
| 902 | txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + | 915 | txcmd_phys = pci_map_single(priv->pci_dev, out_cmd, |
| 903 | offsetof(struct iwl_cmd, hdr); | 916 | sizeof(struct iwl_cmd), PCI_DMA_TODEVICE); |
| 917 | txcmd_phys += offsetof(struct iwl_cmd, hdr); | ||
| 904 | 918 | ||
| 905 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 919 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
| 906 | * first entry */ | 920 | * first entry */ |
| @@ -1004,7 +1018,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1004 | u32 idx; | 1018 | u32 idx; |
| 1005 | u16 fix_size; | 1019 | u16 fix_size; |
| 1006 | dma_addr_t phys_addr; | 1020 | dma_addr_t phys_addr; |
| 1007 | int ret; | 1021 | int len, ret; |
| 1008 | unsigned long flags; | 1022 | unsigned long flags; |
| 1009 | 1023 | ||
| 1010 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | 1024 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); |
| @@ -1034,7 +1048,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1034 | control_flags = (u32 *) tfd; | 1048 | control_flags = (u32 *) tfd; |
| 1035 | 1049 | ||
| 1036 | idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); | 1050 | idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); |
| 1037 | out_cmd = &txq->cmd[idx]; | 1051 | out_cmd = txq->cmd[idx]; |
| 1038 | 1052 | ||
| 1039 | out_cmd->hdr.cmd = cmd->id; | 1053 | out_cmd->hdr.cmd = cmd->id; |
| 1040 | memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); | 1054 | memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); |
| @@ -1048,9 +1062,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1048 | INDEX_TO_SEQ(q->write_ptr)); | 1062 | INDEX_TO_SEQ(q->write_ptr)); |
| 1049 | if (out_cmd->meta.flags & CMD_SIZE_HUGE) | 1063 | if (out_cmd->meta.flags & CMD_SIZE_HUGE) |
| 1050 | out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); | 1064 | out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); |
| 1051 | 1065 | len = (idx == TFD_CMD_SLOTS) ? | |
| 1052 | phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + | 1066 | IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); |
| 1053 | offsetof(struct iwl_cmd, hdr); | 1067 | phys_addr = pci_map_single(priv->pci_dev, out_cmd, len, |
| 1068 | PCI_DMA_TODEVICE); | ||
| 1069 | phys_addr += offsetof(struct iwl_cmd, hdr); | ||
| 1054 | iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); | 1070 | iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); |
| 1055 | 1071 | ||
| 1056 | IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " | 1072 | IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " |
| @@ -1115,6 +1131,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
| 1115 | { | 1131 | { |
| 1116 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 1132 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
| 1117 | struct iwl_queue *q = &txq->q; | 1133 | struct iwl_queue *q = &txq->q; |
| 1134 | struct iwl_tfd_frame *bd = &txq->bd[index]; | ||
| 1135 | dma_addr_t dma_addr; | ||
| 1136 | int is_odd, buf_len; | ||
| 1118 | int nfreed = 0; | 1137 | int nfreed = 0; |
| 1119 | 1138 | ||
| 1120 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | 1139 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { |
| @@ -1132,6 +1151,19 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
| 1132 | q->write_ptr, q->read_ptr); | 1151 | q->write_ptr, q->read_ptr); |
| 1133 | queue_work(priv->workqueue, &priv->restart); | 1152 | queue_work(priv->workqueue, &priv->restart); |
| 1134 | } | 1153 | } |
| 1154 | is_odd = (index/2) & 0x1; | ||
| 1155 | if (is_odd) { | ||
| 1156 | dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) | | ||
| 1157 | (IWL_GET_BITS(bd->pa[index], | ||
| 1158 | tb2_addr_hi20) << 16); | ||
| 1159 | buf_len = IWL_GET_BITS(bd->pa[index], tb2_len); | ||
| 1160 | } else { | ||
| 1161 | dma_addr = le32_to_cpu(bd->pa[index].tb1_addr); | ||
| 1162 | buf_len = IWL_GET_BITS(bd->pa[index], tb1_len); | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | pci_unmap_single(priv->pci_dev, dma_addr, buf_len, | ||
| 1166 | PCI_DMA_TODEVICE); | ||
| 1135 | nfreed++; | 1167 | nfreed++; |
| 1136 | } | 1168 | } |
| 1137 | } | 1169 | } |
| @@ -1163,7 +1195,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1163 | BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); | 1195 | BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); |
| 1164 | 1196 | ||
| 1165 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1197 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); |
| 1166 | cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1198 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; |
| 1167 | 1199 | ||
| 1168 | /* Input error checking is done when commands are added to queue. */ | 1200 | /* Input error checking is done when commands are added to queue. */ |
| 1169 | if (cmd->meta.flags & CMD_WANT_SKB) { | 1201 | if (cmd->meta.flags & CMD_WANT_SKB) { |
