AT91 SDIO WiFi no working

Ludovic Desroches ludovic.desroches at atmel.com
Tue Jul 19 10:30:48 EDT 2011


Hello all.

On 7/13/2011 8:27 PM, Paulo Fragoso wrote:
> Hi,
>
> We are trying to run SDIO WiFI with a board based on AT91sam9 and our 
> configuration and firmware files are apparently ok but now we have got 
> this erro:
>
> root at buildroot:~# modprobe libertas
> root at buildroot:~# modprobe libertas_sdio.ko 
> helper_name=/lib/firmware/sd8686_v8_
> helper.bin fw_name=/lib/firmware/sd8686_v8.bin
> libertas_sdio: Libertas SDIO driver
> libertas_sdio: Copyright Pierre Ossman
> libertas: can't load helper firmware
> libertas: failed to load helper firmware
> libertas_sdio: probe of mmc0:0001:1 failed with error -2
>
> udev is running too, what might be happening?
>
> Thanks,
> Paulo.
>
I am also facing some problems using the libertas driver. I am not sure 
that it's the same problem as Paulo because I don't know which kernel 
version he is using. It's probably not the best place to talk about this 
because I don't think the problem is coming from at91 mmc driver, that's 
why I also send this message  to libertas-dev.

I have made my tests with 3.0-rc7 version this what I have (I have added 
some traces) :

    root at at91sam9g20ek:~# insmod libertas.ko libertas_debug=0x5063a7
    [   52.220000] libertas enter: lbs_init_module()
    [   52.220000] libertas leave: lbs_init_module()
    root at at91sam9g20ek:~#
    root at at91sam9g20ek:~#
    root at at91sam9g20ek:~#
    root at at91sam9g20ek:~# insmod libertas_sdio.ko
    helper_name="helper_sd.bin" fw_nam
    e="sd8686.bin"
    [   55.450000] libertas enter: if_sdio_init_module()
    [   55.450000] libertas_sdio: Libertas SDIO driver
    [   55.460000] libertas_sdio: Copyright Pierre Ossman
    [   55.460000] libertas leave: if_sdio_init_module(), ret 0
    root at at91sam9g20ek:~# [   58.020000] mmc1: new SDIO card at address 0001
    [   58.030000] libertas enter: if_sdio_probe()
    [   58.030000] libertas sdio: class = 0x7, vendor = 0x2DF, device =
    0x9103, model = 0xB, ioport = 0x10000
    [   58.040000] libertas enter: if_sdio_prog_firmware()
    [   58.060000] libertas sdio: firmware status = 0x0
    [   58.060000] libertas sdio: scratch ret = 0
    [   58.060000] libertas_sdio mmc1:0001:1: load user helper firmware:
    helper_sd.bin
    [   58.110000] libertas_sdio mmc1:0001:1: helperfw size: 2516
    [   58.120000] libertas_sdio mmc1:0001:1: load user main firmware:
    sd8686.bin
    [   58.170000] libertas_sdio mmc1:0001:1: mainfw size: 2516
    [   58.170000] libertas enter: if_sdio_prog_helper()
    [   58.380000] libertas sdio: waiting for helper to boot...
    [   58.380000] libertas leave: if_sdio_prog_helper(), ret 0
    [   58.390000] libertas sdio: Helper firmware loaded
    [   58.390000] libertas enter: if_sdio_prog_real()
    [   58.400000] libertas sdio: firmware size: 2516
    [   58.400000] libertas sdio: firmware wants 16 bytes
    [   58.410000] libertas sdio: sending 16 bytes (32 bytes) chunk
    [   58.420000] libertas sdio: firmware wants 17 bytes
    [   58.420000] libertas sdio: firmware helper signalled error
    [   58.430000] libertas_sdio: failed to load firmware
    [   58.430000] libertas leave: if_sdio_prog_real(), ret -5
    [   58.440000] libertas leave: if_sdio_prog_firmware(), ret -5
    [   58.450000] libertas leave: if_sdio_probe(), ret -5
    [   58.450000] libertas_sdio: probe of mmc1:0001:1 failed with error -5


