Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 134239
b: refs/heads/master
c: 1a9f509
h: refs/heads/master
i:
  134237: 194ea03
  134235: ad1ebec
  134231: 06a51ca
  134223: c97f204
  134207: eb4d205
v: v3
  • Loading branch information
Michael Buesch authored and John W. Linville committed Jan 29, 2009
1 parent ebf4d20 commit 13c893d
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2f47690ed42a85820783dee7f16ae47edadf8fad
refs/heads/master: 1a9f509368ceb24fc66be961be15c69966f5eb5d
32 changes: 31 additions & 1 deletion trunk/drivers/net/wireless/b43/b43.h
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,39 @@ struct b43_wl {
struct work_struct txpower_adjust_work;
};

/* The type of the firmware file. */
enum b43_firmware_file_type {
B43_FWTYPE_PROPRIETARY,
B43_FWTYPE_OPENSOURCE,
B43_NR_FWTYPES,
};

/* Context data for fetching firmware. */
struct b43_request_fw_context {
/* The device we are requesting the fw for. */
struct b43_wldev *dev;
/* The type of firmware to request. */
enum b43_firmware_file_type req_type;
/* Error messages for each firmware type. */
char errors[B43_NR_FWTYPES][128];
/* Temporary buffer for storing the firmware name. */
char fwname[64];
/* A fatal error occured while requesting. Firmware reqest
* can not continue, as any other reqest will also fail. */
int fatal_failure;
};

/* In-memory representation of a cached microcode file. */
struct b43_firmware_file {
const char *filename;
const struct firmware *data;
/* Type of the firmware file name. Note that this does only indicate
* the type by the firmware name. NOT the file contents.
* If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource
* instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware
* binary code, not just the filename.
*/
enum b43_firmware_file_type type;
};

/* Pointers to the firmware data and meta information about it. */
Expand All @@ -677,7 +706,8 @@ struct b43_firmware {
/* Firmware patchlevel */
u16 patch;

/* Set to true, if we are using an opensource firmware. */
/* Set to true, if we are using an opensource firmware.
* Use this to check for proprietary vs opensource. */
bool opensource;
/* Set to true, if the core needs a PCM firmware, but
* we failed to load one. This is always false for
Expand Down
154 changes: 111 additions & 43 deletions trunk/drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,7 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
return ret;
}

static void do_release_fw(struct b43_firmware_file *fw)
void b43_do_release_fw(struct b43_firmware_file *fw)
{
release_firmware(fw->data);
fw->data = NULL;
Expand All @@ -1943,10 +1943,10 @@ static void do_release_fw(struct b43_firmware_file *fw)

static void b43_release_firmware(struct b43_wldev *dev)
{
do_release_fw(&dev->fw.ucode);
do_release_fw(&dev->fw.pcm);
do_release_fw(&dev->fw.initvals);
do_release_fw(&dev->fw.initvals_band);
b43_do_release_fw(&dev->fw.ucode);
b43_do_release_fw(&dev->fw.pcm);
b43_do_release_fw(&dev->fw.initvals);
b43_do_release_fw(&dev->fw.initvals_band);
}

static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
Expand All @@ -1963,42 +1963,60 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
b43warn(wl, text);
}

static int do_request_fw(struct b43_wldev *dev,
const char *name,
struct b43_firmware_file *fw,
bool silent)
int b43_do_request_fw(struct b43_request_fw_context *ctx,
const char *name,
struct b43_firmware_file *fw)
{
char path[sizeof(modparam_fwpostfix) + 32];
const struct firmware *blob;
struct b43_fw_header *hdr;
u32 size;
int err;

if (!name) {
/* Don't fetch anything. Free possibly cached firmware. */
do_release_fw(fw);
/* FIXME: We should probably keep it anyway, to save some headache
* on suspend/resume with multiband devices. */
b43_do_release_fw(fw);
return 0;
}
if (fw->filename) {
if (strcmp(fw->filename, name) == 0)
if ((fw->type == ctx->req_type) &&
(strcmp(fw->filename, name) == 0))
return 0; /* Already have this fw. */
/* Free the cached firmware first. */
do_release_fw(fw);
/* FIXME: We should probably do this later after we successfully
* got the new fw. This could reduce headache with multiband devices.
* We could also redesign this to cache the firmware for all possible
* bands all the time. */
b43_do_release_fw(fw);
}

switch (ctx->req_type) {
case B43_FWTYPE_PROPRIETARY:
snprintf(ctx->fwname, sizeof(ctx->fwname),
"b43%s/%s.fw",
modparam_fwpostfix, name);
break;
case B43_FWTYPE_OPENSOURCE:
snprintf(ctx->fwname, sizeof(ctx->fwname),
"b43-open%s/%s.fw",
modparam_fwpostfix, name);
break;
default:
B43_WARN_ON(1);
return -ENOSYS;
}

