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

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

b43legacy: Load firmware from work queue instead of from probe routine



Recent changes in udev are causing problems for drivers that load firmware
from the probe routine. As b43legacy has such a structure, it must be changed.
As this driver loads 3 or 4 firmware files, changing to the asynchronous routine
request_firmware_nowait() would be complicated. In this implementation, the probe
routine starts a work 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 843dc664
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -581,6 +581,9 @@ struct b43legacy_wl {
	struct mutex mutex;		/* locks wireless core state */
	struct mutex mutex;		/* locks wireless core state */
	spinlock_t leds_lock;		/* lock for leds */
	spinlock_t leds_lock;		/* lock for leds */


	/* firmware loading work */
	struct work_struct firmware_load;

	/* We can only have one operating interface (802.11 core)
	/* We can only have one operating interface (802.11 core)
	 * at a time. General information about this interface follows.
	 * at a time. General information about this interface follows.
	 */
	 */
+20 −13
Original line number Original line Diff line number Diff line
@@ -1557,8 +1557,15 @@ static int do_request_fw(struct b43legacy_wldev *dev,
	return -EPROTO;
	return -EPROTO;
}
}


static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
static int b43legacy_one_core_attach(struct ssb_device *dev,
				     struct b43legacy_wl *wl);
static void b43legacy_one_core_detach(struct ssb_device *dev);

static void b43legacy_request_firmware(struct work_struct *work)
{
{
	struct b43legacy_wl *wl = container_of(work,
				  struct b43legacy_wl, firmware_load);
	struct b43legacy_wldev *dev = wl->current_dev;
	struct b43legacy_firmware *fw = &dev->fw;
	struct b43legacy_firmware *fw = &dev->fw;
	const u8 rev = dev->dev->id.revision;
	const u8 rev = dev->dev->id.revision;
	const char *filename;
	const char *filename;
@@ -1624,8 +1631,14 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
		if (err)
		if (err)
			goto err_load;
			goto err_load;
	}
	}
	err = ieee80211_register_hw(wl->hw);
	if (err)
		goto err_one_core_detach;
	return;


	return 0;
err_one_core_detach:
	b43legacy_one_core_detach(dev->dev);
	goto error;


err_load:
err_load:
	b43legacy_print_fw_helptext(dev->wl);
	b43legacy_print_fw_helptext(dev->wl);
@@ -1639,7 +1652,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)


error:
error:
	b43legacy_release_firmware(dev);
	b43legacy_release_firmware(dev);
	return err;
	return;
}
}


static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
@@ -2153,9 +2166,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
	macctl |= B43legacy_MACCTL_INFRA;
	macctl |= B43legacy_MACCTL_INFRA;
	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);


	err = b43legacy_request_firmware(dev);
	if (err)
		goto out;
	err = b43legacy_upload_microcode(dev);
	err = b43legacy_upload_microcode(dev);
	if (err)
	if (err)
		goto out; /* firmware is released later */
		goto out; /* firmware is released later */
@@ -3860,17 +3870,13 @@ static int b43legacy_probe(struct ssb_device *dev,
	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, b43legacy_request_firmware);
		if (err)
	schedule_work(&wl->firmware_load);
			goto err_one_core_detach;
	}


out:
out:
	return err;
	return err;


err_one_core_detach:
	b43legacy_one_core_detach(dev);
err_wireless_exit:
err_wireless_exit:
	if (first)
	if (first)
		b43legacy_wireless_exit(dev, wl);
		b43legacy_wireless_exit(dev, wl);
@@ -3885,6 +3891,7 @@ static void b43legacy_remove(struct ssb_device *dev)
	/* We must cancel any work here before unregistering from ieee80211,
	/* We must cancel any work here before unregistering from ieee80211,
	 * as the ieee80211 unreg will destroy the workqueue. */
	 * as the ieee80211 unreg will destroy the workqueue. */
	cancel_work_sync(&wldev->restart_work);
	cancel_work_sync(&wldev->restart_work);
	cancel_work_sync(&wl->firmware_load);


	B43legacy_WARN_ON(!wl);
	B43legacy_WARN_ON(!wl);
	if (wl->current_dev == wldev)
	if (wl->current_dev == wldev)