2
* Copyright (c) 2010 Atheros Communications Inc.
2
* Copyright (c) 2010-2011 Atheros Communications Inc.
4
4
* Permission to use, copy, modify, and/or distribute this software for any
5
5
* purpose with or without fee is hereby granted, provided that the above
23
23
return "WMI_ECHO_CMDID";
24
24
case WMI_ACCESS_MEMORY_CMDID:
25
25
return "WMI_ACCESS_MEMORY_CMDID";
26
case WMI_GET_FW_VERSION:
27
return "WMI_GET_FW_VERSION";
26
28
case WMI_DISABLE_INTR_CMDID:
27
29
return "WMI_DISABLE_INTR_CMDID";
28
30
case WMI_ENABLE_INTR_CMDID:
29
31
return "WMI_ENABLE_INTR_CMDID";
30
case WMI_RX_LINK_CMDID:
31
return "WMI_RX_LINK_CMDID";
32
32
case WMI_ATH_INIT_CMDID:
33
33
return "WMI_ATH_INIT_CMDID";
34
34
case WMI_ABORT_TXQ_CMDID:
35
35
return "WMI_ABORT_TXQ_CMDID";
36
36
case WMI_STOP_TX_DMA_CMDID:
37
37
return "WMI_STOP_TX_DMA_CMDID";
38
case WMI_STOP_DMA_RECV_CMDID:
39
return "WMI_STOP_DMA_RECV_CMDID";
40
38
case WMI_ABORT_TX_DMA_CMDID:
41
39
return "WMI_ABORT_TX_DMA_CMDID";
42
40
case WMI_DRAIN_TXQ_CMDID:
51
49
return "WMI_FLUSH_RECV_CMDID";
52
50
case WMI_SET_MODE_CMDID:
53
51
return "WMI_SET_MODE_CMDID";
55
return "WMI_RESET_CMDID";
56
52
case WMI_NODE_CREATE_CMDID:
57
53
return "WMI_NODE_CREATE_CMDID";
58
54
case WMI_NODE_REMOVE_CMDID:
61
57
return "WMI_VAP_REMOVE_CMDID";
62
58
case WMI_VAP_CREATE_CMDID:
63
59
return "WMI_VAP_CREATE_CMDID";
64
case WMI_BEACON_UPDATE_CMDID:
65
return "WMI_BEACON_UPDATE_CMDID";
66
60
case WMI_REG_READ_CMDID:
67
61
return "WMI_REG_READ_CMDID";
68
62
case WMI_REG_WRITE_CMDID:
71
65
return "WMI_RC_STATE_CHANGE_CMDID";
72
66
case WMI_RC_RATE_UPDATE_CMDID:
73
67
return "WMI_RC_RATE_UPDATE_CMDID";
74
case WMI_DEBUG_INFO_CMDID:
75
return "WMI_DEBUG_INFO_CMDID";
77
return "WMI_HOST_ATTACH";
78
68
case WMI_TARGET_IC_UPDATE_CMDID:
79
69
return "WMI_TARGET_IC_UPDATE_CMDID";
80
case WMI_TGT_STATS_CMDID:
81
return "WMI_TGT_STATS_CMDID";
82
70
case WMI_TX_AGGR_ENABLE_CMDID:
83
71
return "WMI_TX_AGGR_ENABLE_CMDID";
84
72
case WMI_TGT_DETACH_CMDID:
85
73
return "WMI_TGT_DETACH_CMDID";
86
case WMI_TGT_TXQ_ENABLE_CMDID:
87
return "WMI_TGT_TXQ_ENABLE_CMDID";
88
case WMI_AGGR_LIMIT_CMD:
89
return "WMI_AGGR_LIMIT_CMD";
74
case WMI_NODE_UPDATE_CMDID:
75
return "WMI_NODE_UPDATE_CMDID";
76
case WMI_INT_STATS_CMDID:
77
return "WMI_INT_STATS_CMDID";
78
case WMI_TX_STATS_CMDID:
79
return "WMI_TX_STATS_CMDID";
80
case WMI_RX_STATS_CMDID:
81
return "WMI_RX_STATS_CMDID";
82
case WMI_BITRATE_MASK_CMDID:
83
return "WMI_BITRATE_MASK_CMDID";
103
97
wmi->drv_priv = priv;
104
98
wmi->stopped = false;
99
skb_queue_head_init(&wmi->wmi_event_queue);
100
spin_lock_init(&wmi->wmi_lock);
101
spin_lock_init(&wmi->event_lock);
105
102
mutex_init(&wmi->op_mutex);
106
103
mutex_init(&wmi->multi_write_mutex);
107
104
init_completion(&wmi->cmd_wait);
105
INIT_LIST_HEAD(&wmi->pending_tx_events);
106
tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet,
120
120
kfree(priv->wmi);
123
void ath9k_swba_tasklet(unsigned long data)
125
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
126
struct ath_common *common = ath9k_hw_common(priv->ah);
128
ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n");
130
ath9k_htc_swba(priv, priv->wmi->beacon_pending);
123
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
127
tasklet_kill(&priv->wmi->wmi_event_tasklet);
128
spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
129
__skb_queue_purge(&priv->wmi->wmi_event_queue);
130
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
133
void ath9k_wmi_event_tasklet(unsigned long data)
135
struct wmi *wmi = (struct wmi *)data;
136
struct ath9k_htc_priv *priv = wmi->drv_priv;
137
struct wmi_cmd_hdr *hdr;
139
struct wmi_event_swba *swba;
140
struct sk_buff *skb = NULL;
145
spin_lock_irqsave(&wmi->wmi_lock, flags);
146
skb = __skb_dequeue(&wmi->wmi_event_queue);
148
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
151
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
153
hdr = (struct wmi_cmd_hdr *) skb->data;
154
cmd_id = be16_to_cpu(hdr->command_id);
155
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
158
case WMI_SWBA_EVENTID:
159
swba = (struct wmi_event_swba *) wmi_event;
160
ath9k_htc_swba(priv, swba);
162
case WMI_FATAL_EVENTID:
163
ieee80211_queue_work(wmi->drv_priv->hw,
164
&wmi->drv_priv->fatal_work);
166
case WMI_TXSTATUS_EVENTID:
167
spin_lock_bh(&priv->tx.tx_lock);
168
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
169
spin_unlock_bh(&priv->tx.tx_lock);
172
spin_unlock_bh(&priv->tx.tx_lock);
174
ath9k_htc_txstatus(priv, wmi_event);
134
184
void ath9k_fatal_work(struct work_struct *work)
169
215
cmd_id = be16_to_cpu(hdr->command_id);
171
217
if (cmd_id & 0x1000) {
172
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
174
case WMI_SWBA_EVENTID:
175
wmi->beacon_pending = *(u8 *)wmi_event;
176
tasklet_schedule(&wmi->drv_priv->swba_tasklet);
178
case WMI_FATAL_EVENTID:
179
ieee80211_queue_work(wmi->drv_priv->hw,
180
&wmi->drv_priv->fatal_work);
182
case WMI_TXRATE_EVENTID:
183
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
184
txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
185
wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
218
spin_lock(&wmi->wmi_lock);
219
__skb_queue_tail(&wmi->wmi_event_queue, skb);
220
spin_unlock(&wmi->wmi_lock);
221
tasklet_schedule(&wmi->wmi_event_tasklet);
247
277
hdr->command_id = cpu_to_be16(cmd);
248
278
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
250
return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL);
280
return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid);
253
283
int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,