int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, void *payload, u16 payload_size) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_set_param_var *param_hdr; u8 *param; int ret; param = kzalloc(payload_size + sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL); if (!param) { IWM_ERR(iwm, "Couldn't allocate param\n"); return -ENOMEM; } param_hdr = (struct iwm_umac_cmd_set_param_var *)param; umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR; umac_cmd.resp = 0; param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR); param_hdr->key = cpu_to_le16(key); param_hdr->len = cpu_to_le16(payload_size); memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var), payload, payload_size); ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param, sizeof(struct iwm_umac_cmd_set_param_var) + payload_size); kfree(param); return ret; }
int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm, struct iwm_umac_notif_stop_resume_tx *ntf) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_stop_resume_tx stp_res_cmd; struct iwm_sta_info *sta_info; u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id); int i; sta_info = &iwm->sta_table[sta_id]; if (!sta_info->valid) { IWM_ERR(iwm, "Invalid STA: %d\n", sta_id); return -EINVAL; } umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX; umac_cmd.resp = 0; stp_res_cmd.flags = ntf->flags; stp_res_cmd.sta_id = ntf->sta_id; stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk; for (i = 0; i < IWM_UMAC_TID_NR; i++) stp_res_cmd.last_seq_num[i] = sta_info->tid_info[i].last_seq_num; return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd, sizeof(struct iwm_umac_cmd_stop_resume_tx)); }
int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, bool resp) { struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload; struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; int ret; u8 oid = hdr->oid; if (!test_bit(IWM_STATUS_READY, &iwm->status)) { IWM_ERR(iwm, "Interface is not ready yet"); return -EAGAIN; } umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; umac_cmd.resp = resp; ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, payload, payload_size); if (resp) { ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue, test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), 3 * HZ); return ret ? 0 : -EBUSY; } return ret; }
int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, bool resp) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; umac_cmd.resp = resp; return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, payload, payload_size); }
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_stats_req stats_req; stats_req.flags = cpu_to_le32(flags); umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST; umac_cmd.resp = 0; return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req, sizeof(struct iwm_umac_cmd_stats_req)); }
int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_reset reset; reset.flags = reset_flags; umac_cmd.id = UMAC_CMD_OPCODE_RESET; umac_cmd.resp = resp; return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset, sizeof(struct iwm_umac_cmd_reset)); }
int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id) { struct iwm_udma_wifi_cmd udma_cmd; struct iwm_umac_cmd umac_cmd; struct iwm_tx_info *tx_info = skb_to_tx_info(skb); udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */ udma_cmd.credit_group = pool_id; udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; udma_cmd.lmac_offset = 0; umac_cmd.id = REPLY_TX; umac_cmd.color = tx_info->color; umac_cmd.resp = 0; return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, skb->data, skb->len); }
int iwm_send_umac_channel_list(struct iwm_priv *iwm) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_get_channel_list *ch_list; int size = sizeof(struct iwm_umac_cmd_get_channel_list) + sizeof(struct iwm_umac_channel_info) * 4; int ret; ch_list = kzalloc(size, GFP_KERNEL); if (!ch_list) { IWM_ERR(iwm, "Couldn't allocate channel list cmd\n"); return -ENOMEM; } ch_list->ch[0].band = UMAC_BAND_2GHZ; ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ; ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID; ch_list->ch[1].band = UMAC_BAND_5GHZ; ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ; ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID; ch_list->ch[2].band = UMAC_BAND_2GHZ; ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ; ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; ch_list->ch[3].band = UMAC_BAND_5GHZ; ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ; ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; ch_list->count = cpu_to_le16(4); umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST; umac_cmd.resp = 1; ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size); kfree(ch_list); return ret; }
int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value) { struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_set_param_fix param; if ((tbl != UMAC_PARAM_TBL_CFG_FIX) && (tbl != UMAC_PARAM_TBL_FA_CFG_FIX)) return -EINVAL; umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX; umac_cmd.resp = 0; param.tbl = cpu_to_le16(tbl); param.key = cpu_to_le16(key); param.value = cpu_to_le32(value); return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ¶m, sizeof(struct iwm_umac_cmd_set_param_fix)); }
static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id) { int ret; u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0; u32 addr; struct iwm_udma_wifi_cmd udma_cmd; struct iwm_umac_cmd umac_cmd; struct iwm_umac_cmd_eeprom_proxy eeprom_cmd; if (eeprom_id > (IWM_EEPROM_LAST - 1)) return -EINVAL; entry_size = eeprom_map[eeprom_id].length; if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) { /* indirect data */ u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA + IWM_EEPROM_INDIRECT_OFFSET; eeprom_map[eeprom_id].offset = *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1; } addr = eeprom_map[eeprom_id].offset; udma_cmd.eop = 1; udma_cmd.credit_group = 0x4; udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD; udma_cmd.lmac_offset = 0; umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY; umac_cmd.resp = 1; while (entry_size > 0) { chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN); eeprom_cmd.hdr.type = cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ); eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset); eeprom_cmd.hdr.len = cpu_to_le32(chunk_size); ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &eeprom_cmd, sizeof(struct iwm_umac_cmd_eeprom_proxy)); if (ret < 0) { IWM_ERR(iwm, "Couldn't read eeprom\n"); return ret; } ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY, IWM_SRC_UMAC, 2*HZ); if (ret < 0) { IWM_ERR(iwm, "Did not get any eeprom answer\n"); return ret; } data_offset += chunk_size; addr_offset += chunk_size; entry_size -= chunk_size; } return 0; }