2
* Copyright (c) 2010 Atheros Communications Inc.
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.
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.
19
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
20
u16 len, u8 flags, u8 epid,
21
struct ath9k_htc_tx_ctl *tx_ctl)
23
struct htc_frame_hdr *hdr;
24
struct htc_endpoint *endpoint = &target->endpoint[epid];
27
hdr = (struct htc_frame_hdr *)
28
skb_push(skb, sizeof(struct htc_frame_hdr));
29
hdr->endpoint_id = epid;
31
hdr->payload_len = cpu_to_be16(len);
33
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
38
static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint)
40
enum htc_endpoint_id avail_epid;
42
for (avail_epid = (ENDPOINT_MAX - 1); avail_epid > ENDPOINT0; avail_epid--)
43
if (endpoint[avail_epid].service_id == 0)
44
return &endpoint[avail_epid];
48
static u8 service_to_ulpipe(u16 service_id)
67
static u8 service_to_dlpipe(u16 service_id)
86
static void htc_process_target_rdy(struct htc_target *target,
89
struct htc_endpoint *endpoint;
90
struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf;
92
target->credit_size = be16_to_cpu(htc_ready_msg->credit_size);
94
endpoint = &target->endpoint[ENDPOINT0];
95
endpoint->service_id = HTC_CTRL_RSVD_SVC;
96
endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
97
atomic_inc(&target->tgt_ready);
98
complete(&target->target_wait);
101
static void htc_process_conn_rsp(struct htc_target *target,
102
struct htc_frame_hdr *htc_hdr)
104
struct htc_conn_svc_rspmsg *svc_rspmsg;
105
struct htc_endpoint *endpoint, *tmp_endpoint = NULL;
108
enum htc_endpoint_id epid, tepid;
110
svc_rspmsg = (struct htc_conn_svc_rspmsg *)
111
((void *) htc_hdr + sizeof(struct htc_frame_hdr));
113
if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
114
epid = svc_rspmsg->endpoint_id;
115
service_id = be16_to_cpu(svc_rspmsg->service_id);
116
max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len);
117
endpoint = &target->endpoint[epid];
119
for (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--) {
120
tmp_endpoint = &target->endpoint[tepid];
121
if (tmp_endpoint->service_id == service_id) {
122
tmp_endpoint->service_id = 0;
127
if (tepid == ENDPOINT0)
130
endpoint->service_id = service_id;
131
endpoint->max_txqdepth = tmp_endpoint->max_txqdepth;
132
endpoint->ep_callbacks = tmp_endpoint->ep_callbacks;
133
endpoint->ul_pipeid = tmp_endpoint->ul_pipeid;
134
endpoint->dl_pipeid = tmp_endpoint->dl_pipeid;
135
endpoint->max_msglen = max_msglen;
136
target->conn_rsp_epid = epid;
137
complete(&target->cmd_wait);
139
target->conn_rsp_epid = ENDPOINT_UNUSED;
143
static int htc_config_pipe_credits(struct htc_target *target)
146
struct htc_config_pipe_msg *cp_msg;
149
skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
151
dev_err(target->dev, "failed to allocate send buffer\n");
154
skb_reserve(skb, sizeof(struct htc_frame_hdr));
156
cp_msg = (struct htc_config_pipe_msg *)
157
skb_put(skb, sizeof(struct htc_config_pipe_msg));
159
cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID);
160
cp_msg->pipe_id = USB_WLAN_TX_PIPE;
161
cp_msg->credits = target->credits;
163
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
165
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
169
time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
171
dev_err(target->dev, "HTC credit config timeout\n");
181
static int htc_setup_complete(struct htc_target *target)
184
struct htc_comp_msg *comp_msg;
185
int ret = 0, time_left;
187
skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
189
dev_err(target->dev, "failed to allocate send buffer\n");
192
skb_reserve(skb, sizeof(struct htc_frame_hdr));
194
comp_msg = (struct htc_comp_msg *)
195
skb_put(skb, sizeof(struct htc_comp_msg));
196
comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID);
198
target->htc_flags |= HTC_OP_START_WAIT;
200
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
204
time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
206
dev_err(target->dev, "HTC start timeout\n");
219
int htc_init(struct htc_target *target)
223
ret = htc_config_pipe_credits(target);
227
return htc_setup_complete(target);
230
int htc_connect_service(struct htc_target *target,
231
struct htc_service_connreq *service_connreq,
232
enum htc_endpoint_id *conn_rsp_epid)
235
struct htc_endpoint *endpoint;
236
struct htc_conn_svc_msg *conn_msg;
239
/* Find an available endpoint */
240
endpoint = get_next_avail_ep(target->endpoint);
242
dev_err(target->dev, "Endpoint is not available for"
243
"service %d\n", service_connreq->service_id);
247
endpoint->service_id = service_connreq->service_id;
248
endpoint->max_txqdepth = service_connreq->max_send_qdepth;
249
endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id);
250
endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id);
251
endpoint->ep_callbacks = service_connreq->ep_callbacks;
253
skb = alloc_skb(sizeof(struct htc_conn_svc_msg) +
254
sizeof(struct htc_frame_hdr), GFP_ATOMIC);
256
dev_err(target->dev, "Failed to allocate buf to send"
257
"service connect req\n");
261
skb_reserve(skb, sizeof(struct htc_frame_hdr));
263
conn_msg = (struct htc_conn_svc_msg *)
264
skb_put(skb, sizeof(struct htc_conn_svc_msg));
265
conn_msg->service_id = cpu_to_be16(service_connreq->service_id);
266
conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID);
267
conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags);
268
conn_msg->dl_pipeid = endpoint->dl_pipeid;
269
conn_msg->ul_pipeid = endpoint->ul_pipeid;
271
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
275
time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
277
dev_err(target->dev, "Service connection timeout for: %d\n",
278
service_connreq->service_id);
282
*conn_rsp_epid = target->conn_rsp_epid;
289
int htc_send(struct htc_target *target, struct sk_buff *skb,
290
enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
292
return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl);
295
void htc_stop(struct htc_target *target)
297
enum htc_endpoint_id epid;
298
struct htc_endpoint *endpoint;
300
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
301
endpoint = &target->endpoint[epid];
302
if (endpoint->service_id != 0)
303
target->hif->stop(target->hif_dev, endpoint->ul_pipeid);
307
void htc_start(struct htc_target *target)
309
enum htc_endpoint_id epid;
310
struct htc_endpoint *endpoint;
312
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
313
endpoint = &target->endpoint[epid];
314
if (endpoint->service_id != 0)
315
target->hif->start(target->hif_dev,
316
endpoint->ul_pipeid);
320
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
321
struct sk_buff *skb, bool txok)
323
struct htc_endpoint *endpoint;
324
struct htc_frame_hdr *htc_hdr = NULL;
326
if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) {
327
complete(&htc_handle->cmd_wait);
328
htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS;
332
if (htc_handle->htc_flags & HTC_OP_START_WAIT) {
333
complete(&htc_handle->cmd_wait);
334
htc_handle->htc_flags &= ~HTC_OP_START_WAIT;
339
htc_hdr = (struct htc_frame_hdr *) skb->data;
340
endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id];
341
skb_pull(skb, sizeof(struct htc_frame_hdr));
343
if (endpoint->ep_callbacks.tx) {
344
endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
345
skb, htc_hdr->endpoint_id,
352
/* HTC-generated packets are freed here. */
353
if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0)
354
dev_kfree_skb_any(skb);
360
* HTC Messages are handled directly here and the obtained SKB
363
* Sevice messages (Data, WMI) passed to the corresponding
364
* endpoint RX handlers, which have to free the SKB.
366
void ath9k_htc_rx_msg(struct htc_target *htc_handle,
367
struct sk_buff *skb, u32 len, u8 pipe_id)
369
struct htc_frame_hdr *htc_hdr;
370
enum htc_endpoint_id epid;
371
struct htc_endpoint *endpoint;
374
if (!htc_handle || !skb)
377
htc_hdr = (struct htc_frame_hdr *) skb->data;
378
epid = htc_hdr->endpoint_id;
380
if (epid >= ENDPOINT_MAX) {
381
if (pipe_id != USB_REG_IN_PIPE)
382
dev_kfree_skb_any(skb);
388
if (epid == ENDPOINT0) {
391
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
392
if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
393
/* Move past the Watchdog pattern */
394
htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
397
/* Get the message ID */
398
msg_id = (__be16 *) ((void *) htc_hdr +
399
sizeof(struct htc_frame_hdr));
401
/* Now process HTC messages */
402
switch (be16_to_cpu(*msg_id)) {
403
case HTC_MSG_READY_ID:
404
htc_process_target_rdy(htc_handle, htc_hdr);
406
case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
407
htc_process_conn_rsp(htc_handle, htc_hdr);
416
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER)
417
skb_trim(skb, len - htc_hdr->control[0]);
419
skb_pull(skb, sizeof(struct htc_frame_hdr));
421
endpoint = &htc_handle->endpoint[epid];
422
if (endpoint->ep_callbacks.rx)
423
endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv,
428
struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
429
struct ath9k_htc_hif *hif,
432
struct htc_endpoint *endpoint;
433
struct htc_target *target;
435
target = kzalloc(sizeof(struct htc_target), GFP_KERNEL);
437
printk(KERN_ERR "Unable to allocate memory for"
442
init_completion(&target->target_wait);
443
init_completion(&target->cmd_wait);
446
target->hif_dev = hif_handle;
449
/* Assign control endpoint pipe IDs */
450
endpoint = &target->endpoint[ENDPOINT0];
451
endpoint->ul_pipeid = hif->control_ul_pipe;
452
endpoint->dl_pipeid = hif->control_dl_pipe;
454
atomic_set(&target->tgt_ready, 0);
459
void ath9k_htc_hw_free(struct htc_target *htc)
464
int ath9k_htc_hw_init(struct htc_target *target,
465
struct device *dev, u16 devid, char *product)
467
if (ath9k_htc_probe_device(target, dev, devid, product)) {
468
printk(KERN_ERR "Failed to initialize the device\n");
475
void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug)
478
ath9k_htc_disconnect_device(target, hot_unplug);