int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) { struct ieee80211_rx_status status; struct ieee80211_hdr *hdr; struct wcn36xx_rx_bd *bd; u16 fc, sn; /* * All fields must be 0, otherwise it can lead to * unexpected consequences. */ memset(&status, 0, sizeof(status)); bd = (struct wcn36xx_rx_bd *)skb->data; buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); skb_pull(skb, bd->pdu.mpdu_header_off); status.mactime = 10; status.freq = wcn->current_channel->center_freq; status.band = wcn->current_channel->band; status.signal = -RSSI0(bd); status.antenna = 1; status.rate_idx = 1; status.flag = 0; status.rx_flags = 0; status.flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | RX_FLAG_DECRYPTED; wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x " "status->vendor_radiotap_len=%x", status.flag, status.vendor_radiotap_len); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); hdr = (struct ieee80211_hdr *) skb->data; fc = __le16_to_cpu(hdr->frame_control); sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); if (ieee80211_is_beacon(hdr->frame_control)) { wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d", skb, skb->len, fc, sn); wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ", (char *)skb->data, skb->len); } else { wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d", skb, skb->len, fc, sn); wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ", (char *)skb->data, skb->len); } ieee80211_rx_ni(wcn->hw, skb); return 0; }
static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) { struct wcn36xx *wcn = hw->priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x", changed); if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { int ch = WCN36XX_HW_CHANNEL(wcn); wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d", ch); wcn36xx_smd_switch_channel(wcn, ch); } return 0; }
static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, void *buf, size_t len) { struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; if (len < sizeof(*rsp)) return -EINVAL; rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { wcn36xx_warn("hal add sta self failure: %d", rsp->status); return -EIO; } wcn36xx_dbg(WCN36XX_DBG_HAL, "hal add sta self status %d " "self_sta_index %d dpu_index %d", rsp->status, rsp->self_sta_index, rsp->dpu_index); wcn->current_vif->sta_index = rsp->self_sta_index; wcn->current_vif->dpu_desc_index = rsp->dpu_index; return 0; }
static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data) { wcn36xx_dbg(WCN36XX_DBG_DXE, "wcn36xx_dxe_write_register: addr=%x, data=%x", addr, data); writel(data, wcn->mmio + addr); }
void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) { struct ieee80211_tx_info *info; struct sk_buff *skb; unsigned long flags; spin_lock_irqsave(&wcn->dxe_lock, flags); skb = wcn->tx_ack_skb; wcn->tx_ack_skb = NULL; spin_unlock_irqrestore(&wcn->dxe_lock, flags); if (!skb) { wcn36xx_warn("Spurious TX complete indication\n"); return; } info = IEEE80211_SKB_CB(skb); if (status == 1) info->flags |= IEEE80211_TX_STAT_ACK; wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); ieee80211_tx_status_irqsafe(wcn->hw, skb); ieee80211_wake_queues(wcn->hw); }
int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, struct sk_buff *skb) { struct wcn36xx_hal_send_probe_resp_req_msg msg; INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); /* // TODO need to find out why this is needed? */ /* msg_body.beacon_length = skb_beacon->len + 6; */ if (skb->len > BEACON_TEMPLATE_SIZE) { wcn36xx_warn("probe response template is too big: %d", skb->len); return -E2BIG; } msg.probe_resp_template_len = skb->len; memcpy(&msg.probe_resp_template, skb->data, skb->len); memcpy(&msg.bssid, &wcn->addresses[0], ETH_ALEN); PREPARE_HAL_BUF(wcn->smd_buf, msg); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal update probe rsp len %d bssid %pM", msg.probe_resp_template_len, msg.bssid); return wcn36xx_smd_send_and_wait(wcn, msg.header.len); };
int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct sk_buff *skb_beacon, u16 tim_off, u16 p2p_off) { struct wcn36xx_hal_send_beacon_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); /* TODO need to find out why this is needed? */ msg_body.beacon_length = skb_beacon->len + 6; /* TODO make this as a const */ if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); memcpy(&(msg_body.beacon[4]), skb_beacon->data, skb_beacon->len); } else { wcn36xx_error("Beacon is to big: beacon size=%d", msg_body.beacon_length); return -ENOMEM; } memcpy(&msg_body.bssid, &wcn->addresses[0], ETH_ALEN); /* TODO need to find out why this is needed? */ msg_body.tim_ie_offset = tim_off+4; msg_body.p2p_ie_offset = p2p_off; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal send beacon beacon_length %d", msg_body.beacon_length); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); };
static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, void *buf, size_t len) { struct wcn36xx_hal_config_sta_rsp_msg *rsp; struct config_sta_rsp_params *params; if (len < sizeof(*rsp)) return -EINVAL; rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; params = &rsp->params; if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { wcn36xx_warn("hal config sta response failure: %d", params->status); return -EIO; } wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d", params->status, params->sta_index, params->bssid_index, params->p2p); return 0; }
static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data) { *data = readl(wcn->mmio + addr); wcn36xx_dbg(WCN36XX_DBG_DXE, "wcn36xx_dxe_read_register: addr=%x, data=%x", addr, *data); }
static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, void *buf, size_t len) { struct wcn36xx_hal_config_bss_rsp_msg *rsp; struct wcn36xx_hal_config_bss_rsp_params *params; if (len < sizeof(*rsp)) return -EINVAL; rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; params = &rsp->bss_rsp_params; if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { wcn36xx_warn("hal config bss response failure: %d", params->status); return -EIO; } wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" " sta_idx %d self_idx %d bcast_idx %d mac %pM power %d", params->status, params->bss_index, params->dpu_desc_index, params->bss_sta_index, params->bss_self_sta_index, params->bss_bcast_sta_idx, params->mac, params->tx_mgmt_power); wcn->current_vif->sta_index = params->bss_sta_index; wcn->current_vif->dpu_desc_index = params->dpu_desc_index; return 0; }
static void wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) { struct wcn36xx_hal_switch_channel_rsp_msg *rsp; rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d", rsp->channel_number, rsp->status); }
static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data) { wcn36xx_dbg(WCN36XX_DBG_DXE, "wcn36xx_ccu_write_register: addr=%x, data=%x\n", addr, data); writel(data, wcn->ccu_base + addr); }
static void wcn36xx_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total, u64 multicast) { wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter"); changed &= WCN36XX_SUPPORTED_FILTERS; *total &= WCN36XX_SUPPORTED_FILTERS; }
static int wcn36xx_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_iftype new_type, bool p2p) { wcn36xx_dbg(WCN36XX_DBG_MAC, "mac change interface vif %p new_type %d p2p %d", vif, new_type, p2p); return 0; }
static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) { struct wcn36xx *wcn = (struct wcn36xx *)dev; int int_src, int_reason; wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) { wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, &int_reason); /* TODO: Check int_reason */ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, WCN36XX_INT_MASK_CHAN_TX_H); wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, WCN36XX_INT_MASK_CHAN_TX_H); wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); } if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, &int_reason); /* TODO: Check int_reason */ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, WCN36XX_INT_MASK_CHAN_TX_L); wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, WCN36XX_INT_MASK_CHAN_TX_L); wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); } return IRQ_HANDLED; }
int wcn36xx_smd_delete_bss(struct wcn36xx *wcn) { struct wcn36xx_hal_delete_bss_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); msg_body.bss_index = 0; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d", msg_body.bss_index); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_init_scan(struct wcn36xx *wcn) { struct wcn36xx_hal_init_scan_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); msg_body.mode = HAL_SYS_MODE_SCAN; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d", msg_body.mode); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
static int wcn36xx_smd_join_rsp(void *buf, size_t len) { struct wcn36xx_hal_join_rsp_msg *rsp; if (wcn36xx_smd_rsp_status_check(buf, len)) return -EIO; rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; wcn36xx_dbg(WCN36XX_DBG_HAL, "hal rsp join status %d tx_mgmt_power %d", rsp->status, rsp->tx_mgmt_power); return 0; }
int wcn36xx_smd_end_scan(struct wcn36xx *wcn, int ch) { struct wcn36xx_hal_end_scan_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); msg_body.scan_channel = (u8)ch; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d", msg_body.scan_channel); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
static void wcn36xx_stop(struct ieee80211_hw *hw) { struct wcn36xx *wcn = hw->priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop"); wcn36xx_debugfs_exit(wcn); wcn36xx_smd_stop(wcn); wcn36xx_dxe_deinit(wcn); wcn36xx_smd_close(wcn); wcn36xx_dxe_free_mem_pools(wcn); wcn36xx_dxe_free_ctl_blks(wcn); kfree(wcn->smd_buf); }
int wcn36xx_smd_start(struct wcn36xx *wcn) { struct wcn36xx_hal_mac_start_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); msg_body.params.type = DRIVER_TYPE_PRODUCTION; msg_body.params.len = 0; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d", msg_body.params.type); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, u8 *addr, u32 status) { struct wcn36xx_hal_add_sta_self_req msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); memcpy(&msg_body.self_addr, addr, ETH_ALEN); msg_body.status = status; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal add sta self self_addr %pM status %d", msg_body.self_addr, msg_body.status); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_delete_sta(struct wcn36xx *wcn) { struct wcn36xx_hal_delete_sta_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); msg_body.sta_index = 1; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete sta sta_index %d", msg_body.sta_index); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, const u8 *sta_mac, enum wcn36xx_hal_link_state state) { struct wcn36xx_hal_set_link_state_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); memcpy(&msg_body.bssid, bssid, ETH_ALEN); memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); msg_body.state = state; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal set link state bssid %pM self_mac_addr %pM state %d", msg_body.bssid, msg_body.self_mac_addr, msg_body.state); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, const struct wcn36xx_hal_config_sta_req_msg *orig) { struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, &msg_body.sta_params); PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d", sta->action, sta->sta_index, sta->bssid_index, sta->bssid, sta->type, sta->mac, sta->aid); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) { struct wcn36xx_hal_join_req_msg msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); memcpy(&msg_body.bssid, bssid, ETH_ALEN); memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); msg_body.channel = ch; msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; msg_body.max_tx_power = 0xbf; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d", msg_body.bssid, msg_body.self_sta_mac_addr, msg_body.channel, msg_body.link_state); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) { struct wcn36xx_hal_update_scan_params_req msg_body; INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); /* TODO read this from config */ msg_body.dot11d_enabled = 0; msg_body.dot11d_resolved = 0; msg_body.channel_count = 26; msg_body.active_min_ch_time = 60; msg_body.active_max_ch_time = 120; msg_body.passive_min_ch_time = 60; msg_body.passive_max_ch_time = 110; msg_body.state = 0; PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal update scan params channel_count %d", msg_body.channel_count); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct wcn36xx_vif *vif_priv, struct sk_buff *skb, bool is_low) { struct wcn36xx_dxe_ctl *ctl = NULL; struct wcn36xx_dxe_desc *desc = NULL; struct wcn36xx_dxe_ch *ch = NULL; unsigned long flags; ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; ctl = ch->head_blk_ctl; spin_lock_irqsave(&ctl->next->skb_lock, flags); /* * If skb is not null that means that we reached the tail of the ring * hence ring is full. Stop queues to let mac80211 back off until ring * has an empty slot again. */ if (NULL != ctl->next->skb) { ieee80211_stop_queues(wcn->hw); wcn->queues_stopped = true; spin_unlock_irqrestore(&ctl->next->skb_lock, flags); return -EBUSY; } spin_unlock_irqrestore(&ctl->next->skb_lock, flags); ctl->skb = NULL; desc = ctl->desc; /* Set source address of the BD we send */ desc->src_addr_l = ctl->bd_phy_addr; desc->dst_addr_l = ch->dxe_wq; desc->fr_len = sizeof(struct wcn36xx_tx_bd); desc->ctrl = ch->ctrl_bd; wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", (char *)desc, sizeof(*desc)); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "BD >>> ", (char *)ctl->bd_cpu_addr, sizeof(struct wcn36xx_tx_bd)); /* Set source address of the SKB we send */ ctl = ctl->next; ctl->skb = skb; desc = ctl->desc; if (ctl->bd_cpu_addr) { wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); return -EINVAL; } desc->src_addr_l = dma_map_single(NULL, ctl->skb->data, ctl->skb->len, DMA_TO_DEVICE); desc->dst_addr_l = ch->dxe_wq; desc->fr_len = ctl->skb->len; /* set dxe descriptor to VALID */ desc->ctrl = ch->ctrl_skb; wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", (char *)desc, sizeof(*desc)); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", (char *)ctl->skb->data, ctl->skb->len); /* Move the head of the ring to the next empty descriptor */ ch->head_blk_ctl = ctl->next; /* * When connected and trying to send data frame chip can be in sleep * mode and writing to the register will not wake up the chip. Instead * notify chip about new frame through SMSM bus. */ if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { wcn->ctrl_ops->smsm_change_state( 0, WCN36XX_SMSM_WLAN_TX_ENABLE); } else { /* indicate End Of Packet and generate interrupt on descriptor * done. */ wcn36xx_dxe_write_register(wcn, ch->reg_ctrl, ch->def_ctrl); } return 0; }
static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, const struct wcn36xx_hal_config_bss_req_msg *orig) { struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); /* convert orig to v1 */ memcpy(&msg_body.bss_params.bssid, &orig->bss_params.bssid, ETH_ALEN); memcpy(&msg_body.bss_params.self_mac_addr, &orig->bss_params.self_mac_addr, ETH_ALEN); msg_body.bss_params.bss_type = orig->bss_params.bss_type; msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; msg_body.bss_params.nw_type = orig->bss_params.nw_type; msg_body.bss_params.short_slot_time_supported = orig->bss_params.short_slot_time_supported; msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; msg_body.bss_params.lln_non_gf_coexist = orig->bss_params.lln_non_gf_coexist; msg_body.bss_params.lsig_tx_op_protection_full_support = orig->bss_params.lsig_tx_op_protection_full_support; msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; msg_body.bss_params.tx_channel_width_set = orig->bss_params.tx_channel_width_set; msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; msg_body.bss_params.reserved = orig->bss_params.reserved; memcpy(&msg_body.bss_params.ssid, &orig->bss_params.ssid, sizeof(orig->bss_params.ssid)); msg_body.bss_params.action = orig->bss_params.action; msg_body.bss_params.rateset = orig->bss_params.rateset; msg_body.bss_params.ht = orig->bss_params.ht; msg_body.bss_params.obss_prot_enabled = orig->bss_params.obss_prot_enabled; msg_body.bss_params.rmf = orig->bss_params.rmf; msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; msg_body.bss_params.dual_cts_protection = orig->bss_params.dual_cts_protection; msg_body.bss_params.max_probe_resp_retry_limit = orig->bss_params.max_probe_resp_retry_limit; msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; msg_body.bss_params.proxy_probe_resp = orig->bss_params.proxy_probe_resp; msg_body.bss_params.edca_params_valid = orig->bss_params.edca_params_valid; memcpy(&msg_body.bss_params.acbe, &orig->bss_params.acbe, sizeof(orig->bss_params.acbe)); memcpy(&msg_body.bss_params.acbk, &orig->bss_params.acbk, sizeof(orig->bss_params.acbk)); memcpy(&msg_body.bss_params.acvi, &orig->bss_params.acvi, sizeof(orig->bss_params.acvi)); memcpy(&msg_body.bss_params.acvo, &orig->bss_params.acvo, sizeof(orig->bss_params.acvo)); msg_body.bss_params.ext_set_sta_key_param_valid = orig->bss_params.ext_set_sta_key_param_valid; memcpy(&msg_body.bss_params.ext_set_sta_key_param, &orig->bss_params.ext_set_sta_key_param, sizeof(orig->bss_params.acvo)); msg_body.bss_params.wcn36xx_hal_persona = orig->bss_params.wcn36xx_hal_persona; msg_body.bss_params.spectrum_mgt_enable = orig->bss_params.spectrum_mgt_enable; msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, &msg_body.bss_params.sta); PREPARE_HAL_BUF(wcn->smd_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d", bss->bssid, bss->self_mac_addr, bss->bss_type, bss->oper_mode, bss->nw_type); wcn36xx_dbg(WCN36XX_DBG_HAL, "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM", sta->bssid, sta->action, sta->sta_index, sta->bssid_index, sta->aid, sta->type, sta->mac); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); }
int wcn36xx_smd_config_bss(struct wcn36xx *wcn, enum nl80211_iftype type, const u8 *bssid, bool update, u16 beacon_interval) { struct wcn36xx_hal_config_bss_req_msg msg; struct wcn36xx_hal_config_bss_params *bss; struct wcn36xx_hal_config_sta_params *sta; INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); bss = &msg.bss_params; sta = &bss->sta; WARN_ON(is_zero_ether_addr(bssid)); memcpy(&bss->bssid, bssid, ETH_ALEN); memcpy(&bss->self_mac_addr, &wcn->addresses[0], ETH_ALEN); if (type == NL80211_IFTYPE_STATION) { bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; /* STA */ bss->oper_mode = 1; } else if (type == NL80211_IFTYPE_AP) { bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; /* AP */ bss->oper_mode = 0; } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_MESH_POINT) { bss->bss_type = WCN36XX_HAL_IBSS_MODE; /* STA */ bss->oper_mode = 1; } else { wcn36xx_warn("Unknown type for bss config: %d", type); } bss->nw_type = WCN36XX_HAL_11G_NW_TYPE; bss->short_slot_time_supported = 0; bss->lla_coexist = 0; bss->llb_coexist = 0; bss->llg_coexist = 0; bss->ht20_coexist = 0; bss->lln_non_gf_coexist = 0; bss->lsig_tx_op_protection_full_support = 0; bss->rifs_mode = 0; bss->beacon_interval = beacon_interval; bss->dtim_period = 2; bss->tx_channel_width_set = 0; bss->oper_channel = wcn->ch; bss->ext_channel = 0; bss->reserved = 0; memcpy(&sta->bssid, bssid, ETH_ALEN); sta->aid = wcn->aid; sta->type = 0; sta->short_preamble_supported = 0; memcpy(&sta->mac, &wcn->addresses[0], ETH_ALEN); sta->listen_interval = 8; sta->wmm_enabled = 0; sta->ht_capable = 0; sta->tx_channel_width_set = 0; sta->rifs_mode = 0; sta->lsig_txop_protection = 0; sta->max_ampdu_size = 0; sta->max_ampdu_density = 0; sta->sgi_40mhz = 0; sta->sgi_20Mhz = 0; memcpy(&sta->supported_rates, &wcn->supported_rates, sizeof(wcn->supported_rates)); sta->rmf = 0; sta->encrypt_type = 0; sta->action = 0; sta->uapsd = 0; sta->max_sp_len = 0; sta->green_field_capable = 0; sta->mimo_ps = 0; sta->delayed_ba_support = 0; sta->max_ampdu_duration = 0; sta->dsss_cck_mode_40mhz = 0; sta->sta_index = 0xff; sta->bssid_index = 0; sta->p2p = 0; /* wcn->ssid is only valid in AP and IBSS mode */ bss->ssid.length = wcn->ssid.length; memcpy(bss->ssid.ssid, wcn->ssid.ssid, wcn->ssid.length); bss->action = 0; /* FIXME: set rateset */ bss->ht = 0; bss->obss_prot_enabled = 0; bss->rmf = 0; bss->ht_oper_mode = 0; bss->dual_cts_protection = 0; bss->max_probe_resp_retry_limit = 0; bss->hidden_ssid = 0; bss->proxy_probe_resp = 0; bss->edca_params_valid = 0; /* FIXME: set acbe, acbk, acvi and acvo */ bss->ext_set_sta_key_param_valid = 0; /* FIXME: set ext_set_sta_key_param */ bss->wcn36xx_hal_persona = 1; bss->spectrum_mgt_enable = 0; bss->tx_mgmt_power = 0; bss->max_tx_power = 0x10; if (update) { sta->bssid_index = 0; bss->action = 1; } else { sta->bssid_index = 0xff; bss->action = 0; } if (!(wcn->fw_major == 1 && wcn->fw_minor == 2 && wcn->fw_version == 2 && wcn->fw_revision == 24)) return wcn36xx_smd_config_bss_v1(wcn, &msg); PREPARE_HAL_BUF(wcn->smd_buf, msg); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d", bss->bssid, bss->self_mac_addr, bss->bss_type, bss->oper_mode, bss->nw_type); wcn36xx_dbg(WCN36XX_DBG_HAL, "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM", sta->bssid, sta->action, sta->sta_index, sta->bssid_index, sta->aid, sta->type, sta->mac); return wcn36xx_smd_send_and_wait(wcn, msg.header.len); }