diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/wmi.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.c | 197 | 
1 files changed, 171 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 9d69a1769926..7a52d2082b79 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -858,20 +858,20 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,  	len = sizeof(*txrx_streams);  	txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,  							  len); -	txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_2G; +	txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_2G);  	txrx_streams->supported_tx_streams = -				 args->chains[NL80211_BAND_2GHZ].tx; +				cpu_to_le32(args->chains[NL80211_BAND_2GHZ].tx);  	txrx_streams->supported_rx_streams = -				 args->chains[NL80211_BAND_2GHZ].rx; +				cpu_to_le32(args->chains[NL80211_BAND_2GHZ].rx);  	txrx_streams++;  	txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,  							  len); -	txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_5G; +	txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_5G);  	txrx_streams->supported_tx_streams = -				 args->chains[NL80211_BAND_5GHZ].tx; +				cpu_to_le32(args->chains[NL80211_BAND_5GHZ].tx);  	txrx_streams->supported_rx_streams = -				 args->chains[NL80211_BAND_5GHZ].rx; +				cpu_to_le32(args->chains[NL80211_BAND_5GHZ].rx);  	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,  		   "WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n", @@ -1900,7 +1900,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,  		if (arg->bw_160)  			cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);  		if (arg->bw_320) -			cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ); +			cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ);  		/* Typically if STBC is enabled for VHT it should be enabled  		 * for HT as well @@ -2723,6 +2723,149 @@ int ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath12k *ar,  	return ret;  } +int ath12k_wmi_set_bios_cmd(struct ath12k_base *ab, u32 param_id, +			    const u8 *buf, size_t buf_len) +{ +	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; +	struct wmi_pdev_set_bios_interface_cmd *cmd; +	struct wmi_tlv *tlv; +	struct sk_buff *skb; +	u8 *ptr; +	u32 len, len_aligned; +	int ret; + +	len_aligned = roundup(buf_len, sizeof(u32)); +	len = sizeof(*cmd) + TLV_HDR_SIZE + len_aligned; + +	skb = ath12k_wmi_alloc_skb(wmi_ab, len); +	if (!skb) +		return -ENOMEM; + +	cmd = (struct wmi_pdev_set_bios_interface_cmd *)skb->data; +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD, +						 sizeof(*cmd)); +	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC); +	cmd->param_type_id = cpu_to_le32(param_id); +	cmd->length = cpu_to_le32(buf_len); + +	ptr = skb->data + sizeof(*cmd); +	tlv = (struct wmi_tlv *)ptr; +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len_aligned); +	ptr += TLV_HDR_SIZE; +	memcpy(ptr, buf, buf_len); + +	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], +				  skb, +				  WMI_PDEV_SET_BIOS_INTERFACE_CMDID); +	if (ret) { +		ath12k_warn(ab, +			    "failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID parameter id %d: %d\n", +			    param_id, ret); +		dev_kfree_skb(skb); +	} + +	return 0; +} + +int ath12k_wmi_set_bios_sar_cmd(struct ath12k_base *ab, const u8 *psar_table) +{ +	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; +	struct wmi_pdev_set_bios_sar_table_cmd *cmd; +	struct wmi_tlv *tlv; +	struct sk_buff *skb; +	int ret; +	u8 *buf_ptr; +	u32 len, sar_table_len_aligned, sar_dbs_backoff_len_aligned; +	const u8 *psar_value = psar_table + ATH12K_ACPI_POWER_LIMIT_DATA_OFFSET; +	const u8 *pdbs_value = psar_table + ATH12K_ACPI_DBS_BACKOFF_DATA_OFFSET; + +	sar_table_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_TABLE_LEN, sizeof(u32)); +	sar_dbs_backoff_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN, +					      sizeof(u32)); +	len = sizeof(*cmd) + TLV_HDR_SIZE + sar_table_len_aligned + +		TLV_HDR_SIZE + sar_dbs_backoff_len_aligned; + +	skb = ath12k_wmi_alloc_skb(wmi_ab, len); +	if (!skb) +		return -ENOMEM; + +	cmd = (struct wmi_pdev_set_bios_sar_table_cmd *)skb->data; +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD, +						 sizeof(*cmd)); +	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC); +	cmd->sar_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_TABLE_LEN); +	cmd->dbs_backoff_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN); + +	buf_ptr = skb->data + sizeof(*cmd); +	tlv = (struct wmi_tlv *)buf_ptr; +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, +					 sar_table_len_aligned); +	buf_ptr += TLV_HDR_SIZE; +	memcpy(buf_ptr, psar_value, ATH12K_ACPI_BIOS_SAR_TABLE_LEN); + +	buf_ptr += sar_table_len_aligned; +	tlv = (struct wmi_tlv *)buf_ptr; +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, +					 sar_dbs_backoff_len_aligned); +	buf_ptr += TLV_HDR_SIZE; +	memcpy(buf_ptr, pdbs_value, ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN); + +	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], +				  skb, +				  WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID); +	if (ret) { +		ath12k_warn(ab, +			    "failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID %d\n", +			    ret); +		dev_kfree_skb(skb); +	} + +	return ret; +} + +int ath12k_wmi_set_bios_geo_cmd(struct ath12k_base *ab, const u8 *pgeo_table) +{ +	struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; +	struct wmi_pdev_set_bios_geo_table_cmd *cmd; +	struct wmi_tlv *tlv; +	struct sk_buff *skb; +	int ret; +	u8 *buf_ptr; +	u32 len, sar_geo_len_aligned; +	const u8 *pgeo_value = pgeo_table + ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET; + +	sar_geo_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN, sizeof(u32)); +	len = sizeof(*cmd) + TLV_HDR_SIZE + sar_geo_len_aligned; + +	skb = ath12k_wmi_alloc_skb(wmi_ab, len); +	if (!skb) +		return -ENOMEM; + +	cmd = (struct wmi_pdev_set_bios_geo_table_cmd *)skb->data; +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, +						 sizeof(*cmd)); +	cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC); +	cmd->geo_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN); + +	buf_ptr = skb->data + sizeof(*cmd); +	tlv = (struct wmi_tlv *)buf_ptr; +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, sar_geo_len_aligned); +	buf_ptr += TLV_HDR_SIZE; +	memcpy(buf_ptr, pgeo_value, ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN); + +	ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], +				  skb, +				  WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID); +	if (ret) { +		ath12k_warn(ab, +			    "failed to send WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID %d\n", +			    ret); +		dev_kfree_skb(skb); +	} + +	return ret; +} +  int ath12k_wmi_delba_send(struct ath12k *ar, u32 vdev_id, const u8 *mac,  			  u32 tid, u32 initiator, u32 reason)  { @@ -3324,7 +3467,8 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf  	wmi_cfg->bpf_instruction_size = cpu_to_le32(tg_cfg->bpf_instruction_size);  	wmi_cfg->max_bssid_rx_filters = cpu_to_le32(tg_cfg->max_bssid_rx_filters);  	wmi_cfg->use_pdev_id = cpu_to_le32(tg_cfg->use_pdev_id); -	wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config); +	wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config | +				     WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64);  	wmi_cfg->peer_map_unmap_version = cpu_to_le32(tg_cfg->peer_map_unmap_version);  	wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);  	wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count); @@ -4041,6 +4185,7 @@ static void ath12k_wmi_free_dbring_caps(struct ath12k_base *ab)  {  	kfree(ab->db_caps);  	ab->db_caps = NULL; +	ab->num_db_cap = 0;  }  static int ath12k_wmi_dma_ring_caps(struct ath12k_base *ab, @@ -5927,13 +6072,11 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)  		}  	} -	/* TODO: Pending handle beacon implementation -	 *if (ieee80211_is_beacon(hdr->frame_control)) -	 *	ath12k_mac_handle_beacon(ar, skb); -	 */ +	if (ieee80211_is_beacon(hdr->frame_control)) +		ath12k_mac_handle_beacon(ar, skb);  	ath12k_dbg(ab, ATH12K_DBG_MGMT, -		   "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", +		   "event mgmt rx skb %p len %d ftype %02x stype %02x\n",  		   skb, skb->len,  		   fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); @@ -6137,42 +6280,44 @@ static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)  {  	struct wmi_roam_event roam_ev = {};  	struct ath12k *ar; +	u32 vdev_id; +	u8 roam_reason;  	if (ath12k_pull_roam_ev(ab, skb, &roam_ev) != 0) {  		ath12k_warn(ab, "failed to extract roam event");  		return;  	} +	vdev_id = le32_to_cpu(roam_ev.vdev_id); +	roam_reason = u32_get_bits(le32_to_cpu(roam_ev.reason), +				   WMI_ROAM_REASON_MASK); +  	ath12k_dbg(ab, ATH12K_DBG_WMI, -		   "wmi roam event vdev %u reason 0x%08x rssi %d\n", -		   roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi); +		   "wmi roam event vdev %u reason %d rssi %d\n", +		   vdev_id, roam_reason, roam_ev.rssi);  	rcu_read_lock(); -	ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(roam_ev.vdev_id)); +	ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);  	if (!ar) { -		ath12k_warn(ab, "invalid vdev id in roam ev %d", -			    roam_ev.vdev_id); +		ath12k_warn(ab, "invalid vdev id in roam ev %d", vdev_id);  		rcu_read_unlock();  		return;  	} -	if (le32_to_cpu(roam_ev.reason) >= WMI_ROAM_REASON_MAX) +	if (roam_reason >= WMI_ROAM_REASON_MAX)  		ath12k_warn(ab, "ignoring unknown roam event reason %d on vdev %i\n", -			    roam_ev.reason, roam_ev.vdev_id); +			    roam_reason, vdev_id); -	switch (le32_to_cpu(roam_ev.reason)) { +	switch (roam_reason) {  	case WMI_ROAM_REASON_BEACON_MISS: -		/* TODO: Pending beacon miss and connection_loss_work -		 * implementation -		 * ath12k_mac_handle_beacon_miss(ar, vdev_id); -		 */ +		ath12k_mac_handle_beacon_miss(ar, vdev_id);  		break;  	case WMI_ROAM_REASON_BETTER_AP:  	case WMI_ROAM_REASON_LOW_RSSI:  	case WMI_ROAM_REASON_SUITABLE_AP_FOUND:  	case WMI_ROAM_REASON_HO_FAILED:  		ath12k_warn(ab, "ignoring not implemented roam event reason %d on vdev %i\n", -			    roam_ev.reason, roam_ev.vdev_id); +			    roam_reason, vdev_id);  		break;  	}  |