linux/drivers/net/wireless/ath/wil6210/wmi.c

// SPDX-License-Identifier: ISC
/*
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/moduleparam.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>

#include "wil6210.h"
#include "txrx.h"
#include "wmi.h"
#include "trace.h"

/* set the default max assoc sta to max supported by driver */
uint max_assoc_sta =;
module_param(max_assoc_sta, uint, 0444);
MODULE_PARM_DESC();

int agg_wsize; /* = 0; */
module_param(agg_wsize, int, 0644);
MODULE_PARM_DESC();

u8 led_id =;
module_param(led_id, byte, 0444);
MODULE_PARM_DESC();

#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP
#define WIL_WMI_PCP_STOP_TO_MS

/**
 * DOC: WMI event receiving - theory of operations
 *
 * When firmware about to report WMI event, it fills memory area
 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
 * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
 *
 * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
 * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
 * and handles events within the @wmi_event_worker. Every event get detached
 * from list, processed and deleted.
 *
 * Purpose for this mechanism is to release IRQ thread; otherwise,
 * if WMI event handling involves another WMI command flow, this 2-nd flow
 * won't be completed because of blocked IRQ thread.
 */

/**
 * DOC: Addressing - theory of operations
 *
 * There are several buses present on the WIL6210 card.
 * Same memory areas are visible at different address on
 * the different busses. There are 3 main bus masters:
 *  - MAC CPU (ucode)
 *  - User CPU (firmware)
 *  - AHB (host)
 *
 * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
 * AHB addresses starting from 0x880000
 *
 * Internally, firmware uses addresses that allow faster access but
 * are invisible from the host. To read from these addresses, alternative
 * AHB address must be used.
 */

/* sparrow_fw_mapping provides memory remapping table for sparrow
 *
 * array size should be in sync with the declaration in the wil6210.h
 *
 * Sparrow memory mapping:
 * Linker address         PCI/Host address
 *                        0x880000 .. 0xa80000  2Mb BAR0
 * 0x800000 .. 0x808000   0x900000 .. 0x908000  32k DCCM
 * 0x840000 .. 0x860000   0x908000 .. 0x928000  128k PERIPH
 */
const struct fw_map sparrow_fw_mapping[] =;

/* sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
 * it is a bit larger to support extra features
 */
const struct fw_map sparrow_d0_mac_rgf_ext =;

/* talyn_fw_mapping provides memory remapping table for Talyn
 *
 * array size should be in sync with the declaration in the wil6210.h
 *
 * Talyn memory mapping:
 * Linker address         PCI/Host address
 *                        0x880000 .. 0xc80000  4Mb BAR0
 * 0x800000 .. 0x820000   0xa00000 .. 0xa20000  128k DCCM
 * 0x840000 .. 0x858000   0xa20000 .. 0xa38000  96k PERIPH
 */
const struct fw_map talyn_fw_mapping[] =;

/* talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
 *
 * array size should be in sync with the declaration in the wil6210.h
 *
 * Talyn MB memory mapping:
 * Linker address         PCI/Host address
 *                        0x880000 .. 0xc80000  4Mb BAR0
 * 0x800000 .. 0x820000   0xa00000 .. 0xa20000  128k DCCM
 * 0x840000 .. 0x858000   0xa20000 .. 0xa38000  96k PERIPH
 */
const struct fw_map talyn_mb_fw_mapping[] =;

struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];

struct blink_on_off_time led_blink_time[] =;

struct auth_no_hdr {} __packed;

u8 led_polarity =;

/**
 * wmi_addr_remap - return AHB address for given firmware internal (linker) address
 * @x: internal address
 * If address have no valid AHB mapping, return 0
 */
static u32 wmi_addr_remap(u32 x)
{}

/**
 * wil_find_fw_mapping - find fw_mapping entry by section name
 * @section: section name
 *
 * Return pointer to section or NULL if not found
 */
struct fw_map *wil_find_fw_mapping(const char *section)
{}

/**
 * wmi_buffer_block - Check address validity for WMI buffer; remap if needed
 * @wil: driver data
 * @ptr_: internal (linker) fw/ucode address
 * @size: if non zero, validate the block does not
 *  exceed the device memory (bar)
 *
 * Valid buffer should be DWORD aligned
 *
 * return address for accessing buffer from the host;
 * if buffer is not valid, return NULL.
 */
void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size)
{}

void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
{}

/* Check address validity */
void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
{}

int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
		 struct wil6210_mbox_hdr *hdr)
{}

static const char *cmdid2name(u16 cmdid)
{}

static const char *eventid2name(u16 eventid)
{}

static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid,
		      void *buf, u16 len)
{}

int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len)
{}

/*=== Event handlers ===*/
static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_tx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id,
				  void *d, int len)
{}

static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_disconnect(struct wil6210_vif *vif, int id,
			       void *d, int len)
{}

/*
 * Firmware reports EAPOL frame using WME event.
 * Reconstruct Ethernet frame and deliver it via normal Rx
 */
static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_ring_en(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
			      void *d, int len)
{}

static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id,
				 void *d, int len)
{}

static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{}

static void
wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void wil_link_stats_store_basic(struct wil6210_vif *vif,
				       struct wmi_link_stats_basic *basic)
{}

static void wil_link_stats_store_global(struct wil6210_vif *vif,
					struct wmi_link_stats_global *global)
{}

static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf,
				 bool has_next, void *payload,
				 size_t payload_size)
{}

static void
wmi_evt_link_stats(struct wil6210_vif *vif, int id, void *d, int len)
{}

