aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index bdb1d7e7979d..72c27a3e5528 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1087,6 +1087,71 @@ static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
1087 return 0; 1087 return 0;
1088} 1088}
1089 1089
1090static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
1091 unsigned long buf_size,
1092 struct iwm_wifi_cmd *cmd)
1093{
1094 struct iwm_umac_notif_stop_resume_tx *stp_res_tx =
1095 (struct iwm_umac_notif_stop_resume_tx *)buf;
1096 struct iwm_sta_info *sta_info;
1097 struct iwm_tid_info *tid_info;
1098 u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id);
1099 u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk);
1100 int bit, ret = 0;
1101 bool stop = false;
1102
1103 IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n"
1104 "\tflags: 0x%x\n"
1105 "\tSTA id: %d\n"
1106 "\tTID bitmask: 0x%x\n",
1107 stp_res_tx->flags, stp_res_tx->sta_id,
1108 stp_res_tx->stop_resume_tid_msk);
1109
1110 if (stp_res_tx->flags & UMAC_STOP_TX_FLAG)
1111 stop = true;
1112
1113 sta_info = &iwm->sta_table[sta_id];
1114 if (!sta_info->valid) {
1115 IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n",
1116 sta_id, stp_res_tx->sta_id);
1117 return -EINVAL;
1118 }
1119
1120 for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
1121 tid_info = &sta_info->tid_info[bit];
1122
1123 mutex_lock(&tid_info->mutex);
1124 tid_info->stopped = stop;
1125 mutex_unlock(&tid_info->mutex);
1126
1127 if (!stop) {
1128 struct iwm_tx_queue *txq;
1129 u16 queue = iwm_tid_to_queue(bit);
1130
1131 if (queue < 0)
1132 continue;
1133
1134 txq = &iwm->txq[queue];
1135 /*
1136 * If we resume, we have to move our SKBs
1137 * back to the tx queue and queue some work.
1138 */
1139 spin_lock_bh(&txq->lock);
1140 skb_queue_splice_init(&txq->queue, &txq->stopped_queue);
1141 spin_unlock_bh(&txq->lock);
1142
1143 queue_work(txq->wq, &txq->worker);
1144 }
1145
1146 }
1147
1148 /* We send an ACK only for the stop case */
1149 if (stop)
1150 ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx);
1151
1152 return ret;
1153}
1154
1090static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, 1155static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
1091 unsigned long buf_size, 1156 unsigned long buf_size,
1092 struct iwm_wifi_cmd *cmd) 1157 struct iwm_wifi_cmd *cmd)
@@ -1371,6 +1436,7 @@ static const iwm_handler iwm_umac_handlers[] =
1371 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, 1436 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics,
1372 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, 1437 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy,
1373 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, 1438 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list,
1439 [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx,
1374 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, 1440 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1375 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, 1441 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper,
1376}; 1442};