]> Pileus Git - ~andy/linux/blob - drivers/staging/csr/csr_wifi_hip_download.c
Merge branch 'staging/for_v3.7' into v4l_for_linus
[~andy/linux] / drivers / staging / csr / csr_wifi_hip_download.c
1 /*****************************************************************************
2
3             (c) Cambridge Silicon Radio Limited 2012
4             All rights reserved and confidential information of CSR
5
6             Refer to LICENSE.txt included with this source for details
7             on the license terms.
8
9 *****************************************************************************/
10
11 /*
12  * ---------------------------------------------------------------------------
13  * FILE: csr_wifi_hip_download.c
14  *
15  * PURPOSE:
16  *      Routines for downloading firmware to UniFi.
17  *
18  * ---------------------------------------------------------------------------
19  */
20 #include <linux/slab.h>
21 #include "csr_wifi_hip_unifi.h"
22 #include "csr_wifi_hip_unifiversion.h"
23 #include "csr_wifi_hip_card.h"
24 #include "csr_wifi_hip_xbv.h"
25
26 #undef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
27
28 static CsrResult do_patch_download(card_t *card, void *dlpriv,
29                                    xbv1_t *pfwinfo, u32 boot_ctrl_addr);
30
31 static CsrResult do_patch_convert_download(card_t *card,
32                                            void *dlpriv, xbv1_t *pfwinfo);
33
34 /*
35  * ---------------------------------------------------------------------------
36  *  _find_in_slut
37  *
38  *      Find the offset of the appropriate object in the SLUT of a card
39  *
40  *  Arguments:
41  *      card            Pointer to card struct
42  *      psym            Pointer to symbol object.
43  *                         id set up by caller
44  *                         obj will be set up by this function
45  *      pslut           Pointer to SLUT address, if 0xffffffff then it must be
46  *                         read from the chip.
47  *  Returns:
48  *      CSR_RESULT_SUCCESS on success
49  *      Non-zero on error,
50  *      CSR_WIFI_HIP_RESULT_NOT_FOUND if not found
51  * ---------------------------------------------------------------------------
52  */
53 static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
54 {
55     u32 slut_address;
56     u16 finger_print;
57     CsrResult r;
58     CsrResult csrResult;
59
60     /* Get SLUT address */
61     if (*pslut == 0xffffffff)
62     {
63         r = card_wait_for_firmware_to_start(card, &slut_address);
64         if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
65         {
66             return r;
67         }
68         if (r != CSR_RESULT_SUCCESS)
69         {
70             unifi_error(card->ospriv, "Firmware hasn't started\n");
71             func_exit_r(r);
72             return r;
73         }
74         *pslut = slut_address;
75
76         /*
77          * Firmware has started so set the SDIO bus clock to the initial speed,
78          * faster than UNIFI_SDIO_CLOCK_SAFE_HZ, to speed up the f/w download.
79          */
80         csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ);
81         if (csrResult != CSR_RESULT_SUCCESS)
82         {
83             r = ConvertCsrSdioToCsrHipResult(card, csrResult);
84             func_exit_r(r);
85             return r;
86         }
87         card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
88     }
89     else
90     {
91         slut_address = *pslut;  /* Use previously discovered address */
92     }
93     unifi_trace(card->ospriv, UDBG4, "SLUT addr: 0x%lX\n", slut_address);
94
95     /*
96      * Check the SLUT fingerprint.
97      * The slut_address is a generic pointer so we must use unifi_card_read16().
98      */
99     unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n");
100     finger_print = 0;
101     r = unifi_card_read16(card, slut_address, &finger_print);
102     if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
103     {
104         return r;
105     }
106     if (r != CSR_RESULT_SUCCESS)
107     {
108         unifi_error(card->ospriv, "Failed to read SLUT finger print\n");
109         func_exit_r(r);
110         return r;
111     }
112
113     if (finger_print != SLUT_FINGERPRINT)
114     {
115         unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n");
116         func_exit_r(CSR_RESULT_FAILURE);
117         return CSR_RESULT_FAILURE;
118     }
119
120     /* Symbol table starts imedately after the fingerprint */
121     slut_address += 2;
122
123     while (1)
124     {
125         u16 id;
126         u32 obj;
127
128         r = unifi_card_read16(card, slut_address, &id);
129         if (r != CSR_RESULT_SUCCESS)
130         {
131             func_exit_r(r);
132             return r;
133         }
134         slut_address += 2;
135
136         if (id == CSR_SLT_END)
137         {
138             /* End of table reached: not found */
139             r = CSR_WIFI_HIP_RESULT_RANGE;
140             break;
141         }
142
143         r = unifi_read32(card, slut_address, &obj);
144         if (r != CSR_RESULT_SUCCESS)
145         {
146             func_exit_r(r);
147             return r;
148         }
149         slut_address += 4;
150
151         unifi_trace(card->ospriv, UDBG3, "  found SLUT id %02d.%08lx\n", id, obj);
152
153         r = CSR_WIFI_HIP_RESULT_NOT_FOUND;
154         /* Found search term? */
155         if (id == psym->id)
156         {
157             unifi_trace(card->ospriv, UDBG1, " matched SLUT id %02d.%08lx\n", id, obj);
158             psym->obj = obj;
159             r = CSR_RESULT_SUCCESS;
160             break;
161         }
162     }
163
164     func_exit_r(r);
165     return r;
166 }
167
168
169 /*
170  * ---------------------------------------------------------------------------
171  *  do_patch_convert_download
172  *
173  *      Download the given firmware image to the UniFi, converting from FWDL
174  *      to PTDL XBV format.
175  *
176  *  Arguments:
177  *      card            Pointer to card struct
178  *      dlpriv          Pointer to source firmware image
179  *      fwinfo          Pointer to source firmware info struct
180  *
181  *  Returns:
182  *      CSR_RESULT_SUCCESS on success, CSR error code on error
183  *
184  *  Notes:
185  * ---------------------------------------------------------------------------
186  */
187 static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo)
188 {
189     CsrResult r;
190     u32 slut_base = 0xffffffff;
191     void *pfw;
192     u32 psize;
193     symbol_t sym;
194
195     /* Reset the chip to guarantee that the ROM loader is running */
196     r = unifi_init(card);
197     if (r != CSR_RESULT_SUCCESS)
198     {
199         unifi_error(card->ospriv,
200                     "do_patch_convert_download: failed to re-init UniFi\n");
201         return r;
202     }
203
204     /* If no unifi_helper is running, the firmware version must be read */
205     if (card->build_id == 0)
206     {
207         u32 ver = 0;
208         sym.id = CSR_SLT_BUILD_ID_NUMBER;
209         sym.obj = 0; /* To be updated by _find_in_slut() */
210
211         unifi_trace(card->ospriv, UDBG1, "Need f/w version\n");
212
213         /* Find chip build id entry in SLUT */
214         r = _find_in_slut(card, &sym, &slut_base);
215         if (r != CSR_RESULT_SUCCESS)
216         {
217             unifi_error(card->ospriv, "Failed to find CSR_SLT_BUILD_ID_NUMBER\n");
218             return CSR_RESULT_FAILURE;
219         }
220
221         /* Read running f/w version */
222         r = unifi_read32(card, sym.obj, &ver);
223         if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
224         {
225             return r;
226         }
227         if (r != CSR_RESULT_SUCCESS)
228         {
229             unifi_error(card->ospriv, "Failed to read f/w id\n");
230             return CSR_RESULT_FAILURE;
231         }
232         card->build_id = ver;
233     }
234
235     /* Convert the ptest firmware to a patch against the running firmware */
236     pfw = xbv_to_patch(card, unifi_fw_read, dlpriv, pfwinfo, &psize);
237     if (!pfw)
238     {
239         unifi_error(card->ospriv, "Failed to convert f/w to patch");
240         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
241     }
242     else
243     {
244         void *desc;
245         sym.id = CSR_SLT_BOOT_LOADER_CONTROL;
246         sym.obj = 0; /* To be updated by _find_in_slut() */
247
248         /* Find boot loader control entry in SLUT */
249         r = _find_in_slut(card, &sym, &slut_base);
250         if (r != CSR_RESULT_SUCCESS)
251         {
252             unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n");
253             kfree(pfw);
254             return CSR_RESULT_FAILURE;
255         }
256
257         r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
258         if (r != CSR_RESULT_SUCCESS)
259         {
260             unifi_error(card->ospriv, "Failed to wake UniFi\n");
261         }
262
263         /* Get a dlpriv for the patch buffer so that unifi_fw_read() can
264          * access it.
265          */
266         desc = unifi_fw_open_buffer(card->ospriv, pfw, psize);
267         if (!desc)
268         {
269             kfree(pfw);
270             return CSR_WIFI_HIP_RESULT_NO_MEMORY;
271         }
272
273         /* Download the patch */
274         unifi_info(card->ospriv, "Downloading converted f/w as patch\n");
275         r = unifi_dl_patch(card, desc, sym.obj);
276         kfree(pfw);
277         unifi_fw_close_buffer(card->ospriv, desc);
278
279         if (r != CSR_RESULT_SUCCESS)
280         {
281             unifi_error(card->ospriv, "Converted patch download failed\n");
282             func_exit_r(r);
283             return r;
284         }
285         else
286         {
287             unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n");
288         }
289
290         /* This command starts the firmware */
291         r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART);
292         if (r != CSR_RESULT_SUCCESS)
293         {
294             unifi_error(card->ospriv, "Failed to write loader restart cmd\n");
295         }
296
297         func_exit_r(r);
298         return r;
299     }
300 }
301
302
303 /*
304  * ---------------------------------------------------------------------------
305  *  unifi_dl_firmware
306  *
307  *      Download the given firmware image to the UniFi.
308  *
309  *  Arguments:
310  *      card            Pointer to card struct
311  *      dlpriv          A context pointer from the calling function to be
312  *                      passed when calling unifi_fw_read().
313  *
314  *  Returns:
315  *      CSR_RESULT_SUCCESS on success,
316  *      CSR_WIFI_HIP_RESULT_NO_MEMORY         memory allocation failed
317  *      CSR_WIFI_HIP_RESULT_INVALID_VALUE         error in XBV file
318  *      CSR_RESULT_FAILURE            SDIO error
319  *
320  *  Notes:
321  *      Stops and resets the chip, does the download and runs the new
322  *      firmware.
323  * ---------------------------------------------------------------------------
324  */
325 CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
326 {
327     xbv1_t *fwinfo;
328     CsrResult r;
329
330     func_enter();
331
332     fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
333     if (fwinfo == NULL)
334     {
335         unifi_error(card->ospriv, "Failed to allocate memory for firmware\n");
336         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
337     }
338
339     /*
340      * Scan the firmware file to find the TLVs we are interested in.
341      * These are:
342      *   - check we support the file format version in VERF
343      *   - SLTP Symbol Lookup Table Pointer
344      *   - FWDL firmware download segments
345      *   - FWOV firmware overlay segment
346      *   - VMEQ Register probe tests to verify matching h/w
347      */
348     r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
349     if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware)
350     {
351         unifi_error(card->ospriv, "File type is %s, expected firmware.\n",
352                     fwinfo->mode == xbv_patch?"patch" : "unknown");
353         kfree(fwinfo);
354         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
355     }
356
357     /* UF6xxx doesn't accept firmware, only patches. Therefore we convert
358      * the file to patch format with version numbers matching the current
359      * running firmware, and then download via the patch mechanism.
360      * The sole purpose of this is to support production test firmware across
361      * different ROM releases, the test firmware being provided in non-patch
362      * format.
363      */
364     if (card->chip_id > SDIO_CARD_ID_UNIFI_2)
365     {
366         unifi_info(card->ospriv, "Must convert f/w to patch format\n");
367         r = do_patch_convert_download(card, dlpriv, fwinfo);
368     }
369     else
370     {
371         /* Older UniFi chips allowed firmware to be directly loaded onto the
372          * chip, which is no longer supported.
373          */
374         unifi_error(card->ospriv, "Only patch downloading supported\n");
375         r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
376     }
377
378     kfree(fwinfo);
379     func_exit_r(r);
380     return r;
381 } /* unifi_dl_firmware() */
382
383
384 /*
385  * ---------------------------------------------------------------------------
386  *  unifi_dl_patch
387  *
388  *      Load the given patch set into UniFi.
389  *
390  *  Arguments:
391  *      card            Pointer to card struct
392  *      dlpriv          The os specific handle to the firmware file.
393  *      boot_ctrl       The address of the boot loader control structure.
394  *
395  *  Returns:
396  *      CSR_RESULT_SUCCESS on success,
397  *      CSR_WIFI_HIP_RESULT_NO_MEMORY         memory allocation failed
398  *      CSR_WIFI_HIP_RESULT_INVALID_VALUE         error in XBV file
399  *      CSR_RESULT_FAILURE            SDIO error
400  *
401  *  Notes:
402  *      This ends up telling UniFi to restart.
403  * ---------------------------------------------------------------------------
404  */
405 CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
406 {
407     xbv1_t *fwinfo;
408     CsrResult r;
409
410     func_enter();
411
412     unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl);
413
414     fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
415     if (fwinfo == NULL)
416     {
417         unifi_error(card->ospriv, "Failed to allocate memory for patches\n");
418         func_exit();
419         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
420     }
421
422     /*
423      * Scan the firmware file to find the TLVs we are interested in.
424      * These are:
425      *   - check we support the file format version in VERF
426      *   - FWID The build ID of the ROM that we can patch
427      *   - PTDL patch download segments
428      */
429     r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
430     if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch)
431     {
432         kfree(fwinfo);
433         unifi_error(card->ospriv, "Failed to read in patch file\n");
434         func_exit();
435         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
436     }
437
438     /*
439      * We have to check the build id read from the SLUT against that
440      * for the patch file.  They have to match exactly.
441      *    "card->build_id" == XBV1.PTCH.FWID
442      */
443     if (card->build_id != fwinfo->build_id)
444     {
445         unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n",
446                     card->build_id, fwinfo->build_id);
447         kfree(fwinfo);
448 #ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
449         func_exit();
450         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
451 #else
452         fwinfo = NULL;
453         dlpriv = NULL;
454         return CSR_RESULT_SUCCESS;
455 #endif
456     }
457
458     r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl);
459     if (r != CSR_RESULT_SUCCESS)
460     {
461         unifi_error(card->ospriv, "Failed to patch image\n");
462     }
463
464     kfree(fwinfo);
465
466     func_exit_r(r);
467     return r;
468 } /* unifi_dl_patch() */
469
470
471 void* unifi_dl_fw_read_start(card_t *card, s8 is_fw)
472 {
473     card_info_t card_info;
474
475     unifi_card_info(card, &card_info);
476     unifi_trace(card->ospriv, UDBG5,
477                 "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n",
478                 card_info.chip_id, card_info.chip_version,
479                 card_info.fw_build, card_info.fw_hip_version,
480                 card_info.sdio_block_size);
481
482     return unifi_fw_read_start(card->ospriv, is_fw, &card_info);
483 }
484
485
486 /*
487  * ---------------------------------------------------------------------------
488  *  safe_read_shared_location
489  *
490  *      Read a shared memory location repeatedly until we get two readings
491  *      the same.
492  *
493  *  Arguments:
494  *      card            Pointer to card context struct.
495  *      unifi_addr      UniFi shared-data-memory address to access.
496  *      pdata           Pointer to a byte variable for the value read.
497  *
498  *
499  *  Returns:
500  *      CSR_RESULT_SUCCESS on success, CSR error code on failure
501  * ---------------------------------------------------------------------------
502  */
503 static CsrResult safe_read_shared_location(card_t *card, u32 address, u8 *pdata)
504 {
505     CsrResult r;
506     u16 limit = 1000;
507     u8 b, b2;
508
509     *pdata = 0;
510
511     r = unifi_read_8_or_16(card, address, &b);
512     if (r != CSR_RESULT_SUCCESS)
513     {
514         return r;
515     }
516
517     while (limit--)
518     {
519         r = unifi_read_8_or_16(card, address, &b2);
520         if (r != CSR_RESULT_SUCCESS)
521         {
522             return r;
523         }
524
525         /* When we have a stable value, return it */
526         if (b == b2)
527         {
528             *pdata = b;
529             return CSR_RESULT_SUCCESS;
530         }
531
532         b = b2;
533     }
534
535     return CSR_RESULT_FAILURE;
536 } /* safe_read_shared_location() */
537
538
539 /*
540  * ---------------------------------------------------------------------------
541  *  unifi_do_loader_op
542  *
543  *      Send a loader / boot_loader command to the UniFi and wait for
544  *      it to complete.
545  *
546  *  Arguments:
547  *      card            Pointer to card context struct.
548  *      op_addr         The address of the loader operation control word.
549  *      opcode          The operation to perform.
550  *
551  *  Returns:
552  *      CSR_RESULT_SUCCESS    on success
553  *      CSR_RESULT_FAILURE    SDIO error or SDIO/XAP timeout
554  * ---------------------------------------------------------------------------
555  */
556
557 /*
558  * Ideally instead of sleeping, we want to busy wait.
559  * Currently there is no framework API to do this. When it becomes available,
560  * we can use it to busy wait using usecs
561  */
562 #define OPERATION_TIMEOUT_LOOPS (100)  /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */
563 #define OPERATION_TIMEOUT_DELAY 1      /* msec, or 200usecs */
564
565 CsrResult unifi_do_loader_op(card_t *card, u32 op_addr, u8 opcode)
566 {
567     CsrResult r;
568     s16 op_retries;
569
570     unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr);
571
572     /* Set the Operation command byte to the opcode */
573     r = unifi_write_8_or_16(card, op_addr, opcode);
574     if (r != CSR_RESULT_SUCCESS)
575     {
576         unifi_error(card->ospriv, "Failed to write loader copy command\n");
577         return r;
578     }
579
580     /* Wait for Operation command byte to be Idle */
581     /* Typically takes ~100us */
582     op_retries = 0;
583     r = CSR_RESULT_SUCCESS;
584     while (1)
585     {
586         u8 op;
587
588         /*
589          * Read the memory location until two successive reads give
590          * the same value.
591          * Then handle it.
592          */
593         r = safe_read_shared_location(card, op_addr, &op);
594         if (r != CSR_RESULT_SUCCESS)
595         {
596             unifi_error(card->ospriv, "Failed to read loader status\n");
597             break;
598         }
599
600         if (op == UNIFI_LOADER_IDLE)
601         {
602             /* Success */
603             break;
604         }
605
606         if (op != opcode)
607         {
608             unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op);
609             r = CSR_RESULT_FAILURE;
610             break;
611         }
612
613         /* Allow 500us timeout */
614         if (++op_retries >= OPERATION_TIMEOUT_LOOPS)
615         {
616             unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n");
617             /* Stop XAPs to aid post-mortem */
618             r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH);
619             if (r != CSR_RESULT_SUCCESS)
620             {
621                 unifi_error(card->ospriv, "Failed to stop UniFi processors\n");
622             }
623             else
624             {
625                 r = CSR_RESULT_FAILURE;
626             }
627             break;
628         }
629         CsrThreadSleep(OPERATION_TIMEOUT_DELAY);
630     } /* Loop exits with r != CSR_RESULT_SUCCESS on error */
631
632     return r;
633 }     /* unifi_do_loader_op() */
634
635
636 /*
637  * ---------------------------------------------------------------------------
638  *  send_ptdl_to_unifi
639  *
640  *      Copy a patch block from userland to the UniFi.
641  *      This function reads data, 2K at a time, from userland and writes
642  *      it to the UniFi.
643  *
644  *  Arguments:
645  *      card            A pointer to the card structure
646  *      dlpriv          The os specific handle for the firmware file
647  *      ptdl            A pointer ot the PTDL block
648  *      handle          The buffer handle to use for the xfer
649  *      op_addr         The address of the loader operation control word
650  *
651  *  Returns:
652  *      Number of bytes sent (Positive) or negative value indicating
653  *      error code:
654  *      CSR_WIFI_HIP_RESULT_NO_MEMORY         memory allocation failed
655  *      CSR_WIFI_HIP_RESULT_INVALID_VALUE         error in XBV file
656  *      CSR_RESULT_FAILURE            SDIO error
657  * ---------------------------------------------------------------------------
658  */
659 static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
660                                     const struct PTDL *ptdl, u32 handle,
661                                     u32 op_addr)
662 {
663     u32 offset;
664     u8 *buf;
665     s32 data_len;
666     u32 write_len;
667     CsrResult r;
668     const u16 buf_size = 2 * 1024;
669
670     offset = ptdl->dl_offset;
671     data_len = ptdl->dl_size;
672
673     if (data_len > buf_size)
674     {
675         unifi_error(card->ospriv, "PTDL block is too large (%u)\n",
676                     ptdl->dl_size);
677         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
678     }
679
680     buf = kmalloc(buf_size, GFP_KERNEL);
681     if (buf == NULL)
682     {
683         unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
684         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
685     }
686
687     r = CSR_RESULT_SUCCESS;
688
689     if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len)
690     {
691         unifi_error(card->ospriv, "Failed to read from file\n");
692     }
693     else
694     {
695         /* We can always round these if the host wants to */
696         if (card->sdio_io_block_pad)
697         {
698             write_len = (data_len + (card->sdio_io_block_size - 1)) &
699                         ~(card->sdio_io_block_size - 1);
700
701             /* Zero out the rest of the buffer (This isn't needed, but it
702              * makes debugging things later much easier). */
703             memset(buf + data_len, 0, write_len - data_len);
704         }
705         else
706         {
707             write_len = data_len;
708         }
709
710         r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE);
711         if (r != CSR_RESULT_SUCCESS)
712         {
713             unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n",
714                         data_len, handle);
715         }
716         else
717         {
718             /*
719              * Can change the order of things to overlap read from file
720              * with copy to unifi
721              */
722             r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH);
723         }
724     }
725
726     kfree(buf);
727
728     if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
729     {
730         unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n",
731                     ptdl->dl_size);
732     }
733
734     return r;
735 } /* send_ptdl_to_unifi() */
736
737
738 /*
739  * ---------------------------------------------------------------------------
740  *  do_patch_download
741  *
742  *      This function downloads a set of patches to UniFi and then
743  *      causes it to restart.
744  *
745  *  Arguments:
746  *      card            Pointer to card struct.
747  *      dlpriv          A context pointer from the calling function to be
748  *                      used when reading the XBV file.  This can be NULL
749  *                      in which case not patches are applied.
750  *      pfwinfo         Pointer to a fwinfo struct describing the f/w
751  *                      XBV file.
752  *      boot_ctrl_addr  The address of the boot loader control structure.
753  *
754  *  Returns:
755  *      0 on success, or an error code
756  *      CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number
757  * ---------------------------------------------------------------------------
758  */
759 static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, u32 boot_ctrl_addr)
760 {
761     CsrResult r;
762     s32 i;
763     u16 loader_version;
764     u16 handle;
765     u32 total_bytes;
766
767     /*
768      * Read info from the SDIO Loader Control Data Structure
769      */
770     /* Check the loader version */
771     r = unifi_card_read16(card, boot_ctrl_addr, &loader_version);
772     if (r != CSR_RESULT_SUCCESS)
773     {
774         unifi_error(card->ospriv, "Patch download: Failed to read loader version\n");
775         return r;
776     }
777     unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version);
778     switch (loader_version)
779     {
780         case 0x0000:
781             break;
782
783         default:
784             unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n",
785                         loader_version);
786             return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
787     }
788
789     /* Retrieve the handle to use with CMD53 */
790     r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle);
791     if (r != CSR_RESULT_SUCCESS)
792     {
793         unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n");
794         return r;
795     }
796
797     /* Set the mask of LEDs to flash */
798     if (card->loader_led_mask)
799     {
800         r = unifi_card_write16(card, boot_ctrl_addr + 2,
801                                (u16)card->loader_led_mask);
802         if (r != CSR_RESULT_SUCCESS)
803         {
804             unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n");
805             return r;
806         }
807     }
808
809     total_bytes = 0;
810
811     /* Copy download data to UniFi memory */
812     for (i = 0; i < pfwinfo->num_ptdl; i++)
813     {
814         unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n",
815                     i,
816                     pfwinfo->ptdl[i].dl_size,
817                     pfwinfo->ptdl[i].dl_offset);
818
819         r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i],
820                                handle, boot_ctrl_addr + 6);
821         if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
822         {
823             return r;
824         }
825         if (r != CSR_RESULT_SUCCESS)
826         {
827             unifi_error(card->ospriv, "Patch failed after %u bytes\n",
828                         total_bytes);
829             return r;
830         }
831         total_bytes += pfwinfo->ptdl[i].dl_size;
832     }
833
834     return CSR_RESULT_SUCCESS;
835 } /* do_patch_download() */
836
837