xref: /openbmc/linux/drivers/net/wireless/ath/ath6kl/bmi.c (revision cfc301ed)
1 /*
2  * Copyright (c) 2004-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 #include "core.h"
18 #include "hif-ops.h"
19 #include "target.h"
20 #include "debug.h"
21 
22 static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
23 {
24 	u32 addr;
25 	unsigned long timeout;
26 	int ret;
27 
28 	ar->bmi.cmd_credits = 0;
29 
30 	/* Read the counter register to get the command credits */
31 	addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
32 
33 	timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
34 	while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) {
35 
36 		/*
37 		 * Hit the credit counter with a 4-byte access, the first byte
38 		 * read will hit the counter and cause a decrement, while the
39 		 * remaining 3 bytes has no effect. The rationale behind this
40 		 * is to make all HIF accesses 4-byte aligned.
41 		 */
42 		ret = hif_read_write_sync(ar, addr,
43 					 (u8 *)&ar->bmi.cmd_credits, 4,
44 					 HIF_RD_SYNC_BYTE_INC);
45 		if (ret) {
46 			ath6kl_err("Unable to decrement the command credit count register: %d\n",
47 				   ret);
48 			return ret;
49 		}
50 
51 		/* The counter is only 8 bits.
52 		 * Ignore anything in the upper 3 bytes
53 		 */
54 		ar->bmi.cmd_credits &= 0xFF;
55 	}
56 
57 	if (!ar->bmi.cmd_credits) {
58 		ath6kl_err("bmi communication timeout\n");
59 		return -ETIMEDOUT;
60 	}
61 
62 	return 0;
63 }
64 
65 static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar)
66 {
67 	unsigned long timeout;
68 	u32 rx_word = 0;
69 	int ret = 0;
70 
71 	timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
72 	while (time_before(jiffies, timeout) && !rx_word) {
73 		ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS,
74 					  (u8 *)&rx_word, sizeof(rx_word),
75 					  HIF_RD_SYNC_BYTE_INC);
76 		if (ret) {
77 			ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n");
78 			return ret;
79 		}
80 
81 		 /* all we really want is one bit */
82 		rx_word &= (1 << ENDPOINT1);
83 	}
84 
85 	if (!rx_word) {
86 		ath6kl_err("bmi_recv_buf FIFO empty\n");
87 		return -EINVAL;
88 	}
89 
90 	return ret;
91 }
92 
93 static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
94 {
95 	int ret;
96 	u32 addr;
97 
98 	ret = ath6kl_get_bmi_cmd_credits(ar);
99 	if (ret)
100 		return ret;
101 
102 	addr = ar->mbox_info.htc_addr;
103 
104 	ret = hif_read_write_sync(ar, addr, buf, len,
105 				  HIF_WR_SYNC_BYTE_INC);
106 	if (ret)
107 		ath6kl_err("unable to send the bmi data to the device\n");
108 
109 	return ret;
110 }
111 
112 static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len)
113 {
114 	int ret;
115 	u32 addr;
116 
117 	/*
118 	 * During normal bootup, small reads may be required.
119 	 * Rather than issue an HIF Read and then wait as the Target
120 	 * adds successive bytes to the FIFO, we wait here until
121 	 * we know that response data is available.
122 	 *
123 	 * This allows us to cleanly timeout on an unexpected
124 	 * Target failure rather than risk problems at the HIF level.
125 	 * In particular, this avoids SDIO timeouts and possibly garbage
126 	 * data on some host controllers.  And on an interconnect
127 	 * such as Compact Flash (as well as some SDIO masters) which
128 	 * does not provide any indication on data timeout, it avoids
129 	 * a potential hang or garbage response.
130 	 *
131 	 * Synchronization is more difficult for reads larger than the
132 	 * size of the MBOX FIFO (128B), because the Target is unable
133 	 * to push the 129th byte of data until AFTER the Host posts an
134 	 * HIF Read and removes some FIFO data.  So for large reads the
135 	 * Host proceeds to post an HIF Read BEFORE all the data is
136 	 * actually available to read.  Fortunately, large BMI reads do
137 	 * not occur in practice -- they're supported for debug/development.
138 	 *
139 	 * So Host/Target BMI synchronization is divided into these cases:
140 	 *  CASE 1: length < 4
141 	 *        Should not happen
142 	 *
143 	 *  CASE 2: 4 <= length <= 128
144 	 *        Wait for first 4 bytes to be in FIFO
145 	 *        If CONSERVATIVE_BMI_READ is enabled, also wait for
146 	 *        a BMI command credit, which indicates that the ENTIRE
147 	 *        response is available in the the FIFO
148 	 *
149 	 *  CASE 3: length > 128
150 	 *        Wait for the first 4 bytes to be in FIFO
151 	 *
152 	 * For most uses, a small timeout should be sufficient and we will
153 	 * usually see a response quickly; but there may be some unusual
154 	 * (debug) cases of BMI_EXECUTE where we want an larger timeout.
155 	 * For now, we use an unbounded busy loop while waiting for
156 	 * BMI_EXECUTE.
157 	 *
158 	 * If BMI_EXECUTE ever needs to support longer-latency execution,
159 	 * especially in production, this code needs to be enhanced to sleep
160 	 * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
161 	 * a function of Host processor speed.
162 	 */
163 	if (len >= 4) { /* NB: Currently, always true */
164 		ret = ath6kl_bmi_get_rx_lkahd(ar);
165 		if (ret)
166 			return ret;
167 	}
168 
169 	addr = ar->mbox_info.htc_addr;
170 	ret = hif_read_write_sync(ar, addr, buf, len,
171 				  HIF_RD_SYNC_BYTE_INC);
172 	if (ret) {
173 		ath6kl_err("Unable to read the bmi data from the device: %d\n",
174 			   ret);
175 		return ret;
176 	}
177 
178 	return 0;
179 }
180 
181 int ath6kl_bmi_done(struct ath6kl *ar)
182 {
183 	int ret;
184 	u32 cid = BMI_DONE;
185 
186 	if (ar->bmi.done_sent) {
187 		ath6kl_dbg(ATH6KL_DBG_BMI, "bmi done skipped\n");
188 		return 0;
189 	}
190 
191 	ar->bmi.done_sent = true;
192 
193 	ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
194 	if (ret) {
195 		ath6kl_err("Unable to send bmi done: %d\n", ret);
196 		return ret;
197 	}
198 
199 	ath6kl_bmi_cleanup(ar);
200 
201 	return 0;
202 }
203 
204 int ath6kl_bmi_get_target_info(struct ath6kl *ar,
205 			       struct ath6kl_bmi_target_info *targ_info)
206 {
207 	int ret;
208 	u32 cid = BMI_GET_TARGET_INFO;
209 
210 	if (ar->bmi.done_sent) {
211 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
212 		return -EACCES;
213 	}
214 
215 	ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
216 	if (ret) {
217 		ath6kl_err("Unable to send get target info: %d\n", ret);
218 		return ret;
219 	}
220 
221 	ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version,
222 				  sizeof(targ_info->version));
223 	if (ret) {
224 		ath6kl_err("Unable to recv target info: %d\n", ret);
225 		return ret;
226 	}
227 
228 	if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) {
229 		/* Determine how many bytes are in the Target's targ_info */
230 		ret = ath6kl_bmi_recv_buf(ar,
231 				   (u8 *)&targ_info->byte_count,
232 				   sizeof(targ_info->byte_count));
233 		if (ret) {
234 			ath6kl_err("unable to read target info byte count: %d\n",
235 				   ret);
236 			return ret;
237 		}
238 
239 		/*
240 		 * The target's targ_info doesn't match the host's targ_info.
241 		 * We need to do some backwards compatibility to make this work.
242 		 */
243 		if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) {
244 			WARN_ON(1);
245 			return -EINVAL;
246 		}
247 
248 		/* Read the remainder of the targ_info */
249 		ret = ath6kl_bmi_recv_buf(ar,
250 				   ((u8 *)targ_info) +
251 				   sizeof(targ_info->byte_count),
252 				   sizeof(*targ_info) -
253 				   sizeof(targ_info->byte_count));
254 
255 		if (ret) {
256 			ath6kl_err("Unable to read target info (%d bytes): %d\n",
257 				   targ_info->byte_count, ret);
258 			return ret;
259 		}
260 	}
261 
262 	ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n",
263 		targ_info->version, targ_info->type);
264 
265 	return 0;
266 }
267 
268 int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
269 {
270 	u32 cid = BMI_READ_MEMORY;
271 	int ret;
272 	u32 offset;
273 	u32 len_remain, rx_len;
274 	u16 size;
275 
276 	if (ar->bmi.done_sent) {
277 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
278 		return -EACCES;
279 	}
280 
281 	size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len);
282 	if (size > MAX_BMI_CMDBUF_SZ) {
283 		WARN_ON(1);
284 		return -EINVAL;
285 	}
286 	memset(ar->bmi.cmd_buf, 0, size);
287 
288 	ath6kl_dbg(ATH6KL_DBG_BMI,
289 		   "bmi read memory: device: addr: 0x%x, len: %d\n",
290 		   addr, len);
291 
292 	len_remain = len;
293 
294 	while (len_remain) {
295 		rx_len = (len_remain < BMI_DATASZ_MAX) ?
296 					len_remain : BMI_DATASZ_MAX;
297 		offset = 0;
298 		memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
299 		offset += sizeof(cid);
300 		memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
301 		offset += sizeof(addr);
302 		memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len));
303 		offset += sizeof(len);
304 
305 		ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
306 		if (ret) {
307 			ath6kl_err("Unable to write to the device: %d\n",
308 				   ret);
309 			return ret;
310 		}
311 		ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len);
312 		if (ret) {
313 			ath6kl_err("Unable to read from the device: %d\n",
314 				   ret);
315 			return ret;
316 		}
317 		memcpy(&buf[len - len_remain], ar->bmi.cmd_buf, rx_len);
318 		len_remain -= rx_len; addr += rx_len;
319 	}
320 
321 	return 0;
322 }
323 
324 int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
325 {
326 	u32 cid = BMI_WRITE_MEMORY;
327 	int ret;
328 	u32 offset;
329 	u32 len_remain, tx_len;
330 	const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len);
331 	u8 aligned_buf[BMI_DATASZ_MAX];
332 	u8 *src;
333 
334 	if (ar->bmi.done_sent) {
335 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
336 		return -EACCES;
337 	}
338 
339 	if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) {
340 		WARN_ON(1);
341 		return -EINVAL;
342 	}
343 
344 	memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header);
345 
346 	ath6kl_dbg(ATH6KL_DBG_BMI,
347 		  "bmi write memory: addr: 0x%x, len: %d\n", addr, len);
348 
349 	len_remain = len;
350 	while (len_remain) {
351 		src = &buf[len - len_remain];
352 
353 		if (len_remain < (BMI_DATASZ_MAX - header)) {
354 			if (len_remain & 3) {
355 				/* align it with 4 bytes */
356 				len_remain = len_remain +
357 					     (4 - (len_remain & 3));
358 				memcpy(aligned_buf, src, len_remain);
359 				src = aligned_buf;
360 			}
361 			tx_len = len_remain;
362 		} else {
363 			tx_len = (BMI_DATASZ_MAX - header);
364 		}
365 
366 		offset = 0;
367 		memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
368 		offset += sizeof(cid);
369 		memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
370 		offset += sizeof(addr);
371 		memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
372 		offset += sizeof(tx_len);
373 		memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len);
374 		offset += tx_len;
375 
376 		ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
377 		if (ret) {
378 			ath6kl_err("Unable to write to the device: %d\n",
379 				   ret);
380 			return ret;
381 		}
382 		len_remain -= tx_len; addr += tx_len;
383 	}
384 
385 	return 0;
386 }
387 
388 int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
389 {
390 	u32 cid = BMI_EXECUTE;
391 	int ret;
392 	u32 offset;
393 	u16 size;
394 
395 	if (ar->bmi.done_sent) {
396 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
397 		return -EACCES;
398 	}
399 
400 	size = sizeof(cid) + sizeof(addr) + sizeof(param);
401 	if (size > MAX_BMI_CMDBUF_SZ) {
402 		WARN_ON(1);
403 		return -EINVAL;
404 	}
405 	memset(ar->bmi.cmd_buf, 0, size);
406 
407 	ath6kl_dbg(ATH6KL_DBG_BMI, "bmi execute: addr: 0x%x, param: %d)\n",
408 		   addr, *param);
409 
410 	offset = 0;
411 	memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
412 	offset += sizeof(cid);
413 	memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
414 	offset += sizeof(addr);
415 	memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param));
416 	offset += sizeof(*param);
417 
418 	ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
419 	if (ret) {
420 		ath6kl_err("Unable to write to the device: %d\n", ret);
421 		return ret;
422 	}
423 
424 	ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
425 	if (ret) {
426 		ath6kl_err("Unable to read from the device: %d\n", ret);
427 		return ret;
428 	}
429 
430 	memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
431 
432 	return 0;
433 }
434 
435 int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
436 {
437 	u32 cid = BMI_SET_APP_START;
438 	int ret;
439 	u32 offset;
440 	u16 size;
441 
442 	if (ar->bmi.done_sent) {
443 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
444 		return -EACCES;
445 	}
446 
447 	size = sizeof(cid) + sizeof(addr);
448 	if (size > MAX_BMI_CMDBUF_SZ) {
449 		WARN_ON(1);
450 		return -EINVAL;
451 	}
452 	memset(ar->bmi.cmd_buf, 0, size);
453 
454 	ath6kl_dbg(ATH6KL_DBG_BMI, "bmi set app start: addr: 0x%x\n", addr);
455 
456 	offset = 0;
457 	memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
458 	offset += sizeof(cid);
459 	memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
460 	offset += sizeof(addr);
461 
462 	ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
463 	if (ret) {
464 		ath6kl_err("Unable to write to the device: %d\n", ret);
465 		return ret;
466 	}
467 
468 	return 0;
469 }
470 
471 int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
472 {
473 	u32 cid = BMI_READ_SOC_REGISTER;
474 	int ret;
475 	u32 offset;
476 	u16 size;
477 
478 	if (ar->bmi.done_sent) {
479 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
480 		return -EACCES;
481 	}
482 
483 	size = sizeof(cid) + sizeof(addr);
484 	if (size > MAX_BMI_CMDBUF_SZ) {
485 		WARN_ON(1);
486 		return -EINVAL;
487 	}
488 	memset(ar->bmi.cmd_buf, 0, size);
489 
490 	ath6kl_dbg(ATH6KL_DBG_BMI, "bmi read SOC reg: addr: 0x%x\n", addr);
491 
492 	offset = 0;
493 	memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
494 	offset += sizeof(cid);
495 	memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
496 	offset += sizeof(addr);
497 
498 	ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
499 	if (ret) {
500 		ath6kl_err("Unable to write to the device: %d\n", ret);
501 		return ret;
502 	}
503 
504 	ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
505 	if (ret) {
506 		ath6kl_err("Unable to read from the device: %d\n", ret);
507 		return ret;
508 	}
509 	memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
510 
511 	return 0;
512 }
513 
514 int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
515 {
516 	u32 cid = BMI_WRITE_SOC_REGISTER;
517 	int ret;
518 	u32 offset;
519 	u16 size;
520 
521 	if (ar->bmi.done_sent) {
522 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
523 		return -EACCES;
524 	}
525 
526 	size = sizeof(cid) + sizeof(addr) + sizeof(param);
527 	if (size > MAX_BMI_CMDBUF_SZ) {
528 		WARN_ON(1);
529 		return -EINVAL;
530 	}
531 	memset(ar->bmi.cmd_buf, 0, size);
532 
533 	ath6kl_dbg(ATH6KL_DBG_BMI,
534 		   "bmi write SOC reg: addr: 0x%x, param: %d\n",
535 		    addr, param);
536 
537 	offset = 0;
538 	memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
539 	offset += sizeof(cid);
540 	memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
541 	offset += sizeof(addr);
542 	memcpy(&(ar->bmi.cmd_buf[offset]), &param, sizeof(param));
543 	offset += sizeof(param);
544 
545 	ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
546 	if (ret) {
547 		ath6kl_err("Unable to write to the device: %d\n", ret);
548 		return ret;
549 	}
550 
551 	return 0;
552 }
553 
554 int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
555 {
556 	u32 cid = BMI_LZ_DATA;
557 	int ret;
558 	u32 offset;
559 	u32 len_remain, tx_len;
560 	const u32 header = sizeof(cid) + sizeof(len);
561 	u16 size;
562 
563 	if (ar->bmi.done_sent) {
564 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
565 		return -EACCES;
566 	}
567 
568 	size = BMI_DATASZ_MAX + header;
569 	if (size > MAX_BMI_CMDBUF_SZ) {
570 		WARN_ON(1);
571 		return -EINVAL;
572 	}
573 	memset(ar->bmi.cmd_buf, 0, size);
574 
575 	ath6kl_dbg(ATH6KL_DBG_BMI, "bmi send LZ data: len: %d)\n",
576 		   len);
577 
578 	len_remain = len;
579 	while (len_remain) {
580 		tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ?
581 			  len_remain : (BMI_DATASZ_MAX - header);
582 
583 		offset = 0;
584 		memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
585 		offset += sizeof(cid);
586 		memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
587 		offset += sizeof(tx_len);
588 		memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain],
589 			tx_len);
590 		offset += tx_len;
591 
592 		ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
593 		if (ret) {
594 			ath6kl_err("Unable to write to the device: %d\n",
595 				   ret);
596 			return ret;
597 		}
598 
599 		len_remain -= tx_len;
600 	}
601 
602 	return 0;
603 }
604 
605 int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
606 {
607 	u32 cid = BMI_LZ_STREAM_START;
608 	int ret;
609 	u32 offset;
610 	u16 size;
611 
612 	if (ar->bmi.done_sent) {
613 		ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
614 		return -EACCES;
615 	}
616 
617 	size = sizeof(cid) + sizeof(addr);
618 	if (size > MAX_BMI_CMDBUF_SZ) {
619 		WARN_ON(1);
620 		return -EINVAL;
621 	}
622 	memset(ar->bmi.cmd_buf, 0, size);
623 
624 	ath6kl_dbg(ATH6KL_DBG_BMI,
625 		   "bmi LZ stream start: addr: 0x%x)\n",
626 		    addr);
627 
628 	offset = 0;
629 	memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
630 	offset += sizeof(cid);
631 	memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
632 	offset += sizeof(addr);
633 
634 	ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
635 	if (ret) {
636 		ath6kl_err("Unable to start LZ stream to the device: %d\n",
637 			   ret);
638 		return ret;
639 	}
640 
641 	return 0;
642 }
643 
644 int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
645 {
646 	int ret;
647 	u32 last_word = 0;
648 	u32 last_word_offset = len & ~0x3;
649 	u32 unaligned_bytes = len & 0x3;
650 
651 	ret = ath6kl_bmi_lz_stream_start(ar, addr);
652 	if (ret)
653 		return ret;
654 
655 	if (unaligned_bytes) {
656 		/* copy the last word into a zero padded buffer */
657 		memcpy(&last_word, &buf[last_word_offset], unaligned_bytes);
658 	}
659 
660 	ret = ath6kl_bmi_lz_data(ar, buf, last_word_offset);
661 	if (ret)
662 		return ret;
663 
664 	if (unaligned_bytes)
665 		ret = ath6kl_bmi_lz_data(ar, (u8 *)&last_word, 4);
666 
667 	if (!ret) {
668 		/* Close compressed stream and open a new (fake) one.
669 		 * This serves mainly to flush Target caches. */
670 		ret = ath6kl_bmi_lz_stream_start(ar, 0x00);
671 	}
672 	return ret;
673 }
674 
675 int ath6kl_bmi_init(struct ath6kl *ar)
676 {
677 	ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
678 
679 	if (!ar->bmi.cmd_buf)
680 		return -ENOMEM;
681 
682 	return 0;
683 }
684 
685 void ath6kl_bmi_cleanup(struct ath6kl *ar)
686 {
687 	kfree(ar->bmi.cmd_buf);
688 	ar->bmi.cmd_buf = NULL;
689 }
690