1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (c) 2010-2011 Atheros Communications Inc. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Permission to use, copy, modify, and/or distribute this software for any 5*4882a593Smuzhiyun * purpose with or without fee is hereby granted, provided that the above 6*4882a593Smuzhiyun * copyright notice and this permission notice appear in all copies. 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9*4882a593Smuzhiyun * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10*4882a593Smuzhiyun * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11*4882a593Smuzhiyun * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13*4882a593Smuzhiyun * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14*4882a593Smuzhiyun * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15*4882a593Smuzhiyun */ 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #ifndef WMI_H 18*4882a593Smuzhiyun #define WMI_H 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun struct wmi_event_txrate { 21*4882a593Smuzhiyun __be32 txrate; 22*4882a593Smuzhiyun struct { 23*4882a593Smuzhiyun u8 rssi_thresh; 24*4882a593Smuzhiyun u8 per; 25*4882a593Smuzhiyun } rc_stats; 26*4882a593Smuzhiyun } __packed; 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun struct wmi_cmd_hdr { 29*4882a593Smuzhiyun __be16 command_id; 30*4882a593Smuzhiyun __be16 seq_no; 31*4882a593Smuzhiyun } __packed; 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun struct wmi_fw_version { 34*4882a593Smuzhiyun __be16 major; 35*4882a593Smuzhiyun __be16 minor; 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun } __packed; 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun struct wmi_event_swba { 40*4882a593Smuzhiyun __be64 tsf; 41*4882a593Smuzhiyun u8 beacon_pending; 42*4882a593Smuzhiyun } __packed; 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun /* 45*4882a593Smuzhiyun * 64 - HTC header - WMI header - 1 / txstatus 46*4882a593Smuzhiyun * And some other hdr. space is also accounted for. 47*4882a593Smuzhiyun * 12 seems to be the magic number. 48*4882a593Smuzhiyun */ 49*4882a593Smuzhiyun #define HTC_MAX_TX_STATUS 12 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_ACK BIT(0) 52*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_FILT BIT(1) 53*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_RTC_CTS BIT(2) 54*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_MCS BIT(3) 55*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_CW40 BIT(4) 56*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_SGI BIT(5) 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* 59*4882a593Smuzhiyun * Legacy rates are indicated as indices. 60*4882a593Smuzhiyun * HT rates are indicated as dot11 numbers. 61*4882a593Smuzhiyun * This allows us to resrict the rate field 62*4882a593Smuzhiyun * to 4 bits. 63*4882a593Smuzhiyun */ 64*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_RATE 0x0f 65*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_RATE_S 0 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_EPID 0xf0 68*4882a593Smuzhiyun #define ATH9K_HTC_TXSTAT_EPID_S 4 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun struct __wmi_event_txstatus { 71*4882a593Smuzhiyun u8 cookie; 72*4882a593Smuzhiyun u8 ts_rate; /* Also holds EP ID */ 73*4882a593Smuzhiyun u8 ts_flags; 74*4882a593Smuzhiyun }; 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun struct wmi_event_txstatus { 77*4882a593Smuzhiyun u8 cnt; 78*4882a593Smuzhiyun struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; 79*4882a593Smuzhiyun } __packed; 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun enum wmi_cmd_id { 82*4882a593Smuzhiyun WMI_ECHO_CMDID = 0x0001, 83*4882a593Smuzhiyun WMI_ACCESS_MEMORY_CMDID, 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun /* Commands to Target */ 86*4882a593Smuzhiyun WMI_GET_FW_VERSION, 87*4882a593Smuzhiyun WMI_DISABLE_INTR_CMDID, 88*4882a593Smuzhiyun WMI_ENABLE_INTR_CMDID, 89*4882a593Smuzhiyun WMI_ATH_INIT_CMDID, 90*4882a593Smuzhiyun WMI_ABORT_TXQ_CMDID, 91*4882a593Smuzhiyun WMI_STOP_TX_DMA_CMDID, 92*4882a593Smuzhiyun WMI_ABORT_TX_DMA_CMDID, 93*4882a593Smuzhiyun WMI_DRAIN_TXQ_CMDID, 94*4882a593Smuzhiyun WMI_DRAIN_TXQ_ALL_CMDID, 95*4882a593Smuzhiyun WMI_START_RECV_CMDID, 96*4882a593Smuzhiyun WMI_STOP_RECV_CMDID, 97*4882a593Smuzhiyun WMI_FLUSH_RECV_CMDID, 98*4882a593Smuzhiyun WMI_SET_MODE_CMDID, 99*4882a593Smuzhiyun WMI_NODE_CREATE_CMDID, 100*4882a593Smuzhiyun WMI_NODE_REMOVE_CMDID, 101*4882a593Smuzhiyun WMI_VAP_REMOVE_CMDID, 102*4882a593Smuzhiyun WMI_VAP_CREATE_CMDID, 103*4882a593Smuzhiyun WMI_REG_READ_CMDID, 104*4882a593Smuzhiyun WMI_REG_WRITE_CMDID, 105*4882a593Smuzhiyun WMI_RC_STATE_CHANGE_CMDID, 106*4882a593Smuzhiyun WMI_RC_RATE_UPDATE_CMDID, 107*4882a593Smuzhiyun WMI_TARGET_IC_UPDATE_CMDID, 108*4882a593Smuzhiyun WMI_TX_AGGR_ENABLE_CMDID, 109*4882a593Smuzhiyun WMI_TGT_DETACH_CMDID, 110*4882a593Smuzhiyun WMI_NODE_UPDATE_CMDID, 111*4882a593Smuzhiyun WMI_INT_STATS_CMDID, 112*4882a593Smuzhiyun WMI_TX_STATS_CMDID, 113*4882a593Smuzhiyun WMI_RX_STATS_CMDID, 114*4882a593Smuzhiyun WMI_BITRATE_MASK_CMDID, 115*4882a593Smuzhiyun WMI_REG_RMW_CMDID, 116*4882a593Smuzhiyun }; 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun enum wmi_event_id { 119*4882a593Smuzhiyun WMI_TGT_RDY_EVENTID = 0x1001, 120*4882a593Smuzhiyun WMI_SWBA_EVENTID, 121*4882a593Smuzhiyun WMI_FATAL_EVENTID, 122*4882a593Smuzhiyun WMI_TXTO_EVENTID, 123*4882a593Smuzhiyun WMI_BMISS_EVENTID, 124*4882a593Smuzhiyun WMI_DELBA_EVENTID, 125*4882a593Smuzhiyun WMI_TXSTATUS_EVENTID, 126*4882a593Smuzhiyun }; 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun #define MAX_CMD_NUMBER 62 129*4882a593Smuzhiyun #define MAX_RMW_CMD_NUMBER 15 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun struct register_write { 132*4882a593Smuzhiyun __be32 reg; 133*4882a593Smuzhiyun __be32 val; 134*4882a593Smuzhiyun }; 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun struct register_rmw { 137*4882a593Smuzhiyun __be32 reg; 138*4882a593Smuzhiyun __be32 set; 139*4882a593Smuzhiyun __be32 clr; 140*4882a593Smuzhiyun } __packed; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun struct ath9k_htc_tx_event { 143*4882a593Smuzhiyun int count; 144*4882a593Smuzhiyun struct __wmi_event_txstatus txs; 145*4882a593Smuzhiyun struct list_head list; 146*4882a593Smuzhiyun }; 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun struct wmi { 149*4882a593Smuzhiyun struct ath9k_htc_priv *drv_priv; 150*4882a593Smuzhiyun struct htc_target *htc; 151*4882a593Smuzhiyun enum htc_endpoint_id ctrl_epid; 152*4882a593Smuzhiyun struct mutex op_mutex; 153*4882a593Smuzhiyun struct completion cmd_wait; 154*4882a593Smuzhiyun u16 last_seq_id; 155*4882a593Smuzhiyun struct sk_buff_head wmi_event_queue; 156*4882a593Smuzhiyun struct tasklet_struct wmi_event_tasklet; 157*4882a593Smuzhiyun u16 tx_seq_id; 158*4882a593Smuzhiyun u8 *cmd_rsp_buf; 159*4882a593Smuzhiyun u32 cmd_rsp_len; 160*4882a593Smuzhiyun bool stopped; 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun struct list_head pending_tx_events; 163*4882a593Smuzhiyun spinlock_t event_lock; 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun spinlock_t wmi_lock; 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun /* multi write section */ 168*4882a593Smuzhiyun atomic_t mwrite_cnt; 169*4882a593Smuzhiyun struct register_write multi_write[MAX_CMD_NUMBER]; 170*4882a593Smuzhiyun u32 multi_write_idx; 171*4882a593Smuzhiyun struct mutex multi_write_mutex; 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun /* multi rmw section */ 174*4882a593Smuzhiyun atomic_t m_rmw_cnt; 175*4882a593Smuzhiyun struct register_rmw multi_rmw[MAX_RMW_CMD_NUMBER]; 176*4882a593Smuzhiyun u32 multi_rmw_idx; 177*4882a593Smuzhiyun struct mutex multi_rmw_mutex; 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun }; 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); 182*4882a593Smuzhiyun int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, 183*4882a593Smuzhiyun enum htc_endpoint_id *wmi_ctrl_epid); 184*4882a593Smuzhiyun int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, 185*4882a593Smuzhiyun u8 *cmd_buf, u32 cmd_len, 186*4882a593Smuzhiyun u8 *rsp_buf, u32 rsp_len, 187*4882a593Smuzhiyun u32 timeout); 188*4882a593Smuzhiyun void ath9k_wmi_event_tasklet(struct tasklet_struct *t); 189*4882a593Smuzhiyun void ath9k_fatal_work(struct work_struct *work); 190*4882a593Smuzhiyun void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); 191*4882a593Smuzhiyun void ath9k_stop_wmi(struct ath9k_htc_priv *priv); 192*4882a593Smuzhiyun void ath9k_destroy_wmi(struct ath9k_htc_priv *priv); 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun #define WMI_CMD(_wmi_cmd) \ 195*4882a593Smuzhiyun do { \ 196*4882a593Smuzhiyun ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \ 197*4882a593Smuzhiyun (u8 *) &cmd_rsp, \ 198*4882a593Smuzhiyun sizeof(cmd_rsp), HZ*2); \ 199*4882a593Smuzhiyun } while (0) 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun #define WMI_CMD_BUF(_wmi_cmd, _buf) \ 202*4882a593Smuzhiyun do { \ 203*4882a593Smuzhiyun ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \ 204*4882a593Smuzhiyun (u8 *) _buf, sizeof(*_buf), \ 205*4882a593Smuzhiyun &cmd_rsp, sizeof(cmd_rsp), HZ*2); \ 206*4882a593Smuzhiyun } while (0) 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun #endif /* WMI_H */ 209