Root/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
28static CsrResult do_patch_download(card_t *card, void *dlpriv,
29                                   xbv1_t *pfwinfo, u32 boot_ctrl_addr);
30
31static 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 */
53static 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 */
187static 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            return CSR_RESULT_FAILURE;
254        }
255
256        r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
257        if (r != CSR_RESULT_SUCCESS)
258        {
259            unifi_error(card->ospriv, "Failed to wake UniFi\n");
260        }
261
262        /* Get a dlpriv for the patch buffer so that unifi_fw_read() can
263         * access it.
264         */
265        desc = unifi_fw_open_buffer(card->ospriv, pfw, psize);
266        if (!desc)
267        {
268            return CSR_WIFI_HIP_RESULT_NO_MEMORY;
269        }
270
271        /* Download the patch */
272        unifi_info(card->ospriv, "Downloading converted f/w as patch\n");
273        r = unifi_dl_patch(card, desc, sym.obj);
274        kfree(pfw);
275        unifi_fw_close_buffer(card->ospriv, desc);
276
277        if (r != CSR_RESULT_SUCCESS)
278        {
279            unifi_error(card->ospriv, "Converted patch download failed\n");
280            func_exit_r(r);
281            return r;
282        }
283        else
284        {
285            unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n");
286        }
287
288        /* This command starts the firmware */
289        r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART);
290        if (r != CSR_RESULT_SUCCESS)
291        {
292            unifi_error(card->ospriv, "Failed to write loader restart cmd\n");
293        }
294
295        func_exit_r(r);
296        return r;
297    }
298}
299
300
301/*
302 * ---------------------------------------------------------------------------
303 * unifi_dl_firmware
304 *
305 * Download the given firmware image to the UniFi.
306 *
307 * Arguments:
308 * card Pointer to card struct
309 * dlpriv A context pointer from the calling function to be
310 * passed when calling unifi_fw_read().
311 *
312 * Returns:
313 * CSR_RESULT_SUCCESS on success,
314 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
315 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
316 * CSR_RESULT_FAILURE SDIO error
317 *
318 * Notes:
319 * Stops and resets the chip, does the download and runs the new
320 * firmware.
321 * ---------------------------------------------------------------------------
322 */
323CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
324{
325    xbv1_t *fwinfo;
326    CsrResult r;
327
328    func_enter();
329
330    fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
331    if (fwinfo == NULL)
332    {
333        unifi_error(card->ospriv, "Failed to allocate memory for firmware\n");
334        return CSR_WIFI_HIP_RESULT_NO_MEMORY;
335    }
336
337    /*
338     * Scan the firmware file to find the TLVs we are interested in.
339     * These are:
340     * - check we support the file format version in VERF
341     * - SLTP Symbol Lookup Table Pointer
342     * - FWDL firmware download segments
343     * - FWOV firmware overlay segment
344     * - VMEQ Register probe tests to verify matching h/w
345     */
346    r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
347    if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware)
348    {
349        unifi_error(card->ospriv, "File type is %s, expected firmware.\n",
350                    fwinfo->mode == xbv_patch?"patch" : "unknown");
351        kfree(fwinfo);
352        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
353    }
354
355    /* UF6xxx doesn't accept firmware, only patches. Therefore we convert
356     * the file to patch format with version numbers matching the current
357     * running firmware, and then download via the patch mechanism.
358     * The sole purpose of this is to support production test firmware across
359     * different ROM releases, the test firmware being provided in non-patch
360     * format.
361     */
362    if (card->chip_id > SDIO_CARD_ID_UNIFI_2)
363    {
364        unifi_info(card->ospriv, "Must convert f/w to patch format\n");
365        r = do_patch_convert_download(card, dlpriv, fwinfo);
366    }
367    else
368    {
369        /* Older UniFi chips allowed firmware to be directly loaded onto the
370         * chip, which is no longer supported.
371         */
372        unifi_error(card->ospriv, "Only patch downloading supported\n");
373        r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
374    }
375
376    kfree(fwinfo);
377    func_exit_r(r);
378    return r;
379} /* unifi_dl_firmware() */
380
381
382/*
383 * ---------------------------------------------------------------------------
384 * unifi_dl_patch
385 *
386 * Load the given patch set into UniFi.
387 *
388 * Arguments:
389 * card Pointer to card struct
390 * dlpriv The os specific handle to the firmware file.
391 * boot_ctrl The address of the boot loader control structure.
392 *
393 * Returns:
394 * CSR_RESULT_SUCCESS on success,
395 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
396 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
397 * CSR_RESULT_FAILURE SDIO error
398 *
399 * Notes:
400 * This ends up telling UniFi to restart.
401 * ---------------------------------------------------------------------------
402 */
403CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
404{
405    xbv1_t *fwinfo;
406    CsrResult r;
407
408    func_enter();
409
410    unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl);
411
412    fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
413    if (fwinfo == NULL)
414    {
415        unifi_error(card->ospriv, "Failed to allocate memory for patches\n");
416        func_exit();
417        return CSR_WIFI_HIP_RESULT_NO_MEMORY;
418    }
419
420    /*
421     * Scan the firmware file to find the TLVs we are interested in.
422     * These are:
423     * - check we support the file format version in VERF
424     * - FWID The build ID of the ROM that we can patch
425     * - PTDL patch download segments
426     */
427    r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
428    if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch)
429    {
430        kfree(fwinfo);
431        unifi_error(card->ospriv, "Failed to read in patch file\n");
432        func_exit();
433        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
434    }
435
436    /*
437     * We have to check the build id read from the SLUT against that
438     * for the patch file. They have to match exactly.
439     * "card->build_id" == XBV1.PTCH.FWID
440     */
441    if (card->build_id != fwinfo->build_id)
442    {
443        unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n",
444                    card->build_id, fwinfo->build_id);
445        kfree(fwinfo);
446#ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
447        func_exit();
448        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
449#else
450        fwinfo = NULL;
451        dlpriv = NULL;
452        return CSR_RESULT_SUCCESS;
453#endif
454    }
455
456    r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl);
457    if (r != CSR_RESULT_SUCCESS)
458    {
459        unifi_error(card->ospriv, "Failed to patch image\n");
460    }
461
462    kfree(fwinfo);
463
464    func_exit_r(r);
465    return r;
466} /* unifi_dl_patch() */
467
468
469void* unifi_dl_fw_read_start(card_t *card, s8 is_fw)
470{
471    card_info_t card_info;
472
473    unifi_card_info(card, &card_info);
474    unifi_trace(card->ospriv, UDBG5,
475                "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n",
476                card_info.chip_id, card_info.chip_version,
477                card_info.fw_build, card_info.fw_hip_version,
478                card_info.sdio_block_size);
479
480    return unifi_fw_read_start(card->ospriv, is_fw, &card_info);
481}
482
483
484/*
485 * ---------------------------------------------------------------------------
486 * safe_read_shared_location
487 *
488 * Read a shared memory location repeatedly until we get two readings
489 * the same.
490 *
491 * Arguments:
492 * card Pointer to card context struct.
493 * unifi_addr UniFi shared-data-memory address to access.
494 * pdata Pointer to a byte variable for the value read.
495 *
496 *
497 * Returns:
498 * CSR_RESULT_SUCCESS on success, CSR error code on failure
499 * ---------------------------------------------------------------------------
500 */
501static CsrResult safe_read_shared_location(card_t *card, u32 address, u8 *pdata)
502{
503    CsrResult r;
504    u16 limit = 1000;
505    u8 b, b2;
506
507    *pdata = 0;
508
509    r = unifi_read_8_or_16(card, address, &b);
510    if (r != CSR_RESULT_SUCCESS)
511    {
512        return r;
513    }
514
515    while (limit--)
516    {
517        r = unifi_read_8_or_16(card, address, &b2);
518        if (r != CSR_RESULT_SUCCESS)
519        {
520            return r;
521        }
522
523        /* When we have a stable value, return it */
524        if (b == b2)
525        {
526            *pdata = b;
527            return CSR_RESULT_SUCCESS;
528        }
529
530        b = b2;
531    }
532
533    return CSR_RESULT_FAILURE;
534} /* safe_read_shared_location() */
535
536
537/*
538 * ---------------------------------------------------------------------------
539 * unifi_do_loader_op
540 *
541 * Send a loader / boot_loader command to the UniFi and wait for
542 * it to complete.
543 *
544 * Arguments:
545 * card Pointer to card context struct.
546 * op_addr The address of the loader operation control word.
547 * opcode The operation to perform.
548 *
549 * Returns:
550 * CSR_RESULT_SUCCESS on success
551 * CSR_RESULT_FAILURE SDIO error or SDIO/XAP timeout
552 * ---------------------------------------------------------------------------
553 */
554
555/*
556 * Ideally instead of sleeping, we want to busy wait.
557 * Currently there is no framework API to do this. When it becomes available,
558 * we can use it to busy wait using usecs
559 */
560#define OPERATION_TIMEOUT_LOOPS (100) /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */
561#define OPERATION_TIMEOUT_DELAY 1 /* msec, or 200usecs */
562
563CsrResult unifi_do_loader_op(card_t *card, u32 op_addr, u8 opcode)
564{
565    CsrResult r;
566    s16 op_retries;
567
568    unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr);
569
570    /* Set the Operation command byte to the opcode */
571    r = unifi_write_8_or_16(card, op_addr, opcode);
572    if (r != CSR_RESULT_SUCCESS)
573    {
574        unifi_error(card->ospriv, "Failed to write loader copy command\n");
575        return r;
576    }
577
578    /* Wait for Operation command byte to be Idle */
579    /* Typically takes ~100us */
580    op_retries = 0;
581    r = CSR_RESULT_SUCCESS;
582    while (1)
583    {
584        u8 op;
585
586        /*
587         * Read the memory location until two successive reads give
588         * the same value.
589         * Then handle it.
590         */
591        r = safe_read_shared_location(card, op_addr, &op);
592        if (r != CSR_RESULT_SUCCESS)
593        {
594            unifi_error(card->ospriv, "Failed to read loader status\n");
595            break;
596        }
597
598        if (op == UNIFI_LOADER_IDLE)
599        {
600            /* Success */
601            break;
602        }
603
604        if (op != opcode)
605        {
606            unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op);
607            r = CSR_RESULT_FAILURE;
608            break;
609        }
610
611        /* Allow 500us timeout */
612        if (++op_retries >= OPERATION_TIMEOUT_LOOPS)
613        {
614            unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n");
615            /* Stop XAPs to aid post-mortem */
616            r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH);
617            if (r != CSR_RESULT_SUCCESS)
618            {
619                unifi_error(card->ospriv, "Failed to stop UniFi processors\n");
620            }
621            else
622            {
623                r = CSR_RESULT_FAILURE;
624            }
625            break;
626        }
627        CsrThreadSleep(OPERATION_TIMEOUT_DELAY);
628    } /* Loop exits with r != CSR_RESULT_SUCCESS on error */
629
630    return r;
631} /* unifi_do_loader_op() */
632
633
634/*
635 * ---------------------------------------------------------------------------
636 * send_ptdl_to_unifi
637 *
638 * Copy a patch block from userland to the UniFi.
639 * This function reads data, 2K at a time, from userland and writes
640 * it to the UniFi.
641 *
642 * Arguments:
643 * card A pointer to the card structure
644 * dlpriv The os specific handle for the firmware file
645 * ptdl A pointer ot the PTDL block
646 * handle The buffer handle to use for the xfer
647 * op_addr The address of the loader operation control word
648 *
649 * Returns:
650 * Number of bytes sent (Positive) or negative value indicating
651 * error code:
652 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
653 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
654 * CSR_RESULT_FAILURE SDIO error
655 * ---------------------------------------------------------------------------
656 */
657static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
658                                    const struct PTDL *ptdl, u32 handle,
659                                    u32 op_addr)
660{
661    u32 offset;
662    u8 *buf;
663    s32 data_len;
664    u32 write_len;
665    CsrResult r;
666    const u16 buf_size = 2 * 1024;
667
668    offset = ptdl->dl_offset;
669    data_len = ptdl->dl_size;
670
671    if (data_len > buf_size)
672    {
673        unifi_error(card->ospriv, "PTDL block is too large (%u)\n",
674                    ptdl->dl_size);
675        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
676    }
677
678    buf = kmalloc(buf_size, GFP_KERNEL);
679    if (buf == NULL)
680    {
681        unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
682        return CSR_WIFI_HIP_RESULT_NO_MEMORY;
683    }
684
685    r = CSR_RESULT_SUCCESS;
686
687    if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len)
688    {
689        unifi_error(card->ospriv, "Failed to read from file\n");
690    }
691    else
692    {
693        /* We can always round these if the host wants to */
694        if (card->sdio_io_block_pad)
695        {
696            write_len = (data_len + (card->sdio_io_block_size - 1)) &
697                        ~(card->sdio_io_block_size - 1);
698
699            /* Zero out the rest of the buffer (This isn't needed, but it
700             * makes debugging things later much easier). */
701            memset(buf + data_len, 0, write_len - data_len);
702        }
703        else
704        {
705            write_len = data_len;
706        }
707
708        r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE);
709        if (r != CSR_RESULT_SUCCESS)
710        {
711            unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n",
712                        data_len, handle);
713        }
714        else
715        {
716            /*
717             * Can change the order of things to overlap read from file
718             * with copy to unifi
719             */
720            r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH);
721        }
722    }
723
724    kfree(buf);
725
726    if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
727    {
728        unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n",
729                    ptdl->dl_size);
730    }
731
732    return r;
733} /* send_ptdl_to_unifi() */
734
735
736/*
737 * ---------------------------------------------------------------------------
738 * do_patch_download
739 *
740 * This function downloads a set of patches to UniFi and then
741 * causes it to restart.
742 *
743 * Arguments:
744 * card Pointer to card struct.
745 * dlpriv A context pointer from the calling function to be
746 * used when reading the XBV file. This can be NULL
747 * in which case not patches are applied.
748 * pfwinfo Pointer to a fwinfo struct describing the f/w
749 * XBV file.
750 * boot_ctrl_addr The address of the boot loader control structure.
751 *
752 * Returns:
753 * 0 on success, or an error code
754 * CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number
755 * ---------------------------------------------------------------------------
756 */
757static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, u32 boot_ctrl_addr)
758{
759    CsrResult r;
760    s32 i;
761    u16 loader_version;
762    u16 handle;
763    u32 total_bytes;
764
765    /*
766     * Read info from the SDIO Loader Control Data Structure
767     */
768    /* Check the loader version */
769    r = unifi_card_read16(card, boot_ctrl_addr, &loader_version);
770    if (r != CSR_RESULT_SUCCESS)
771    {
772        unifi_error(card->ospriv, "Patch download: Failed to read loader version\n");
773        return r;
774    }
775    unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version);
776    switch (loader_version)
777    {
778        case 0x0000:
779            break;
780
781        default:
782            unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n",
783                        loader_version);
784            return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
785    }
786
787    /* Retrieve the handle to use with CMD53 */
788    r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle);
789    if (r != CSR_RESULT_SUCCESS)
790    {
791        unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n");
792        return r;
793    }
794
795    /* Set the mask of LEDs to flash */
796    if (card->loader_led_mask)
797    {
798        r = unifi_card_write16(card, boot_ctrl_addr + 2,
799                               (u16)card->loader_led_mask);
800        if (r != CSR_RESULT_SUCCESS)
801        {
802            unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n");
803            return r;
804        }
805    }
806
807    total_bytes = 0;
808
809    /* Copy download data to UniFi memory */
810    for (i = 0; i < pfwinfo->num_ptdl; i++)
811    {
812        unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n",
813                    i,
814                    pfwinfo->ptdl[i].dl_size,
815                    pfwinfo->ptdl[i].dl_offset);
816
817        r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i],
818                               handle, boot_ctrl_addr + 6);
819        if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
820        {
821            return r;
822        }
823        if (r != CSR_RESULT_SUCCESS)
824        {
825            unifi_error(card->ospriv, "Patch failed after %u bytes\n",
826                        total_bytes);
827            return r;
828        }
829        total_bytes += pfwinfo->ptdl[i].dl_size;
830    }
831
832    return CSR_RESULT_SUCCESS;
833} /* do_patch_download() */
834
835
836

Archive Download this file



interactive