Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: Coi-l/wcn36xx
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;
}
Exemplo n.º 3
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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;
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
};
Exemplo n.º 7
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
};
Exemplo n.º 8
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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;
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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;
}
Exemplo n.º 11
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 12
0
Arquivo: dxe.c Projeto: Lyude/linux
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);
}
Exemplo n.º 13
0
Arquivo: main.c Projeto: Coi-l/wcn36xx
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;
}
Exemplo n.º 14
0
Arquivo: main.c Projeto: Coi-l/wcn36xx
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;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 17
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 18
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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;
}
Exemplo n.º 19
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 20
0
Arquivo: main.c Projeto: Coi-l/wcn36xx
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);
}
Exemplo n.º 21
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 22
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 23
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);

}
Exemplo n.º 24
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 25
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 26
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 27
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}
Exemplo n.º 30
0
Arquivo: smd.c Projeto: kvalo/wcn36xx
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);
}