Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b6fa586 authored by Larry Finger's avatar Larry Finger Committed by John W. Linville
Browse files

b43: Load firmware from a work queue and not from the probe routine



Recent changes in udev are causing problems for drivers that load firmware
from the probe routine. As b43 has such a structure, it must be changed.
As this driver loads more than 1 firmware file, changing to the asynchronous routine
request_firmware_nowait() would be complicated. In this implementation, the probe
routine starts a queue that calls the firmware loading routines.

Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a3ea2c76
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -932,6 +932,9 @@ struct b43_wl {
	/* Flag that implement the queues stopping. */
	/* Flag that implement the queues stopping. */
	bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
	bool tx_queue_stopped[B43_QOS_QUEUE_NUM];


	/* firmware loading work */
	struct work_struct firmware_load;

	/* The device LEDs. */
	/* The device LEDs. */
	struct b43_leds leds;
	struct b43_leds leds;


+32 −27
Original line number Original line Diff line number Diff line
@@ -2390,8 +2390,14 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
	return err;
	return err;
}
}


static int b43_request_firmware(struct b43_wldev *dev)
static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
static void b43_one_core_detach(struct b43_bus_dev *dev);

static void b43_request_firmware(struct work_struct *work)
{
{
	struct b43_wl *wl = container_of(work,
			    struct b43_wl, firmware_load);
	struct b43_wldev *dev = wl->current_dev;
	struct b43_request_fw_context *ctx;
	struct b43_request_fw_context *ctx;
	unsigned int i;
	unsigned int i;
	int err;
	int err;
@@ -2399,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev)


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


	ctx->req_type = B43_FWTYPE_PROPRIETARY;
	ctx->req_type = B43_FWTYPE_PROPRIETARY;
	err = b43_try_request_fw(ctx);
	err = b43_try_request_fw(ctx);
	if (!err)
	if (!err)
		goto out; /* Successfully loaded it. */
		goto start_ieee80211; /* Successfully loaded it. */
	err = ctx->fatal_failure;
	/* Was fw version known? */
	if (err)
	if (ctx->fatal_failure)
		goto out;
		goto out;


	/* proprietary fw not found, try open source */
	ctx->req_type = B43_FWTYPE_OPENSOURCE;
	ctx->req_type = B43_FWTYPE_OPENSOURCE;
	err = b43_try_request_fw(ctx);
	err = b43_try_request_fw(ctx);
	if (!err)
	if (!err)
		goto out; /* Successfully loaded it. */
		goto start_ieee80211; /* Successfully loaded it. */
	err = ctx->fatal_failure;
	if(ctx->fatal_failure)
	if (err)
		goto out;
		goto out;


	/* Could not find a usable firmware. Print the errors. */
	/* Could not find a usable firmware. Print the errors. */
@@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev)
			b43err(dev->wl, errmsg);
			b43err(dev->wl, errmsg);
	}
	}
	b43_print_fw_helptext(dev->wl, 1);
	b43_print_fw_helptext(dev->wl, 1);
	err = -ENOENT;
	goto out;

start_ieee80211:
	err = ieee80211_register_hw(wl->hw);
	if (err)
		goto err_one_core_detach;
	b43_leds_register(wl->current_dev);
	goto out;

err_one_core_detach:
	b43_one_core_detach(dev->dev);


out:
out:
	kfree(ctx);
	kfree(ctx);
	return err;
}
}


static int b43_upload_microcode(struct b43_wldev *dev)
static int b43_upload_microcode(struct b43_wldev *dev)
@@ -3023,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev)
	macctl |= B43_MACCTL_INFRA;
	macctl |= B43_MACCTL_INFRA;
	b43_write32(dev, B43_MMIO_MACCTL, macctl);
	b43_write32(dev, B43_MMIO_MACCTL, macctl);


	err = b43_request_firmware(dev);
	if (err)
		goto out;
	err = b43_upload_microcode(dev);
	err = b43_upload_microcode(dev);
	if (err)
	if (err)
		goto out;	/* firmware is released later */
		goto out;	/* firmware is released later */
@@ -4155,6 +4167,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
	mutex_unlock(&wl->mutex);
	mutex_unlock(&wl->mutex);
	cancel_delayed_work_sync(&dev->periodic_work);
	cancel_delayed_work_sync(&dev->periodic_work);
	cancel_work_sync(&wl->tx_work);
	cancel_work_sync(&wl->tx_work);
	cancel_work_sync(&wl->firmware_load);
	mutex_lock(&wl->mutex);
	mutex_lock(&wl->mutex);
	dev = wl->current_dev;
	dev = wl->current_dev;
	if (!dev || b43_status(dev) < B43_STAT_STARTED) {
	if (!dev || b43_status(dev) < B43_STAT_STARTED) {
@@ -5314,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core)
	if (err)
	if (err)
		goto bcma_err_wireless_exit;
		goto bcma_err_wireless_exit;


	err = ieee80211_register_hw(wl->hw);
	/* setup and start work to load firmware */
	if (err)
	INIT_WORK(&wl->firmware_load, b43_request_firmware);
		goto bcma_err_one_core_detach;
	schedule_work(&wl->firmware_load);
	b43_leds_register(wl->current_dev);


bcma_out:
bcma_out:
	return err;
	return err;


bcma_err_one_core_detach:
	b43_one_core_detach(dev);
bcma_err_wireless_exit:
bcma_err_wireless_exit:
	ieee80211_free_hw(wl->hw);
	ieee80211_free_hw(wl->hw);
	return err;
	return err;
@@ -5390,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
	if (err)
	if (err)
		goto err_wireless_exit;
		goto err_wireless_exit;


	if (first) {
	/* setup and start work to load firmware */
		err = ieee80211_register_hw(wl->hw);
	INIT_WORK(&wl->firmware_load, b43_request_firmware);
		if (err)
	schedule_work(&wl->firmware_load);
			goto err_one_core_detach;
		b43_leds_register(wl->current_dev);
	}


      out:
      out:
	return err;
	return err;


      err_one_core_detach:
	b43_one_core_detach(dev);
      err_wireless_exit:
      err_wireless_exit:
	if (first)
	if (first)
		b43_wireless_exit(dev, wl);
		b43_wireless_exit(dev, wl);