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