The first problem is the main firmware size which is the size of the 
helper firmware.

Now the second problem:

    [1140] msg_queue_insert: seq 540 queued, 'add' 'firmware'
    [1170] run_program: 'firmware.sh'
    [1140] udev_event_run: seq 540 forked, pid [1170], 'add' 'firmware',
    0 seconds old
    [1170] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    helper_sd.bin'
    [1170] run_program: '/lib/udev/firmware.sh' returned with status 0
    [1170] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1170] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1170] run_program: '/lib/udev/firmware.sh'
    [1170] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    helper_sd.bin'
    [1170] run_program: '/lib/udev/firmware.sh' returned with status 0
    [1170] udev_event_run: seq 540 finished with 0
    [1140] msg_queue_insert: seq 541 queued, 'remove' 'firmware'
    [1175] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1175] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1175] udev_event_run: seq 541 finished with 0
    [1140] udev_event_run: seq 541 forked, pid [1175], 'remove'
    'firmware', 0 seconds old
    [1140] msg_queue_insert: seq 542 queued, 'add' 'firmware'
    [1140] udev_event_run: seq 542 forked, pid [1176], 'add' 'firmware',
    0 seconds old
    [1176] run_program: 'firmware.sh'
    [1176] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    sd8686.bin'
    [1176] run_program: '/lib/udev/firmware.sh' (stderr) 'udev firmware
    loader misses sysfs directory'
    [1176] run_program: '/lib/udev/firmware.sh' returned with status 1
    [1176] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1176] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1176] run_program: '/lib/udev/firmware.sh'
    [1176] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    sd8686.bin'
    [1176] run_program: '/lib/udev/firmware.sh' (stderr) 'udev firmware
    loader misses sysfs directory'
    [1176] run_program: '/lib/udev/firmware.sh' returned with status 1
    [1176] udev_event_run: seq 542 finished with -1


I don't understand why I have two to firmware.sh for helper_sd.bin and 
also for sd8686.bin. The second part I don't understand is why the sysfs 
entries for the firmware have been removed between the two uevent.


