1
0
mirror of https://git.yoctoproject.org/meta-ti synced 2026-06-07 03:11:59 +00:00

linux-mainline: Add patches to enable libertas firmware loading asynchronously

When using udev >=177 libertas driver does not load properly the firmware [1].
The patches 0001-0016 were taken from [2] and can be viewed at [3]. Patch 0017
I created to fix compiler complaining for missing symbol is_interrupt when
DEBUG set.
The patch series was tested with meta-gumstix on overo with udev-175 and
udev-182.

[1] http://www.spinics.net/lists/linux-wireless/msg85541.html
[2] git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git
[3] http://git.kernel.org/?p=linux/kernel/git/linville/wireless-next.git;a=history;f=drivers/net/wireless/libertas;hb=HEAD

Signed-off-by: Andreas Müller <schnitzeltony@googlemail.com>
Signed-off-by: Denys Dmytriyenko <denys@ti.com>
This commit is contained in:
Andreas Müller
2012-05-25 11:11:57 +02:00
committed by Denys Dmytriyenko
parent a7426c1dad
commit 275240af94
17 changed files with 2165 additions and 2 deletions
@@ -0,0 +1,80 @@
From d632eb1bf22e11def74e4e53cc47d790fbdba105 Mon Sep 17 00:00:00 2001
From: Greg Kroah-Hartman <gregkh@suse.de>
Date: Fri, 18 Nov 2011 09:44:20 -0800
Subject: [PATCH 01/17] USB: convert drivers/net/* to use module_usb_driver()
This converts the drivers in drivers/net/* to use the
module_usb_driver() macro which makes the code smaller and a bit
simpler.
Added bonus is that it removes some unneeded kernel log messages about
drivers loading and/or unloading.
Cc: Wolfgang Grandegger <wg@grandegger.com>
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: Oliver Neukum <oliver@neukum.name>
Cc: Peter Korsgaard <jacmet@sunsite.dk>
Cc: Petko Manolov <petkan@users.sourceforge.net>
Cc: Steve Glendinning <steve.glendinning@smsc.com>
Cc: Christian Lamparter <chunkeey@googlemail.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Dan Williams <dcbw@redhat.com>
Cc: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Cc: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Gertjan van Wingerde <gwingerde@gmail.com>
Cc: Helmut Schaa <helmut.schaa@googlemail.com>
Cc: Herton Ronaldo Krzesinski <herton@canonical.com>
Cc: Hin-Tak Leung <htl10@users.sourceforge.net>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Chaoming Li <chaoming_li@realsil.com.cn>
Cc: Lucas De Marchi <lucas.demarchi@profusion.mobi>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Roel Kluin <roel.kluin@gmail.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Jiri Pirko <jpirko@redhat.com>
Cc: Pavel Roskin <proski@gnu.org>
Cc: Yoann DI-RUZZA <y.diruzza@lim.eu>
Cc: George <george0505@realtek.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/net/wireless/libertas/if_usb.c | 24 +-----------------------
1 files changed, 1 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index db879c3..b5fbbc7 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -1184,29 +1184,7 @@ static struct usb_driver if_usb_driver = {
.reset_resume = if_usb_resume,
};
-static int __init if_usb_init_module(void)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- ret = usb_register(&if_usb_driver);
-
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-
-static void __exit if_usb_exit_module(void)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
-
- usb_deregister(&if_usb_driver);
-
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-module_init(if_usb_init_module);
-module_exit(if_usb_exit_module);
+module_usb_driver(if_usb_driver);
MODULE_DESCRIPTION("8388 USB WLAN Driver");
MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc.");
--
1.7.4.4
@@ -0,0 +1,55 @@
From 3db1cd5c05f35fb43eb134df6f321de4e63141f2 Mon Sep 17 00:00:00 2001
From: Rusty Russell <rusty@rustcorp.com.au>
Date: Mon, 19 Dec 2011 13:56:45 +0000
Subject: [PATCH 02/17] net: fix assignment of 0/1 to bool variables.
DaveM said:
Please, this kind of stuff rots forever and not using bool properly
drives me crazy.
Joe Perches <joe@perches.com> gave me the spatch script:
@@
bool b;
@@
-b = 0
+b = false
@@
bool b;
@@
-b = 1
+b = true
I merely installed coccinelle, read the documentation and took credit.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/wireless/libertas/if_cs.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index e269351..3f7bf4d 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -859,7 +859,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
* Most of the libertas cards can do unaligned register access, but some
* weird ones cannot. That's especially true for the CF8305 card.
*/
- card->align_regs = 0;
+ card->align_regs = false;
card->model = get_model(p_dev->manf_id, p_dev->card_id);
if (card->model == MODEL_UNKNOWN) {
@@ -871,7 +871,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
/* Check if we have a current silicon */
prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
if (card->model == MODEL_8305) {
- card->align_regs = 1;
+ card->align_regs = true;
if (prod_id < IF_CS_CF8305_B1_REV) {
pr_err("8305 rev B0 and older are not supported\n");
ret = -ENODEV;
--
1.7.4.4
@@ -0,0 +1,26 @@
From f4ae40a6a50a98ac23d4b285f739455e926a473e Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 24 Jul 2011 04:33:43 -0400
Subject: [PATCH 03/17] switch debugfs to umode_t
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/wireless/libertas/debugfs.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index d8d8f0d..c192671 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -704,7 +704,7 @@ out_unlock:
struct lbs_debugfs_files {
const char *name;
- int perm;
+ umode_t perm;
struct file_operations fops;
};
--
1.7.4.4
@@ -0,0 +1,54 @@
From e404decb0fb017be80552adee894b35307b6c7b4 Mon Sep 17 00:00:00 2001
From: Joe Perches <joe@perches.com>
Date: Sun, 29 Jan 2012 12:56:23 +0000
Subject: [PATCH 04/17] drivers/net: Remove unnecessary k.alloc/v.alloc OOM
messages
alloc failures use dump_stack so emitting an additional
out-of-memory message is an unnecessary duplication.
Remove the allocation failure messages.
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/wireless/libertas/if_cs.c | 5 ++---
drivers/net/wireless/libertas/if_usb.c | 4 +---
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 3f7bf4d..234ee88 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -815,10 +815,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
lbs_deb_enter(LBS_DEB_CS);
card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
- if (!card) {
- pr_err("error in kzalloc\n");
+ if (!card)
goto out;
- }
+
card->p_dev = p_dev;
p_dev->priv = card;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index b5fbbc7..74da5f1 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -261,10 +261,8 @@ static int if_usb_probe(struct usb_interface *intf,
udev = interface_to_usbdev(intf);
cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
- if (!cardp) {
- pr_err("Out of memory allocating private data\n");
+ if (!cardp)
goto error;
- }
setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
init_waitqueue_head(&cardp->fw_wq);
--
1.7.4.4
@@ -0,0 +1,80 @@
From 377526578f2c343ea281a918b18ece1fca65005c Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Wed, 14 Mar 2012 22:34:33 +0000
Subject: [PATCH 05/17] libertas: remove dump_survey implementation
libertas provides a dump_survey implementation based on reading of
a RSSI value. However, this RSSI value is calculated based on the
last received beacon from the associated AP - it is not a good
way of surveying a channel in general, and even causes an error
if the card is not associated to a network.
As this is not appropriate as a survey, remove it. This fixes an
issue where something in userspace is repeatedly calling site-survey
during boot, resulting in many repeated errors as the RSSI value cannot
be read before associating.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/cfg.c | 37 -----------------------------------
1 files changed, 0 insertions(+), 37 deletions(-)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index a7cd311..3fa1ece 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1631,42 +1631,6 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
/*
- * "Site survey", here just current channel and noise level
- */
-
-static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
- int idx, struct survey_info *survey)
-{
- struct lbs_private *priv = wiphy_priv(wiphy);
- s8 signal, noise;
- int ret;
-
- if (dev == priv->mesh_dev)
- return -EOPNOTSUPP;
-
- if (idx != 0)
- ret = -ENOENT;
-
- lbs_deb_enter(LBS_DEB_CFG80211);
-
- survey->channel = ieee80211_get_channel(wiphy,
- ieee80211_channel_to_frequency(priv->channel,
- IEEE80211_BAND_2GHZ));
-
- ret = lbs_get_rssi(priv, &signal, &noise);
- if (ret == 0) {
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = noise;
- }
-
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
- return ret;
-}
-
-
-
-
-/*
* Change interface
*/
@@ -2068,7 +2032,6 @@ static struct cfg80211_ops lbs_cfg80211_ops = {
.del_key = lbs_cfg_del_key,
.set_default_key = lbs_cfg_set_default_key,
.get_station = lbs_cfg_get_station,
- .dump_survey = lbs_get_survey,
.change_virtual_intf = lbs_change_intf,
.join_ibss = lbs_join_ibss,
.leave_ibss = lbs_leave_ibss,
--
1.7.4.4
@@ -0,0 +1,95 @@
From a7b957a277215da1830596c0791307a999fe5153 Mon Sep 17 00:00:00 2001
From: Jesper Juhl <jj@chaosbits.net>
Date: Mon, 9 Apr 2012 22:51:07 +0200
Subject: [PATCH 07/17] wireless, libertas: remove redundant NULL tests before
calling release_firmware()
release_firmware() tests for, and deals gracefully with, NULL
pointers. Remove redundant explicit tests before calling the function.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/if_cs.c | 6 ++----
drivers/net/wireless/libertas/if_sdio.c | 6 ++----
drivers/net/wireless/libertas/if_spi.c | 6 ++----
drivers/net/wireless/libertas/main.c | 12 ++++--------
4 files changed, 10 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 234ee88..171a06b 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -951,10 +951,8 @@ out2:
out1:
pcmcia_disable_device(p_dev);
out:
- if (helper)
- release_firmware(helper);
- if (mainfw)
- release_firmware(mainfw);
+ release_firmware(helper);
+ release_firmware(mainfw);
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 9804ebc..15bfe2f 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -751,10 +751,8 @@ success:
ret = 0;
out:
- if (helper)
- release_firmware(helper);
- if (mainfw)
- release_firmware(mainfw);
+ release_firmware(helper);
+ release_firmware(mainfw);
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 50b1ee7..7a5df4f 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1095,10 +1095,8 @@ static int if_spi_init_card(struct if_spi_card *card)
goto out;
out:
- if (helper)
- release_firmware(helper);
- if (mainfw)
- release_firmware(mainfw);
+ release_firmware(helper);
+ release_firmware(mainfw);
lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 957681d..3b81b70 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1269,14 +1269,10 @@ int lbs_get_firmware(struct device *dev, const char *user_helper,
fail:
/* Failed */
- if (*helper) {
- release_firmware(*helper);
- *helper = NULL;
- }
- if (*mainfw) {
- release_firmware(*mainfw);
- *mainfw = NULL;
- }
+ release_firmware(*helper);
+ *helper = NULL;
+ release_firmware(*mainfw);
+ *mainfw = NULL;
return -ENOENT;
}
--
1.7.4.4
@@ -0,0 +1,48 @@
From effcc625eb4ab3b10b4744237fd37e8f7dcd6511 Mon Sep 17 00:00:00 2001
From: Amitkumar Karwar <akarwar@marvell.com>
Date: Wed, 28 Mar 2012 11:38:01 -0700
Subject: [PATCH 08/17] libertas: fix signedness bug in lbs_auth_to_authtype()
Return type for lbs_auth_to_authtype() is changed from "u8" to
"int" to return negative error code correctly.
Also an error check is added in connect handler for invalid auth
type.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/cfg.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 3fa1ece..2fa879b 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -103,7 +103,7 @@ static const u32 cipher_suites[] = {
* Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
* in the firmware spec
*/
-static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
+static int lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
{
int ret = -ENOTSUPP;
@@ -1411,7 +1411,12 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
goto done;
}
- lbs_set_authtype(priv, sme);
+ ret = lbs_set_authtype(priv, sme);
+ if (ret == -ENOTSUPP) {
+ wiphy_err(wiphy, "unsupported authtype 0x%x\n", sme->auth_type);
+ goto done;
+ }
+
lbs_set_radio(priv, preamble, 1);
/* Do the actual association */
--
1.7.4.4
@@ -0,0 +1,35 @@
From 1e66eda1d40c9ce3ff38782da066a14e1b88ac50 Mon Sep 17 00:00:00 2001
From: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Mon, 16 Apr 2012 17:44:00 +0200
Subject: [PATCH 09/17] drivers/net/wireless/libertas/if_usb.c: add missing
debugging code
Add a corresponding leave call on error failure.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/if_usb.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 74da5f1..ce4938d 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -1128,8 +1128,10 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
lbs_deb_enter(LBS_DEB_USB);
- if (priv->psstate != PS_STATE_FULL_POWER)
- return -1;
+ if (priv->psstate != PS_STATE_FULL_POWER) {
+ ret = -1;
+ goto out;
+ }
#ifdef CONFIG_OLPC
if (machine_is_olpc()) {
--
1.7.4.4
@@ -0,0 +1,618 @@
From 370803c25dd77332ee4ca97884c3a5e1e1eafbca Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Mon, 16 Apr 2012 23:52:42 +0100
Subject: [PATCH 10/17] libertas: Firmware loading simplifications
Remove the ability to pass module parameters with firmware filenames
for USB and SDIO interfaces.
Remove the ability to pass custom "user" filenames to lbs_get_firmware().
Remove the ability to reprogram internal device memory with a different
firmware from the USB driver (we don't know of any users), and simplify
the OLPC firmware loading quirk to simply placing the OLPC firmware
at the top of the list (we don't know of any users other than OLPC).
Move lbs_get_firmware() into its own file.
These simplifications should have no real-life effect but make the
upcoming transition to asynchronous firmware loading considerably less
painful.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/Makefile | 1 +
drivers/net/wireless/libertas/decl.h | 3 +-
drivers/net/wireless/libertas/firmware.c | 79 ++++++++++++++
drivers/net/wireless/libertas/if_cs.c | 4 +-
drivers/net/wireless/libertas/if_sdio.c | 25 +----
drivers/net/wireless/libertas/if_spi.c | 5 +-
drivers/net/wireless/libertas/if_usb.c | 169 ++----------------------------
drivers/net/wireless/libertas/main.c | 101 ------------------
8 files changed, 94 insertions(+), 293 deletions(-)
create mode 100644 drivers/net/wireless/libertas/firmware.c
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index f7d01bf..eac72f7 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -6,6 +6,7 @@ libertas-y += ethtool.o
libertas-y += main.o
libertas-y += rx.o
libertas-y += tx.o
+libertas-y += firmware.o
libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
usb8xxx-objs += if_usb.o
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index bc951ab..2fb2e31 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -66,8 +66,7 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
-int lbs_get_firmware(struct device *dev, const char *user_helper,
- const char *user_mainfw, u32 card_model,
+int lbs_get_firmware(struct device *dev, u32 card_model,
const struct lbs_fw_table *fw_table,
const struct firmware **helper,
const struct firmware **mainfw);
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
new file mode 100644
index 0000000..0c8c845
--- /dev/null
+++ b/drivers/net/wireless/libertas/firmware.c
@@ -0,0 +1,79 @@
+/*
+ * Firmware loading and handling functions.
+ */
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+
+#include "decl.h"
+
+/**
+ * lbs_get_firmware - Retrieves two-stage firmware
+ *
+ * @dev: A pointer to &device structure
+ * @card_model: Bus-specific card model ID used to filter firmware table
+ * elements
+ * @fw_table: Table of firmware file names and device model numbers
+ * terminated by an entry with a NULL helper name
+ * @helper: On success, the helper firmware; caller must free
+ * @mainfw: On success, the main firmware; caller must free
+ *
+ * returns: 0 on success, non-zero on failure
+ */
+int lbs_get_firmware(struct device *dev, u32 card_model,
+ const struct lbs_fw_table *fw_table,
+ const struct firmware **helper,
+ const struct firmware **mainfw)
+{
+ const struct lbs_fw_table *iter;
+ int ret;
+
+ BUG_ON(helper == NULL);
+ BUG_ON(mainfw == NULL);
+
+ /* Search for firmware to use from the table. */
+ iter = fw_table;
+ while (iter && iter->helper) {
+ if (iter->model != card_model)
+ goto next;
+
+ if (*helper == NULL) {
+ ret = request_firmware(helper, iter->helper, dev);
+ if (ret)
+ goto next;
+
+ /* If the device has one-stage firmware (ie cf8305) and
+ * we've got it then we don't need to bother with the
+ * main firmware.
+ */
+ if (iter->fwname == NULL)
+ return 0;
+ }
+
+ if (*mainfw == NULL) {
+ ret = request_firmware(mainfw, iter->fwname, dev);
+ if (ret) {
+ /* Clear the helper to ensure we don't have
+ * mismatched firmware pairs.
+ */
+ release_firmware(*helper);
+ *helper = NULL;
+ }
+ }
+
+ if (*helper && *mainfw)
+ return 0;
+
+ next:
+ iter++;
+ }
+
+ /* Failed */
+ release_firmware(*helper);
+ *helper = NULL;
+ release_firmware(*mainfw);
+ *mainfw = NULL;
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware);
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 171a06b..cee5052 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -890,8 +890,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out2;
}
- ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model,
- &fw_table[0], &helper, &mainfw);
+ ret = lbs_get_firmware(&p_dev->dev, card->model, &fw_table[0],
+ &helper, &mainfw);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto out2;
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 15bfe2f..6590feb 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -65,12 +65,6 @@ static void if_sdio_interrupt(struct sdio_func *func);
*/
static u8 user_rmmod;
-static char *lbs_helper_name = NULL;
-module_param_named(helper_name, lbs_helper_name, charp, 0644);
-
-static char *lbs_fw_name = NULL;
-module_param_named(fw_name, lbs_fw_name, charp, 0644);
-
static const struct sdio_device_id if_sdio_ids[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
@@ -124,11 +118,6 @@ struct if_sdio_card {
unsigned long ioport;
unsigned int scratch_reg;
- const char *helper;
- const char *firmware;
- bool helper_allocated;
- bool firmware_allocated;
-
u8 buffer[65536] __attribute__((aligned(4)));
spinlock_t lock;
@@ -725,8 +714,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
goto success;
}
- ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
- card->model, &fw_table[0], &helper, &mainfw);
+ ret = lbs_get_firmware(&card->func->dev, card->model, &fw_table[0],
+ &helper, &mainfw);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto out;
@@ -1242,10 +1231,6 @@ free:
kfree(packet);
}
- if (card->helper_allocated)
- kfree(card->helper);
- if (card->firmware_allocated)
- kfree(card->firmware);
kfree(card);
goto out;
@@ -1293,12 +1278,6 @@ static void if_sdio_remove(struct sdio_func *func)
kfree(packet);
}
- if (card->helper_allocated)
- kfree(card->helper);
- if (card->firmware_allocated)
- kfree(card->firmware);
- kfree(card);
-
lbs_deb_leave(LBS_DEB_SDIO);
}
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 7a5df4f..9604a1c 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1064,9 +1064,8 @@ static int if_spi_init_card(struct if_spi_card *card)
goto out;
}
- err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
- card->card_id, &fw_table[0], &helper,
- &mainfw);
+ err = lbs_get_firmware(&card->spi->dev, card->card_id,
+ &fw_table[0], &helper, &mainfw);
if (err) {
netdev_err(priv->dev, "failed to find firmware (%d)\n",
err);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index ce4938d..f29471b 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -29,9 +29,6 @@
#define MESSAGE_HEADER_LEN 4
-static char *lbs_fw_name = NULL;
-module_param_named(fw_name, lbs_fw_name, charp, 0644);
-
MODULE_FIRMWARE("libertas/usb8388_v9.bin");
MODULE_FIRMWARE("libertas/usb8388_v5.bin");
MODULE_FIRMWARE("libertas/usb8388.bin");
@@ -55,10 +52,7 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int __if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd);
-static int if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd);
+static int if_usb_prog_firmware(struct if_usb_card *cardp);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
@@ -67,69 +61,6 @@ static void if_usb_free(struct if_usb_card *cardp);
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
static int if_usb_reset_device(struct if_usb_card *cardp);
-/* sysfs hooks */
-
-/*
- * Set function to write firmware to device's persistent memory
- */
-static ssize_t if_usb_firmware_set(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->ml_priv;
- struct if_usb_card *cardp = priv->card;
- int ret;
-
- BUG_ON(buf == NULL);
-
- ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW);
- if (ret == 0)
- return count;
-
- return ret;
-}
-
-/*
- * lbs_flash_fw attribute to be exported per ethX interface through sysfs
- * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to
- * the device's persistent memory:
- * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw
- */
-static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
-
-/**
- * if_usb_boot2_set - write firmware to device's persistent memory
- *
- * @dev: target device
- * @attr: device attributes
- * @buf: firmware buffer to write
- * @count: number of bytes to write
- *
- * returns: number of bytes written or negative error code
- */
-static ssize_t if_usb_boot2_set(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->ml_priv;
- struct if_usb_card *cardp = priv->card;
- int ret;
-
- BUG_ON(buf == NULL);
-
- ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2);
- if (ret == 0)
- return count;
-
- return ret;
-}
-
-/*
- * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs
- * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware
- * to the device's persistent memory:
- * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2
- */
-static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set);
-
/**
* if_usb_write_bulk_callback - callback function to handle the status
* of the URB
@@ -314,13 +245,10 @@ static int if_usb_probe(struct usb_interface *intf,
}
/* Upload firmware */
- kparam_block_sysfs_write(fw_name);
- if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) {
- kparam_unblock_sysfs_write(fw_name);
+ if (if_usb_prog_firmware(cardp)) {
lbs_deb_usbd(&udev->dev, "FW upload failed\n");
goto err_prog_firmware;
}
- kparam_unblock_sysfs_write(fw_name);
if (!(priv = lbs_add_card(cardp, &intf->dev)))
goto err_prog_firmware;
@@ -349,14 +277,6 @@ static int if_usb_probe(struct usb_interface *intf,
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
- if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw))
- netdev_err(priv->dev,
- "cannot register lbs_flash_fw attribute\n");
-
- if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
- netdev_err(priv->dev,
- "cannot register lbs_flash_boot2 attribute\n");
-
/*
* EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
*/
@@ -389,9 +309,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
lbs_deb_enter(LBS_DEB_MAIN);
- device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2);
- device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw);
-
cardp->surprise_removed = 1;
if (priv) {
@@ -912,58 +829,12 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
return ret;
}
-
-/**
-* if_usb_prog_firmware - programs the firmware subject to cmd
-*
-* @cardp: the if_usb_card descriptor
-* @fwname: firmware or boot2 image file name
-* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW,
-* or BOOT_CMD_UPDATE_BOOT2.
-* returns: 0 or error code
-*/
-static int if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd)
-{
- struct lbs_private *priv = cardp->priv;
- unsigned long flags, caps;
- int ret;
-
- caps = priv->fwcapinfo;
- if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) ||
- ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE)))
- return -EOPNOTSUPP;
-
- /* Ensure main thread is idle. */
- spin_lock_irqsave(&priv->driver_lock, flags);
- while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) {
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- if (wait_event_interruptible(priv->waitq,
- (priv->cur_cmd == NULL &&
- priv->dnld_sent == DNLD_RES_RECEIVED))) {
- return -ERESTARTSYS;
- }
- spin_lock_irqsave(&priv->driver_lock, flags);
- }
- priv->dnld_sent = DNLD_BOOTCMD_SENT;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- ret = __if_usb_prog_firmware(cardp, fwname, cmd);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- priv->dnld_sent = DNLD_RES_RECEIVED;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- wake_up(&priv->waitq);
-
- return ret;
-}
-
/* table of firmware file names */
static const struct {
u32 model;
const char *fwname;
} fw_table[] = {
+ { MODEL_8388, "libertas/usb8388_olpc.bin" },
{ MODEL_8388, "libertas/usb8388_v9.bin" },
{ MODEL_8388, "libertas/usb8388_v5.bin" },
{ MODEL_8388, "libertas/usb8388.bin" },
@@ -971,35 +842,10 @@ static const struct {
{ MODEL_8682, "libertas/usb8682.bin" }
};
-#ifdef CONFIG_OLPC
-
-static int try_olpc_fw(struct if_usb_card *cardp)
-{
- int retval = -ENOENT;
-
- /* try the OLPC firmware first; fall back to fw_table list */
- if (machine_is_olpc() && cardp->model == MODEL_8388)
- retval = request_firmware(&cardp->fw,
- "libertas/usb8388_olpc.bin", &cardp->udev->dev);
- return retval;
-}
-
-#else
-static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
-#endif /* !CONFIG_OLPC */
-
-static int get_fw(struct if_usb_card *cardp, const char *fwname)
+static int get_fw(struct if_usb_card *cardp)
{
int i;
- /* Try user-specified firmware first */
- if (fwname)
- return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
-
- /* Handle OLPC firmware */
- if (try_olpc_fw(cardp) == 0)
- return 0;
-
/* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model)
@@ -1012,8 +858,7 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname)
return -ENOENT;
}
-static int __if_usb_prog_firmware(struct if_usb_card *cardp,
- const char *fwname, int cmd)
+static int if_usb_prog_firmware(struct if_usb_card *cardp)
{
int i = 0;
static int reset_count = 10;
@@ -1021,7 +866,7 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp,
lbs_deb_enter(LBS_DEB_USB);
- ret = get_fw(cardp, fwname);
+ ret = get_fw(cardp);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto done;
@@ -1053,7 +898,7 @@ restart:
do {
int j = 0;
i++;
- if_usb_issue_boot_command(cardp, cmd);
+ if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
/* wait for command response */
do {
j++;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 3b81b70..fa09585 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1177,107 +1177,6 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
}
EXPORT_SYMBOL_GPL(lbs_notify_command_response);
-/**
- * lbs_get_firmware - Retrieves two-stage firmware
- *
- * @dev: A pointer to &device structure
- * @user_helper: User-defined helper firmware file
- * @user_mainfw: User-defined main firmware file
- * @card_model: Bus-specific card model ID used to filter firmware table
- * elements
- * @fw_table: Table of firmware file names and device model numbers
- * terminated by an entry with a NULL helper name
- * @helper: On success, the helper firmware; caller must free
- * @mainfw: On success, the main firmware; caller must free
- *
- * returns: 0 on success, non-zero on failure
- */
-int lbs_get_firmware(struct device *dev, const char *user_helper,
- const char *user_mainfw, u32 card_model,
- const struct lbs_fw_table *fw_table,
- const struct firmware **helper,
- const struct firmware **mainfw)
-{
- const struct lbs_fw_table *iter;
- int ret;
-
- BUG_ON(helper == NULL);
- BUG_ON(mainfw == NULL);
-
- /* Try user-specified firmware first */
- if (user_helper) {
- ret = request_firmware(helper, user_helper, dev);
- if (ret) {
- dev_err(dev, "couldn't find helper firmware %s\n",
- user_helper);
- goto fail;
- }
- }
- if (user_mainfw) {
- ret = request_firmware(mainfw, user_mainfw, dev);
- if (ret) {
- dev_err(dev, "couldn't find main firmware %s\n",
- user_mainfw);
- goto fail;
- }
- }
-
- if (*helper && *mainfw)
- 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
- * make sure that found helper & main are from the same entry in
- * fw_table.
- */
- iter = fw_table;
- while (iter && iter->helper) {
- if (iter->model != card_model)
- goto next;
-
- if (*helper == NULL) {
- ret = request_firmware(helper, iter->helper, dev);
- if (ret)
- goto next;
-
- /* If the device has one-stage firmware (ie cf8305) and
- * we've got it then we don't need to bother with the
- * main firmware.
- */
- if (iter->fwname == NULL)
- return 0;
- }
-
- if (*mainfw == NULL) {
- ret = request_firmware(mainfw, iter->fwname, dev);
- if (ret && !user_helper) {
- /* Clear the helper if it wasn't user-specified
- * and the main firmware load failed, to ensure
- * we don't have mismatched firmware pairs.
- */
- release_firmware(*helper);
- *helper = NULL;
- }
- }
-
- if (*helper && *mainfw)
- return 0;
-
- next:
- iter++;
- }
-
- fail:
- /* Failed */
- release_firmware(*helper);
- *helper = NULL;
- release_firmware(*mainfw);
- *mainfw = NULL;
-
- return -ENOENT;
-}
-EXPORT_SYMBOL_GPL(lbs_get_firmware);
-
static int __init lbs_init_module(void)
{
lbs_deb_enter(LBS_DEB_MAIN);
--
1.7.4.4
@@ -0,0 +1,46 @@
From 0beecac8abb3af890d470df541142d55343382d6 Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Mon, 16 Apr 2012 23:53:02 +0100
Subject: [PATCH 11/17] libertas: harden-up exit paths
These simple sanity check avoids extra complexity in error paths when
moving to asynchronous firmware loading (which means the device may fail to
init some time after its creation).
Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/main.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index fa09585..7eaf992 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1033,7 +1033,9 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_MAIN);
lbs_remove_mesh(priv);
- lbs_scan_deinit(priv);
+
+ if (priv->wiphy_registered)
+ lbs_scan_deinit(priv);
/* worker thread destruction blocks on the in-flight command which
* should have been cleared already in lbs_stop_card().
@@ -1128,6 +1130,11 @@ void lbs_stop_card(struct lbs_private *priv)
goto out;
dev = priv->dev;
+ /* If the netdev isn't registered, it means that lbs_start_card() was
+ * never called so we have nothing to do here. */
+ if (dev->reg_state != NETREG_REGISTERED)
+ goto out;
+
netif_stop_queue(dev);
netif_carrier_off(dev);
--
1.7.4.4
@@ -0,0 +1,269 @@
From 534111c78c59a8db89c570fd07489243dc366a05 Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Mon, 16 Apr 2012 23:53:26 +0100
Subject: [PATCH 12/17] libertas: add asynchronous firmware loading capability
As described at
http://article.gmane.org/gmane.linux.kernel.wireless.general/86084
libertas is taking a long time to load because it loads firmware
during module loading.
Add a new API for interface drivers to load their firmware
asynchronously. The same semantics of the firmware table are followed
like before.
Interface drivers will be converted in follow-up patches, then we can
remove the old, synchronous firmware loading function.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/decl.h | 8 ++
drivers/net/wireless/libertas/dev.h | 10 ++
drivers/net/wireless/libertas/firmware.c | 143 ++++++++++++++++++++++++++++++
drivers/net/wireless/libertas/main.c | 3 +
4 files changed, 164 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 2fb2e31..84a3aa7 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -19,6 +19,10 @@ struct lbs_fw_table {
};
struct lbs_private;
+typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret,
+ const struct firmware *helper, const struct firmware *mainfw);
+
+struct lbs_private;
struct sk_buff;
struct net_device;
struct cmd_ds_command;
@@ -70,5 +74,9 @@ int lbs_get_firmware(struct device *dev, u32 card_model,
const struct lbs_fw_table *fw_table,
const struct firmware **helper,
const struct firmware **mainfw);
+int lbs_get_firmware_async(struct lbs_private *priv, struct device *device,
+ u32 card_model, const struct lbs_fw_table *fw_table,
+ lbs_fw_cb callback);
+void lbs_wait_for_firmware_load(struct lbs_private *priv);
#endif
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f3fd447..6720054 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -7,6 +7,7 @@
#define _LBS_DEV_H_
#include "defs.h"
+#include "decl.h"
#include "host.h"
#include <linux/kfifo.h>
@@ -180,6 +181,15 @@ struct lbs_private {
wait_queue_head_t scan_q;
/* Whether the scan was initiated internally and not by cfg80211 */
bool internal_scan;
+
+ /* Firmware load */
+ u32 fw_model;
+ wait_queue_head_t fw_waitq;
+ struct device *fw_device;
+ const struct firmware *helper_fw;
+ const struct lbs_fw_table *fw_table;
+ const struct lbs_fw_table *fw_iter;
+ lbs_fw_cb fw_callback;
};
extern struct cmd_confirm_sleep confirm_sleep;
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
index 0c8c845..cd23f1a 100644
--- a/drivers/net/wireless/libertas/firmware.c
+++ b/drivers/net/wireless/libertas/firmware.c
@@ -3,10 +3,151 @@
*/
#include <linux/firmware.h>
+#include <linux/firmware.h>
#include <linux/module.h>
+#include "dev.h"
#include "decl.h"
+static void load_next_firmware_from_table(struct lbs_private *private);
+
+static void lbs_fw_loaded(struct lbs_private *priv, int ret,
+ const struct firmware *helper, const struct firmware *mainfw)
+{
+ unsigned long flags;
+
+ lbs_deb_fw("firmware load complete, code %d\n", ret);
+
+ /* User must free helper/mainfw */
+ priv->fw_callback(priv, ret, helper, mainfw);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->fw_callback = NULL;
+ wake_up(&priv->fw_waitq);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+}
+
+static void do_load_firmware(struct lbs_private *priv, const char *name,
+ void (*cb)(const struct firmware *fw, void *context))
+{
+ int ret;
+
+ lbs_deb_fw("Requesting %s\n", name);
+ ret = request_firmware_nowait(THIS_MODULE, true, name,
+ priv->fw_device, GFP_KERNEL, priv, cb);
+ if (ret) {
+ lbs_deb_fw("request_firmware_nowait error %d\n", ret);
+ lbs_fw_loaded(priv, ret, NULL, NULL);
+ }
+}
+
+static void main_firmware_cb(const struct firmware *firmware, void *context)
+{
+ struct lbs_private *priv = context;
+
+ if (!firmware) {
+ /* Failed to find firmware: try next table entry */
+ load_next_firmware_from_table(priv);
+ return;
+ }
+
+ /* Firmware found! */
+ lbs_fw_loaded(priv, 0, priv->helper_fw, firmware);
+}
+
+static void helper_firmware_cb(const struct firmware *firmware, void *context)
+{
+ struct lbs_private *priv = context;
+
+ if (!firmware) {
+ /* Failed to find firmware: try next table entry */
+ load_next_firmware_from_table(priv);
+ return;
+ }
+
+ /* Firmware found! */
+ if (priv->fw_iter->fwname) {
+ priv->helper_fw = firmware;
+ do_load_firmware(priv, priv->fw_iter->fwname, main_firmware_cb);
+ } else {
+ /* No main firmware needed for this helper --> success! */
+ lbs_fw_loaded(priv, 0, firmware, NULL);
+ }
+}
+
+static void load_next_firmware_from_table(struct lbs_private *priv)
+{
+ const struct lbs_fw_table *iter;
+
+ if (!priv->fw_iter)
+ iter = priv->fw_table;
+ else
+ iter = ++priv->fw_iter;
+
+ if (priv->helper_fw) {
+ release_firmware(priv->helper_fw);
+ priv->helper_fw = NULL;
+ }
+
+next:
+ if (!iter->helper) {
+ /* End of table hit. */
+ lbs_fw_loaded(priv, -ENOENT, NULL, NULL);
+ return;
+ }
+
+ if (iter->model != priv->fw_model) {
+ iter++;
+ goto next;
+ }
+
+ priv->fw_iter = iter;
+ do_load_firmware(priv, iter->helper, helper_firmware_cb);
+}
+
+void lbs_wait_for_firmware_load(struct lbs_private *priv)
+{
+ wait_event(priv->fw_waitq, priv->fw_callback == NULL);
+}
+
+/**
+ * lbs_get_firmware_async - Retrieves firmware asynchronously. Can load
+ * either a helper firmware and a main firmware (2-stage), or just the helper.
+ *
+ * @priv: Pointer to lbs_private instance
+ * @dev: A pointer to &device structure
+ * @card_model: Bus-specific card model ID used to filter firmware table
+ * elements
+ * @fw_table: Table of firmware file names and device model numbers
+ * terminated by an entry with a NULL helper name
+ * @callback: User callback to invoke when firmware load succeeds or fails.
+ */
+int lbs_get_firmware_async(struct lbs_private *priv, struct device *device,
+ u32 card_model, const struct lbs_fw_table *fw_table,
+ lbs_fw_cb callback)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->fw_callback) {
+ lbs_deb_fw("firmware load already in progress\n");
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ return -EBUSY;
+ }
+
+ priv->fw_device = device;
+ priv->fw_callback = callback;
+ priv->fw_table = fw_table;
+ priv->fw_iter = NULL;
+ priv->fw_model = card_model;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ lbs_deb_fw("Starting async firmware load\n");
+ load_next_firmware_from_table(priv);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware_async);
+
/**
* lbs_get_firmware - Retrieves two-stage firmware
*
@@ -18,6 +159,8 @@
* @helper: On success, the helper firmware; caller must free
* @mainfw: On success, the main firmware; caller must free
*
+ * Deprecated: use lbs_get_firmware_async() instead.
+ *
* returns: 0 on success, non-zero on failure
*/
int lbs_get_firmware(struct device *dev, u32 card_model,
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 7eaf992..e96ee0a 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -878,6 +878,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->is_host_sleep_configured = 0;
priv->is_host_sleep_activated = 0;
init_waitqueue_head(&priv->host_sleep_q);
+ init_waitqueue_head(&priv->fw_waitq);
mutex_init(&priv->lock);
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
@@ -1037,6 +1038,8 @@ void lbs_remove_card(struct lbs_private *priv)
if (priv->wiphy_registered)
lbs_scan_deinit(priv);
+ lbs_wait_for_firmware_load(priv);
+
/* worker thread destruction blocks on the in-flight command which
* should have been cleared already in lbs_stop_card().
*/
--
1.7.4.4
@@ -0,0 +1,320 @@
From 66d647efe5e845c77f745478480c5e96218b7f3d Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Mon, 16 Apr 2012 23:53:43 +0100
Subject: [PATCH 13/17] libertas SDIO: convert to asynchronous firmware
loading
Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/if_sdio.c | 206 ++++++++++++++++++-------------
1 files changed, 121 insertions(+), 85 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 6590feb..76caeba 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -117,6 +117,8 @@ struct if_sdio_card {
int model;
unsigned long ioport;
unsigned int scratch_reg;
+ bool started;
+ wait_queue_head_t pwron_waitq;
u8 buffer[65536] __attribute__((aligned(4)));
@@ -129,6 +131,9 @@ struct if_sdio_card {
u8 rx_unit;
};
+static void if_sdio_finish_power_on(struct if_sdio_card *card);
+static int if_sdio_power_off(struct if_sdio_card *card);
+
/********************************************************************/
/* I/O */
/********************************************************************/
@@ -669,12 +674,39 @@ out:
return ret;
}
+static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret,
+ const struct firmware *helper,
+ const struct firmware *mainfw)
+{
+ struct if_sdio_card *card = priv->card;
+
+ if (ret) {
+ pr_err("failed to find firmware (%d)\n", ret);
+ return;
+ }
+
+ ret = if_sdio_prog_helper(card, helper);
+ if (ret)
+ goto out;
+
+ lbs_deb_sdio("Helper firmware loaded\n");
+
+ ret = if_sdio_prog_real(card, mainfw);
+ if (ret)
+ goto out;
+
+ lbs_deb_sdio("Firmware loaded\n");
+ if_sdio_finish_power_on(card);
+
+out:
+ release_firmware(helper);
+ release_firmware(mainfw);
+}
+
static int if_sdio_prog_firmware(struct if_sdio_card *card)
{
int ret;
u16 scratch;
- const struct firmware *helper = NULL;
- const struct firmware *mainfw = NULL;
lbs_deb_enter(LBS_DEB_SDIO);
@@ -708,41 +740,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
*/
if (scratch == IF_SDIO_FIRMWARE_OK) {
lbs_deb_sdio("firmware already loaded\n");
- goto success;
+ if_sdio_finish_power_on(card);
+ return 0;
} else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) {
lbs_deb_sdio("firmware may be running\n");
- goto success;
- }
-
- ret = lbs_get_firmware(&card->func->dev, card->model, &fw_table[0],
- &helper, &mainfw);
- if (ret) {
- pr_err("failed to find firmware (%d)\n", ret);
- goto out;
+ if_sdio_finish_power_on(card);
+ return 0;
}
- ret = if_sdio_prog_helper(card, helper);
- if (ret)
- goto out;
-
- lbs_deb_sdio("Helper firmware loaded\n");
-
- ret = if_sdio_prog_real(card, mainfw);
- if (ret)
- goto out;
-
- lbs_deb_sdio("Firmware loaded\n");
-
-success:
- sdio_claim_host(card->func);
- sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
- sdio_release_host(card->func);
- ret = 0;
+ ret = lbs_get_firmware_async(card->priv, &card->func->dev, card->model,
+ fw_table, if_sdio_do_prog_firmware);
out:
- release_firmware(helper);
- release_firmware(mainfw);
-
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -751,55 +760,15 @@ out:
/* Power management */
/********************************************************************/
-static int if_sdio_power_on(struct if_sdio_card *card)
+/* Finish power on sequence (after firmware is loaded) */
+static void if_sdio_finish_power_on(struct if_sdio_card *card)
{
struct sdio_func *func = card->func;
struct lbs_private *priv = card->priv;
- struct mmc_host *host = func->card->host;
int ret;
sdio_claim_host(func);
-
- ret = sdio_enable_func(func);
- if (ret)
- goto release;
-
- /* For 1-bit transfers to the 8686 model, we need to enable the
- * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
- * bit to allow access to non-vendor registers. */
- if ((card->model == MODEL_8686) &&
- (host->caps & MMC_CAP_SDIO_IRQ) &&
- (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
- u8 reg;
-
- func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
- if (ret)
- goto disable;
-
- reg |= SDIO_BUS_ECSI;
- sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
- if (ret)
- goto disable;
- }
-
- card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
- if (ret)
- goto disable;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
- if (ret)
- goto disable;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
- if (ret)
- goto disable;
-
- sdio_release_host(func);
- ret = if_sdio_prog_firmware(card);
- sdio_claim_host(func);
- if (ret)
- goto disable;
+ sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
/*
* Get rx_unit if the chip is SD8688 or newer.
@@ -824,7 +793,7 @@ static int if_sdio_power_on(struct if_sdio_card *card)
*/
ret = sdio_claim_irq(func, if_sdio_interrupt);
if (ret)
- goto disable;
+ goto release;
/*
* Enable interrupts now that everything is set up
@@ -850,11 +819,79 @@ static int if_sdio_power_on(struct if_sdio_card *card)
}
priv->fw_ready = 1;
+ wake_up(&card->pwron_waitq);
- return 0;
+ if (!card->started) {
+ ret = lbs_start_card(priv);
+ if_sdio_power_off(card);
+ if (ret == 0) {
+ card->started = true;
+ /* Tell PM core that we don't need the card to be
+ * powered now */
+ pm_runtime_put_noidle(&func->dev);
+ }
+ }
+
+ return;
release_irq:
sdio_release_irq(func);
+release:
+ sdio_release_host(func);
+}
+
+static int if_sdio_power_on(struct if_sdio_card *card)
+{
+ struct sdio_func *func = card->func;
+ struct mmc_host *host = func->card->host;
+ int ret;
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ /* For 1-bit transfers to the 8686 model, we need to enable the
+ * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
+ * bit to allow access to non-vendor registers. */
+ if ((card->model == MODEL_8686) &&
+ (host->caps & MMC_CAP_SDIO_IRQ) &&
+ (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
+ u8 reg;
+
+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+ reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+
+ reg |= SDIO_BUS_ECSI;
+ sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+ }
+
+ card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
+ if (ret)
+ goto disable;
+
+ sdio_release_host(func);
+ ret = if_sdio_prog_firmware(card);
+ if (ret) {
+ sdio_disable_func(func);
+ return ret;
+ }
+
+ return 0;
+
disable:
sdio_disable_func(func);
release:
@@ -1061,11 +1098,17 @@ static int if_sdio_power_save(struct lbs_private *priv)
static int if_sdio_power_restore(struct lbs_private *priv)
{
struct if_sdio_card *card = priv->card;
+ int r;
/* Make sure the card will not be powered off by runtime PM */
pm_runtime_get_sync(&card->func->dev);
- return if_sdio_power_on(card);
+ r = if_sdio_power_on(card);
+ if (r)
+ return r;
+
+ wait_event(card->pwron_waitq, priv->fw_ready);
+ return 0;
}
@@ -1166,6 +1209,7 @@ static int if_sdio_probe(struct sdio_func *func,
spin_lock_init(&card->lock);
card->workqueue = create_workqueue("libertas_sdio");
INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
+ init_waitqueue_head(&card->pwron_waitq);
/* Check if we support this card */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
@@ -1207,14 +1251,6 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret)
goto err_activate_card;
- ret = lbs_start_card(priv);
- if_sdio_power_off(card);
- if (ret)
- goto err_activate_card;
-
- /* Tell PM core that we don't need the card to be powered now */
- pm_runtime_put_noidle(&func->dev);
-
out:
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
--
1.7.4.4
@@ -0,0 +1,201 @@
From ce84bb69f50e6f6cfeabc9b965365290f4184417 Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Mon, 16 Apr 2012 23:53:55 +0100
Subject: [PATCH 14/17] libertas USB: convert to asynchronous firmware loading
Signed-off-by: Daniel Drake <dsd@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/if_usb.c | 102 +++++++++++++------------------
1 files changed, 43 insertions(+), 59 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index f29471b..75403e6 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -41,6 +41,16 @@ enum {
MODEL_8682 = 0x2
};
+/* table of firmware file names */
+static const struct lbs_fw_table fw_table[] = {
+ { MODEL_8388, "libertas/usb8388_olpc.bin", NULL },
+ { MODEL_8388, "libertas/usb8388_v9.bin", NULL },
+ { MODEL_8388, "libertas/usb8388_v5.bin", NULL },
+ { MODEL_8388, "libertas/usb8388.bin", NULL },
+ { MODEL_8388, "usb8388.bin", NULL },
+ { MODEL_8682, "libertas/usb8682.bin", NULL }
+};
+
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
@@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
+ const struct firmware *fw,
+ const struct firmware *unused);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
@@ -187,6 +199,7 @@ static int if_usb_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *endpoint;
struct lbs_private *priv;
struct if_usb_card *cardp;
+ int r = -ENOMEM;
int i;
udev = interface_to_usbdev(intf);
@@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc;
}
- /* Upload firmware */
- if (if_usb_prog_firmware(cardp)) {
- lbs_deb_usbd(&udev->dev, "FW upload failed\n");
- goto err_prog_firmware;
- }
-
if (!(priv = lbs_add_card(cardp, &intf->dev)))
- goto err_prog_firmware;
+ goto err_add_card;
cardp->priv = priv;
- cardp->priv->fw_ready = 1;
priv->hw_host_to_card = if_usb_host_to_card;
priv->enter_deep_sleep = NULL;
@@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf,
cardp->boot2_version = udev->descriptor.bcdDevice;
- if_usb_submit_rx_urb(cardp);
-
- if (lbs_start_card(priv))
- goto err_start_card;
-
- if_usb_setup_firmware(priv);
-
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
- /*
- * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
- */
- priv->wol_criteria = EHS_REMOVE_WAKEUP;
- if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
- priv->ehs_remove_supported = false;
+ r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
+ fw_table, if_usb_prog_firmware);
+ if (r)
+ goto err_get_fw;
return 0;
-err_start_card:
+err_get_fw:
lbs_remove_card(priv);
-err_prog_firmware:
+err_add_card:
if_usb_reset_device(cardp);
dealloc:
if_usb_free(cardp);
error:
- return -ENOMEM;
+ return r;
}
/**
@@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
return ret;
}
-/* table of firmware file names */
-static const struct {
- u32 model;
- const char *fwname;
-} fw_table[] = {
- { MODEL_8388, "libertas/usb8388_olpc.bin" },
- { MODEL_8388, "libertas/usb8388_v9.bin" },
- { MODEL_8388, "libertas/usb8388_v5.bin" },
- { MODEL_8388, "libertas/usb8388.bin" },
- { MODEL_8388, "usb8388.bin" },
- { MODEL_8682, "libertas/usb8682.bin" }
-};
-
-static int get_fw(struct if_usb_card *cardp)
-{
- int i;
-
- /* Otherwise search for firmware to use */
- for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
- if (fw_table[i].model != cardp->model)
- continue;
- if (request_firmware(&cardp->fw, fw_table[i].fwname,
- &cardp->udev->dev) == 0)
- return 0;
- }
-
- return -ENOENT;
-}
-
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
+static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
+ const struct firmware *fw,
+ const struct firmware *unused)
{
+ struct if_usb_card *cardp = priv->card;
int i = 0;
static int reset_count = 10;
- int ret = 0;
lbs_deb_enter(LBS_DEB_USB);
- ret = get_fw(cardp);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto done;
}
+ cardp->fw = fw;
if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
ret = -EINVAL;
goto release_fw;
@@ -954,13 +924,27 @@ restart:
goto release_fw;
}
+ cardp->priv->fw_ready = 1;
+ if_usb_submit_rx_urb(cardp);
+
+ if (lbs_start_card(priv))
+ goto release_fw;
+
+ if_usb_setup_firmware(priv);
+
+ /*
+ * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
+ */
+ priv->wol_criteria = EHS_REMOVE_WAKEUP;
+ if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
+ priv->ehs_remove_supported = false;
+
release_fw:
release_firmware(cardp->fw);
cardp->fw = NULL;
done:
- lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
- return ret;
+ lbs_deb_leave(LBS_DEB_USB);
}
--
1.7.4.4
@@ -0,0 +1,154 @@
From 488c3ee77ea0e63c9ae4736b1610aaf39c6527ee Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Wed, 18 Apr 2012 20:09:44 +0100
Subject: [PATCH 15/17] libertas CS: convert to asynchronous firmware loading
Signed-off-by: Daniel Drake <dsd@laptop.org>
Tested-by: Dan Williams <dcbw@redhat.com>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/if_cs.c | 88 ++++++++++++++++++--------------
1 files changed, 49 insertions(+), 39 deletions(-)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index cee5052..16beaf3 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -738,6 +738,50 @@ done:
return ret;
}
+static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
+ const struct firmware *helper,
+ const struct firmware *mainfw)
+{
+ struct if_cs_card *card = priv->card;
+
+ if (ret) {
+ pr_err("failed to find firmware (%d)\n", ret);
+ return;
+ }
+
+ /* Load the firmware */
+ ret = if_cs_prog_helper(card, helper);
+ if (ret == 0 && (card->model != MODEL_8305))
+ ret = if_cs_prog_real(card, mainfw);
+ if (ret)
+ goto out;
+
+ /* Now actually get the IRQ */
+ ret = request_irq(card->p_dev->irq, if_cs_interrupt,
+ IRQF_SHARED, DRV_NAME, card);
+ if (ret) {
+ pr_err("error in request_irq\n");
+ goto out;
+ }
+
+ /*
+ * Clear any interrupt cause that happened while sending
+ * firmware/initializing card
+ */
+ if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
+ if_cs_enable_ints(card);
+
+ /* And finally bring the card up */
+ priv->fw_ready = 1;
+ if (lbs_start_card(priv) != 0) {
+ pr_err("could not activate card\n");
+ free_irq(card->p_dev->irq, card);
+ }
+
+out:
+ release_firmware(helper);
+ release_firmware(mainfw);
+}
/********************************************************************/
@@ -809,8 +853,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
unsigned int prod_id;
struct lbs_private *priv;
struct if_cs_card *card;
- const struct firmware *helper = NULL;
- const struct firmware *mainfw = NULL;
lbs_deb_enter(LBS_DEB_CS);
@@ -890,20 +932,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out2;
}
- ret = lbs_get_firmware(&p_dev->dev, card->model, &fw_table[0],
- &helper, &mainfw);
- if (ret) {
- pr_err("failed to find firmware (%d)\n", ret);
- goto out2;
- }
-
- /* Load the firmware early, before calling into libertas.ko */
- ret = if_cs_prog_helper(card, helper);
- if (ret == 0 && (card->model != MODEL_8305))
- ret = if_cs_prog_real(card, mainfw);
- if (ret)
- goto out2;
-
/* Make this card known to the libertas driver */
priv = lbs_add_card(card, &p_dev->dev);
if (!priv) {
@@ -911,37 +939,22 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out2;
}
- /* Finish setting up fields in lbs_private */
+ /* Set up fields in lbs_private */
card->priv = priv;
priv->card = card;
priv->hw_host_to_card = if_cs_host_to_card;
priv->enter_deep_sleep = NULL;
priv->exit_deep_sleep = NULL;
priv->reset_deep_sleep_wakeup = NULL;
- priv->fw_ready = 1;
- /* Now actually get the IRQ */
- ret = request_irq(p_dev->irq, if_cs_interrupt,
- IRQF_SHARED, DRV_NAME, card);
+ /* Get firmware */
+ ret = lbs_get_firmware_async(priv, &p_dev->dev, card->model, fw_table,
+ if_cs_prog_firmware);
if (ret) {
- pr_err("error in request_irq\n");
- goto out3;
- }
-
- /*
- * Clear any interrupt cause that happened while sending
- * firmware/initializing card
- */
- if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
- if_cs_enable_ints(card);
-
- /* And finally bring the card up */
- if (lbs_start_card(priv) != 0) {
- pr_err("could not activate card\n");
+ pr_err("failed to find firmware (%d)\n", ret);
goto out3;
}
- ret = 0;
goto out;
out3:
@@ -951,9 +964,6 @@ out2:
out1:
pcmcia_disable_device(p_dev);
out:
- release_firmware(helper);
- release_firmware(mainfw);
-
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
--
1.7.4.4
@@ -0,0 +1,30 @@
From 7608f165734eaeb530ba2442c0413e6e9630ad83 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Thu, 19 Apr 2012 13:54:12 +0200
Subject: [PATCH 16/17] libertas: add missing include
Without it, I get compile errors due to missing TASK_NORMAL,
TASK_UNINTERRUPTIBLE and schedule.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/libertas/firmware.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
index cd23f1a..77f6504 100644
--- a/drivers/net/wireless/libertas/firmware.c
+++ b/drivers/net/wireless/libertas/firmware.c
@@ -5,6 +5,7 @@
#include <linux/firmware.h>
#include <linux/firmware.h>
#include <linux/module.h>
+#include <linux/sched.h>
#include "dev.h"
#include "decl.h"
--
1.7.4.4
@@ -0,0 +1,36 @@
From 94938a2b8b1db241843abfe98168b81bf9273165 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@googlemail.com>
Date: Mon, 21 May 2012 17:01:23 +0200
Subject: [PATCH] remove debug msgs due to missing in_interrupt
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Andreas M??ller <schnitzeltony@googlemail.com>
---
drivers/net/wireless/libertas/defs.h | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index ab966f0..a80b40e 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -46,14 +46,7 @@
extern unsigned int lbs_debug;
-#ifdef DEBUG
-#define LBS_DEB_LL(grp, grpnam, fmt, args...) \
-do { if ((lbs_debug & (grp)) == (grp)) \
- printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
- in_interrupt() ? " (INT)" : "", ## args); } while (0)
-#else
#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
-#endif
#define lbs_deb_enter(grp) \
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
--
1.7.4.4
+18 -2
View File
@@ -10,7 +10,7 @@ PV = "3.2.18"
SRCREV_pn-${PN} = "52c6b95f8a2edaff98b779f15b2f4d69b61b18b9"
# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
MACHINE_KERNEL_PR_append = "a"
MACHINE_KERNEL_PR_append = "b"
FILESPATH =. "${FILE_DIRNAME}/linux-mainline-3.2:${FILE_DIRNAME}/linux-mainline-3.2/${MACHINE}:"
@@ -74,7 +74,23 @@ SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.gi
file://omap_fixes/0006-OMAP-HWMOD-add-es3plus-to-am36xx-am35xx.patch \
file://sgx/0001-Revert-OMAP-DSS2-remove-update_mode-from-omapdss-v3.2.patch \
file://led/0001-leds-heartbeat-stop-on-shutdown-reboot-or-panic.patch \
\
file://libertas/0001-USB-convert-drivers-net-to-use-module_usb_driver.patch \
file://libertas/0002-net-fix-assignment-of-0-1-to-bool-variables.patch \
file://libertas/0003-switch-debugfs-to-umode_t.patch \
file://libertas/0004-drivers-net-Remove-unnecessary-k.alloc-v.alloc-OOM-m.patch \
file://libertas/0005-libertas-remove-dump_survey-implementation.patch \
file://libertas/0007-wireless-libertas-remove-redundant-NULL-tests-before.patch \
file://libertas/0008-libertas-fix-signedness-bug-in-lbs_auth_to_authtype.patch \
file://libertas/0009-drivers-net-wireless-libertas-if_usb.c-add-missing-d.patch \
file://libertas/0010-libertas-Firmware-loading-simplifications.patch \
file://libertas/0011-libertas-harden-up-exit-paths.patch \
file://libertas/0012-libertas-add-asynchronous-firmware-loading-capabilit.patch \
file://libertas/0013-libertas-SDIO-convert-to-asynchronous-firmware-loadi.patch \
file://libertas/0014-libertas-USB-convert-to-asynchronous-firmware-loadin.patch \
file://libertas/0015-libertas-CS-convert-to-asynchronous-firmware-loading.patch \
file://libertas/0016-libertas-add-missing-include.patch \
file://libertas/0017-remove-debug-msgs-due-to-missing-in_interrupt.patch \
\
file://defconfig"
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \