1 /*
2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include "htc.h"
20
htc_issue_send(struct htc_target * target,struct sk_buff * skb,u16 len,u8 flags,u8 epid)21 static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
22 u16 len, u8 flags, u8 epid)
23
24 {
25 struct htc_frame_hdr *hdr;
26 struct htc_endpoint *endpoint = &target->endpoint[epid];
27 int status;
28
29 hdr = (struct htc_frame_hdr *)
30 skb_push(skb, sizeof(struct htc_frame_hdr));
31 hdr->endpoint_id = epid;
32 hdr->flags = flags;
33 hdr->payload_len = cpu_to_be16(len);
34
35 status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
36
37 return status;
38 }
39
get_next_avail_ep(struct htc_endpoint * endpoint)40 static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint)
41 {
42 enum htc_endpoint_id avail_epid;
43
44 for (avail_epid = (ENDPOINT_MAX - 1); avail_epid > ENDPOINT0; avail_epid--)
45 if (endpoint[avail_epid].service_id == 0)
46 return &endpoint[avail_epid];
47 return NULL;
48 }
49
service_to_ulpipe(u16 service_id)50 static u8 service_to_ulpipe(u16 service_id)
51 {
52 switch (service_id) {
53 case WMI_CONTROL_SVC:
54 return 4;
55 case WMI_BEACON_SVC:
56 case WMI_CAB_SVC:
57 case WMI_UAPSD_SVC:
58 case WMI_MGMT_SVC:
59 case WMI_DATA_VO_SVC:
60 case WMI_DATA_VI_SVC:
61 case WMI_DATA_BE_SVC:
62 case WMI_DATA_BK_SVC:
63 return 1;
64 default:
65 return 0;
66 }
67 }
68
service_to_dlpipe(u16 service_id)69 static u8 service_to_dlpipe(u16 service_id)
70 {
71 switch (service_id) {
72 case WMI_CONTROL_SVC:
73 return 3;
74 case WMI_BEACON_SVC:
75 case WMI_CAB_SVC:
76 case WMI_UAPSD_SVC:
77 case WMI_MGMT_SVC:
78 case WMI_DATA_VO_SVC:
79 case WMI_DATA_VI_SVC:
80 case WMI_DATA_BE_SVC:
81 case WMI_DATA_BK_SVC:
82 return 2;
83 default:
84 return 0;
85 }
86 }
87
htc_process_target_rdy(struct htc_target * target,void * buf)88 static void htc_process_target_rdy(struct htc_target *target,
89 void *buf)
90 {
91 struct htc_endpoint *endpoint;
92 struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf;
93
94 target->credit_size = be16_to_cpu(htc_ready_msg->credit_size);
95
96 endpoint = &target->endpoint[ENDPOINT0];
97 endpoint->service_id = HTC_CTRL_RSVD_SVC;
98 endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
99 atomic_inc(&target->tgt_ready);
100 complete(&target->target_wait);
101 }
102
htc_process_conn_rsp(struct htc_target * target,struct htc_frame_hdr * htc_hdr)103 static void htc_process_conn_rsp(struct htc_target *target,
104 struct htc_frame_hdr *htc_hdr)
105 {
106 struct htc_conn_svc_rspmsg *svc_rspmsg;
107 struct htc_endpoint *endpoint, *tmp_endpoint = NULL;
108 u16 service_id;
109 u16 max_msglen;
110 enum htc_endpoint_id epid, tepid;
111
112 svc_rspmsg = (struct htc_conn_svc_rspmsg *)
113 ((void *) htc_hdr + sizeof(struct htc_frame_hdr));
114
115 if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
116 epid = svc_rspmsg->endpoint_id;
117 if (epid < 0 || epid >= ENDPOINT_MAX)
118 return;
119
120 service_id = be16_to_cpu(svc_rspmsg->service_id);
121 max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len);
122 endpoint = &target->endpoint[epid];
123
124 for (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--) {
125 tmp_endpoint = &target->endpoint[tepid];
126 if (tmp_endpoint->service_id == service_id) {
127 tmp_endpoint->service_id = 0;
128 break;
129 }
130 }
131
132 if (tepid == ENDPOINT0)
133 return;
134
135 endpoint->service_id = service_id;
136 endpoint->max_txqdepth = tmp_endpoint->max_txqdepth;
137 endpoint->ep_callbacks = tmp_endpoint->ep_callbacks;
138 endpoint->ul_pipeid = tmp_endpoint->ul_pipeid;
139 endpoint->dl_pipeid = tmp_endpoint->dl_pipeid;
140 endpoint->max_msglen = max_msglen;
141 target->conn_rsp_epid = epid;
142 complete(&target->cmd_wait);
143 } else {
144 target->conn_rsp_epid = ENDPOINT_UNUSED;
145 }
146 }
147
htc_config_pipe_credits(struct htc_target * target)148 static int htc_config_pipe_credits(struct htc_target *target)
149 {
150 struct sk_buff *skb;
151 struct htc_config_pipe_msg *cp_msg;
152 int ret;
153 unsigned long time_left;
154
155 skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
156 if (!skb) {
157 dev_err(target->dev, "failed to allocate send buffer\n");
158 return -ENOMEM;
159 }
160 skb_reserve(skb, sizeof(struct htc_frame_hdr));
161
162 cp_msg = (struct htc_config_pipe_msg *)
163 skb_put(skb, sizeof(struct htc_config_pipe_msg));
164
165 cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID);
166 cp_msg->pipe_id = USB_WLAN_TX_PIPE;
167 cp_msg->credits = target->credits;
168
169 target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
170
171 ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
172 if (ret)
173 goto err;
174
175 time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
176 if (!time_left) {
177 dev_err(target->dev, "HTC credit config timeout\n");
178 kfree_skb(skb);
179 return -ETIMEDOUT;
180 }
181
182 return 0;
183 err:
184 kfree_skb(skb);
185 return -EINVAL;
186 }
187
htc_setup_complete(struct htc_target * target)188 static int htc_setup_complete(struct htc_target *target)
189 {
190 struct sk_buff *skb;
191 struct htc_comp_msg *comp_msg;
192 int ret = 0;
193 unsigned long time_left;
194
195 skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
196 if (!skb) {
197 dev_err(target->dev, "failed to allocate send buffer\n");
198 return -ENOMEM;
199 }
200 skb_reserve(skb, sizeof(struct htc_frame_hdr));
201
202 comp_msg = (struct htc_comp_msg *)
203 skb_put(skb, sizeof(struct htc_comp_msg));
204 comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID);
205
206 target->htc_flags |= HTC_OP_START_WAIT;
207
208 ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
209 if (ret)
210 goto err;
211
212 time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
213 if (!time_left) {
214 dev_err(target->dev, "HTC start timeout\n");
215 kfree_skb(skb);
216 return -ETIMEDOUT;
217 }
218
219 return 0;
220
221 err:
222 kfree_skb(skb);
223 return -EINVAL;
224 }
225
226 /* HTC APIs */
227
htc_init(struct htc_target * target)228 int htc_init(struct htc_target *target)
229 {
230 int ret;
231
232 ret = htc_config_pipe_credits(target);
233 if (ret)
234 return ret;
235
236 return htc_setup_complete(target);
237 }
238
htc_connect_service(struct htc_target * target,struct htc_service_connreq * service_connreq,enum htc_endpoint_id * conn_rsp_epid)239 int htc_connect_service(struct htc_target *target,
240 struct htc_service_connreq *service_connreq,
241 enum htc_endpoint_id *conn_rsp_epid)
242 {
243 struct sk_buff *skb;
244 struct htc_endpoint *endpoint;
245 struct htc_conn_svc_msg *conn_msg;
246 int ret;
247 unsigned long time_left;
248
249 /* Find an available endpoint */
250 endpoint = get_next_avail_ep(target->endpoint);
251 if (!endpoint) {
252 dev_err(target->dev, "Endpoint is not available for"
253 "service %d\n", service_connreq->service_id);
254 return -EINVAL;
255 }
256
257 endpoint->service_id = service_connreq->service_id;
258 endpoint->max_txqdepth = service_connreq->max_send_qdepth;
259 endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id);
260 endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id);
261 endpoint->ep_callbacks = service_connreq->ep_callbacks;
262
263 skb = alloc_skb(sizeof(struct htc_conn_svc_msg) +
264 sizeof(struct htc_frame_hdr), GFP_ATOMIC);
265 if (!skb) {
266 dev_err(target->dev, "Failed to allocate buf to send"
267 "service connect req\n");
268 return -ENOMEM;
269 }
270
271 skb_reserve(skb, sizeof(struct htc_frame_hdr));
272
273 conn_msg = (struct htc_conn_svc_msg *)
274 skb_put(skb, sizeof(struct htc_conn_svc_msg));
275 conn_msg->service_id = cpu_to_be16(service_connreq->service_id);
276 conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID);
277 conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags);
278 conn_msg->dl_pipeid = endpoint->dl_pipeid;
279 conn_msg->ul_pipeid = endpoint->ul_pipeid;
280
281 ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
282 if (ret)
283 goto err;
284
285 time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
286 if (!time_left) {
287 dev_err(target->dev, "Service connection timeout for: %d\n",
288 service_connreq->service_id);
289 kfree_skb(skb);
290 return -ETIMEDOUT;
291 }
292
293 *conn_rsp_epid = target->conn_rsp_epid;
294 return 0;
295 err:
296 kfree_skb(skb);
297 return ret;
298 }
299
htc_send(struct htc_target * target,struct sk_buff * skb)300 int htc_send(struct htc_target *target, struct sk_buff *skb)
301 {
302 struct ath9k_htc_tx_ctl *tx_ctl;
303
304 tx_ctl = HTC_SKB_CB(skb);
305 return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid);
306 }
307
htc_send_epid(struct htc_target * target,struct sk_buff * skb,enum htc_endpoint_id epid)308 int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
309 enum htc_endpoint_id epid)
310 {
311 return htc_issue_send(target, skb, skb->len, 0, epid);
312 }
313
htc_stop(struct htc_target * target)314 void htc_stop(struct htc_target *target)
315 {
316 target->hif->stop(target->hif_dev);
317 }
318
htc_start(struct htc_target * target)319 void htc_start(struct htc_target *target)
320 {
321 target->hif->start(target->hif_dev);
322 }
323
htc_sta_drain(struct htc_target * target,u8 idx)324 void htc_sta_drain(struct htc_target *target, u8 idx)
325 {
326 target->hif->sta_drain(target->hif_dev, idx);
327 }
328
ath9k_htc_txcompletion_cb(struct htc_target * htc_handle,struct sk_buff * skb,bool txok)329 void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
330 struct sk_buff *skb, bool txok)
331 {
332 struct htc_endpoint *endpoint;
333 struct htc_frame_hdr *htc_hdr = NULL;
334
335 if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) {
336 complete(&htc_handle->cmd_wait);
337 htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS;
338 goto ret;
339 }
340
341 if (htc_handle->htc_flags & HTC_OP_START_WAIT) {
342 complete(&htc_handle->cmd_wait);
343 htc_handle->htc_flags &= ~HTC_OP_START_WAIT;
344 goto ret;
345 }
346
347 if (skb) {
348 htc_hdr = (struct htc_frame_hdr *) skb->data;
349 if (htc_hdr->endpoint_id >= ARRAY_SIZE(htc_handle->endpoint))
350 goto ret;
351 endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id];
352 skb_pull(skb, sizeof(struct htc_frame_hdr));
353
354 if (endpoint->ep_callbacks.tx) {
355 endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
356 skb, htc_hdr->endpoint_id,
357 txok);
358 } else {
359 kfree_skb(skb);
360 }
361 }
362
363 return;
364 ret:
365 kfree_skb(skb);
366 }
367
ath9k_htc_fw_panic_report(struct htc_target * htc_handle,struct sk_buff * skb)368 static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
369 struct sk_buff *skb)
370 {
371 uint32_t *pattern = (uint32_t *)skb->data;
372
373 switch (*pattern) {
374 case 0x33221199:
375 {
376 struct htc_panic_bad_vaddr *htc_panic;
377 htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
378 dev_err(htc_handle->dev, "ath: firmware panic! "
379 "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
380 htc_panic->exccause, htc_panic->pc,
381 htc_panic->badvaddr);
382 break;
383 }
384 case 0x33221299:
385 {
386 struct htc_panic_bad_epid *htc_panic;
387 htc_panic = (struct htc_panic_bad_epid *) skb->data;
388 dev_err(htc_handle->dev, "ath: firmware panic! "
389 "bad epid: 0x%08x\n", htc_panic->epid);
390 break;
391 }
392 default:
393 dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
394 break;
395 }
396 }
397
398 /*
399 * HTC Messages are handled directly here and the obtained SKB
400 * is freed.
401 *
402 * Service messages (Data, WMI) passed to the corresponding
403 * endpoint RX handlers, which have to free the SKB.
404 */
ath9k_htc_rx_msg(struct htc_target * htc_handle,struct sk_buff * skb,u32 len,u8 pipe_id)405 void ath9k_htc_rx_msg(struct htc_target *htc_handle,
406 struct sk_buff *skb, u32 len, u8 pipe_id)
407 {
408 struct htc_frame_hdr *htc_hdr;
409 enum htc_endpoint_id epid;
410 struct htc_endpoint *endpoint;
411 __be16 *msg_id;
412
413 if (!htc_handle || !skb)
414 return;
415
416 htc_hdr = (struct htc_frame_hdr *) skb->data;
417 epid = htc_hdr->endpoint_id;
418
419 if (epid == 0x99) {
420 ath9k_htc_fw_panic_report(htc_handle, skb);
421 kfree_skb(skb);
422 return;
423 }
424
425 if (epid < 0 || epid >= ENDPOINT_MAX) {
426 if (pipe_id != USB_REG_IN_PIPE)
427 dev_kfree_skb_any(skb);
428 else
429 kfree_skb(skb);
430 return;
431 }
432
433 if (epid == ENDPOINT0) {
434
435 /* Handle trailer */
436 if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
437 if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
438 /* Move past the Watchdog pattern */
439 htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
440 }
441
442 /* Get the message ID */
443 msg_id = (__be16 *) ((void *) htc_hdr +
444 sizeof(struct htc_frame_hdr));
445
446 /* Now process HTC messages */
447 switch (be16_to_cpu(*msg_id)) {
448 case HTC_MSG_READY_ID:
449 htc_process_target_rdy(htc_handle, htc_hdr);
450 break;
451 case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
452 htc_process_conn_rsp(htc_handle, htc_hdr);
453 break;
454 default:
455 break;
456 }
457
458 kfree_skb(skb);
459
460 } else {
461 if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER)
462 skb_trim(skb, len - htc_hdr->control[0]);
463
464 skb_pull(skb, sizeof(struct htc_frame_hdr));
465
466 endpoint = &htc_handle->endpoint[epid];
467 if (endpoint->ep_callbacks.rx)
468 endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv,
469 skb, epid);
470 }
471 }
472
ath9k_htc_hw_alloc(void * hif_handle,struct ath9k_htc_hif * hif,struct device * dev)473 struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
474 struct ath9k_htc_hif *hif,
475 struct device *dev)
476 {
477 struct htc_endpoint *endpoint;
478 struct htc_target *target;
479
480 target = kzalloc(sizeof(struct htc_target), GFP_KERNEL);
481 if (!target)
482 return NULL;
483
484 init_completion(&target->target_wait);
485 init_completion(&target->cmd_wait);
486
487 target->hif = hif;
488 target->hif_dev = hif_handle;
489 target->dev = dev;
490
491 /* Assign control endpoint pipe IDs */
492 endpoint = &target->endpoint[ENDPOINT0];
493 endpoint->ul_pipeid = hif->control_ul_pipe;
494 endpoint->dl_pipeid = hif->control_dl_pipe;
495
496 atomic_set(&target->tgt_ready, 0);
497
498 return target;
499 }
500
ath9k_htc_hw_free(struct htc_target * htc)501 void ath9k_htc_hw_free(struct htc_target *htc)
502 {
503 kfree(htc);
504 }
505
ath9k_htc_hw_init(struct htc_target * target,struct device * dev,u16 devid,char * product,u32 drv_info)506 int ath9k_htc_hw_init(struct htc_target *target,
507 struct device *dev, u16 devid,
508 char *product, u32 drv_info)
509 {
510 if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) {
511 pr_err("Failed to initialize the device\n");
512 return -ENODEV;
513 }
514
515 return 0;
516 }
517
ath9k_htc_hw_deinit(struct htc_target * target,bool hot_unplug)518 void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug)
519 {
520 if (target)
521 ath9k_htc_disconnect_device(target, hot_unplug);
522 }
523