snprintf(path, ARRAY_SIZE(path),
"b43%s/%s.fw",
modparam_fwpostfix, name);
err = request_firmware(&blob, path, dev->dev->dev);
err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
if (err == -ENOENT) {
if (!silent) {
b43err(dev->wl, "Firmware file \"%s\" not found\n",
path);
}
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
"Firmware file \"%s\" not found\n", ctx->fwname);
return err;
} else if (err) {
b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n",
path, err);
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
"Firmware file \"%s\" request failed (err=%d)\n",
ctx->fwname, err);
return err;
}
if (blob->size < sizeof(struct b43_fw_header))
Expand All @@ -2021,20 +2039,24 @@ static int do_request_fw(struct b43_wldev *dev,

fw->data = blob;
fw->filename = name;
fw->type = ctx->req_type;

return 0;

err_format:
b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
"Firmware file \"%s\" format error.\n", ctx->fwname);
release_firmware(blob);

return -EPROTO;
}

static int b43_request_firmware(struct b43_wldev *dev)
static int b43_try_request_fw(struct b43_request_fw_context *ctx)
{
struct b43_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
struct b43_wldev *dev = ctx->dev;
struct b43_firmware *fw = &ctx->dev->fw;
const u8 rev = ctx->dev->dev->id.revision;
const char *filename;
u32 tmshigh;
int err;
Expand All @@ -2049,7 +2071,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
filename = "ucode13";
else
goto err_no_ucode;
err = do_request_fw(dev, filename, &fw->ucode, 0);
err = b43_do_request_fw(ctx, filename, &fw->ucode);
if (err)
goto err_load;

Expand All @@ -2061,7 +2083,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
else
goto err_no_pcm;
fw->pcm_request_failed = 0;
err = do_request_fw(dev, filename, &fw->pcm, 1);
err = b43_do_request_fw(ctx, filename, &fw->pcm);
if (err == -ENOENT) {
/* We did not find a PCM file? Not fatal, but
* core rev <= 10 must do without hwcrypto then. */
Expand Down Expand Up @@ -2097,7 +2119,7 @@ static int b43_request_firmware(struct b43_wldev *dev)
default:
goto err_no_initvals;
}
err = do_request_fw(dev, filename, &fw->initvals, 0);
err = b43_do_request_fw(ctx, filename, &fw->initvals);
if (err)
goto err_load;

Expand Down Expand Up @@ -2131,37 +2153,83 @@ static int b43_request_firmware(struct b43_wldev *dev)
default:
goto err_no_initvals;
}
err = do_request_fw(dev, filename, &fw->initvals_band, 0);
err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
if (err)
goto err_load;

return 0;

err_load:
b43_print_fw_helptext(dev->wl, 1);
goto error;

err_no_ucode:
err = -ENODEV;
b43err(dev->wl, "No microcode available for core rev %u\n", rev);
err = ctx->fatal_failure = -EOPNOTSUPP;
b43err(dev->wl, "The driver does not know which firmware (ucode) "
"is required for your device (wl-core rev %u)\n", rev);
goto error;

err_no_pcm:
err = -ENODEV;
b43err(dev->wl, "No PCM available for core rev %u\n", rev);
err = ctx->fatal_failure = -EOPNOTSUPP;
b43err(dev->wl, "The driver does not know which firmware (PCM) "
"is required for your device (wl-core rev %u)\n", rev);
goto error;

err_no_initvals:
err = -ENODEV;
b43err(dev->wl, "No Initial Values firmware file for PHY %u, "
"core rev %u\n", dev->phy.type, rev);
err = ctx->fatal_failure = -EOPNOTSUPP;
b43err(dev->wl, "The driver does not know which firmware (initvals) "
"is required for your device (wl-core rev %u)\n", rev);
goto error;

err_load:
/* We failed to load this firmware image. The error message
* already is in ctx->errors. Return and let our caller decide
* what to do. */
goto error;

error:
b43_release_firmware(dev);
return err;
}

static int b43_request_firmware(struct b43_wldev *dev)
{
struct b43_request_fw_context *ctx;
unsigned int i;
int err;
const char *errmsg;

ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->dev = dev;

ctx->req_type = B43_FWTYPE_PROPRIETARY;
err = b43_try_request_fw(ctx);
if (!err)
goto out; /* Successfully loaded it. */
err = ctx->fatal_failure;
if (err)
goto out;

ctx->req_type = B43_FWTYPE_OPENSOURCE;
err = b43_try_request_fw(ctx);
if (!err)
goto out; /* Successfully loaded it. */
err = ctx->fatal_failure;
if (err)
goto out;

/* Could not find a usable firmware. Print the errors. */
for (i = 0; i < B43_NR_FWTYPES; i++) {
errmsg = ctx->errors[i];
if (strlen(errmsg))
b43err(dev->wl, errmsg);
}
b43_print_fw_helptext(dev->wl, 1);
err = -ENOENT;

out:
kfree(ctx);
return err;
}

static int b43_upload_microcode(struct b43_wldev *dev)
{
const size_t hdr_len = sizeof(struct b43_fw_header);
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/net/wireless/b43/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,11 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
void b43_mac_suspend(struct b43_wldev *dev);
void b43_mac_enable(struct b43_wldev *dev);


struct b43_request_fw_context;
int b43_do_request_fw(struct b43_request_fw_context *ctx,
const char *name,
struct b43_firmware_file *fw);
void b43_do_release_fw(struct b43_firmware_file *fw);

#endif /* B43_MAIN_H_ */

0 comments on commit 13c893d

Please sign in to comment.