/* find cid and ringid for the station vif
 *
 * return error, if other interfaces are used or ring was not found
 */
static int wil_find_cid_ringid_sta(struct wil6210_priv *wil,
				   struct wil6210_vif *vif,
				   int *cid,
				   int *ringid)
{}

static void
wmi_evt_auth_status(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void
wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len)
{}

static void
wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
{}

/* Some events are ignored for purpose; and need not be interpreted as
 * "unhandled events"
 */
static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
{}

static const struct {} wmi_evt_handlers[] =;

/*
 * Run in IRQ context
 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
 * that will be eventually handled by the @wmi_event_worker in the thread
 * context of thread "wil6210_wmi"
 */
void wmi_recv_cmd(struct wil6210_priv *wil)
{}

int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
	     u16 reply_id, void *reply, u16 reply_size, int to_msec)
{}

int wmi_echo(struct wil6210_priv *wil)
{}

int wmi_set_mac_address(struct wil6210_priv *wil, const void *addr)
{}

int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
{}

int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold)
{}

int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype,
		  u8 chan, u8 wmi_edmg_chan, u8 hidden_ssid, u8 is_go)
{}

int wmi_pcp_stop(struct wil6210_vif *vif)
{}

int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid)
{}

int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid)
{}

int wmi_set_channel(struct wil6210_priv *wil, int channel)
{}

int wmi_get_channel(struct wil6210_priv *wil, int *channel)
{}

int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi)
{}

int wmi_start_listen(struct wil6210_vif *vif)
{}

int wmi_start_search(struct wil6210_vif *vif)
{}

int wmi_stop_discovery(struct wil6210_vif *vif)
{}

int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index,
		       const void *mac_addr, int key_usage)
{}

int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
		       const void *mac_addr, int key_len, const void *key,
		       int key_usage)
{}

int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
{}

int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
{}

/**
 * wmi_rxon - turn radio on/off
 * @wil:	driver data
 * @on:		turn on if true, off otherwise
 *
 * Only switch radio. Channel should be set separately.
 * No timeout for rxon - radio turned on forever unless some other call
 * turns it off
 */
int wmi_rxon(struct wil6210_priv *wil, bool on)
{}

int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
{}

int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
{}

int wmi_get_all_temperatures(struct wil6210_priv *wil,
			     struct wmi_temp_sense_all_done_event
			     *sense_all_evt)
{}

int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
		       bool del_sta)
{}

int wmi_addba(struct wil6210_priv *wil, u8 mid,
	      u8 ringid, u8 size, u16 timeout)
{}

int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
{}

int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason)
{}

int wmi_addba_rx_resp(struct wil6210_priv *wil,
		      u8 mid, u8 cid, u8 tid, u8 token,
		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
{}

int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
			   u8 token, u16 status, bool amsdu, u16 agg_wsize,
			   u16 timeout)
{}

int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
			   enum wmi_ps_profile_type ps_profile)
{}

int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
{}

int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
{}

int wmi_abort_scan(struct wil6210_vif *vif)
{}

int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid)
{}

void wmi_event_flush(struct wil6210_priv *wil)
{}

static const char *suspend_status2name(u8 status)
{}

int wmi_suspend(struct wil6210_priv *wil)
{}

static void resume_triggers2string(u32 triggers, char *string, int str_size)
{}

int wmi_resume(struct wil6210_priv *wil)
{}

int wmi_port_allocate(struct wil6210_priv *wil, u8 mid,
		      const u8 *mac, enum nl80211_iftype iftype)
{}

int wmi_port_delete(struct wil6210_priv *wil, u8 mid)
{}

static bool wmi_evt_call_handler(struct wil6210_vif *vif, int id,
				 void *d, int len)
{}

static void wmi_event_handle(struct wil6210_priv *wil,
			     struct wil6210_mbox_hdr *hdr)
{}

/*
 * Retrieve next WMI event from the pending list
 */
static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
{}

/*
 * Handler for the WMI events
 */
void wmi_event_worker(struct work_struct *work)
{}

bool wil_is_wmi_idle(struct wil6210_priv *wil)
{}

static void
wmi_sched_scan_set_ssids(struct wil6210_priv *wil,
			 struct wmi_start_sched_scan_cmd *cmd,
			 struct cfg80211_ssid *ssids, int n_ssids,
			 struct cfg80211_match_set *match_sets,
			 int n_match_sets)
{}

static void
wmi_sched_scan_set_channels(struct wil6210_priv *wil,
			    struct wmi_start_sched_scan_cmd *cmd,
			    u32 n_channels,
			    struct ieee80211_channel **channels)
{}

static void
wmi_sched_scan_set_plans(struct wil6210_priv *wil,
			 struct wmi_start_sched_scan_cmd *cmd,
			 struct cfg80211_sched_scan_plan *scan_plans,
			 int n_scan_plans)
{}

int wmi_start_sched_scan(struct wil6210_priv *wil,
			 struct cfg80211_sched_scan_request *request)
{}

int wmi_stop_sched_scan(struct wil6210_priv *wil)
{}

int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len)
{}

int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
		    u8 channel, u16 duration_ms)
{}

int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id)
{}

int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil, u16 max_rx_pl_per_desc)
{}

int wil_wmi_rx_sring_add(struct wil6210_priv *wil, u16 ring_id)
{}

int wil_wmi_rx_desc_ring_add(struct wil6210_priv *wil, int status_ring_id)
{}

int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid,
			     int tid)
{}

int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id)
{}

int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
{}

int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
			    s32 rssi_thold, u32 rssi_hyst)
{}