The function dealing with firmwares is lbs_get_firmware where we have 
two successive request_firmware calls. I am confused about the behavior 
but I had the feeling that the two successive request_firmware calls was 
the problem because the main firmware size is those of the helper 
firmware. That's why I did this:

    commit 53ad5481c1d659da920e950f47ae25cbfc288239
    Author: Ludovic Desroches <ludovic.desroches at atmel.com>
    Date:   Tue Jul 19 15:52:26 2011 +0200

         libertas: separate helper and main firmware request

         Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>

    diff --git a/drivers/net/wireless/libertas/if_sdio.c
    b/drivers/net/wireless/libertas/if_sdio.c
    index 224e985..01e530c 100644
    --- a/drivers/net/wireless/libertas/if_sdio.c
    +++ b/drivers/net/wireless/libertas/if_sdio.c
    @@ -723,7 +723,7 @@ static int if_sdio_prog_firmware(struct
    if_sdio_card *card)
          }

          ret = lbs_get_firmware(&card->func->dev, lbs_helper_name,
    lbs_fw_name,
    -                card->model, &fw_table[0], &helper, &mainfw);
    +                card->model, &fw_table[0], &helper, NULL);
          if (ret) {
              pr_err("failed to find firmware (%d)\n", ret);
              goto out;
    @@ -735,6 +735,10 @@ static int if_sdio_prog_firmware(struct
    if_sdio_card *card)

          lbs_deb_sdio("Helper firmware loaded\n");

    +    ret = lbs_get_firmware(&card->func->dev, lbs_helper_name,
    lbs_fw_name,
    +                card->model, &fw_table[0], NULL, &mainfw);
    +
    +
          ret = if_sdio_prog_real(card, mainfw);
          if (ret)
              goto out;
    diff --git a/drivers/net/wireless/libertas/main.c
    b/drivers/net/wireless/libertas/main.c
    index 8c40949..b35ca07 100644
    --- a/drivers/net/wireless/libertas/main.c
    +++ b/drivers/net/wireless/libertas/main.c
    @@ -1075,11 +1075,9 @@ int lbs_get_firmware(struct device *dev,
    const char *user_helper,
          const struct lbs_fw_table *iter;
          int ret;

    -    BUG_ON(helper == NULL);
    -    BUG_ON(mainfw == NULL);
    -
          /* Try user-specified firmware first */
    -    if (user_helper) {
    +    if (user_helper && helper) {
    +        dev_info(dev, "load user helper firmware: %s\n", user_helper);
              ret = request_firmware(helper, user_helper, dev);
              if (ret) {
                  dev_err(dev, "couldn't find helper firmware %s\n",
    @@ -1087,7 +1085,8 @@ int lbs_get_firmware(struct device *dev, const
    char *user_helper,
                  goto fail;
              }
          }
    -    if (user_mainfw) {
    +    if (user_mainfw && mainfw) {
    +        dev_info(dev, "load user main firmware: %s\n", user_mainfw);
              ret = request_firmware(mainfw, user_mainfw, dev);
              if (ret) {
                  dev_err(dev, "couldn't find main firmware %s\n",
    @@ -1096,8 +1095,7 @@ int lbs_get_firmware(struct device *dev, const
    char *user_helper,
              }
          }

    -    if (*helper && *mainfw)
    -        return 0;
    +    return 0;

          /* Otherwise search for firmware to use.  If neither the helper or
           * the main firmware were specified by the user, then we need to



Everything is ok with my patch but I would like to understand what 
happens, why I need this patch and if it is correct or just a lucky 
horrible hack ! Here the udev logs seems more logical even if I still 
have two requests for each firmware. The first call is ok but the second 
fails because of missing sysfs entries.

    [1113] msg_queue_insert: seq 524 queued, 'add' 'firmware'
    [1113] udev_event_run: seq 524 forked, pid [1125], 'add' 'firmware',
    0 seconds old
    [1125] run_program: 'firmware.sh'
    [1125] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    helper_sd.bin'
    [1125] run_program: '/lib/udev/firmware.sh' returned with status 0
    [1125] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1125] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1125] run_program: '/lib/udev/firmware.sh'
    [1125] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    helper_sd.bin'
    [1125] run_program: '/lib/udev/firmware.sh' (stderr) 'udev firmware
    loader misses sysfs directory'
    [1125] run_program: '/lib/udev/firmware.sh' returned with status 1
    [1125] udev_event_run: seq 524 finished with -1
    [1113] msg_queue_insert: seq 525 queued, 'remove' 'firmware'
    [1113] udev_event_run: seq 525 forked, pid [1130], 'remove'
    'firmware', 0 seconds old
    [1130] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1130] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1130] udev_event_run: seq 525 finished with 0
    [   95.140000] libertas_sdio mmc1:0001:1: load user main firmware:
    sd8686.bin
    [1113] msg_queue_insert: seq 526 queued, 'add' 'firmware'
    [1113] udev_event_run: seq 526 forked, pid [1131], 'add' 'firmware',
    0 seconds old
    [1131] run_program: 'firmware.sh'
    [1131] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    sd8686.bin'
    [1131] run_program: '/lib/udev/firmware.sh' returned with status 0
    [1131] pass_env_to_socket: passed -1 bytes to socket
    '@/org/kernel/udev/monitor',
    [1131] pass_env_to_socket: passed -1 bytes to socket
    '/org/kernel/udev/monitor',
    [1131] run_program: '/lib/udev/firmware.sh'
    [1131] run_program: '/lib/udev/firmware.sh' (stdout) 'firmware:
    sd8686.bin'
    [1131] run_program: '/lib/udev/firmware.sh' (stderr) 'udev firmware
    loader misses sysfs directory'
    [1131] run_program: '/lib/udev/firmware.sh' returned with status 1
    [1131] udev_event_run: seq 526 finished with -1


Thanks for you help.

Regards,

Ludovic





More information about the linux-arm-kernel mailing list