diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-11-16 14:07:54 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-16 14:07:54 -0500 |
commit | dfbebe14428803402293d9a8bf1efef7221d8b78 (patch) | |
tree | cd81cb3822ef4fca5925ef3bf0775eb74e905e57 | |
parent | 0f62248501cbf5047486601d7e39d5ee36d478c2 (diff) | |
parent | d18aa87fbfe80f33076942d11f19c9d813e835b1 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Conflicts:
drivers/net/wireless/iwlwifi/pcie/trans.c
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/agn.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/commands.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/lib.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/main.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/rx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tx.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/ucode.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/rx.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 85 |
17 files changed, 183 insertions, 112 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 727fbb5db9d..5cf43236421 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -133,12 +133,3 @@ config IWLWIFI_P2P | |||
133 | support when it is loaded. | 133 | support when it is loaded. |
134 | 134 | ||
135 | Say Y only if you want to experiment with P2P. | 135 | Say Y only if you want to experiment with P2P. |
136 | |||
137 | config IWLWIFI_EXPERIMENTAL_MFP | ||
138 | bool "support MFP (802.11w) even if uCode doesn't advertise" | ||
139 | depends on IWLWIFI | ||
140 | help | ||
141 | This option enables experimental MFP (802.11W) support | ||
142 | even if the microcode doesn't advertise it. | ||
143 | |||
144 | Say Y only if you want to experiment with MFP. | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 75e12f29d9e..33b3ad2e546 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -176,8 +176,8 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
176 | /* lib */ | 176 | /* lib */ |
177 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 177 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
178 | void iwlagn_temperature(struct iwl_priv *priv); | 178 | void iwlagn_temperature(struct iwl_priv *priv); |
179 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 179 | int iwlagn_txfifo_flush(struct iwl_priv *priv); |
180 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 180 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv); |
181 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 181 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
182 | int iwl_send_statistics_request(struct iwl_priv *priv, | 182 | int iwl_send_statistics_request(struct iwl_priv *priv, |
183 | u8 flags, bool clear); | 183 | u8 flags, bool clear); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 01128c96b5d..71ab76b2b39 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -986,8 +986,7 @@ struct iwl_rem_sta_cmd { | |||
986 | 986 | ||
987 | #define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00) | 987 | #define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00) |
988 | 988 | ||
989 | #define IWL_DROP_SINGLE 0 | 989 | #define IWL_DROP_ALL BIT(1) |
990 | #define IWL_DROP_ALL (BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN)) | ||
991 | 990 | ||
992 | /* | 991 | /* |
993 | * REPLY_TXFIFO_FLUSH = 0x1e(command and response) | 992 | * REPLY_TXFIFO_FLUSH = 0x1e(command and response) |
@@ -1004,14 +1003,14 @@ struct iwl_rem_sta_cmd { | |||
1004 | * the flush operation ends when both the scheduler DMA done and TXFIFO empty | 1003 | * the flush operation ends when both the scheduler DMA done and TXFIFO empty |
1005 | * are set. | 1004 | * are set. |
1006 | * | 1005 | * |
1007 | * @fifo_control: bit mask for which queues to flush | 1006 | * @queue_control: bit mask for which queues to flush |
1008 | * @flush_control: flush controls | 1007 | * @flush_control: flush controls |
1009 | * 0: Dump single MSDU | 1008 | * 0: Dump single MSDU |
1010 | * 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable. | 1009 | * 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable. |
1011 | * 2: Dump all FIFO | 1010 | * 2: Dump all FIFO |
1012 | */ | 1011 | */ |
1013 | struct iwl_txfifo_flush_cmd { | 1012 | struct iwl_txfifo_flush_cmd { |
1014 | __le32 fifo_control; | 1013 | __le32 queue_control; |
1015 | __le16 flush_control; | 1014 | __le16 flush_control; |
1016 | __le16 reserved; | 1015 | __le16 reserved; |
1017 | } __packed; | 1016 | } __packed; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 1a98fa3ab06..769a08bca86 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -2101,7 +2101,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, | |||
2101 | if (iwl_is_rfkill(priv)) | 2101 | if (iwl_is_rfkill(priv)) |
2102 | return -EFAULT; | 2102 | return -EFAULT; |
2103 | 2103 | ||
2104 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | 2104 | iwlagn_dev_txfifo_flush(priv); |
2105 | 2105 | ||
2106 | return count; | 2106 | return count; |
2107 | } | 2107 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index bef88c1a2c9..7e59be4b89b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
136 | * 1. acquire mutex before calling | 136 | * 1. acquire mutex before calling |
137 | * 2. make sure rf is on and not in exit state | 137 | * 2. make sure rf is on and not in exit state |
138 | */ | 138 | */ |
139 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | 139 | int iwlagn_txfifo_flush(struct iwl_priv *priv) |
140 | { | 140 | { |
141 | struct iwl_txfifo_flush_cmd flush_cmd; | 141 | struct iwl_txfifo_flush_cmd flush_cmd; |
142 | struct iwl_host_cmd cmd = { | 142 | struct iwl_host_cmd cmd = { |
@@ -146,35 +146,34 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | |||
146 | .data = { &flush_cmd, }, | 146 | .data = { &flush_cmd, }, |
147 | }; | 147 | }; |
148 | 148 | ||
149 | might_sleep(); | ||
150 | |||
151 | memset(&flush_cmd, 0, sizeof(flush_cmd)); | 149 | memset(&flush_cmd, 0, sizeof(flush_cmd)); |
152 | if (flush_control & BIT(IWL_RXON_CTX_BSS)) | 150 | |
153 | flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK | | 151 | flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK | |
154 | IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | | 152 | IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | |
155 | IWL_SCD_MGMT_MSK; | 153 | IWL_SCD_MGMT_MSK; |
156 | if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && | 154 | if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) |
157 | (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) | 155 | flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK | |
158 | flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | | 156 | IWL_PAN_SCD_VI_MSK | |
159 | IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | | 157 | IWL_PAN_SCD_BE_MSK | |
160 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | | 158 | IWL_PAN_SCD_BK_MSK | |
161 | IWL_PAN_SCD_MULTICAST_MSK; | 159 | IWL_PAN_SCD_MGMT_MSK | |
160 | IWL_PAN_SCD_MULTICAST_MSK; | ||
162 | 161 | ||
163 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE) | 162 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE) |
164 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; | 163 | flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; |
165 | 164 | ||
166 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", | 165 | IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", |
167 | flush_cmd.fifo_control); | 166 | flush_cmd.queue_control); |
168 | flush_cmd.flush_control = cpu_to_le16(flush_control); | 167 | flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); |
169 | 168 | ||
170 | return iwl_dvm_send_cmd(priv, &cmd); | 169 | return iwl_dvm_send_cmd(priv, &cmd); |
171 | } | 170 | } |
172 | 171 | ||
173 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | 172 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) |
174 | { | 173 | { |
175 | mutex_lock(&priv->mutex); | 174 | mutex_lock(&priv->mutex); |
176 | ieee80211_stop_queues(priv->hw); | 175 | ieee80211_stop_queues(priv->hw); |
177 | if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { | 176 | if (iwlagn_txfifo_flush(priv)) { |
178 | IWL_ERR(priv, "flush request fail\n"); | 177 | IWL_ERR(priv, "flush request fail\n"); |
179 | goto done; | 178 | goto done; |
180 | } | 179 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index ff8162d4c45..cb443d54f9b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -168,10 +168,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
168 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 168 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
169 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 169 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
170 | 170 | ||
171 | #ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP | ||
172 | /* enable 11w if the uCode advertise */ | 171 | /* enable 11w if the uCode advertise */ |
173 | if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) | 172 | if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) |
174 | #endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */ | ||
175 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 173 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
176 | 174 | ||
177 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 175 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
@@ -1019,7 +1017,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | |||
1019 | */ | 1017 | */ |
1020 | if (drop) { | 1018 | if (drop) { |
1021 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | 1019 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); |
1022 | if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { | 1020 | if (iwlagn_txfifo_flush(priv)) { |
1023 | IWL_ERR(priv, "flush request fail\n"); | 1021 | IWL_ERR(priv, "flush request fail\n"); |
1024 | goto done; | 1022 | goto done; |
1025 | } | 1023 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 475df45c832..03cbfa765f8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -511,7 +511,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) | |||
511 | return; | 511 | return; |
512 | 512 | ||
513 | IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); | 513 | IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); |
514 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | 514 | iwlagn_dev_txfifo_flush(priv); |
515 | } | 515 | } |
516 | 516 | ||
517 | /* | 517 | /* |
@@ -1204,7 +1204,7 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | |||
1204 | return -EINVAL; | 1204 | return -EINVAL; |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); | 1207 | IWL_DEBUG_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); |
1208 | 1208 | ||
1209 | priv->hw_params.tx_chains_num = | 1209 | priv->hw_params.tx_chains_num = |
1210 | num_of_ant(priv->eeprom_data->valid_tx_ant); | 1210 | num_of_ant(priv->eeprom_data->valid_tx_ant); |
@@ -1214,9 +1214,9 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | |||
1214 | priv->hw_params.rx_chains_num = | 1214 | priv->hw_params.rx_chains_num = |
1215 | num_of_ant(priv->eeprom_data->valid_rx_ant); | 1215 | num_of_ant(priv->eeprom_data->valid_rx_ant); |
1216 | 1216 | ||
1217 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | 1217 | IWL_DEBUG_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", |
1218 | priv->eeprom_data->valid_tx_ant, | 1218 | priv->eeprom_data->valid_tx_ant, |
1219 | priv->eeprom_data->valid_rx_ant); | 1219 | priv->eeprom_data->valid_rx_ant); |
1220 | 1220 | ||
1221 | return 0; | 1221 | return 0; |
1222 | } | 1222 | } |
@@ -1231,7 +1231,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1231 | struct iwl_op_mode *op_mode; | 1231 | struct iwl_op_mode *op_mode; |
1232 | u16 num_mac; | 1232 | u16 num_mac; |
1233 | u32 ucode_flags; | 1233 | u32 ucode_flags; |
1234 | struct iwl_trans_config trans_cfg; | 1234 | struct iwl_trans_config trans_cfg = {}; |
1235 | static const u8 no_reclaim_cmds[] = { | 1235 | static const u8 no_reclaim_cmds[] = { |
1236 | REPLY_RX_PHY_CMD, | 1236 | REPLY_RX_PHY_CMD, |
1237 | REPLY_RX_MPDU_CMD, | 1237 | REPLY_RX_MPDU_CMD, |
@@ -1507,10 +1507,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1507 | 1507 | ||
1508 | iwl_tt_exit(priv); | 1508 | iwl_tt_exit(priv); |
1509 | 1509 | ||
1510 | /*This will stop the queues, move the device to low power state */ | ||
1511 | priv->ucode_loaded = false; | ||
1512 | iwl_trans_stop_device(priv->trans); | ||
1513 | |||
1514 | kfree(priv->eeprom_blob); | 1510 | kfree(priv->eeprom_blob); |
1515 | iwl_free_eeprom_data(priv->eeprom_data); | 1511 | iwl_free_eeprom_data(priv->eeprom_data); |
1516 | 1512 | ||
@@ -1926,8 +1922,6 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
1926 | * commands by clearing the ready bit */ | 1922 | * commands by clearing the ready bit */ |
1927 | clear_bit(STATUS_READY, &priv->status); | 1923 | clear_bit(STATUS_READY, &priv->status); |
1928 | 1924 | ||
1929 | wake_up(&priv->trans->wait_command_queue); | ||
1930 | |||
1931 | if (!ondemand) { | 1925 | if (!ondemand) { |
1932 | /* | 1926 | /* |
1933 | * If firmware keep reloading, then it indicate something | 1927 | * If firmware keep reloading, then it indicate something |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 5a9c325804f..9a8d5020774 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -631,8 +631,6 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, | |||
631 | test_bit(STATUS_RF_KILL_HW, &priv->status))) | 631 | test_bit(STATUS_RF_KILL_HW, &priv->status))) |
632 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 632 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, |
633 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 633 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
634 | else | ||
635 | wake_up(&priv->trans->wait_command_queue); | ||
636 | return 0; | 634 | return 0; |
637 | } | 635 | } |
638 | 636 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index f5ca73a8987..4ae031f6726 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -1075,14 +1075,11 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) | |||
1075 | 1075 | ||
1076 | static void iwlagn_set_tx_status(struct iwl_priv *priv, | 1076 | static void iwlagn_set_tx_status(struct iwl_priv *priv, |
1077 | struct ieee80211_tx_info *info, | 1077 | struct ieee80211_tx_info *info, |
1078 | struct iwlagn_tx_resp *tx_resp, | 1078 | struct iwlagn_tx_resp *tx_resp) |
1079 | bool is_agg) | ||
1080 | { | 1079 | { |
1081 | u16 status = le16_to_cpu(tx_resp->status.status); | 1080 | u16 status = le16_to_cpu(tx_resp->status.status); |
1082 | 1081 | ||
1083 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1082 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1084 | if (is_agg) | ||
1085 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
1086 | info->flags |= iwl_tx_status_to_mac80211(status); | 1083 | info->flags |= iwl_tx_status_to_mac80211(status); |
1087 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | 1084 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), |
1088 | info); | 1085 | info); |
@@ -1231,7 +1228,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1231 | if (is_agg && !iwl_is_tx_success(status)) | 1228 | if (is_agg && !iwl_is_tx_success(status)) |
1232 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1229 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1233 | iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), | 1230 | iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), |
1234 | tx_resp, is_agg); | 1231 | tx_resp); |
1235 | if (!is_agg) | 1232 | if (!is_agg) |
1236 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1233 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
1237 | 1234 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 2cb1efbc5ed..95e6d33f515 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -254,7 +254,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
254 | int ret; | 254 | int ret; |
255 | int i; | 255 | int i; |
256 | 256 | ||
257 | iwl_trans_fw_alive(priv->trans); | 257 | iwl_trans_fw_alive(priv->trans, 0); |
258 | 258 | ||
259 | if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN && | 259 | if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN && |
260 | priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) { | 260 | priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 678717bf62e..b3fde5f7b9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -306,7 +306,7 @@ TRACE_EVENT(iwlwifi_dev_rx_data, | |||
306 | memcpy(__get_dynamic_array(data), | 306 | memcpy(__get_dynamic_array(data), |
307 | ((u8 *)rxbuf) + offs, len - offs); | 307 | ((u8 *)rxbuf) + offs, len - offs); |
308 | ), | 308 | ), |
309 | TP_printk("[%s] TX frame data", __get_str(dev)) | 309 | TP_printk("[%s] RX frame data", __get_str(dev)) |
310 | ); | 310 | ); |
311 | 311 | ||
312 | #undef TRACE_SYSTEM | 312 | #undef TRACE_SYSTEM |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index f10170fe879..4a9dc9629ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -889,8 +889,8 @@ int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | |||
889 | { | 889 | { |
890 | if (data->eeprom_version >= trans->cfg->eeprom_ver || | 890 | if (data->eeprom_version >= trans->cfg->eeprom_ver || |
891 | data->calib_version >= trans->cfg->eeprom_calib_ver) { | 891 | data->calib_version >= trans->cfg->eeprom_calib_ver) { |
892 | IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", | 892 | IWL_DEBUG_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", |
893 | data->eeprom_version, data->calib_version); | 893 | data->eeprom_version, data->calib_version); |
894 | return 0; | 894 | return 0; |
895 | } | 895 | } |
896 | 896 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index f75ea6d73ff..e378ea6dca9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -221,14 +221,21 @@ struct iwl_device_cmd { | |||
221 | /** | 221 | /** |
222 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command | 222 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command |
223 | * | 223 | * |
224 | * IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's | 224 | * @IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's |
225 | * ring. The transport layer doesn't map the command's buffer to DMA, but | 225 | * ring. The transport layer doesn't map the command's buffer to DMA, but |
226 | * rather copies it to an previously allocated DMA buffer. This flag tells | 226 | * rather copies it to an previously allocated DMA buffer. This flag tells |
227 | * the transport layer not to copy the command, but to map the existing | 227 | * the transport layer not to copy the command, but to map the existing |
228 | * buffer. This can save memcpy and is worth with very big comamnds. | 228 | * buffer (that is passed in) instead. This saves the memcpy and allows |
229 | * commands that are bigger than the fixed buffer to be submitted. | ||
230 | * Note that a TFD entry after a NOCOPY one cannot be a normal copied one. | ||
231 | * @IWL_HCMD_DFL_DUP: Only valid without NOCOPY, duplicate the memory for this | ||
232 | * chunk internally and free it again after the command completes. This | ||
233 | * can (currently) be used only once per command. | ||
234 | * Note that a TFD entry after a DUP one cannot be a normal copied one. | ||
229 | */ | 235 | */ |
230 | enum iwl_hcmd_dataflag { | 236 | enum iwl_hcmd_dataflag { |
231 | IWL_HCMD_DFL_NOCOPY = BIT(0), | 237 | IWL_HCMD_DFL_NOCOPY = BIT(0), |
238 | IWL_HCMD_DFL_DUP = BIT(1), | ||
232 | }; | 239 | }; |
233 | 240 | ||
234 | /** | 241 | /** |
@@ -348,14 +355,17 @@ struct iwl_trans; | |||
348 | * @start_fw: allocates and inits all the resources for the transport | 355 | * @start_fw: allocates and inits all the resources for the transport |
349 | * layer. Also kick a fw image. | 356 | * layer. Also kick a fw image. |
350 | * May sleep | 357 | * May sleep |
351 | * @fw_alive: called when the fw sends alive notification | 358 | * @fw_alive: called when the fw sends alive notification. If the fw provides |
359 | * the SCD base address in SRAM, then provide it here, or 0 otherwise. | ||
352 | * May sleep | 360 | * May sleep |
353 | * @stop_device:stops the whole device (embedded CPU put to reset) | 361 | * @stop_device:stops the whole device (embedded CPU put to reset) |
354 | * May sleep | 362 | * May sleep |
355 | * @wowlan_suspend: put the device into the correct mode for WoWLAN during | 363 | * @wowlan_suspend: put the device into the correct mode for WoWLAN during |
356 | * suspend. This is optional, if not implemented WoWLAN will not be | 364 | * suspend. This is optional, if not implemented WoWLAN will not be |
357 | * supported. This callback may sleep. | 365 | * supported. This callback may sleep. |
358 | * @send_cmd:send a host command | 366 | * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted. |
367 | * If RFkill is asserted in the middle of a SYNC host command, it must | ||
368 | * return -ERFKILL straight away. | ||
359 | * May sleep only if CMD_SYNC is set | 369 | * May sleep only if CMD_SYNC is set |
360 | * @tx: send an skb | 370 | * @tx: send an skb |
361 | * Must be atomic | 371 | * Must be atomic |
@@ -385,7 +395,7 @@ struct iwl_trans_ops { | |||
385 | int (*start_hw)(struct iwl_trans *iwl_trans); | 395 | int (*start_hw)(struct iwl_trans *iwl_trans); |
386 | void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving); | 396 | void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving); |
387 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw); | 397 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw); |
388 | void (*fw_alive)(struct iwl_trans *trans); | 398 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); |
389 | void (*stop_device)(struct iwl_trans *trans); | 399 | void (*stop_device)(struct iwl_trans *trans); |
390 | 400 | ||
391 | void (*wowlan_suspend)(struct iwl_trans *trans); | 401 | void (*wowlan_suspend)(struct iwl_trans *trans); |
@@ -438,7 +448,6 @@ enum iwl_trans_state { | |||
438 | * Set during transport allocation. | 448 | * Set during transport allocation. |
439 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. | 449 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. |
440 | * @pm_support: set to true in start_hw if link pm is supported | 450 | * @pm_support: set to true in start_hw if link pm is supported |
441 | * @wait_command_queue: the wait_queue for SYNC host commands | ||
442 | * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. | 451 | * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. |
443 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | 452 | * The user should use iwl_trans_{alloc,free}_tx_cmd. |
444 | * @dev_cmd_headroom: room needed for the transport's private use before the | 453 | * @dev_cmd_headroom: room needed for the transport's private use before the |
@@ -465,8 +474,6 @@ struct iwl_trans { | |||
465 | 474 | ||
466 | bool pm_support; | 475 | bool pm_support; |
467 | 476 | ||
468 | wait_queue_head_t wait_command_queue; | ||
469 | |||
470 | /* The following fields are internal only */ | 477 | /* The following fields are internal only */ |
471 | struct kmem_cache *dev_cmd_pool; | 478 | struct kmem_cache *dev_cmd_pool; |
472 | size_t dev_cmd_headroom; | 479 | size_t dev_cmd_headroom; |
@@ -508,13 +515,13 @@ static inline void iwl_trans_stop_hw(struct iwl_trans *trans, | |||
508 | trans->state = IWL_TRANS_NO_FW; | 515 | trans->state = IWL_TRANS_NO_FW; |
509 | } | 516 | } |
510 | 517 | ||
511 | static inline void iwl_trans_fw_alive(struct iwl_trans *trans) | 518 | static inline void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr) |
512 | { | 519 | { |
513 | might_sleep(); | 520 | might_sleep(); |
514 | 521 | ||
515 | trans->state = IWL_TRANS_FW_ALIVE; | 522 | trans->state = IWL_TRANS_FW_ALIVE; |
516 | 523 | ||
517 | trans->ops->fw_alive(trans); | 524 | trans->ops->fw_alive(trans, scd_addr); |
518 | } | 525 | } |
519 | 526 | ||
520 | static inline int iwl_trans_start_fw(struct iwl_trans *trans, | 527 | static inline int iwl_trans_start_fw(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 401178f44a3..1f065c630d4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -186,6 +186,8 @@ struct iwl_pcie_tx_queue_entry { | |||
186 | struct iwl_device_cmd *cmd; | 186 | struct iwl_device_cmd *cmd; |
187 | struct iwl_device_cmd *copy_cmd; | 187 | struct iwl_device_cmd *copy_cmd; |
188 | struct sk_buff *skb; | 188 | struct sk_buff *skb; |
189 | /* buffer to free after command completes */ | ||
190 | const void *free_buf; | ||
189 | struct iwl_cmd_meta meta; | 191 | struct iwl_cmd_meta meta; |
190 | }; | 192 | }; |
191 | 193 | ||
@@ -268,6 +270,8 @@ struct iwl_trans_pcie { | |||
268 | 270 | ||
269 | bool ucode_write_complete; | 271 | bool ucode_write_complete; |
270 | wait_queue_head_t ucode_write_waitq; | 272 | wait_queue_head_t ucode_write_waitq; |
273 | wait_queue_head_t wait_command_queue; | ||
274 | |||
271 | unsigned long status; | 275 | unsigned long status; |
272 | u8 cmd_queue; | 276 | u8 cmd_queue; |
273 | u8 cmd_fifo; | 277 | u8 cmd_fifo; |
@@ -286,10 +290,14 @@ struct iwl_trans_pcie { | |||
286 | /***************************************************** | 290 | /***************************************************** |
287 | * DRIVER STATUS FUNCTIONS | 291 | * DRIVER STATUS FUNCTIONS |
288 | ******************************************************/ | 292 | ******************************************************/ |
289 | #define STATUS_HCMD_ACTIVE 0 | 293 | enum { |
290 | #define STATUS_DEVICE_ENABLED 1 | 294 | STATUS_HCMD_ACTIVE, |
291 | #define STATUS_TPOWER_PMI 2 | 295 | STATUS_DEVICE_ENABLED, |
292 | #define STATUS_INT_ENABLED 3 | 296 | STATUS_TPOWER_PMI, |
297 | STATUS_INT_ENABLED, | ||
298 | STATUS_RFKILL, | ||
299 | STATUS_FW_ERROR, | ||
300 | }; | ||
293 | 301 | ||
294 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 302 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
295 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) | 303 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) |
@@ -346,6 +354,7 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | |||
346 | enum dma_data_direction dma_dir); | 354 | enum dma_data_direction dma_dir); |
347 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | 355 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, |
348 | struct sk_buff_head *skbs); | 356 | struct sk_buff_head *skbs); |
357 | void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id); | ||
349 | int iwl_queue_space(const struct iwl_queue *q); | 358 | int iwl_queue_space(const struct iwl_queue *q); |
350 | 359 | ||
351 | /***************************************************** | 360 | /***************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 137af4c46a6..11a93eddc84 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -199,7 +199,6 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) | |||
199 | { | 199 | { |
200 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 200 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
201 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 201 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
202 | struct list_head *element; | ||
203 | struct iwl_rx_mem_buffer *rxb; | 202 | struct iwl_rx_mem_buffer *rxb; |
204 | unsigned long flags; | 203 | unsigned long flags; |
205 | 204 | ||
@@ -221,9 +220,9 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans) | |||
221 | BUG_ON(rxb && rxb->page); | 220 | BUG_ON(rxb && rxb->page); |
222 | 221 | ||
223 | /* Get next free Rx buffer, remove from free list */ | 222 | /* Get next free Rx buffer, remove from free list */ |
224 | element = rxq->rx_free.next; | 223 | rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer, |
225 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | 224 | list); |
226 | list_del(element); | 225 | list_del(&rxb->list); |
227 | 226 | ||
228 | /* Point to Rx buffer via next RBD in circular buffer */ | 227 | /* Point to Rx buffer via next RBD in circular buffer */ |
229 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); | 228 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); |
@@ -260,7 +259,6 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
260 | { | 259 | { |
261 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 260 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
262 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 261 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
263 | struct list_head *element; | ||
264 | struct iwl_rx_mem_buffer *rxb; | 262 | struct iwl_rx_mem_buffer *rxb; |
265 | struct page *page; | 263 | struct page *page; |
266 | unsigned long flags; | 264 | unsigned long flags; |
@@ -308,10 +306,9 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
308 | __free_pages(page, trans_pcie->rx_page_order); | 306 | __free_pages(page, trans_pcie->rx_page_order); |
309 | return; | 307 | return; |
310 | } | 308 | } |
311 | element = rxq->rx_used.next; | 309 | rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer, |
312 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | 310 | list); |
313 | list_del(element); | 311 | list_del(&rxb->list); |
314 | |||
315 | spin_unlock_irqrestore(&rxq->lock, flags); | 312 | spin_unlock_irqrestore(&rxq->lock, flags); |
316 | 313 | ||
317 | BUG_ON(rxb->page); | 314 | BUG_ON(rxb->page); |
@@ -452,6 +449,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
452 | /* The original command isn't needed any more */ | 449 | /* The original command isn't needed any more */ |
453 | kfree(txq->entries[cmd_index].copy_cmd); | 450 | kfree(txq->entries[cmd_index].copy_cmd); |
454 | txq->entries[cmd_index].copy_cmd = NULL; | 451 | txq->entries[cmd_index].copy_cmd = NULL; |
452 | /* nor is the duplicated part of the command */ | ||
453 | kfree(txq->entries[cmd_index].free_buf); | ||
454 | txq->entries[cmd_index].free_buf = NULL; | ||
455 | } | 455 | } |
456 | 456 | ||
457 | /* | 457 | /* |
@@ -565,24 +565,27 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
565 | */ | 565 | */ |
566 | static void iwl_irq_handle_error(struct iwl_trans *trans) | 566 | static void iwl_irq_handle_error(struct iwl_trans *trans) |
567 | { | 567 | { |
568 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
569 | |||
568 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ | 570 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ |
569 | if (trans->cfg->internal_wimax_coex && | 571 | if (trans->cfg->internal_wimax_coex && |
570 | (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & | 572 | (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & |
571 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 573 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
572 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & | 574 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & |
573 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 575 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
574 | struct iwl_trans_pcie *trans_pcie = | ||
575 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
576 | |||
577 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 576 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
578 | iwl_op_mode_wimax_active(trans->op_mode); | 577 | iwl_op_mode_wimax_active(trans->op_mode); |
579 | wake_up(&trans->wait_command_queue); | 578 | wake_up(&trans_pcie->wait_command_queue); |
580 | return; | 579 | return; |
581 | } | 580 | } |
582 | 581 | ||
583 | iwl_dump_csr(trans); | 582 | iwl_dump_csr(trans); |
584 | iwl_dump_fh(trans, NULL); | 583 | iwl_dump_fh(trans, NULL); |
585 | 584 | ||
585 | set_bit(STATUS_FW_ERROR, &trans_pcie->status); | ||
586 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | ||
587 | wake_up(&trans_pcie->wait_command_queue); | ||
588 | |||
586 | iwl_op_mode_nic_error(trans->op_mode); | 589 | iwl_op_mode_nic_error(trans->op_mode); |
587 | } | 590 | } |
588 | 591 | ||
@@ -676,6 +679,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
676 | isr_stats->rfkill++; | 679 | isr_stats->rfkill++; |
677 | 680 | ||
678 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 681 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
682 | if (hw_rfkill) { | ||
683 | set_bit(STATUS_RFKILL, &trans_pcie->status); | ||
684 | if (test_and_clear_bit(STATUS_HCMD_ACTIVE, | ||
685 | &trans_pcie->status)) | ||
686 | IWL_DEBUG_RF_KILL(trans, | ||
687 | "Rfkill while SYNC HCMD in flight\n"); | ||
688 | wake_up(&trans_pcie->wait_command_queue); | ||
689 | } else { | ||
690 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
691 | } | ||
679 | 692 | ||
680 | handled |= CSR_INT_BIT_RF_KILL; | 693 | handled |= CSR_INT_BIT_RF_KILL; |
681 | } | 694 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 4d9dfa7de4e..f21bf661931 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -442,10 +442,10 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, | |||
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
444 | 444 | ||
445 | /** | 445 | /* |
446 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | 446 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's |
447 | */ | 447 | */ |
448 | static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) | 448 | void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) |
449 | { | 449 | { |
450 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 450 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
451 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | 451 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
@@ -496,6 +496,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | |||
496 | for (i = 0; i < txq->q.n_window; i++) { | 496 | for (i = 0; i < txq->q.n_window; i++) { |
497 | kfree(txq->entries[i].cmd); | 497 | kfree(txq->entries[i].cmd); |
498 | kfree(txq->entries[i].copy_cmd); | 498 | kfree(txq->entries[i].copy_cmd); |
499 | kfree(txq->entries[i].free_buf); | ||
499 | } | 500 | } |
500 | 501 | ||
501 | /* De-alloc circular buffer of TFDs */ | 502 | /* De-alloc circular buffer of TFDs */ |
@@ -1023,6 +1024,7 @@ static int iwl_load_given_ucode(struct iwl_trans *trans, | |||
1023 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | 1024 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, |
1024 | const struct fw_img *fw) | 1025 | const struct fw_img *fw) |
1025 | { | 1026 | { |
1027 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1026 | int ret; | 1028 | int ret; |
1027 | bool hw_rfkill; | 1029 | bool hw_rfkill; |
1028 | 1030 | ||
@@ -1032,6 +1034,8 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
1032 | return -EIO; | 1034 | return -EIO; |
1033 | } | 1035 | } |
1034 | 1036 | ||
1037 | clear_bit(STATUS_FW_ERROR, &trans_pcie->status); | ||
1038 | |||
1035 | iwl_enable_rfkill_int(trans); | 1039 | iwl_enable_rfkill_int(trans); |
1036 | 1040 | ||
1037 | /* If platform's RF_KILL switch is NOT set to KILL */ | 1041 | /* If platform's RF_KILL switch is NOT set to KILL */ |
@@ -1076,7 +1080,7 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | |||
1076 | iwl_write_prph(trans, SCD_TXFACT, mask); | 1080 | iwl_write_prph(trans, SCD_TXFACT, mask); |
1077 | } | 1081 | } |
1078 | 1082 | ||
1079 | static void iwl_tx_start(struct iwl_trans *trans) | 1083 | static void iwl_tx_start(struct iwl_trans *trans, u32 scd_base_addr) |
1080 | { | 1084 | { |
1081 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1085 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1082 | u32 a; | 1086 | u32 a; |
@@ -1089,6 +1093,10 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1089 | 1093 | ||
1090 | trans_pcie->scd_base_addr = | 1094 | trans_pcie->scd_base_addr = |
1091 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); | 1095 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); |
1096 | |||
1097 | WARN_ON(scd_base_addr != 0 && | ||
1098 | scd_base_addr != trans_pcie->scd_base_addr); | ||
1099 | |||
1092 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | 1100 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; |
1093 | /* reset conext data memory */ | 1101 | /* reset conext data memory */ |
1094 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; | 1102 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; |
@@ -1134,10 +1142,10 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1134 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1142 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
1135 | } | 1143 | } |
1136 | 1144 | ||
1137 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) | 1145 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) |
1138 | { | 1146 | { |
1139 | iwl_reset_ict(trans); | 1147 | iwl_reset_ict(trans); |
1140 | iwl_tx_start(trans); | 1148 | iwl_tx_start(trans, scd_addr); |
1141 | } | 1149 | } |
1142 | 1150 | ||
1143 | /** | 1151 | /** |
@@ -1243,6 +1251,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1243 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); | 1251 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); |
1244 | clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 1252 | clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); |
1245 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); | 1253 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); |
1254 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
1246 | } | 1255 | } |
1247 | 1256 | ||
1248 | static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) | 1257 | static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) |
@@ -2166,12 +2175,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2166 | goto out_pci_release_regions; | 2175 | goto out_pci_release_regions; |
2167 | } | 2176 | } |
2168 | 2177 | ||
2169 | dev_info(&pdev->dev, "pci_resource_len = 0x%08llx\n", | ||
2170 | (unsigned long long) pci_resource_len(pdev, 0)); | ||
2171 | dev_info(&pdev->dev, "pci_resource_base = %p\n", trans_pcie->hw_base); | ||
2172 | |||
2173 | dev_info(&pdev->dev, "HW Revision ID = 0x%X\n", pdev->revision); | ||
2174 | |||
2175 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 2178 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
2176 | * PCI Tx retries from interfering with C3 CPU state */ | 2179 | * PCI Tx retries from interfering with C3 CPU state */ |
2177 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | 2180 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); |
@@ -2197,7 +2200,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2197 | } | 2200 | } |
2198 | 2201 | ||
2199 | /* Initialize the wait queue for commands */ | 2202 | /* Initialize the wait queue for commands */ |
2200 | init_waitqueue_head(&trans->wait_command_queue); | 2203 | init_waitqueue_head(&trans_pcie->wait_command_queue); |
2201 | spin_lock_init(&trans->reg_lock); | 2204 | spin_lock_init(&trans->reg_lock); |
2202 | 2205 | ||
2203 | snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), | 2206 | snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index db3efbb84d9..dcc7e1256e3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -494,6 +494,8 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | |||
494 | _iwl_write_targ_mem_dwords(trans, stts_addr, | 494 | _iwl_write_targ_mem_dwords(trans, stts_addr, |
495 | zero_val, ARRAY_SIZE(zero_val)); | 495 | zero_val, ARRAY_SIZE(zero_val)); |
496 | 496 | ||
497 | iwl_tx_queue_unmap(trans, txq_id); | ||
498 | |||
497 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | 499 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
498 | } | 500 | } |
499 | 501 | ||
@@ -515,8 +517,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
515 | struct iwl_queue *q = &txq->q; | 517 | struct iwl_queue *q = &txq->q; |
516 | struct iwl_device_cmd *out_cmd; | 518 | struct iwl_device_cmd *out_cmd; |
517 | struct iwl_cmd_meta *out_meta; | 519 | struct iwl_cmd_meta *out_meta; |
520 | void *dup_buf = NULL; | ||
518 | dma_addr_t phys_addr; | 521 | dma_addr_t phys_addr; |
519 | u32 idx; | 522 | int idx; |
520 | u16 copy_size, cmd_size; | 523 | u16 copy_size, cmd_size; |
521 | bool had_nocopy = false; | 524 | bool had_nocopy = false; |
522 | int i; | 525 | int i; |
@@ -533,10 +536,33 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
533 | continue; | 536 | continue; |
534 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { | 537 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { |
535 | had_nocopy = true; | 538 | had_nocopy = true; |
539 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { | ||
540 | idx = -EINVAL; | ||
541 | goto free_dup_buf; | ||
542 | } | ||
543 | } else if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) { | ||
544 | /* | ||
545 | * This is also a chunk that isn't copied | ||
546 | * to the static buffer so set had_nocopy. | ||
547 | */ | ||
548 | had_nocopy = true; | ||
549 | |||
550 | /* only allowed once */ | ||
551 | if (WARN_ON(dup_buf)) { | ||
552 | idx = -EINVAL; | ||
553 | goto free_dup_buf; | ||
554 | } | ||
555 | |||
556 | dup_buf = kmemdup(cmd->data[i], cmd->len[i], | ||
557 | GFP_ATOMIC); | ||
558 | if (!dup_buf) | ||
559 | return -ENOMEM; | ||
536 | } else { | 560 | } else { |
537 | /* NOCOPY must not be followed by normal! */ | 561 | /* NOCOPY must not be followed by normal! */ |
538 | if (WARN_ON(had_nocopy)) | 562 | if (WARN_ON(had_nocopy)) { |
539 | return -EINVAL; | 563 | idx = -EINVAL; |
564 | goto free_dup_buf; | ||
565 | } | ||
540 | copy_size += cmd->len[i]; | 566 | copy_size += cmd->len[i]; |
541 | } | 567 | } |
542 | cmd_size += cmd->len[i]; | 568 | cmd_size += cmd->len[i]; |
@@ -551,8 +577,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
551 | if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, | 577 | if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, |
552 | "Command %s (%#x) is too large (%d bytes)\n", | 578 | "Command %s (%#x) is too large (%d bytes)\n", |
553 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), | 579 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), |
554 | cmd->id, copy_size)) | 580 | cmd->id, copy_size)) { |
555 | return -EINVAL; | 581 | idx = -EINVAL; |
582 | goto free_dup_buf; | ||
583 | } | ||
556 | 584 | ||
557 | spin_lock_bh(&txq->lock); | 585 | spin_lock_bh(&txq->lock); |
558 | 586 | ||
@@ -561,7 +589,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
561 | 589 | ||
562 | IWL_ERR(trans, "No space in command queue\n"); | 590 | IWL_ERR(trans, "No space in command queue\n"); |
563 | iwl_op_mode_cmd_queue_full(trans->op_mode); | 591 | iwl_op_mode_cmd_queue_full(trans->op_mode); |
564 | return -ENOSPC; | 592 | idx = -ENOSPC; |
593 | goto free_dup_buf; | ||
565 | } | 594 | } |
566 | 595 | ||
567 | idx = get_cmd_index(q, q->write_ptr); | 596 | idx = get_cmd_index(q, q->write_ptr); |
@@ -585,7 +614,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
585 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 614 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
586 | if (!cmd->len[i]) | 615 | if (!cmd->len[i]) |
587 | continue; | 616 | continue; |
588 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) | 617 | if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
618 | IWL_HCMD_DFL_DUP)) | ||
589 | break; | 619 | break; |
590 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); | 620 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); |
591 | cmd_pos += cmd->len[i]; | 621 | cmd_pos += cmd->len[i]; |
@@ -627,11 +657,16 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
627 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1); | 657 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1); |
628 | 658 | ||
629 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 659 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
660 | const void *data = cmd->data[i]; | ||
661 | |||
630 | if (!cmd->len[i]) | 662 | if (!cmd->len[i]) |
631 | continue; | 663 | continue; |
632 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | 664 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
665 | IWL_HCMD_DFL_DUP))) | ||
633 | continue; | 666 | continue; |
634 | phys_addr = dma_map_single(trans->dev, (void *)cmd->data[i], | 667 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) |
668 | data = dup_buf; | ||
669 | phys_addr = dma_map_single(trans->dev, (void *)data, | ||
635 | cmd->len[i], DMA_BIDIRECTIONAL); | 670 | cmd->len[i], DMA_BIDIRECTIONAL); |
636 | if (dma_mapping_error(trans->dev, phys_addr)) { | 671 | if (dma_mapping_error(trans->dev, phys_addr)) { |
637 | iwl_unmap_tfd(trans, out_meta, | 672 | iwl_unmap_tfd(trans, out_meta, |
@@ -646,6 +681,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
646 | } | 681 | } |
647 | 682 | ||
648 | out_meta->flags = cmd->flags; | 683 | out_meta->flags = cmd->flags; |
684 | if (WARN_ON_ONCE(txq->entries[idx].free_buf)) | ||
685 | kfree(txq->entries[idx].free_buf); | ||
686 | txq->entries[idx].free_buf = dup_buf; | ||
649 | 687 | ||
650 | txq->need_update = 1; | 688 | txq->need_update = 1; |
651 | 689 | ||
@@ -662,6 +700,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
662 | 700 | ||
663 | out: | 701 | out: |
664 | spin_unlock_bh(&txq->lock); | 702 | spin_unlock_bh(&txq->lock); |
703 | free_dup_buf: | ||
704 | if (idx < 0) | ||
705 | kfree(dup_buf); | ||
665 | return idx; | 706 | return idx; |
666 | } | 707 | } |
667 | 708 | ||
@@ -786,7 +827,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
786 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", | 827 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", |
787 | trans_pcie_get_cmd_string(trans_pcie, | 828 | trans_pcie_get_cmd_string(trans_pcie, |
788 | cmd->hdr.cmd)); | 829 | cmd->hdr.cmd)); |
789 | wake_up(&trans->wait_command_queue); | 830 | wake_up(&trans_pcie->wait_command_queue); |
790 | } | 831 | } |
791 | 832 | ||
792 | meta->flags = 0; | 833 | meta->flags = 0; |
@@ -845,7 +886,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
845 | return ret; | 886 | return ret; |
846 | } | 887 | } |
847 | 888 | ||
848 | ret = wait_event_timeout(trans->wait_command_queue, | 889 | ret = wait_event_timeout(trans_pcie->wait_command_queue, |
849 | !test_bit(STATUS_HCMD_ACTIVE, | 890 | !test_bit(STATUS_HCMD_ACTIVE, |
850 | &trans_pcie->status), | 891 | &trans_pcie->status), |
851 | HOST_COMPLETE_TIMEOUT); | 892 | HOST_COMPLETE_TIMEOUT); |
@@ -874,6 +915,19 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
874 | } | 915 | } |
875 | } | 916 | } |
876 | 917 | ||
918 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { | ||
919 | IWL_ERR(trans, "FW error in SYNC CMD %s\n", | ||
920 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); | ||
921 | ret = -EIO; | ||
922 | goto cancel; | ||
923 | } | ||
924 | |||
925 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { | ||
926 | IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); | ||
927 | ret = -ERFKILL; | ||
928 | goto cancel; | ||
929 | } | ||
930 | |||
877 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { | 931 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { |
878 | IWL_ERR(trans, "Error: Response NULL in '%s'\n", | 932 | IWL_ERR(trans, "Error: Response NULL in '%s'\n", |
879 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); | 933 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); |
@@ -905,9 +959,18 @@ cancel: | |||
905 | 959 | ||
906 | int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | 960 | int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) |
907 | { | 961 | { |
962 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
963 | |||
964 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) | ||
965 | return -EIO; | ||
966 | |||
967 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) | ||
968 | return -ERFKILL; | ||
969 | |||
908 | if (cmd->flags & CMD_ASYNC) | 970 | if (cmd->flags & CMD_ASYNC) |
909 | return iwl_send_cmd_async(trans, cmd); | 971 | return iwl_send_cmd_async(trans, cmd); |
910 | 972 | ||
973 | /* We still can fail on RFKILL that can be asserted while we wait */ | ||
911 | return iwl_send_cmd_sync(trans, cmd); | 974 | return iwl_send_cmd_sync(trans, cmd); |
912 | } | 975 | } |
913 | 976 | ||