0001
0002
0003
0004
0005
0006 #include <linux/etherdevice.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/sched.h>
0010 #include <net/mac80211.h>
0011
0012 #include "iwl-io.h"
0013 #include "iwl-agn-hw.h"
0014 #include "iwl-trans.h"
0015 #include "iwl-modparams.h"
0016
0017 #include "dev.h"
0018 #include "agn.h"
0019
0020 int iwlagn_hw_valid_rtc_data_addr(u32 addr)
0021 {
0022 return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
0023 (addr < IWLAGN_RTC_DATA_UPPER_BOUND);
0024 }
0025
0026 int iwlagn_send_tx_power(struct iwl_priv *priv)
0027 {
0028 struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
0029 u8 tx_ant_cfg_cmd;
0030
0031 if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
0032 "TX Power requested while scanning!\n"))
0033 return -EAGAIN;
0034
0035
0036 tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
0037
0038 if (tx_power_cmd.global_lmt > priv->nvm_data->max_tx_pwr_half_dbm) {
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 tx_power_cmd.global_lmt =
0051 priv->nvm_data->max_tx_pwr_half_dbm;
0052 }
0053 tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
0054 tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
0055
0056 if (IWL_UCODE_API(priv->fw->ucode_ver) == 1)
0057 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
0058 else
0059 tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
0060
0061 return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, 0,
0062 sizeof(tx_power_cmd), &tx_power_cmd);
0063 }
0064
0065 void iwlagn_temperature(struct iwl_priv *priv)
0066 {
0067 lockdep_assert_held(&priv->statistics.lock);
0068
0069
0070 priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
0071 iwl_tt_handler(priv);
0072 }
0073
0074 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band)
0075 {
0076 int idx = 0;
0077 int band_offset = 0;
0078
0079
0080 if (rate_n_flags & RATE_MCS_HT_MSK) {
0081 idx = (rate_n_flags & 0xff);
0082 return idx;
0083
0084 } else {
0085 if (band == NL80211_BAND_5GHZ)
0086 band_offset = IWL_FIRST_OFDM_RATE;
0087 for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
0088 if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
0089 return idx - band_offset;
0090 }
0091
0092 return -1;
0093 }
0094
0095 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
0096 struct ieee80211_vif *vif, bool add)
0097 {
0098 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
0099
0100 if (add)
0101 return iwlagn_add_bssid_station(priv, vif_priv->ctx,
0102 vif->bss_conf.bssid,
0103 &vif_priv->ibss_bssid_sta_id);
0104 return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
0105 vif->bss_conf.bssid);
0106 }
0107
0108
0109
0110
0111
0112
0113
0114
0115 int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
0116 {
0117 struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = {
0118 .flush_control = cpu_to_le16(IWL_DROP_ALL),
0119 };
0120 struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = {
0121 .flush_control = cpu_to_le16(IWL_DROP_ALL),
0122 };
0123
0124 u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
0125 IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK;
0126
0127 if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
0128 queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK |
0129 IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK |
0130 IWL_PAN_SCD_MGMT_MSK |
0131 IWL_PAN_SCD_MULTICAST_MSK;
0132
0133 if (priv->nvm_data->sku_cap_11n_enable)
0134 queue_control |= IWL_AGG_TX_QUEUE_MSK;
0135
0136 if (scd_q_msk)
0137 queue_control = scd_q_msk;
0138
0139 IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control);
0140 flush_cmd_v3.queue_control = cpu_to_le32(queue_control);
0141 flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control);
0142
0143 if (IWL_UCODE_API(priv->fw->ucode_ver) > 2)
0144 return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
0145 sizeof(flush_cmd_v3),
0146 &flush_cmd_v3);
0147 return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
0148 sizeof(flush_cmd_v2), &flush_cmd_v2);
0149 }
0150
0151 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
0152 {
0153 mutex_lock(&priv->mutex);
0154 ieee80211_stop_queues(priv->hw);
0155 if (iwlagn_txfifo_flush(priv, 0)) {
0156 IWL_ERR(priv, "flush request fail\n");
0157 goto done;
0158 }
0159 IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
0160 iwl_trans_wait_tx_queues_empty(priv->trans, 0xffffffff);
0161 done:
0162 ieee80211_wake_queues(priv->hw);
0163 mutex_unlock(&priv->mutex);
0164 }
0165
0166
0167
0168
0169
0170 static const __le32 iwlagn_def_3w_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
0171 cpu_to_le32(0xaaaaaaaa),
0172 cpu_to_le32(0xaaaaaaaa),
0173 cpu_to_le32(0xaeaaaaaa),
0174 cpu_to_le32(0xaaaaaaaa),
0175 cpu_to_le32(0xcc00ff28),
0176 cpu_to_le32(0x0000aaaa),
0177 cpu_to_le32(0xcc00aaaa),
0178 cpu_to_le32(0x0000aaaa),
0179 cpu_to_le32(0xc0004000),
0180 cpu_to_le32(0x00004000),
0181 cpu_to_le32(0xf0005000),
0182 cpu_to_le32(0xf0005000),
0183 };
0184
0185
0186 static const __le32 iwlagn_concurrent_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
0187 cpu_to_le32(0xaaaaaaaa),
0188 cpu_to_le32(0xaaaaaaaa),
0189 cpu_to_le32(0xaaaaaaaa),
0190 cpu_to_le32(0xaaaaaaaa),
0191 cpu_to_le32(0xaaaaaaaa),
0192 cpu_to_le32(0xaaaaaaaa),
0193 cpu_to_le32(0xaaaaaaaa),
0194 cpu_to_le32(0xaaaaaaaa),
0195 cpu_to_le32(0x00000000),
0196 cpu_to_le32(0x00000000),
0197 cpu_to_le32(0x00000000),
0198 cpu_to_le32(0x00000000),
0199 };
0200
0201 void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
0202 {
0203 struct iwl_basic_bt_cmd basic = {
0204 .max_kill = IWLAGN_BT_MAX_KILL_DEFAULT,
0205 .bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT,
0206 .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
0207 .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
0208 };
0209 struct iwl_bt_cmd_v1 bt_cmd_v1;
0210 struct iwl_bt_cmd_v2 bt_cmd_v2;
0211 int ret;
0212
0213 BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
0214 sizeof(basic.bt3_lookup_table));
0215
0216 if (priv->lib->bt_params) {
0217
0218
0219
0220
0221
0222
0223 if (priv->lib->bt_params->bt_session_2) {
0224 bt_cmd_v2.prio_boost = cpu_to_le32(
0225 priv->lib->bt_params->bt_prio_boost);
0226 bt_cmd_v2.tx_prio_boost = 0;
0227 bt_cmd_v2.rx_prio_boost = 0;
0228 } else {
0229
0230 WARN_ON(priv->lib->bt_params->bt_prio_boost & ~0xFF);
0231 bt_cmd_v1.prio_boost =
0232 priv->lib->bt_params->bt_prio_boost;
0233 bt_cmd_v1.tx_prio_boost = 0;
0234 bt_cmd_v1.rx_prio_boost = 0;
0235 }
0236 } else {
0237 IWL_ERR(priv, "failed to construct BT Coex Config\n");
0238 return;
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 basic.kill_ack_mask = priv->kill_ack_mask;
0252 basic.kill_cts_mask = priv->kill_cts_mask;
0253 if (priv->reduced_txpower)
0254 basic.reduce_txpower = IWLAGN_BT_REDUCED_TX_PWR;
0255 basic.valid = priv->bt_valid;
0256
0257
0258
0259
0260
0261
0262
0263 if (!iwlwifi_mod_params.bt_coex_active ||
0264 priv->iw_mode == NL80211_IFTYPE_ADHOC) {
0265 basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
0266 } else {
0267 basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
0268 IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
0269
0270 if (!priv->bt_enable_pspoll)
0271 basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
0272 else
0273 basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
0274
0275 if (priv->bt_ch_announce)
0276 basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
0277 IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
0278 }
0279 priv->bt_enable_flag = basic.flags;
0280 if (priv->bt_full_concurrent)
0281 memcpy(basic.bt3_lookup_table, iwlagn_concurrent_lookup,
0282 sizeof(iwlagn_concurrent_lookup));
0283 else
0284 memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
0285 sizeof(iwlagn_def_3w_lookup));
0286
0287 IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
0288 basic.flags ? "active" : "disabled",
0289 priv->bt_full_concurrent ?
0290 "full concurrency" : "3-wire");
0291
0292 if (priv->lib->bt_params->bt_session_2) {
0293 memcpy(&bt_cmd_v2.basic, &basic,
0294 sizeof(basic));
0295 ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
0296 0, sizeof(bt_cmd_v2), &bt_cmd_v2);
0297 } else {
0298 memcpy(&bt_cmd_v1.basic, &basic,
0299 sizeof(basic));
0300 ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
0301 0, sizeof(bt_cmd_v1), &bt_cmd_v1);
0302 }
0303 if (ret)
0304 IWL_ERR(priv, "failed to send BT Coex Config\n");
0305
0306 }
0307
0308 void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
0309 {
0310 struct iwl_rxon_context *ctx, *found_ctx = NULL;
0311 bool found_ap = false;
0312
0313 lockdep_assert_held(&priv->mutex);
0314
0315
0316 if (rssi_ena) {
0317 for_each_context(priv, ctx) {
0318 if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP &&
0319 iwl_is_associated_ctx(ctx)) {
0320 found_ap = true;
0321 break;
0322 }
0323 }
0324 }
0325
0326
0327
0328
0329
0330 if (!rssi_ena || found_ap) {
0331 if (priv->cur_rssi_ctx) {
0332 ctx = priv->cur_rssi_ctx;
0333 ieee80211_disable_rssi_reports(ctx->vif);
0334 priv->cur_rssi_ctx = NULL;
0335 }
0336 return;
0337 }
0338
0339
0340
0341
0342
0343 for_each_context(priv, ctx) {
0344 if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
0345 iwl_is_associated_ctx(ctx)) {
0346 found_ctx = ctx;
0347 break;
0348 }
0349 }
0350
0351
0352
0353
0354
0355 if (found_ctx == priv->cur_rssi_ctx)
0356 return;
0357
0358
0359
0360
0361
0362
0363
0364 if (priv->cur_rssi_ctx) {
0365 ctx = priv->cur_rssi_ctx;
0366 if (ctx->vif)
0367 ieee80211_disable_rssi_reports(ctx->vif);
0368 }
0369
0370 priv->cur_rssi_ctx = found_ctx;
0371
0372 if (!found_ctx)
0373 return;
0374
0375 ieee80211_enable_rssi_reports(found_ctx->vif,
0376 IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD,
0377 IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD);
0378 }
0379
0380 static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
0381 {
0382 return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
0383 BT_UART_MSG_FRAME3SCOESCO_POS;
0384 }
0385
0386 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
0387 {
0388 struct iwl_priv *priv =
0389 container_of(work, struct iwl_priv, bt_traffic_change_work);
0390 struct iwl_rxon_context *ctx;
0391 int smps_request = -1;
0392
0393 if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
0394
0395 return;
0396 }
0397
0398
0399
0400
0401
0402
0403 IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
0404 priv->bt_traffic_load);
0405
0406 switch (priv->bt_traffic_load) {
0407 case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
0408 if (priv->bt_status)
0409 smps_request = IEEE80211_SMPS_DYNAMIC;
0410 else
0411 smps_request = IEEE80211_SMPS_AUTOMATIC;
0412 break;
0413 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
0414 smps_request = IEEE80211_SMPS_DYNAMIC;
0415 break;
0416 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
0417 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
0418 smps_request = IEEE80211_SMPS_STATIC;
0419 break;
0420 default:
0421 IWL_ERR(priv, "Invalid BT traffic load: %d\n",
0422 priv->bt_traffic_load);
0423 break;
0424 }
0425
0426 mutex_lock(&priv->mutex);
0427
0428
0429
0430
0431
0432
0433
0434
0435 if (test_bit(STATUS_SCAN_HW, &priv->status))
0436 goto out;
0437
0438 iwl_update_chain_flags(priv);
0439
0440 if (smps_request != -1) {
0441 priv->current_ht_config.smps = smps_request;
0442 for_each_context(priv, ctx) {
0443 if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
0444 ieee80211_request_smps(ctx->vif, 0, smps_request);
0445 }
0446 }
0447
0448
0449
0450
0451
0452 iwlagn_bt_coex_rssi_monitor(priv);
0453 out:
0454 mutex_unlock(&priv->mutex);
0455 }
0456
0457
0458
0459
0460
0461
0462 void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv)
0463 {
0464 if (priv->bt_is_sco &&
0465 priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS)
0466 iwlagn_bt_adjust_rssi_monitor(priv, true);
0467 else
0468 iwlagn_bt_adjust_rssi_monitor(priv, false);
0469 }
0470
0471 static void iwlagn_print_uartmsg(struct iwl_priv *priv,
0472 struct iwl_bt_uart_msg *uart_msg)
0473 {
0474 IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
0475 "Update Req = 0x%X\n",
0476 (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
0477 BT_UART_MSG_FRAME1MSGTYPE_POS,
0478 (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >>
0479 BT_UART_MSG_FRAME1SSN_POS,
0480 (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
0481 BT_UART_MSG_FRAME1UPDATEREQ_POS);
0482
0483 IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
0484 "Chl_SeqN = 0x%X, In band = 0x%X\n",
0485 (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
0486 BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
0487 (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >>
0488 BT_UART_MSG_FRAME2TRAFFICLOAD_POS,
0489 (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >>
0490 BT_UART_MSG_FRAME2CHLSEQN_POS,
0491 (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
0492 BT_UART_MSG_FRAME2INBAND_POS);
0493
0494 IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
0495 "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X\n",
0496 (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
0497 BT_UART_MSG_FRAME3SCOESCO_POS,
0498 (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >>
0499 BT_UART_MSG_FRAME3SNIFF_POS,
0500 (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >>
0501 BT_UART_MSG_FRAME3A2DP_POS,
0502 (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >>
0503 BT_UART_MSG_FRAME3ACL_POS,
0504 (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >>
0505 BT_UART_MSG_FRAME3MASTER_POS,
0506 (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
0507 BT_UART_MSG_FRAME3OBEX_POS);
0508
0509 IWL_DEBUG_COEX(priv, "Idle duration = 0x%X\n",
0510 (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
0511 BT_UART_MSG_FRAME4IDLEDURATION_POS);
0512
0513 IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
0514 "eSCO Retransmissions = 0x%X\n",
0515 (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
0516 BT_UART_MSG_FRAME5TXACTIVITY_POS,
0517 (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >>
0518 BT_UART_MSG_FRAME5RXACTIVITY_POS,
0519 (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
0520 BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
0521
0522 IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X\n",
0523 (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
0524 BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
0525 (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
0526 BT_UART_MSG_FRAME6DISCOVERABLE_POS);
0527
0528 IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
0529 "0x%X, Inquiry = 0x%X, Connectable = 0x%X\n",
0530 (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
0531 BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
0532 (BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >>
0533 BT_UART_MSG_FRAME7PAGE_POS,
0534 (BT_UART_MSG_FRAME7INQUIRY_MSK & uart_msg->frame7) >>
0535 BT_UART_MSG_FRAME7INQUIRY_POS,
0536 (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
0537 BT_UART_MSG_FRAME7CONNECTABLE_POS);
0538 }
0539
0540 static bool iwlagn_set_kill_msk(struct iwl_priv *priv,
0541 struct iwl_bt_uart_msg *uart_msg)
0542 {
0543 bool need_update = false;
0544 u8 kill_msk = IWL_BT_KILL_REDUCE;
0545 static const __le32 bt_kill_ack_msg[3] = {
0546 IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
0547 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
0548 IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
0549 static const __le32 bt_kill_cts_msg[3] = {
0550 IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
0551 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
0552 IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
0553
0554 if (!priv->reduced_txpower)
0555 kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
0556 ? IWL_BT_KILL_OVERRIDE : IWL_BT_KILL_DEFAULT;
0557 if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
0558 priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
0559 priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
0560 priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
0561 priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
0562 priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
0563 need_update = true;
0564 }
0565 return need_update;
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
0578 struct iwl_bt_uart_msg *uart_msg)
0579 {
0580 bool need_update = false;
0581 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
0582 int ave_rssi;
0583
0584 if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) {
0585 IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n");
0586 return false;
0587 }
0588
0589 ave_rssi = ieee80211_ave_rssi(ctx->vif);
0590 if (!ave_rssi) {
0591
0592 IWL_DEBUG_COEX(priv, "no rssi data available\n");
0593 return need_update;
0594 }
0595 if (!priv->reduced_txpower &&
0596 !iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
0597 (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) &&
0598 (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
0599 BT_UART_MSG_FRAME3OBEX_MSK)) &&
0600 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
0601 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK))) {
0602
0603 priv->reduced_txpower = true;
0604 priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
0605 need_update = true;
0606 } else if (priv->reduced_txpower &&
0607 (iwl_is_associated(priv, IWL_RXON_CTX_PAN) ||
0608 (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) ||
0609 (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
0610 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) ||
0611 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
0612 BT_UART_MSG_FRAME3OBEX_MSK)))) {
0613
0614 priv->reduced_txpower = false;
0615 priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
0616 need_update = true;
0617 }
0618
0619 return need_update;
0620 }
0621
0622 static void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
0623 struct iwl_rx_cmd_buffer *rxb)
0624 {
0625 struct iwl_rx_packet *pkt = rxb_addr(rxb);
0626 struct iwl_bt_coex_profile_notif *coex = (void *)pkt->data;
0627 struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
0628
0629 if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
0630
0631 return;
0632 }
0633
0634 IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
0635 IWL_DEBUG_COEX(priv, " status: %d\n", coex->bt_status);
0636 IWL_DEBUG_COEX(priv, " traffic load: %d\n", coex->bt_traffic_load);
0637 IWL_DEBUG_COEX(priv, " CI compliance: %d\n",
0638 coex->bt_ci_compliance);
0639 iwlagn_print_uartmsg(priv, uart_msg);
0640
0641 priv->last_bt_traffic_load = priv->bt_traffic_load;
0642 priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg);
0643
0644 if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
0645 if (priv->bt_status != coex->bt_status ||
0646 priv->last_bt_traffic_load != coex->bt_traffic_load) {
0647 if (coex->bt_status) {
0648
0649 if (!priv->bt_ch_announce)
0650 priv->bt_traffic_load =
0651 IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
0652 else
0653 priv->bt_traffic_load =
0654 coex->bt_traffic_load;
0655 } else {
0656
0657 priv->bt_traffic_load =
0658 IWL_BT_COEX_TRAFFIC_LOAD_NONE;
0659 }
0660 priv->bt_status = coex->bt_status;
0661 queue_work(priv->workqueue,
0662 &priv->bt_traffic_change_work);
0663 }
0664 }
0665
0666
0667
0668 if (iwlagn_fill_txpower_mode(priv, uart_msg) ||
0669 iwlagn_set_kill_msk(priv, uart_msg))
0670 queue_work(priv->workqueue, &priv->bt_runtime_config);
0671
0672
0673
0674
0675 priv->bt_ci_compliance = coex->bt_ci_compliance;
0676 }
0677
0678 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
0679 {
0680 priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
0681 iwlagn_bt_coex_profile_notif;
0682 }
0683
0684 void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
0685 {
0686 INIT_WORK(&priv->bt_traffic_change_work,
0687 iwlagn_bt_traffic_change_work);
0688 }
0689
0690 void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
0691 {
0692 cancel_work_sync(&priv->bt_traffic_change_work);
0693 }
0694
0695 static bool is_single_rx_stream(struct iwl_priv *priv)
0696 {
0697 return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
0698 priv->current_ht_config.single_chain_sufficient;
0699 }
0700
0701 #define IWL_NUM_RX_CHAINS_MULTIPLE 3
0702 #define IWL_NUM_RX_CHAINS_SINGLE 2
0703 #define IWL_NUM_IDLE_CHAINS_DUAL 2
0704 #define IWL_NUM_IDLE_CHAINS_SINGLE 1
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716 static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
0717 {
0718 if (priv->lib->bt_params &&
0719 priv->lib->bt_params->advanced_bt_coexist &&
0720 (priv->bt_full_concurrent ||
0721 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
0722
0723
0724
0725
0726 return IWL_NUM_RX_CHAINS_SINGLE;
0727 }
0728
0729 if (is_single_rx_stream(priv))
0730 return IWL_NUM_RX_CHAINS_SINGLE;
0731 else
0732 return IWL_NUM_RX_CHAINS_MULTIPLE;
0733 }
0734
0735
0736
0737
0738
0739 static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
0740 {
0741
0742 switch (priv->current_ht_config.smps) {
0743 case IEEE80211_SMPS_STATIC:
0744 case IEEE80211_SMPS_DYNAMIC:
0745 return IWL_NUM_IDLE_CHAINS_SINGLE;
0746 case IEEE80211_SMPS_AUTOMATIC:
0747 case IEEE80211_SMPS_OFF:
0748 return active_cnt;
0749 default:
0750 WARN(1, "invalid SMPS mode %d",
0751 priv->current_ht_config.smps);
0752 return active_cnt;
0753 }
0754 }
0755
0756
0757 static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
0758 {
0759 u8 res;
0760 res = (chain_bitmap & BIT(0)) >> 0;
0761 res += (chain_bitmap & BIT(1)) >> 1;
0762 res += (chain_bitmap & BIT(2)) >> 2;
0763 res += (chain_bitmap & BIT(3)) >> 3;
0764 return res;
0765 }
0766
0767
0768
0769
0770
0771
0772
0773 void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
0774 {
0775 bool is_single = is_single_rx_stream(priv);
0776 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
0777 u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
0778 u32 active_chains;
0779 u16 rx_chain;
0780
0781
0782
0783
0784
0785 if (priv->chain_noise_data.active_chains)
0786 active_chains = priv->chain_noise_data.active_chains;
0787 else
0788 active_chains = priv->nvm_data->valid_rx_ant;
0789
0790 if (priv->lib->bt_params &&
0791 priv->lib->bt_params->advanced_bt_coexist &&
0792 (priv->bt_full_concurrent ||
0793 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
0794
0795
0796
0797
0798 active_chains = first_antenna(active_chains);
0799 }
0800
0801 rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
0802
0803
0804 active_rx_cnt = iwl_get_active_rx_chain_count(priv);
0805 idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
0806
0807
0808
0809
0810
0811 valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
0812 if (valid_rx_cnt < active_rx_cnt)
0813 active_rx_cnt = valid_rx_cnt;
0814
0815 if (valid_rx_cnt < idle_rx_cnt)
0816 idle_rx_cnt = valid_rx_cnt;
0817
0818 rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
0819 rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
0820
0821 ctx->staging.rx_chain = cpu_to_le16(rx_chain);
0822
0823 if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
0824 ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
0825 else
0826 ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
0827
0828 IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
0829 ctx->staging.rx_chain,
0830 active_rx_cnt, idle_rx_cnt);
0831
0832 WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
0833 active_rx_cnt < idle_rx_cnt);
0834 }
0835
0836 u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
0837 {
0838 int i;
0839 u8 ind = ant;
0840
0841 if (priv->band == NL80211_BAND_2GHZ &&
0842 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
0843 return 0;
0844
0845 for (i = 0; i < RATE_ANT_NUM - 1; i++) {
0846 ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
0847 if (valid & BIT(ind))
0848 return ind;
0849 }
0850 return ant;
0851 }
0852
0853 #ifdef CONFIG_PM_SLEEP
0854 static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
0855 {
0856 int i;
0857
0858 for (i = 0; i < IWLAGN_P1K_SIZE; i++)
0859 out[i] = cpu_to_le16(p1k[i]);
0860 }
0861
0862 struct wowlan_key_data {
0863 struct iwl_rxon_context *ctx;
0864 struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc;
0865 struct iwlagn_wowlan_tkip_params_cmd *tkip;
0866 const u8 *bssid;
0867 bool error, use_rsc_tsc, use_tkip;
0868 };
0869
0870
0871 static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
0872 struct ieee80211_vif *vif,
0873 struct ieee80211_sta *sta,
0874 struct ieee80211_key_conf *key,
0875 void *_data)
0876 {
0877 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
0878 struct wowlan_key_data *data = _data;
0879 struct iwl_rxon_context *ctx = data->ctx;
0880 struct aes_sc *aes_sc, *aes_tx_sc = NULL;
0881 struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
0882 struct iwlagn_p1k_cache *rx_p1ks;
0883 u8 *rx_mic_key;
0884 struct ieee80211_key_seq seq;
0885 u32 cur_rx_iv32 = 0;
0886 u16 p1k[IWLAGN_P1K_SIZE];
0887 int ret, i;
0888
0889 mutex_lock(&priv->mutex);
0890
0891 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
0892 key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
0893 !sta && !ctx->key_mapping_keys)
0894 ret = iwl_set_default_wep_key(priv, ctx, key);
0895 else
0896 ret = iwl_set_dynamic_key(priv, ctx, key, sta);
0897
0898 if (ret) {
0899 IWL_ERR(priv, "Error setting key during suspend!\n");
0900 data->error = true;
0901 }
0902
0903 switch (key->cipher) {
0904 case WLAN_CIPHER_SUITE_TKIP:
0905 if (sta) {
0906 u64 pn64;
0907
0908 tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
0909 tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
0910
0911 rx_p1ks = data->tkip->rx_uni;
0912
0913 pn64 = atomic64_read(&key->tx_pn);
0914 tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
0915 tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
0916
0917 ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
0918 iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
0919
0920 memcpy(data->tkip->mic_keys.tx,
0921 &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
0922 IWLAGN_MIC_KEY_SIZE);
0923
0924 rx_mic_key = data->tkip->mic_keys.rx_unicast;
0925 } else {
0926 tkip_sc =
0927 data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
0928 rx_p1ks = data->tkip->rx_multi;
0929 rx_mic_key = data->tkip->mic_keys.rx_mcast;
0930 }
0931
0932
0933
0934
0935
0936
0937 for (i = 0; i < IWLAGN_NUM_RSC; i++) {
0938 ieee80211_get_key_rx_seq(key, i, &seq);
0939 tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
0940 tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
0941
0942 if (seq.tkip.iv32 > cur_rx_iv32)
0943 cur_rx_iv32 = seq.tkip.iv32;
0944 }
0945
0946 ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k);
0947 iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k);
0948 ieee80211_get_tkip_rx_p1k(key, data->bssid,
0949 cur_rx_iv32 + 1, p1k);
0950 iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k);
0951
0952 memcpy(rx_mic_key,
0953 &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
0954 IWLAGN_MIC_KEY_SIZE);
0955
0956 data->use_tkip = true;
0957 data->use_rsc_tsc = true;
0958 break;
0959 case WLAN_CIPHER_SUITE_CCMP:
0960 if (sta) {
0961 u64 pn64;
0962
0963 aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
0964 aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
0965
0966 pn64 = atomic64_read(&key->tx_pn);
0967 aes_tx_sc->pn = cpu_to_le64(pn64);
0968 } else
0969 aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
0970
0971
0972
0973
0974
0975 for (i = 0; i < IWLAGN_NUM_RSC; i++) {
0976 u8 *pn = seq.ccmp.pn;
0977
0978 ieee80211_get_key_rx_seq(key, i, &seq);
0979 aes_sc[i].pn = cpu_to_le64(
0980 (u64)pn[5] |
0981 ((u64)pn[4] << 8) |
0982 ((u64)pn[3] << 16) |
0983 ((u64)pn[2] << 24) |
0984 ((u64)pn[1] << 32) |
0985 ((u64)pn[0] << 40));
0986 }
0987 data->use_rsc_tsc = true;
0988 break;
0989 }
0990
0991 mutex_unlock(&priv->mutex);
0992 }
0993
0994 int iwlagn_send_patterns(struct iwl_priv *priv,
0995 struct cfg80211_wowlan *wowlan)
0996 {
0997 struct iwlagn_wowlan_patterns_cmd *pattern_cmd;
0998 struct iwl_host_cmd cmd = {
0999 .id = REPLY_WOWLAN_PATTERNS,
1000 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
1001 };
1002 int i, err;
1003
1004 if (!wowlan->n_patterns)
1005 return 0;
1006
1007 cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);
1008
1009 pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
1010 if (!pattern_cmd)
1011 return -ENOMEM;
1012
1013 pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
1014
1015 for (i = 0; i < wowlan->n_patterns; i++) {
1016 int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
1017
1018 memcpy(&pattern_cmd->patterns[i].mask,
1019 wowlan->patterns[i].mask, mask_len);
1020 memcpy(&pattern_cmd->patterns[i].pattern,
1021 wowlan->patterns[i].pattern,
1022 wowlan->patterns[i].pattern_len);
1023 pattern_cmd->patterns[i].mask_size = mask_len;
1024 pattern_cmd->patterns[i].pattern_size =
1025 wowlan->patterns[i].pattern_len;
1026 }
1027
1028 cmd.data[0] = pattern_cmd;
1029 err = iwl_dvm_send_cmd(priv, &cmd);
1030 kfree(pattern_cmd);
1031 return err;
1032 }
1033
1034 int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
1035 {
1036 struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
1037 struct iwl_rxon_cmd rxon;
1038 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
1039 struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
1040 struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
1041 struct iwlagn_d3_config_cmd d3_cfg_cmd = {
1042
1043
1044
1045
1046
1047 .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
1048 };
1049 struct wowlan_key_data key_data = {
1050 .ctx = ctx,
1051 .bssid = ctx->active.bssid_addr,
1052 .use_rsc_tsc = false,
1053 .tkip = &tkip_cmd,
1054 .use_tkip = false,
1055 };
1056 int ret, i;
1057 u16 seq;
1058
1059 key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
1060 if (!key_data.rsc_tsc)
1061 return -ENOMEM;
1062
1063 memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd));
1064
1065
1066
1067
1068
1069 seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ;
1070 wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq);
1071
1072
1073
1074
1075
1076 for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
1077 seq = priv->tid_data[IWL_AP_ID][i].seq_number;
1078 seq -= 0x10;
1079 wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
1080 }
1081
1082 if (wowlan->disconnect)
1083 wakeup_filter_cmd.enabled |=
1084 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
1085 IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE);
1086 if (wowlan->magic_pkt)
1087 wakeup_filter_cmd.enabled |=
1088 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET);
1089 if (wowlan->gtk_rekey_failure)
1090 wakeup_filter_cmd.enabled |=
1091 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
1092 if (wowlan->eap_identity_req)
1093 wakeup_filter_cmd.enabled |=
1094 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ);
1095 if (wowlan->four_way_handshake)
1096 wakeup_filter_cmd.enabled |=
1097 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
1098 if (wowlan->n_patterns)
1099 wakeup_filter_cmd.enabled |=
1100 cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
1101
1102 if (wowlan->rfkill_release)
1103 d3_cfg_cmd.wakeup_flags |=
1104 cpu_to_le32(IWLAGN_D3_WAKEUP_RFKILL);
1105
1106 iwl_scan_cancel_timeout(priv, 200);
1107
1108 memcpy(&rxon, &ctx->active, sizeof(rxon));
1109
1110 priv->ucode_loaded = false;
1111 iwl_trans_stop_device(priv->trans);
1112 ret = iwl_trans_start_hw(priv->trans);
1113 if (ret)
1114 goto out;
1115
1116 priv->wowlan = true;
1117
1118 ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
1119 if (ret)
1120 goto out;
1121
1122
1123 ret = iwl_alive_start(priv);
1124 if (ret)
1125 goto out;
1126
1127 memcpy(&ctx->staging, &rxon, sizeof(rxon));
1128 ret = iwlagn_commit_rxon(priv, ctx);
1129 if (ret)
1130 goto out;
1131
1132 ret = iwl_power_update_mode(priv, true);
1133 if (ret)
1134 goto out;
1135
1136 if (!iwlwifi_mod_params.swcrypto) {
1137
1138 priv->ucode_key_table = 0;
1139 ctx->key_mapping_keys = 0;
1140
1141
1142
1143
1144
1145
1146 mutex_unlock(&priv->mutex);
1147 ieee80211_iter_keys(priv->hw, ctx->vif,
1148 iwlagn_wowlan_program_keys,
1149 &key_data);
1150 mutex_lock(&priv->mutex);
1151 if (key_data.error) {
1152 ret = -EIO;
1153 goto out;
1154 }
1155
1156 if (key_data.use_rsc_tsc) {
1157 struct iwl_host_cmd rsc_tsc_cmd = {
1158 .id = REPLY_WOWLAN_TSC_RSC_PARAMS,
1159 .data[0] = key_data.rsc_tsc,
1160 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
1161 .len[0] = sizeof(*key_data.rsc_tsc),
1162 };
1163
1164 ret = iwl_dvm_send_cmd(priv, &rsc_tsc_cmd);
1165 if (ret)
1166 goto out;
1167 }
1168
1169 if (key_data.use_tkip) {
1170 ret = iwl_dvm_send_cmd_pdu(priv,
1171 REPLY_WOWLAN_TKIP_PARAMS,
1172 0, sizeof(tkip_cmd),
1173 &tkip_cmd);
1174 if (ret)
1175 goto out;
1176 }
1177
1178 if (priv->have_rekey_data) {
1179 memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
1180 memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN);
1181 kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
1182 memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN);
1183 kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
1184 kek_kck_cmd.replay_ctr = priv->replay_ctr;
1185
1186 ret = iwl_dvm_send_cmd_pdu(priv,
1187 REPLY_WOWLAN_KEK_KCK_MATERIAL,
1188 0, sizeof(kek_kck_cmd),
1189 &kek_kck_cmd);
1190 if (ret)
1191 goto out;
1192 }
1193 }
1194
1195 ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, 0,
1196 sizeof(d3_cfg_cmd), &d3_cfg_cmd);
1197 if (ret)
1198 goto out;
1199
1200 ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER,
1201 0, sizeof(wakeup_filter_cmd),
1202 &wakeup_filter_cmd);
1203 if (ret)
1204 goto out;
1205
1206 ret = iwlagn_send_patterns(priv, wowlan);
1207 out:
1208 kfree(key_data.rsc_tsc);
1209 return ret;
1210 }
1211 #endif
1212
1213 int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1214 {
1215 if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
1216 IWL_WARN(priv, "Not sending command - %s KILL\n",
1217 iwl_is_rfkill(priv) ? "RF" : "CT");
1218 return -EIO;
1219 }
1220
1221 if (test_bit(STATUS_FW_ERROR, &priv->status)) {
1222 IWL_ERR(priv, "Command %s failed: FW Error\n",
1223 iwl_get_cmd_string(priv->trans, cmd->id));
1224 return -EIO;
1225 }
1226
1227
1228
1229
1230
1231 if (!priv->ucode_loaded) {
1232 IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
1233 return -EIO;
1234 }
1235
1236
1237
1238
1239
1240
1241 if (!(cmd->flags & CMD_ASYNC))
1242 lockdep_assert_held(&priv->mutex);
1243
1244 return iwl_trans_send_cmd(priv->trans, cmd);
1245 }
1246
1247 int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
1248 u32 flags, u16 len, const void *data)
1249 {
1250 struct iwl_host_cmd cmd = {
1251 .id = id,
1252 .len = { len, },
1253 .data = { data, },
1254 .flags = flags,
1255 };
1256
1257 return iwl_dvm_send_cmd(priv, &cmd);
1258 }