Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 *  Copyright (C) 2008, cozybit Inc.
  3 *  Copyright (C) 2003-2006, Marvell International Ltd.
  4 *
  5 *  This program is free software; you can redistribute it and/or modify
  6 *  it under the terms of the GNU General Public License as published by
  7 *  the Free Software Foundation; either version 2 of the License, or (at
  8 *  your option) any later version.
  9 */
 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 11
 12#include <linux/hardirq.h>
 13#include <linux/slab.h>
 14
 15#include "libertas_tf.h"
 16
 17static const struct channel_range channel_ranges[] = {
 18	{ LBTF_REGDOMAIN_US,		1, 12 },
 19	{ LBTF_REGDOMAIN_CA,		1, 12 },
 20	{ LBTF_REGDOMAIN_EU,		1, 14 },
 21	{ LBTF_REGDOMAIN_JP,		1, 14 },
 22	{ LBTF_REGDOMAIN_SP,		1, 14 },
 23	{ LBTF_REGDOMAIN_FR,		1, 14 },
 24};
 25
 26static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
 27{
 28	LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
 29	LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
 30};
 31
 32static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);
 33
 34
 35/**
 36 *  lbtf_cmd_copyback - Simple callback that copies response back into command
 37 *
 38 *  @priv	A pointer to struct lbtf_private structure
 39 *  @extra	A pointer to the original command structure for which
 40 *		'resp' is a response
 41 *  @resp	A pointer to the command response
 42 *
 43 *  Returns: 0 on success, error on failure
 44 */
 45int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
 46		     struct cmd_header *resp)
 47{
 48	struct cmd_header *buf = (void *)extra;
 49	uint16_t copy_len;
 50
 51	copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
 52	memcpy(buf, resp, copy_len);
 53	return 0;
 54}
 55EXPORT_SYMBOL_GPL(lbtf_cmd_copyback);
 56
 57#define CHAN_TO_IDX(chan) ((chan) - 1)
 58
 59static void lbtf_geo_init(struct lbtf_private *priv)
 60{
 61	const struct channel_range *range = channel_ranges;
 62	u8 ch;
 63	int i;
 64
 65	for (i = 0; i < ARRAY_SIZE(channel_ranges); i++)
 66		if (channel_ranges[i].regdomain == priv->regioncode) {
 67			range = &channel_ranges[i];
 68			break;
 69		}
 70
 71	for (ch = priv->range.start; ch < priv->range.end; ch++)
 72		priv->channels[CHAN_TO_IDX(ch)].flags = 0;
 73}
 74
 75/**
 76 *  lbtf_update_hw_spec: Updates the hardware details.
 77 *
 78 *  @priv    	A pointer to struct lbtf_private structure
 79 *
 80 *  Returns: 0 on success, error on failure
 81 */
 82int lbtf_update_hw_spec(struct lbtf_private *priv)
 83{
 84	struct cmd_ds_get_hw_spec cmd;
 85	int ret = -1;
 86	u32 i;
 87
 88	lbtf_deb_enter(LBTF_DEB_CMD);
 89
 90	memset(&cmd, 0, sizeof(cmd));
 91	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 92	memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
 93	ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
 94	if (ret)
 95		goto out;
 96
 97	priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
 98
 99	/* The firmware release is in an interesting format: the patch
100	 * level is in the most significant nibble ... so fix that: */
101	priv->fwrelease = le32_to_cpu(cmd.fwrelease);
102	priv->fwrelease = (priv->fwrelease << 8) |
103		(priv->fwrelease >> 24 & 0xff);
104
105	printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
106		cmd.permanentaddr,
107		priv->fwrelease >> 24 & 0xff,
108		priv->fwrelease >> 16 & 0xff,
109		priv->fwrelease >>  8 & 0xff,
110		priv->fwrelease       & 0xff,
111		priv->fwcapinfo);
112	lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
113		    cmd.hwifversion, cmd.version);
114
115	/* Clamp region code to 8-bit since FW spec indicates that it should
116	 * only ever be 8-bit, even though the field size is 16-bit.  Some
117	 * firmware returns non-zero high 8 bits here.
118	 */
119	priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
120
121	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
122		/* use the region code to search for the index */
123		if (priv->regioncode == lbtf_region_code_to_index[i])
124			break;
125	}
126
127	/* if it's unidentified region code, use the default (USA) */
128	if (i >= MRVDRV_MAX_REGION_CODE) {
129		priv->regioncode = 0x10;
130		pr_info("unidentified region code; using the default (USA)\n");
131	}
132
133	if (priv->current_addr[0] == 0xff)
134		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
135
136	SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr);
137
138	lbtf_geo_init(priv);
139out:
140	lbtf_deb_leave(LBTF_DEB_CMD);
141	return ret;
142}
143
144/**
145 *  lbtf_set_channel: Set the radio channel
146 *
147 *  @priv	A pointer to struct lbtf_private structure
148 *  @channel	The desired channel, or 0 to clear a locked channel
149 *
150 *  Returns: 0 on success, error on failure
151 */
152int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
153{
154	int ret = 0;
155	struct cmd_ds_802_11_rf_channel cmd;
156
157	lbtf_deb_enter(LBTF_DEB_CMD);
158
159	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
160	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
161	cmd.channel = cpu_to_le16(channel);
162
163	ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
164	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
165	return ret;
166}
167
168int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
169{
170	struct cmd_ds_802_11_beacon_set cmd;
171	int size;
172
173	lbtf_deb_enter(LBTF_DEB_CMD);
174
175	if (beacon->len > MRVL_MAX_BCN_SIZE) {
176		lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
177		return -1;
178	}
179	size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
180	cmd.hdr.size = cpu_to_le16(size);
181	cmd.len = cpu_to_le16(beacon->len);
182	memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
183
184	lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
185
186	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
187	return 0;
188}
189
190int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
191		     int beacon_int)
192{
193	struct cmd_ds_802_11_beacon_control cmd;
194	lbtf_deb_enter(LBTF_DEB_CMD);
195
196	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
197	cmd.action = cpu_to_le16(CMD_ACT_SET);
198	cmd.beacon_enable = cpu_to_le16(beacon_enable);
199	cmd.beacon_period = cpu_to_le16(beacon_int);
200
201	lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
202
203	lbtf_deb_leave(LBTF_DEB_CMD);
204	return 0;
205}
206
207static void lbtf_queue_cmd(struct lbtf_private *priv,
208			  struct cmd_ctrl_node *cmdnode)
209{
210	unsigned long flags;
211	lbtf_deb_enter(LBTF_DEB_HOST);
212
213	if (!cmdnode) {
214		lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
215		goto qcmd_done;
216	}
217
218	if (!cmdnode->cmdbuf->size) {
219		lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
220		goto qcmd_done;
221	}
222
223	cmdnode->result = 0;
224	spin_lock_irqsave(&priv->driver_lock, flags);
225	list_add_tail(&cmdnode->list, &priv->cmdpendingq);
226	spin_unlock_irqrestore(&priv->driver_lock, flags);
227
228	lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
229		     le16_to_cpu(cmdnode->cmdbuf->command));
230
231qcmd_done:
232	lbtf_deb_leave(LBTF_DEB_HOST);
233}
234
235static void lbtf_submit_command(struct lbtf_private *priv,
236			       struct cmd_ctrl_node *cmdnode)
237{
238	unsigned long flags;
239	struct cmd_header *cmd;
240	uint16_t cmdsize;
241	uint16_t command;
242	int timeo = 5 * HZ;
243	int ret;
244
245	lbtf_deb_enter(LBTF_DEB_HOST);
246
247	cmd = cmdnode->cmdbuf;
248
249	spin_lock_irqsave(&priv->driver_lock, flags);
250	priv->cur_cmd = cmdnode;
251	cmdsize = le16_to_cpu(cmd->size);
252	command = le16_to_cpu(cmd->command);
253
254	lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
255		     command, le16_to_cpu(cmd->seqnum), cmdsize);
256	lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
257
258	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
259	spin_unlock_irqrestore(&priv->driver_lock, flags);
260
261	if (ret) {
262		pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
263		/* Let the timer kick in and retry, and potentially reset
264		   the whole thing if the condition persists */
265		timeo = HZ;
266	}
267
268	/* Setup the timer after transmit command */
269	mod_timer(&priv->command_timer, jiffies + timeo);
270
271	lbtf_deb_leave(LBTF_DEB_HOST);
272}
273
274/**
275 *  This function inserts command node to cmdfreeq
276 *  after cleans it. Requires priv->driver_lock held.
277 */
278static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
279					 struct cmd_ctrl_node *cmdnode)
280{
281	lbtf_deb_enter(LBTF_DEB_HOST);
282
283	if (!cmdnode)
284		goto cl_ins_out;
285
286	cmdnode->callback = NULL;
287	cmdnode->callback_arg = 0;
288
289	memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
290
291	list_add_tail(&cmdnode->list, &priv->cmdfreeq);
292
293cl_ins_out:
294	lbtf_deb_leave(LBTF_DEB_HOST);
295}
296
297static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
298	struct cmd_ctrl_node *ptempcmd)
299{
300	unsigned long flags;
301
302	spin_lock_irqsave(&priv->driver_lock, flags);
303	__lbtf_cleanup_and_insert_cmd(priv, ptempcmd);
304	spin_unlock_irqrestore(&priv->driver_lock, flags);
305}
306
307void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
308			  int result)
309{
310	cmd->result = result;
311	cmd->cmdwaitqwoken = 1;
312	wake_up_interruptible(&cmd->cmdwait_q);
313
314	if (!cmd->callback)
315		__lbtf_cleanup_and_insert_cmd(priv, cmd);
316	priv->cur_cmd = NULL;
317}
318
319int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
320{
321	struct cmd_ds_mac_multicast_addr cmd;
322
323	lbtf_deb_enter(LBTF_DEB_CMD);
324
325	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
326	cmd.action = cpu_to_le16(CMD_ACT_SET);
327
328	cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
329
330	lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
331
332	memcpy(cmd.maclist, priv->multicastlist,
333	       priv->nr_of_multicastmacaddr * ETH_ALEN);
334
335	lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
336
337	lbtf_deb_leave(LBTF_DEB_CMD);
338	return 0;
339}
340
341void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
342{
343	struct cmd_ds_set_mode cmd;
344	lbtf_deb_enter(LBTF_DEB_WEXT);
345
346	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
347	cmd.mode = cpu_to_le16(mode);
348	lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
349	lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
350
351	lbtf_deb_leave(LBTF_DEB_WEXT);
352}
353
354void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
355{
356	struct cmd_ds_set_bssid cmd;
357	lbtf_deb_enter(LBTF_DEB_CMD);
358
359	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
360	cmd.activate = activate ? 1 : 0;
361	if (activate)
362		memcpy(cmd.bssid, bssid, ETH_ALEN);
363
364	lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
365	lbtf_deb_leave(LBTF_DEB_CMD);
366}
367
368int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
369{
370	struct cmd_ds_802_11_mac_address cmd;
371	lbtf_deb_enter(LBTF_DEB_CMD);
372
373	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
374	cmd.action = cpu_to_le16(CMD_ACT_SET);
375
376	memcpy(cmd.macadd, mac_addr, ETH_ALEN);
377
378	lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
379	lbtf_deb_leave(LBTF_DEB_CMD);
380	return 0;
381}
382
383int lbtf_set_radio_control(struct lbtf_private *priv)
384{
385	int ret = 0;
386	struct cmd_ds_802_11_radio_control cmd;
387
388	lbtf_deb_enter(LBTF_DEB_CMD);
389
390	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
391	cmd.action = cpu_to_le16(CMD_ACT_SET);
392
393	switch (priv->preamble) {
394	case CMD_TYPE_SHORT_PREAMBLE:
395		cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
396		break;
397
398	case CMD_TYPE_LONG_PREAMBLE:
399		cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
400		break;
401
402	case CMD_TYPE_AUTO_PREAMBLE:
403	default:
404		cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
405		break;
406	}
407
408	if (priv->radioon)
409		cmd.control |= cpu_to_le16(TURN_ON_RF);
410	else
411		cmd.control &= cpu_to_le16(~TURN_ON_RF);
412
413	lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
414		    priv->preamble);
415
416	ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
417
418	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
419	return ret;
420}
421
422void lbtf_set_mac_control(struct lbtf_private *priv)
423{
424	struct cmd_ds_mac_control cmd;
425	lbtf_deb_enter(LBTF_DEB_CMD);
426
427	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
428	cmd.action = cpu_to_le16(priv->mac_control);
429	cmd.reserved = 0;
430
431	lbtf_cmd_async(priv, CMD_MAC_CONTROL,
432		&cmd.hdr, sizeof(cmd));
433
434	lbtf_deb_leave(LBTF_DEB_CMD);
435}
436
437/**
438 *  lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue
439 *
440 *  @priv	A pointer to struct lbtf_private structure
441 *
442 *  Returns: 0 on success.
443 */
444int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
445{
446	int ret = 0;
447	u32 bufsize;
448	u32 i;
449	struct cmd_ctrl_node *cmdarray;
450
451	lbtf_deb_enter(LBTF_DEB_HOST);
452
453	/* Allocate and initialize the command array */
454	bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
455	cmdarray = kzalloc(bufsize, GFP_KERNEL);
456	if (!cmdarray) {
457		lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
458		ret = -1;
459		goto done;
460	}
461	priv->cmd_array = cmdarray;
462
463	/* Allocate and initialize each command buffer in the command array */
464	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
465		cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
466		if (!cmdarray[i].cmdbuf) {
467			lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
468			ret = -1;
469			goto done;
470		}
471	}
472
473	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
474		init_waitqueue_head(&cmdarray[i].cmdwait_q);
475		lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
476	}
477
478	ret = 0;
479
480done:
481	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
482	return ret;
483}
484
485/**
486 *  lbtf_free_cmd_buffer - Frees the cmd buffer.
487 *
488 *  @priv	A pointer to struct lbtf_private structure
489 *
490 *  Returns: 0
491 */
492int lbtf_free_cmd_buffer(struct lbtf_private *priv)
493{
494	struct cmd_ctrl_node *cmdarray;
495	unsigned int i;
496
497	lbtf_deb_enter(LBTF_DEB_HOST);
498
499	/* need to check if cmd array is allocated or not */
500	if (priv->cmd_array == NULL) {
501		lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
502		goto done;
503	}
504
505	cmdarray = priv->cmd_array;
506
507	/* Release shared memory buffers */
508	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
509		kfree(cmdarray[i].cmdbuf);
510		cmdarray[i].cmdbuf = NULL;
511	}
512
513	/* Release cmd_ctrl_node */
514	kfree(priv->cmd_array);
515	priv->cmd_array = NULL;
516
517done:
518	lbtf_deb_leave(LBTF_DEB_HOST);
519	return 0;
520}
521
522/**
523 *  lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue.
524 *
525 *  @priv		A pointer to struct lbtf_private structure
526 *
527 *  Returns: pointer to a struct cmd_ctrl_node or NULL if none available.
528 */
529static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
530{
531	struct cmd_ctrl_node *tempnode;
532	unsigned long flags;
533
534	lbtf_deb_enter(LBTF_DEB_HOST);
535
536	if (!priv)
537		return NULL;
538
539	spin_lock_irqsave(&priv->driver_lock, flags);
540
541	if (!list_empty(&priv->cmdfreeq)) {
542		tempnode = list_first_entry(&priv->cmdfreeq,
543					    struct cmd_ctrl_node, list);
544		list_del(&tempnode->list);
545	} else {
546		lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
547		tempnode = NULL;
548	}
549
550	spin_unlock_irqrestore(&priv->driver_lock, flags);
551
552	lbtf_deb_leave(LBTF_DEB_HOST);
553	return tempnode;
554}
555
556/**
557 *  lbtf_execute_next_command: execute next command in cmd pending queue.
558 *
559 *  @priv     A pointer to struct lbtf_private structure
560 *
561 *  Returns: 0 on success.
562 */
563int lbtf_execute_next_command(struct lbtf_private *priv)
564{
565	struct cmd_ctrl_node *cmdnode = NULL;
566	struct cmd_header *cmd;
567	unsigned long flags;
568	int ret = 0;
569
570	/* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
571	 * only caller to us is lbtf_thread() and we get even when a
572	 * data packet is received */
573	lbtf_deb_enter(LBTF_DEB_THREAD);
574
575	spin_lock_irqsave(&priv->driver_lock, flags);
576
577	if (priv->cur_cmd) {
578		pr_alert("EXEC_NEXT_CMD: already processing command!\n");
579		spin_unlock_irqrestore(&priv->driver_lock, flags);
580		ret = -1;
581		goto done;
582	}
583
584	if (!list_empty(&priv->cmdpendingq)) {
585		cmdnode = list_first_entry(&priv->cmdpendingq,
586					   struct cmd_ctrl_node, list);
587	}
588
589	if (cmdnode) {
590		cmd = cmdnode->cmdbuf;
591
592		list_del(&cmdnode->list);
593		lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
594			    le16_to_cpu(cmd->command));
595		spin_unlock_irqrestore(&priv->driver_lock, flags);
596		lbtf_submit_command(priv, cmdnode);
597	} else
598		spin_unlock_irqrestore(&priv->driver_lock, flags);
599
600	ret = 0;
601done:
602	lbtf_deb_leave(LBTF_DEB_THREAD);
603	return ret;
604}
605
606static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
607	uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
608	int (*callback)(struct lbtf_private *, unsigned long,
609			struct cmd_header *),
610	unsigned long callback_arg)
611{
612	struct cmd_ctrl_node *cmdnode;
613
614	lbtf_deb_enter(LBTF_DEB_HOST);
615
616	if (priv->surpriseremoved) {
617		lbtf_deb_host("PREP_CMD: card removed\n");
618		cmdnode = ERR_PTR(-ENOENT);
619		goto done;
620	}
621
622	cmdnode = lbtf_get_cmd_ctrl_node(priv);
623	if (cmdnode == NULL) {
624		lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
625
626		/* Wake up main thread to execute next command */
627		queue_work(lbtf_wq, &priv->cmd_work);
628		cmdnode = ERR_PTR(-ENOBUFS);
629		goto done;
630	}
631
632	cmdnode->callback = callback;
633	cmdnode->callback_arg = callback_arg;
634
635	/* Copy the incoming command to the buffer */
636	memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
637
638	/* Set sequence number, clean result, move to buffer */
639	priv->seqnum++;
640	cmdnode->cmdbuf->command = cpu_to_le16(command);
641	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
642	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
643	cmdnode->cmdbuf->result  = 0;
644
645	lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
646
647	cmdnode->cmdwaitqwoken = 0;
648	lbtf_queue_cmd(priv, cmdnode);
649	queue_work(lbtf_wq, &priv->cmd_work);
650
651 done:
652	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
653	return cmdnode;
654}
655
656void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
657	struct cmd_header *in_cmd, int in_cmd_size)
658{
659	lbtf_deb_enter(LBTF_DEB_CMD);
660	__lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
661	lbtf_deb_leave(LBTF_DEB_CMD);
662}
663
664int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
665	      struct cmd_header *in_cmd, int in_cmd_size,
666	      int (*callback)(struct lbtf_private *,
667			      unsigned long, struct cmd_header *),
668	      unsigned long callback_arg)
669{
670	struct cmd_ctrl_node *cmdnode;
671	unsigned long flags;
672	int ret = 0;
673
674	lbtf_deb_enter(LBTF_DEB_HOST);
675
676	cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
677				  callback, callback_arg);
678	if (IS_ERR(cmdnode)) {
679		ret = PTR_ERR(cmdnode);
680		goto done;
681	}
682
683	might_sleep();
684	ret = wait_event_interruptible(cmdnode->cmdwait_q,
685				       cmdnode->cmdwaitqwoken);
686	if (ret) {
687		pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
688			    command, ret);
689		goto done;
690	}
691
692	spin_lock_irqsave(&priv->driver_lock, flags);
693	ret = cmdnode->result;
694	if (ret)
695		pr_info("PREP_CMD: command 0x%04x failed: %d\n",
696			    command, ret);
697
698	__lbtf_cleanup_and_insert_cmd(priv, cmdnode);
699	spin_unlock_irqrestore(&priv->driver_lock, flags);
700
701done:
702	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
703	return ret;
704}
705EXPORT_SYMBOL_GPL(__lbtf_cmd);
706
707/* Call holding driver_lock */
708void lbtf_cmd_response_rx(struct lbtf_private *priv)
709{
710	priv->cmd_response_rxed = 1;
711	queue_work(lbtf_wq, &priv->cmd_work);
712}
713EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
714
715int lbtf_process_rx_command(struct lbtf_private *priv)
716{
717	uint16_t respcmd, curcmd;
718	struct cmd_header *resp;
719	int ret = 0;
720	unsigned long flags;
721	uint16_t result;
722
723	lbtf_deb_enter(LBTF_DEB_CMD);
724
725	mutex_lock(&priv->lock);
726	spin_lock_irqsave(&priv->driver_lock, flags);
727
728	if (!priv->cur_cmd) {
729		ret = -1;
730		spin_unlock_irqrestore(&priv->driver_lock, flags);
731		goto done;
732	}
733
734	resp = (void *)priv->cmd_resp_buff;
735	curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
736	respcmd = le16_to_cpu(resp->command);
737	result = le16_to_cpu(resp->result);
738
739	if (net_ratelimit())
740		pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
741			respcmd, le16_to_cpu(resp->seqnum),
742			le16_to_cpu(resp->size));
743
744	if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
745		spin_unlock_irqrestore(&priv->driver_lock, flags);
746		ret = -1;
747		goto done;
748	}
749	if (respcmd != CMD_RET(curcmd)) {
750		spin_unlock_irqrestore(&priv->driver_lock, flags);
751		ret = -1;
752		goto done;
753	}
754
755	if (resp->result == cpu_to_le16(0x0004)) {
756		/* 0x0004 means -EAGAIN. Drop the response, let it time out
757		   and be resubmitted */
758		spin_unlock_irqrestore(&priv->driver_lock, flags);
759		ret = -1;
760		goto done;
761	}
762
763	/* Now we got response from FW, cancel the command timer */
764	del_timer(&priv->command_timer);
765	priv->cmd_timed_out = 0;
766	if (priv->nr_retries)
767		priv->nr_retries = 0;
768
769	/* If the command is not successful, cleanup and return failure */
770	if ((result != 0 || !(respcmd & 0x8000))) {
771		/*
772		 * Handling errors here
773		 */
774		switch (respcmd) {
775		case CMD_RET(CMD_GET_HW_SPEC):
776		case CMD_RET(CMD_802_11_RESET):
777			pr_info("libertastf: reset failed\n");
778			break;
779
780		}
781		lbtf_complete_command(priv, priv->cur_cmd, result);
782		spin_unlock_irqrestore(&priv->driver_lock, flags);
783
784		ret = -1;
785		goto done;
786	}
787
788	spin_unlock_irqrestore(&priv->driver_lock, flags);
789
790	if (priv->cur_cmd && priv->cur_cmd->callback) {
791		ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
792				resp);
793	}
794	spin_lock_irqsave(&priv->driver_lock, flags);
795
796	if (priv->cur_cmd) {
797		/* Clean up and Put current command back to cmdfreeq */
798		lbtf_complete_command(priv, priv->cur_cmd, result);
799	}
800	spin_unlock_irqrestore(&priv->driver_lock, flags);
801
802done:
803	mutex_unlock(&priv->lock);
804	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
805	return ret;
806}