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