diff options
author | Andreas Müller <schnitzeltony@googlemail.com> | 2012-05-25 11:11:57 +0200 |
---|---|---|
committer | Denys Dmytriyenko <denys@ti.com> | 2012-05-29 18:11:01 -0400 |
commit | 275240af94608bd4a2b4c2c7a6160a35c69031ed (patch) | |
tree | 5034eaea0a59e1b2c5668f893d8800f5c706630b | |
parent | a7426c1dad40adc586cb1cbdffebba6d095581a5 (diff) | |
download | meta-ti-275240af94608bd4a2b4c2c7a6160a35c69031ed.tar.gz |
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>
17 files changed, 2165 insertions, 2 deletions
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0001-USB-convert-drivers-net-to-use-module_usb_driver.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0001-USB-convert-drivers-net-to-use-module_usb_driver.patch new file mode 100644 index 00000000..92c77452 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0001-USB-convert-drivers-net-to-use-module_usb_driver.patch | |||
@@ -0,0 +1,80 @@ | |||
1 | From d632eb1bf22e11def74e4e53cc47d790fbdba105 Mon Sep 17 00:00:00 2001 | ||
2 | From: Greg Kroah-Hartman <gregkh@suse.de> | ||
3 | Date: Fri, 18 Nov 2011 09:44:20 -0800 | ||
4 | Subject: [PATCH 01/17] USB: convert drivers/net/* to use module_usb_driver() | ||
5 | |||
6 | This converts the drivers in drivers/net/* to use the | ||
7 | module_usb_driver() macro which makes the code smaller and a bit | ||
8 | simpler. | ||
9 | |||
10 | Added bonus is that it removes some unneeded kernel log messages about | ||
11 | drivers loading and/or unloading. | ||
12 | |||
13 | Cc: Wolfgang Grandegger <wg@grandegger.com> | ||
14 | Cc: Samuel Ortiz <samuel@sortiz.org> | ||
15 | Cc: Oliver Neukum <oliver@neukum.name> | ||
16 | Cc: Peter Korsgaard <jacmet@sunsite.dk> | ||
17 | Cc: Petko Manolov <petkan@users.sourceforge.net> | ||
18 | Cc: Steve Glendinning <steve.glendinning@smsc.com> | ||
19 | Cc: Christian Lamparter <chunkeey@googlemail.com> | ||
20 | Cc: "John W. Linville" <linville@tuxdriver.com> | ||
21 | Cc: Dan Williams <dcbw@redhat.com> | ||
22 | Cc: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | ||
23 | Cc: Ivo van Doorn <IvDoorn@gmail.com> | ||
24 | Cc: Gertjan van Wingerde <gwingerde@gmail.com> | ||
25 | Cc: Helmut Schaa <helmut.schaa@googlemail.com> | ||
26 | Cc: Herton Ronaldo Krzesinski <herton@canonical.com> | ||
27 | Cc: Hin-Tak Leung <htl10@users.sourceforge.net> | ||
28 | Cc: Larry Finger <Larry.Finger@lwfinger.net> | ||
29 | Cc: Chaoming Li <chaoming_li@realsil.com.cn> | ||
30 | Cc: Lucas De Marchi <lucas.demarchi@profusion.mobi> | ||
31 | Cc: "David S. Miller" <davem@davemloft.net> | ||
32 | Cc: Roel Kluin <roel.kluin@gmail.com> | ||
33 | Cc: Paul Gortmaker <paul.gortmaker@windriver.com> | ||
34 | Cc: Jiri Pirko <jpirko@redhat.com> | ||
35 | Cc: Pavel Roskin <proski@gnu.org> | ||
36 | Cc: Yoann DI-RUZZA <y.diruzza@lim.eu> | ||
37 | Cc: George <george0505@realtek.com> | ||
38 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | ||
39 | --- | ||
40 | drivers/net/wireless/libertas/if_usb.c | 24 +----------------------- | ||
41 | 1 files changed, 1 insertions(+), 23 deletions(-) | ||
42 | |||
43 | diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c | ||
44 | index db879c3..b5fbbc7 100644 | ||
45 | --- a/drivers/net/wireless/libertas/if_usb.c | ||
46 | +++ b/drivers/net/wireless/libertas/if_usb.c | ||
47 | @@ -1184,29 +1184,7 @@ static struct usb_driver if_usb_driver = { | ||
48 | .reset_resume = if_usb_resume, | ||
49 | }; | ||
50 | |||
51 | -static int __init if_usb_init_module(void) | ||
52 | -{ | ||
53 | - int ret = 0; | ||
54 | - | ||
55 | - lbs_deb_enter(LBS_DEB_MAIN); | ||
56 | - | ||
57 | - ret = usb_register(&if_usb_driver); | ||
58 | - | ||
59 | - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
60 | - return ret; | ||
61 | -} | ||
62 | - | ||
63 | -static void __exit if_usb_exit_module(void) | ||
64 | -{ | ||
65 | - lbs_deb_enter(LBS_DEB_MAIN); | ||
66 | - | ||
67 | - usb_deregister(&if_usb_driver); | ||
68 | - | ||
69 | - lbs_deb_leave(LBS_DEB_MAIN); | ||
70 | -} | ||
71 | - | ||
72 | -module_init(if_usb_init_module); | ||
73 | -module_exit(if_usb_exit_module); | ||
74 | +module_usb_driver(if_usb_driver); | ||
75 | |||
76 | MODULE_DESCRIPTION("8388 USB WLAN Driver"); | ||
77 | MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc."); | ||
78 | -- | ||
79 | 1.7.4.4 | ||
80 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0002-net-fix-assignment-of-0-1-to-bool-variables.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0002-net-fix-assignment-of-0-1-to-bool-variables.patch new file mode 100644 index 00000000..34ba936e --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0002-net-fix-assignment-of-0-1-to-bool-variables.patch | |||
@@ -0,0 +1,55 @@ | |||
1 | From 3db1cd5c05f35fb43eb134df6f321de4e63141f2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Rusty Russell <rusty@rustcorp.com.au> | ||
3 | Date: Mon, 19 Dec 2011 13:56:45 +0000 | ||
4 | Subject: [PATCH 02/17] net: fix assignment of 0/1 to bool variables. | ||
5 | |||
6 | DaveM said: | ||
7 | Please, this kind of stuff rots forever and not using bool properly | ||
8 | drives me crazy. | ||
9 | |||
10 | Joe Perches <joe@perches.com> gave me the spatch script: | ||
11 | |||
12 | @@ | ||
13 | bool b; | ||
14 | @@ | ||
15 | -b = 0 | ||
16 | +b = false | ||
17 | @@ | ||
18 | bool b; | ||
19 | @@ | ||
20 | -b = 1 | ||
21 | +b = true | ||
22 | |||
23 | I merely installed coccinelle, read the documentation and took credit. | ||
24 | |||
25 | Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> | ||
26 | Signed-off-by: David S. Miller <davem@davemloft.net> | ||
27 | --- | ||
28 | drivers/net/wireless/libertas/if_cs.c | 4 ++-- | ||
29 | 1 files changed, 2 insertions(+), 2 deletions(-) | ||
30 | |||
31 | diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c | ||
32 | index e269351..3f7bf4d 100644 | ||
33 | --- a/drivers/net/wireless/libertas/if_cs.c | ||
34 | +++ b/drivers/net/wireless/libertas/if_cs.c | ||
35 | @@ -859,7 +859,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
36 | * Most of the libertas cards can do unaligned register access, but some | ||
37 | * weird ones cannot. That's especially true for the CF8305 card. | ||
38 | */ | ||
39 | - card->align_regs = 0; | ||
40 | + card->align_regs = false; | ||
41 | |||
42 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | ||
43 | if (card->model == MODEL_UNKNOWN) { | ||
44 | @@ -871,7 +871,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
45 | /* Check if we have a current silicon */ | ||
46 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | ||
47 | if (card->model == MODEL_8305) { | ||
48 | - card->align_regs = 1; | ||
49 | + card->align_regs = true; | ||
50 | if (prod_id < IF_CS_CF8305_B1_REV) { | ||
51 | pr_err("8305 rev B0 and older are not supported\n"); | ||
52 | ret = -ENODEV; | ||
53 | -- | ||
54 | 1.7.4.4 | ||
55 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0003-switch-debugfs-to-umode_t.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0003-switch-debugfs-to-umode_t.patch new file mode 100644 index 00000000..896c7b62 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0003-switch-debugfs-to-umode_t.patch | |||
@@ -0,0 +1,26 @@ | |||
1 | From f4ae40a6a50a98ac23d4b285f739455e926a473e Mon Sep 17 00:00:00 2001 | ||
2 | From: Al Viro <viro@zeniv.linux.org.uk> | ||
3 | Date: Sun, 24 Jul 2011 04:33:43 -0400 | ||
4 | Subject: [PATCH 03/17] switch debugfs to umode_t | ||
5 | |||
6 | Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> | ||
7 | --- | ||
8 | drivers/net/wireless/libertas/debugfs.c | 2 +- | ||
9 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c | ||
12 | index d8d8f0d..c192671 100644 | ||
13 | --- a/drivers/net/wireless/libertas/debugfs.c | ||
14 | +++ b/drivers/net/wireless/libertas/debugfs.c | ||
15 | @@ -704,7 +704,7 @@ out_unlock: | ||
16 | |||
17 | struct lbs_debugfs_files { | ||
18 | const char *name; | ||
19 | - int perm; | ||
20 | + umode_t perm; | ||
21 | struct file_operations fops; | ||
22 | }; | ||
23 | |||
24 | -- | ||
25 | 1.7.4.4 | ||
26 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0004-drivers-net-Remove-unnecessary-k.alloc-v.alloc-OOM-m.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0004-drivers-net-Remove-unnecessary-k.alloc-v.alloc-OOM-m.patch new file mode 100644 index 00000000..7979f1c8 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0004-drivers-net-Remove-unnecessary-k.alloc-v.alloc-OOM-m.patch | |||
@@ -0,0 +1,54 @@ | |||
1 | From e404decb0fb017be80552adee894b35307b6c7b4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Joe Perches <joe@perches.com> | ||
3 | Date: Sun, 29 Jan 2012 12:56:23 +0000 | ||
4 | Subject: [PATCH 04/17] drivers/net: Remove unnecessary k.alloc/v.alloc OOM | ||
5 | messages | ||
6 | |||
7 | alloc failures use dump_stack so emitting an additional | ||
8 | out-of-memory message is an unnecessary duplication. | ||
9 | |||
10 | Remove the allocation failure messages. | ||
11 | |||
12 | Signed-off-by: Joe Perches <joe@perches.com> | ||
13 | Signed-off-by: David S. Miller <davem@davemloft.net> | ||
14 | --- | ||
15 | drivers/net/wireless/libertas/if_cs.c | 5 ++--- | ||
16 | drivers/net/wireless/libertas/if_usb.c | 4 +--- | ||
17 | 2 files changed, 3 insertions(+), 6 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c | ||
20 | index 3f7bf4d..234ee88 100644 | ||
21 | --- a/drivers/net/wireless/libertas/if_cs.c | ||
22 | +++ b/drivers/net/wireless/libertas/if_cs.c | ||
23 | @@ -815,10 +815,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
24 | lbs_deb_enter(LBS_DEB_CS); | ||
25 | |||
26 | card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL); | ||
27 | - if (!card) { | ||
28 | - pr_err("error in kzalloc\n"); | ||
29 | + if (!card) | ||
30 | goto out; | ||
31 | - } | ||
32 | + | ||
33 | card->p_dev = p_dev; | ||
34 | p_dev->priv = card; | ||
35 | |||
36 | diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c | ||
37 | index b5fbbc7..74da5f1 100644 | ||
38 | --- a/drivers/net/wireless/libertas/if_usb.c | ||
39 | +++ b/drivers/net/wireless/libertas/if_usb.c | ||
40 | @@ -261,10 +261,8 @@ static int if_usb_probe(struct usb_interface *intf, | ||
41 | udev = interface_to_usbdev(intf); | ||
42 | |||
43 | cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); | ||
44 | - if (!cardp) { | ||
45 | - pr_err("Out of memory allocating private data\n"); | ||
46 | + if (!cardp) | ||
47 | goto error; | ||
48 | - } | ||
49 | |||
50 | setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); | ||
51 | init_waitqueue_head(&cardp->fw_wq); | ||
52 | -- | ||
53 | 1.7.4.4 | ||
54 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0005-libertas-remove-dump_survey-implementation.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0005-libertas-remove-dump_survey-implementation.patch new file mode 100644 index 00000000..10e9c55b --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0005-libertas-remove-dump_survey-implementation.patch | |||
@@ -0,0 +1,80 @@ | |||
1 | From 377526578f2c343ea281a918b18ece1fca65005c Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Wed, 14 Mar 2012 22:34:33 +0000 | ||
4 | Subject: [PATCH 05/17] libertas: remove dump_survey implementation | ||
5 | |||
6 | libertas provides a dump_survey implementation based on reading of | ||
7 | a RSSI value. However, this RSSI value is calculated based on the | ||
8 | last received beacon from the associated AP - it is not a good | ||
9 | way of surveying a channel in general, and even causes an error | ||
10 | if the card is not associated to a network. | ||
11 | |||
12 | As this is not appropriate as a survey, remove it. This fixes an | ||
13 | issue where something in userspace is repeatedly calling site-survey | ||
14 | during boot, resulting in many repeated errors as the RSSI value cannot | ||
15 | be read before associating. | ||
16 | |||
17 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
18 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
19 | --- | ||
20 | drivers/net/wireless/libertas/cfg.c | 37 ----------------------------------- | ||
21 | 1 files changed, 0 insertions(+), 37 deletions(-) | ||
22 | |||
23 | diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c | ||
24 | index a7cd311..3fa1ece 100644 | ||
25 | --- a/drivers/net/wireless/libertas/cfg.c | ||
26 | +++ b/drivers/net/wireless/libertas/cfg.c | ||
27 | @@ -1631,42 +1631,6 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, | ||
28 | |||
29 | |||
30 | /* | ||
31 | - * "Site survey", here just current channel and noise level | ||
32 | - */ | ||
33 | - | ||
34 | -static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, | ||
35 | - int idx, struct survey_info *survey) | ||
36 | -{ | ||
37 | - struct lbs_private *priv = wiphy_priv(wiphy); | ||
38 | - s8 signal, noise; | ||
39 | - int ret; | ||
40 | - | ||
41 | - if (dev == priv->mesh_dev) | ||
42 | - return -EOPNOTSUPP; | ||
43 | - | ||
44 | - if (idx != 0) | ||
45 | - ret = -ENOENT; | ||
46 | - | ||
47 | - lbs_deb_enter(LBS_DEB_CFG80211); | ||
48 | - | ||
49 | - survey->channel = ieee80211_get_channel(wiphy, | ||
50 | - ieee80211_channel_to_frequency(priv->channel, | ||
51 | - IEEE80211_BAND_2GHZ)); | ||
52 | - | ||
53 | - ret = lbs_get_rssi(priv, &signal, &noise); | ||
54 | - if (ret == 0) { | ||
55 | - survey->filled = SURVEY_INFO_NOISE_DBM; | ||
56 | - survey->noise = noise; | ||
57 | - } | ||
58 | - | ||
59 | - lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
60 | - return ret; | ||
61 | -} | ||
62 | - | ||
63 | - | ||
64 | - | ||
65 | - | ||
66 | -/* | ||
67 | * Change interface | ||
68 | */ | ||
69 | |||
70 | @@ -2068,7 +2032,6 @@ static struct cfg80211_ops lbs_cfg80211_ops = { | ||
71 | .del_key = lbs_cfg_del_key, | ||
72 | .set_default_key = lbs_cfg_set_default_key, | ||
73 | .get_station = lbs_cfg_get_station, | ||
74 | - .dump_survey = lbs_get_survey, | ||
75 | .change_virtual_intf = lbs_change_intf, | ||
76 | .join_ibss = lbs_join_ibss, | ||
77 | .leave_ibss = lbs_leave_ibss, | ||
78 | -- | ||
79 | 1.7.4.4 | ||
80 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0007-wireless-libertas-remove-redundant-NULL-tests-before.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0007-wireless-libertas-remove-redundant-NULL-tests-before.patch new file mode 100644 index 00000000..d86b6e42 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0007-wireless-libertas-remove-redundant-NULL-tests-before.patch | |||
@@ -0,0 +1,95 @@ | |||
1 | From a7b957a277215da1830596c0791307a999fe5153 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jesper Juhl <jj@chaosbits.net> | ||
3 | Date: Mon, 9 Apr 2012 22:51:07 +0200 | ||
4 | Subject: [PATCH 07/17] wireless, libertas: remove redundant NULL tests before | ||
5 | calling release_firmware() | ||
6 | |||
7 | release_firmware() tests for, and deals gracefully with, NULL | ||
8 | pointers. Remove redundant explicit tests before calling the function. | ||
9 | |||
10 | Signed-off-by: Jesper Juhl <jj@chaosbits.net> | ||
11 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
12 | --- | ||
13 | drivers/net/wireless/libertas/if_cs.c | 6 ++---- | ||
14 | drivers/net/wireless/libertas/if_sdio.c | 6 ++---- | ||
15 | drivers/net/wireless/libertas/if_spi.c | 6 ++---- | ||
16 | drivers/net/wireless/libertas/main.c | 12 ++++-------- | ||
17 | 4 files changed, 10 insertions(+), 20 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c | ||
20 | index 234ee88..171a06b 100644 | ||
21 | --- a/drivers/net/wireless/libertas/if_cs.c | ||
22 | +++ b/drivers/net/wireless/libertas/if_cs.c | ||
23 | @@ -951,10 +951,8 @@ out2: | ||
24 | out1: | ||
25 | pcmcia_disable_device(p_dev); | ||
26 | out: | ||
27 | - if (helper) | ||
28 | - release_firmware(helper); | ||
29 | - if (mainfw) | ||
30 | - release_firmware(mainfw); | ||
31 | + release_firmware(helper); | ||
32 | + release_firmware(mainfw); | ||
33 | |||
34 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | ||
35 | return ret; | ||
36 | diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c | ||
37 | index 9804ebc..15bfe2f 100644 | ||
38 | --- a/drivers/net/wireless/libertas/if_sdio.c | ||
39 | +++ b/drivers/net/wireless/libertas/if_sdio.c | ||
40 | @@ -751,10 +751,8 @@ success: | ||
41 | ret = 0; | ||
42 | |||
43 | out: | ||
44 | - if (helper) | ||
45 | - release_firmware(helper); | ||
46 | - if (mainfw) | ||
47 | - release_firmware(mainfw); | ||
48 | + release_firmware(helper); | ||
49 | + release_firmware(mainfw); | ||
50 | |||
51 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
52 | return ret; | ||
53 | diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c | ||
54 | index 50b1ee7..7a5df4f 100644 | ||
55 | --- a/drivers/net/wireless/libertas/if_spi.c | ||
56 | +++ b/drivers/net/wireless/libertas/if_spi.c | ||
57 | @@ -1095,10 +1095,8 @@ static int if_spi_init_card(struct if_spi_card *card) | ||
58 | goto out; | ||
59 | |||
60 | out: | ||
61 | - if (helper) | ||
62 | - release_firmware(helper); | ||
63 | - if (mainfw) | ||
64 | - release_firmware(mainfw); | ||
65 | + release_firmware(helper); | ||
66 | + release_firmware(mainfw); | ||
67 | |||
68 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | ||
69 | |||
70 | diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c | ||
71 | index 957681d..3b81b70 100644 | ||
72 | --- a/drivers/net/wireless/libertas/main.c | ||
73 | +++ b/drivers/net/wireless/libertas/main.c | ||
74 | @@ -1269,14 +1269,10 @@ int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
75 | |||
76 | fail: | ||
77 | /* Failed */ | ||
78 | - if (*helper) { | ||
79 | - release_firmware(*helper); | ||
80 | - *helper = NULL; | ||
81 | - } | ||
82 | - if (*mainfw) { | ||
83 | - release_firmware(*mainfw); | ||
84 | - *mainfw = NULL; | ||
85 | - } | ||
86 | + release_firmware(*helper); | ||
87 | + *helper = NULL; | ||
88 | + release_firmware(*mainfw); | ||
89 | + *mainfw = NULL; | ||
90 | |||
91 | return -ENOENT; | ||
92 | } | ||
93 | -- | ||
94 | 1.7.4.4 | ||
95 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0008-libertas-fix-signedness-bug-in-lbs_auth_to_authtype.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0008-libertas-fix-signedness-bug-in-lbs_auth_to_authtype.patch new file mode 100644 index 00000000..0bacbca1 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0008-libertas-fix-signedness-bug-in-lbs_auth_to_authtype.patch | |||
@@ -0,0 +1,48 @@ | |||
1 | From effcc625eb4ab3b10b4744237fd37e8f7dcd6511 Mon Sep 17 00:00:00 2001 | ||
2 | From: Amitkumar Karwar <akarwar@marvell.com> | ||
3 | Date: Wed, 28 Mar 2012 11:38:01 -0700 | ||
4 | Subject: [PATCH 08/17] libertas: fix signedness bug in lbs_auth_to_authtype() | ||
5 | |||
6 | Return type for lbs_auth_to_authtype() is changed from "u8" to | ||
7 | "int" to return negative error code correctly. | ||
8 | Also an error check is added in connect handler for invalid auth | ||
9 | type. | ||
10 | |||
11 | Reported-by: Dan Carpenter <dan.carpenter@oracle.com> | ||
12 | Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> | ||
13 | Signed-off-by: Kiran Divekar <dkiran@marvell.com> | ||
14 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
15 | --- | ||
16 | drivers/net/wireless/libertas/cfg.c | 9 +++++++-- | ||
17 | 1 files changed, 7 insertions(+), 2 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c | ||
20 | index 3fa1ece..2fa879b 100644 | ||
21 | --- a/drivers/net/wireless/libertas/cfg.c | ||
22 | +++ b/drivers/net/wireless/libertas/cfg.c | ||
23 | @@ -103,7 +103,7 @@ static const u32 cipher_suites[] = { | ||
24 | * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1 | ||
25 | * in the firmware spec | ||
26 | */ | ||
27 | -static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type) | ||
28 | +static int lbs_auth_to_authtype(enum nl80211_auth_type auth_type) | ||
29 | { | ||
30 | int ret = -ENOTSUPP; | ||
31 | |||
32 | @@ -1411,7 +1411,12 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | ||
33 | goto done; | ||
34 | } | ||
35 | |||
36 | - lbs_set_authtype(priv, sme); | ||
37 | + ret = lbs_set_authtype(priv, sme); | ||
38 | + if (ret == -ENOTSUPP) { | ||
39 | + wiphy_err(wiphy, "unsupported authtype 0x%x\n", sme->auth_type); | ||
40 | + goto done; | ||
41 | + } | ||
42 | + | ||
43 | lbs_set_radio(priv, preamble, 1); | ||
44 | |||
45 | /* Do the actual association */ | ||
46 | -- | ||
47 | 1.7.4.4 | ||
48 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0009-drivers-net-wireless-libertas-if_usb.c-add-missing-d.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0009-drivers-net-wireless-libertas-if_usb.c-add-missing-d.patch new file mode 100644 index 00000000..34778146 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0009-drivers-net-wireless-libertas-if_usb.c-add-missing-d.patch | |||
@@ -0,0 +1,35 @@ | |||
1 | From 1e66eda1d40c9ce3ff38782da066a14e1b88ac50 Mon Sep 17 00:00:00 2001 | ||
2 | From: Julia Lawall <Julia.Lawall@lip6.fr> | ||
3 | Date: Mon, 16 Apr 2012 17:44:00 +0200 | ||
4 | Subject: [PATCH 09/17] drivers/net/wireless/libertas/if_usb.c: add missing | ||
5 | debugging code | ||
6 | |||
7 | Add a corresponding leave call on error failure. | ||
8 | |||
9 | Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> | ||
10 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
11 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
12 | --- | ||
13 | drivers/net/wireless/libertas/if_usb.c | 6 ++++-- | ||
14 | 1 files changed, 4 insertions(+), 2 deletions(-) | ||
15 | |||
16 | diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c | ||
17 | index 74da5f1..ce4938d 100644 | ||
18 | --- a/drivers/net/wireless/libertas/if_usb.c | ||
19 | +++ b/drivers/net/wireless/libertas/if_usb.c | ||
20 | @@ -1128,8 +1128,10 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
21 | |||
22 | lbs_deb_enter(LBS_DEB_USB); | ||
23 | |||
24 | - if (priv->psstate != PS_STATE_FULL_POWER) | ||
25 | - return -1; | ||
26 | + if (priv->psstate != PS_STATE_FULL_POWER) { | ||
27 | + ret = -1; | ||
28 | + goto out; | ||
29 | + } | ||
30 | |||
31 | #ifdef CONFIG_OLPC | ||
32 | if (machine_is_olpc()) { | ||
33 | -- | ||
34 | 1.7.4.4 | ||
35 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0010-libertas-Firmware-loading-simplifications.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0010-libertas-Firmware-loading-simplifications.patch new file mode 100644 index 00000000..06d82187 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0010-libertas-Firmware-loading-simplifications.patch | |||
@@ -0,0 +1,618 @@ | |||
1 | From 370803c25dd77332ee4ca97884c3a5e1e1eafbca Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Mon, 16 Apr 2012 23:52:42 +0100 | ||
4 | Subject: [PATCH 10/17] libertas: Firmware loading simplifications | ||
5 | |||
6 | Remove the ability to pass module parameters with firmware filenames | ||
7 | for USB and SDIO interfaces. | ||
8 | |||
9 | Remove the ability to pass custom "user" filenames to lbs_get_firmware(). | ||
10 | |||
11 | Remove the ability to reprogram internal device memory with a different | ||
12 | firmware from the USB driver (we don't know of any users), and simplify | ||
13 | the OLPC firmware loading quirk to simply placing the OLPC firmware | ||
14 | at the top of the list (we don't know of any users other than OLPC). | ||
15 | |||
16 | Move lbs_get_firmware() into its own file. | ||
17 | |||
18 | These simplifications should have no real-life effect but make the | ||
19 | upcoming transition to asynchronous firmware loading considerably less | ||
20 | painful. | ||
21 | |||
22 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
23 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
24 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
25 | --- | ||
26 | drivers/net/wireless/libertas/Makefile | 1 + | ||
27 | drivers/net/wireless/libertas/decl.h | 3 +- | ||
28 | drivers/net/wireless/libertas/firmware.c | 79 ++++++++++++++ | ||
29 | drivers/net/wireless/libertas/if_cs.c | 4 +- | ||
30 | drivers/net/wireless/libertas/if_sdio.c | 25 +---- | ||
31 | drivers/net/wireless/libertas/if_spi.c | 5 +- | ||
32 | drivers/net/wireless/libertas/if_usb.c | 169 ++---------------------------- | ||
33 | drivers/net/wireless/libertas/main.c | 101 ------------------ | ||
34 | 8 files changed, 94 insertions(+), 293 deletions(-) | ||
35 | create mode 100644 drivers/net/wireless/libertas/firmware.c | ||
36 | |||
37 | diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile | ||
38 | index f7d01bf..eac72f7 100644 | ||
39 | --- a/drivers/net/wireless/libertas/Makefile | ||
40 | +++ b/drivers/net/wireless/libertas/Makefile | ||
41 | @@ -6,6 +6,7 @@ libertas-y += ethtool.o | ||
42 | libertas-y += main.o | ||
43 | libertas-y += rx.o | ||
44 | libertas-y += tx.o | ||
45 | +libertas-y += firmware.o | ||
46 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | ||
47 | |||
48 | usb8xxx-objs += if_usb.o | ||
49 | diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h | ||
50 | index bc951ab..2fb2e31 100644 | ||
51 | --- a/drivers/net/wireless/libertas/decl.h | ||
52 | +++ b/drivers/net/wireless/libertas/decl.h | ||
53 | @@ -66,8 +66,7 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | ||
54 | u32 lbs_fw_index_to_data_rate(u8 index); | ||
55 | u8 lbs_data_rate_to_fw_index(u32 rate); | ||
56 | |||
57 | -int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
58 | - const char *user_mainfw, u32 card_model, | ||
59 | +int lbs_get_firmware(struct device *dev, u32 card_model, | ||
60 | const struct lbs_fw_table *fw_table, | ||
61 | const struct firmware **helper, | ||
62 | const struct firmware **mainfw); | ||
63 | diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c | ||
64 | new file mode 100644 | ||
65 | index 0000000..0c8c845 | ||
66 | --- /dev/null | ||
67 | +++ b/drivers/net/wireless/libertas/firmware.c | ||
68 | @@ -0,0 +1,79 @@ | ||
69 | +/* | ||
70 | + * Firmware loading and handling functions. | ||
71 | + */ | ||
72 | + | ||
73 | +#include <linux/firmware.h> | ||
74 | +#include <linux/module.h> | ||
75 | + | ||
76 | +#include "decl.h" | ||
77 | + | ||
78 | +/** | ||
79 | + * lbs_get_firmware - Retrieves two-stage firmware | ||
80 | + * | ||
81 | + * @dev: A pointer to &device structure | ||
82 | + * @card_model: Bus-specific card model ID used to filter firmware table | ||
83 | + * elements | ||
84 | + * @fw_table: Table of firmware file names and device model numbers | ||
85 | + * terminated by an entry with a NULL helper name | ||
86 | + * @helper: On success, the helper firmware; caller must free | ||
87 | + * @mainfw: On success, the main firmware; caller must free | ||
88 | + * | ||
89 | + * returns: 0 on success, non-zero on failure | ||
90 | + */ | ||
91 | +int lbs_get_firmware(struct device *dev, u32 card_model, | ||
92 | + const struct lbs_fw_table *fw_table, | ||
93 | + const struct firmware **helper, | ||
94 | + const struct firmware **mainfw) | ||
95 | +{ | ||
96 | + const struct lbs_fw_table *iter; | ||
97 | + int ret; | ||
98 | + | ||
99 | + BUG_ON(helper == NULL); | ||
100 | + BUG_ON(mainfw == NULL); | ||
101 | + | ||
102 | + /* Search for firmware to use from the table. */ | ||
103 | + iter = fw_table; | ||
104 | + while (iter && iter->helper) { | ||
105 | + if (iter->model != card_model) | ||
106 | + goto next; | ||
107 | + | ||
108 | + if (*helper == NULL) { | ||
109 | + ret = request_firmware(helper, iter->helper, dev); | ||
110 | + if (ret) | ||
111 | + goto next; | ||
112 | + | ||
113 | + /* If the device has one-stage firmware (ie cf8305) and | ||
114 | + * we've got it then we don't need to bother with the | ||
115 | + * main firmware. | ||
116 | + */ | ||
117 | + if (iter->fwname == NULL) | ||
118 | + return 0; | ||
119 | + } | ||
120 | + | ||
121 | + if (*mainfw == NULL) { | ||
122 | + ret = request_firmware(mainfw, iter->fwname, dev); | ||
123 | + if (ret) { | ||
124 | + /* Clear the helper to ensure we don't have | ||
125 | + * mismatched firmware pairs. | ||
126 | + */ | ||
127 | + release_firmware(*helper); | ||
128 | + *helper = NULL; | ||
129 | + } | ||
130 | + } | ||
131 | + | ||
132 | + if (*helper && *mainfw) | ||
133 | + return 0; | ||
134 | + | ||
135 | + next: | ||
136 | + iter++; | ||
137 | + } | ||
138 | + | ||
139 | + /* Failed */ | ||
140 | + release_firmware(*helper); | ||
141 | + *helper = NULL; | ||
142 | + release_firmware(*mainfw); | ||
143 | + *mainfw = NULL; | ||
144 | + | ||
145 | + return -ENOENT; | ||
146 | +} | ||
147 | +EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
148 | diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c | ||
149 | index 171a06b..cee5052 100644 | ||
150 | --- a/drivers/net/wireless/libertas/if_cs.c | ||
151 | +++ b/drivers/net/wireless/libertas/if_cs.c | ||
152 | @@ -890,8 +890,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
153 | goto out2; | ||
154 | } | ||
155 | |||
156 | - ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | ||
157 | - &fw_table[0], &helper, &mainfw); | ||
158 | + ret = lbs_get_firmware(&p_dev->dev, card->model, &fw_table[0], | ||
159 | + &helper, &mainfw); | ||
160 | if (ret) { | ||
161 | pr_err("failed to find firmware (%d)\n", ret); | ||
162 | goto out2; | ||
163 | diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c | ||
164 | index 15bfe2f..6590feb 100644 | ||
165 | --- a/drivers/net/wireless/libertas/if_sdio.c | ||
166 | +++ b/drivers/net/wireless/libertas/if_sdio.c | ||
167 | @@ -65,12 +65,6 @@ static void if_sdio_interrupt(struct sdio_func *func); | ||
168 | */ | ||
169 | static u8 user_rmmod; | ||
170 | |||
171 | -static char *lbs_helper_name = NULL; | ||
172 | -module_param_named(helper_name, lbs_helper_name, charp, 0644); | ||
173 | - | ||
174 | -static char *lbs_fw_name = NULL; | ||
175 | -module_param_named(fw_name, lbs_fw_name, charp, 0644); | ||
176 | - | ||
177 | static const struct sdio_device_id if_sdio_ids[] = { | ||
178 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, | ||
179 | SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, | ||
180 | @@ -124,11 +118,6 @@ struct if_sdio_card { | ||
181 | unsigned long ioport; | ||
182 | unsigned int scratch_reg; | ||
183 | |||
184 | - const char *helper; | ||
185 | - const char *firmware; | ||
186 | - bool helper_allocated; | ||
187 | - bool firmware_allocated; | ||
188 | - | ||
189 | u8 buffer[65536] __attribute__((aligned(4))); | ||
190 | |||
191 | spinlock_t lock; | ||
192 | @@ -725,8 +714,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | ||
193 | goto success; | ||
194 | } | ||
195 | |||
196 | - ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, | ||
197 | - card->model, &fw_table[0], &helper, &mainfw); | ||
198 | + ret = lbs_get_firmware(&card->func->dev, card->model, &fw_table[0], | ||
199 | + &helper, &mainfw); | ||
200 | if (ret) { | ||
201 | pr_err("failed to find firmware (%d)\n", ret); | ||
202 | goto out; | ||
203 | @@ -1242,10 +1231,6 @@ free: | ||
204 | kfree(packet); | ||
205 | } | ||
206 | |||
207 | - if (card->helper_allocated) | ||
208 | - kfree(card->helper); | ||
209 | - if (card->firmware_allocated) | ||
210 | - kfree(card->firmware); | ||
211 | kfree(card); | ||
212 | |||
213 | goto out; | ||
214 | @@ -1293,12 +1278,6 @@ static void if_sdio_remove(struct sdio_func *func) | ||
215 | kfree(packet); | ||
216 | } | ||
217 | |||
218 | - if (card->helper_allocated) | ||
219 | - kfree(card->helper); | ||
220 | - if (card->firmware_allocated) | ||
221 | - kfree(card->firmware); | ||
222 | - kfree(card); | ||
223 | - | ||
224 | lbs_deb_leave(LBS_DEB_SDIO); | ||
225 | } | ||
226 | |||
227 | diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c | ||
228 | index 7a5df4f..9604a1c 100644 | ||
229 | --- a/drivers/net/wireless/libertas/if_spi.c | ||
230 | +++ b/drivers/net/wireless/libertas/if_spi.c | ||
231 | @@ -1064,9 +1064,8 @@ static int if_spi_init_card(struct if_spi_card *card) | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | - err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | ||
236 | - card->card_id, &fw_table[0], &helper, | ||
237 | - &mainfw); | ||
238 | + err = lbs_get_firmware(&card->spi->dev, card->card_id, | ||
239 | + &fw_table[0], &helper, &mainfw); | ||
240 | if (err) { | ||
241 | netdev_err(priv->dev, "failed to find firmware (%d)\n", | ||
242 | err); | ||
243 | diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c | ||
244 | index ce4938d..f29471b 100644 | ||
245 | --- a/drivers/net/wireless/libertas/if_usb.c | ||
246 | +++ b/drivers/net/wireless/libertas/if_usb.c | ||
247 | @@ -29,9 +29,6 @@ | ||
248 | |||
249 | #define MESSAGE_HEADER_LEN 4 | ||
250 | |||
251 | -static char *lbs_fw_name = NULL; | ||
252 | -module_param_named(fw_name, lbs_fw_name, charp, 0644); | ||
253 | - | ||
254 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); | ||
255 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); | ||
256 | MODULE_FIRMWARE("libertas/usb8388.bin"); | ||
257 | @@ -55,10 +52,7 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); | ||
258 | |||
259 | static void if_usb_receive(struct urb *urb); | ||
260 | static void if_usb_receive_fwload(struct urb *urb); | ||
261 | -static int __if_usb_prog_firmware(struct if_usb_card *cardp, | ||
262 | - const char *fwname, int cmd); | ||
263 | -static int if_usb_prog_firmware(struct if_usb_card *cardp, | ||
264 | - const char *fwname, int cmd); | ||
265 | +static int if_usb_prog_firmware(struct if_usb_card *cardp); | ||
266 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | ||
267 | uint8_t *payload, uint16_t nb); | ||
268 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | ||
269 | @@ -67,69 +61,6 @@ static void if_usb_free(struct if_usb_card *cardp); | ||
270 | static int if_usb_submit_rx_urb(struct if_usb_card *cardp); | ||
271 | static int if_usb_reset_device(struct if_usb_card *cardp); | ||
272 | |||
273 | -/* sysfs hooks */ | ||
274 | - | ||
275 | -/* | ||
276 | - * Set function to write firmware to device's persistent memory | ||
277 | - */ | ||
278 | -static ssize_t if_usb_firmware_set(struct device *dev, | ||
279 | - struct device_attribute *attr, const char *buf, size_t count) | ||
280 | -{ | ||
281 | - struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
282 | - struct if_usb_card *cardp = priv->card; | ||
283 | - int ret; | ||
284 | - | ||
285 | - BUG_ON(buf == NULL); | ||
286 | - | ||
287 | - ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); | ||
288 | - if (ret == 0) | ||
289 | - return count; | ||
290 | - | ||
291 | - return ret; | ||
292 | -} | ||
293 | - | ||
294 | -/* | ||
295 | - * lbs_flash_fw attribute to be exported per ethX interface through sysfs | ||
296 | - * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to | ||
297 | - * the device's persistent memory: | ||
298 | - * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw | ||
299 | - */ | ||
300 | -static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); | ||
301 | - | ||
302 | -/** | ||
303 | - * if_usb_boot2_set - write firmware to device's persistent memory | ||
304 | - * | ||
305 | - * @dev: target device | ||
306 | - * @attr: device attributes | ||
307 | - * @buf: firmware buffer to write | ||
308 | - * @count: number of bytes to write | ||
309 | - * | ||
310 | - * returns: number of bytes written or negative error code | ||
311 | - */ | ||
312 | -static ssize_t if_usb_boot2_set(struct device *dev, | ||
313 | - struct device_attribute *attr, const char *buf, size_t count) | ||
314 | -{ | ||
315 | - struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
316 | - struct if_usb_card *cardp = priv->card; | ||
317 | - int ret; | ||
318 | - | ||
319 | - BUG_ON(buf == NULL); | ||
320 | - | ||
321 | - ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); | ||
322 | - if (ret == 0) | ||
323 | - return count; | ||
324 | - | ||
325 | - return ret; | ||
326 | -} | ||
327 | - | ||
328 | -/* | ||
329 | - * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs | ||
330 | - * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware | ||
331 | - * to the device's persistent memory: | ||
332 | - * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2 | ||
333 | - */ | ||
334 | -static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); | ||
335 | - | ||
336 | /** | ||
337 | * if_usb_write_bulk_callback - callback function to handle the status | ||
338 | * of the URB | ||
339 | @@ -314,13 +245,10 @@ static int if_usb_probe(struct usb_interface *intf, | ||
340 | } | ||
341 | |||
342 | /* Upload firmware */ | ||
343 | - kparam_block_sysfs_write(fw_name); | ||
344 | - if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { | ||
345 | - kparam_unblock_sysfs_write(fw_name); | ||
346 | + if (if_usb_prog_firmware(cardp)) { | ||
347 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | ||
348 | goto err_prog_firmware; | ||
349 | } | ||
350 | - kparam_unblock_sysfs_write(fw_name); | ||
351 | |||
352 | if (!(priv = lbs_add_card(cardp, &intf->dev))) | ||
353 | goto err_prog_firmware; | ||
354 | @@ -349,14 +277,6 @@ static int if_usb_probe(struct usb_interface *intf, | ||
355 | usb_get_dev(udev); | ||
356 | usb_set_intfdata(intf, cardp); | ||
357 | |||
358 | - if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) | ||
359 | - netdev_err(priv->dev, | ||
360 | - "cannot register lbs_flash_fw attribute\n"); | ||
361 | - | ||
362 | - if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) | ||
363 | - netdev_err(priv->dev, | ||
364 | - "cannot register lbs_flash_boot2 attribute\n"); | ||
365 | - | ||
366 | /* | ||
367 | * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | ||
368 | */ | ||
369 | @@ -389,9 +309,6 @@ static void if_usb_disconnect(struct usb_interface *intf) | ||
370 | |||
371 | lbs_deb_enter(LBS_DEB_MAIN); | ||
372 | |||
373 | - device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2); | ||
374 | - device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw); | ||
375 | - | ||
376 | cardp->surprise_removed = 1; | ||
377 | |||
378 | if (priv) { | ||
379 | @@ -912,58 +829,12 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) | ||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | - | ||
384 | -/** | ||
385 | -* if_usb_prog_firmware - programs the firmware subject to cmd | ||
386 | -* | ||
387 | -* @cardp: the if_usb_card descriptor | ||
388 | -* @fwname: firmware or boot2 image file name | ||
389 | -* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, | ||
390 | -* or BOOT_CMD_UPDATE_BOOT2. | ||
391 | -* returns: 0 or error code | ||
392 | -*/ | ||
393 | -static int if_usb_prog_firmware(struct if_usb_card *cardp, | ||
394 | - const char *fwname, int cmd) | ||
395 | -{ | ||
396 | - struct lbs_private *priv = cardp->priv; | ||
397 | - unsigned long flags, caps; | ||
398 | - int ret; | ||
399 | - | ||
400 | - caps = priv->fwcapinfo; | ||
401 | - if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) || | ||
402 | - ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE))) | ||
403 | - return -EOPNOTSUPP; | ||
404 | - | ||
405 | - /* Ensure main thread is idle. */ | ||
406 | - spin_lock_irqsave(&priv->driver_lock, flags); | ||
407 | - while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) { | ||
408 | - spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
409 | - if (wait_event_interruptible(priv->waitq, | ||
410 | - (priv->cur_cmd == NULL && | ||
411 | - priv->dnld_sent == DNLD_RES_RECEIVED))) { | ||
412 | - return -ERESTARTSYS; | ||
413 | - } | ||
414 | - spin_lock_irqsave(&priv->driver_lock, flags); | ||
415 | - } | ||
416 | - priv->dnld_sent = DNLD_BOOTCMD_SENT; | ||
417 | - spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
418 | - | ||
419 | - ret = __if_usb_prog_firmware(cardp, fwname, cmd); | ||
420 | - | ||
421 | - spin_lock_irqsave(&priv->driver_lock, flags); | ||
422 | - priv->dnld_sent = DNLD_RES_RECEIVED; | ||
423 | - spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
424 | - | ||
425 | - wake_up(&priv->waitq); | ||
426 | - | ||
427 | - return ret; | ||
428 | -} | ||
429 | - | ||
430 | /* table of firmware file names */ | ||
431 | static const struct { | ||
432 | u32 model; | ||
433 | const char *fwname; | ||
434 | } fw_table[] = { | ||
435 | + { MODEL_8388, "libertas/usb8388_olpc.bin" }, | ||
436 | { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
437 | { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
438 | { MODEL_8388, "libertas/usb8388.bin" }, | ||
439 | @@ -971,35 +842,10 @@ static const struct { | ||
440 | { MODEL_8682, "libertas/usb8682.bin" } | ||
441 | }; | ||
442 | |||
443 | -#ifdef CONFIG_OLPC | ||
444 | - | ||
445 | -static int try_olpc_fw(struct if_usb_card *cardp) | ||
446 | -{ | ||
447 | - int retval = -ENOENT; | ||
448 | - | ||
449 | - /* try the OLPC firmware first; fall back to fw_table list */ | ||
450 | - if (machine_is_olpc() && cardp->model == MODEL_8388) | ||
451 | - retval = request_firmware(&cardp->fw, | ||
452 | - "libertas/usb8388_olpc.bin", &cardp->udev->dev); | ||
453 | - return retval; | ||
454 | -} | ||
455 | - | ||
456 | -#else | ||
457 | -static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; } | ||
458 | -#endif /* !CONFIG_OLPC */ | ||
459 | - | ||
460 | -static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
461 | +static int get_fw(struct if_usb_card *cardp) | ||
462 | { | ||
463 | int i; | ||
464 | |||
465 | - /* Try user-specified firmware first */ | ||
466 | - if (fwname) | ||
467 | - return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | ||
468 | - | ||
469 | - /* Handle OLPC firmware */ | ||
470 | - if (try_olpc_fw(cardp) == 0) | ||
471 | - return 0; | ||
472 | - | ||
473 | /* Otherwise search for firmware to use */ | ||
474 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
475 | if (fw_table[i].model != cardp->model) | ||
476 | @@ -1012,8 +858,7 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
477 | return -ENOENT; | ||
478 | } | ||
479 | |||
480 | -static int __if_usb_prog_firmware(struct if_usb_card *cardp, | ||
481 | - const char *fwname, int cmd) | ||
482 | +static int if_usb_prog_firmware(struct if_usb_card *cardp) | ||
483 | { | ||
484 | int i = 0; | ||
485 | static int reset_count = 10; | ||
486 | @@ -1021,7 +866,7 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, | ||
487 | |||
488 | lbs_deb_enter(LBS_DEB_USB); | ||
489 | |||
490 | - ret = get_fw(cardp, fwname); | ||
491 | + ret = get_fw(cardp); | ||
492 | if (ret) { | ||
493 | pr_err("failed to find firmware (%d)\n", ret); | ||
494 | goto done; | ||
495 | @@ -1053,7 +898,7 @@ restart: | ||
496 | do { | ||
497 | int j = 0; | ||
498 | i++; | ||
499 | - if_usb_issue_boot_command(cardp, cmd); | ||
500 | + if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB); | ||
501 | /* wait for command response */ | ||
502 | do { | ||
503 | j++; | ||
504 | diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c | ||
505 | index 3b81b70..fa09585 100644 | ||
506 | --- a/drivers/net/wireless/libertas/main.c | ||
507 | +++ b/drivers/net/wireless/libertas/main.c | ||
508 | @@ -1177,107 +1177,6 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | ||
509 | } | ||
510 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); | ||
511 | |||
512 | -/** | ||
513 | - * lbs_get_firmware - Retrieves two-stage firmware | ||
514 | - * | ||
515 | - * @dev: A pointer to &device structure | ||
516 | - * @user_helper: User-defined helper firmware file | ||
517 | - * @user_mainfw: User-defined main firmware file | ||
518 | - * @card_model: Bus-specific card model ID used to filter firmware table | ||
519 | - * elements | ||
520 | - * @fw_table: Table of firmware file names and device model numbers | ||
521 | - * terminated by an entry with a NULL helper name | ||
522 | - * @helper: On success, the helper firmware; caller must free | ||
523 | - * @mainfw: On success, the main firmware; caller must free | ||
524 | - * | ||
525 | - * returns: 0 on success, non-zero on failure | ||
526 | - */ | ||
527 | -int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
528 | - const char *user_mainfw, u32 card_model, | ||
529 | - const struct lbs_fw_table *fw_table, | ||
530 | - const struct firmware **helper, | ||
531 | - const struct firmware **mainfw) | ||
532 | -{ | ||
533 | - const struct lbs_fw_table *iter; | ||
534 | - int ret; | ||
535 | - | ||
536 | - BUG_ON(helper == NULL); | ||
537 | - BUG_ON(mainfw == NULL); | ||
538 | - | ||
539 | - /* Try user-specified firmware first */ | ||
540 | - if (user_helper) { | ||
541 | - ret = request_firmware(helper, user_helper, dev); | ||
542 | - if (ret) { | ||
543 | - dev_err(dev, "couldn't find helper firmware %s\n", | ||
544 | - user_helper); | ||
545 | - goto fail; | ||
546 | - } | ||
547 | - } | ||
548 | - if (user_mainfw) { | ||
549 | - ret = request_firmware(mainfw, user_mainfw, dev); | ||
550 | - if (ret) { | ||
551 | - dev_err(dev, "couldn't find main firmware %s\n", | ||
552 | - user_mainfw); | ||
553 | - goto fail; | ||
554 | - } | ||
555 | - } | ||
556 | - | ||
557 | - if (*helper && *mainfw) | ||
558 | - return 0; | ||
559 | - | ||
560 | - /* Otherwise search for firmware to use. If neither the helper or | ||
561 | - * the main firmware were specified by the user, then we need to | ||
562 | - * make sure that found helper & main are from the same entry in | ||
563 | - * fw_table. | ||
564 | - */ | ||
565 | - iter = fw_table; | ||
566 | - while (iter && iter->helper) { | ||
567 | - if (iter->model != card_model) | ||
568 | - goto next; | ||
569 | - | ||
570 | - if (*helper == NULL) { | ||
571 | - ret = request_firmware(helper, iter->helper, dev); | ||
572 | - if (ret) | ||
573 | - goto next; | ||
574 | - | ||
575 | - /* If the device has one-stage firmware (ie cf8305) and | ||
576 | - * we've got it then we don't need to bother with the | ||
577 | - * main firmware. | ||
578 | - */ | ||
579 | - if (iter->fwname == NULL) | ||
580 | - return 0; | ||
581 | - } | ||
582 | - | ||
583 | - if (*mainfw == NULL) { | ||
584 | - ret = request_firmware(mainfw, iter->fwname, dev); | ||
585 | - if (ret && !user_helper) { | ||
586 | - /* Clear the helper if it wasn't user-specified | ||
587 | - * and the main firmware load failed, to ensure | ||
588 | - * we don't have mismatched firmware pairs. | ||
589 | - */ | ||
590 | - release_firmware(*helper); | ||
591 | - *helper = NULL; | ||
592 | - } | ||
593 | - } | ||
594 | - | ||
595 | - if (*helper && *mainfw) | ||
596 | - return 0; | ||
597 | - | ||
598 | - next: | ||
599 | - iter++; | ||
600 | - } | ||
601 | - | ||
602 | - fail: | ||
603 | - /* Failed */ | ||
604 | - release_firmware(*helper); | ||
605 | - *helper = NULL; | ||
606 | - release_firmware(*mainfw); | ||
607 | - *mainfw = NULL; | ||
608 | - | ||
609 | - return -ENOENT; | ||
610 | -} | ||
611 | -EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
612 | - | ||
613 | static int __init lbs_init_module(void) | ||
614 | { | ||
615 | lbs_deb_enter(LBS_DEB_MAIN); | ||
616 | -- | ||
617 | 1.7.4.4 | ||
618 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0011-libertas-harden-up-exit-paths.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0011-libertas-harden-up-exit-paths.patch new file mode 100644 index 00000000..4891dea8 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0011-libertas-harden-up-exit-paths.patch | |||
@@ -0,0 +1,46 @@ | |||
1 | From 0beecac8abb3af890d470df541142d55343382d6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Mon, 16 Apr 2012 23:53:02 +0100 | ||
4 | Subject: [PATCH 11/17] libertas: harden-up exit paths | ||
5 | |||
6 | These simple sanity check avoids extra complexity in error paths when | ||
7 | moving to asynchronous firmware loading (which means the device may fail to | ||
8 | init some time after its creation). | ||
9 | |||
10 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
11 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
12 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
13 | --- | ||
14 | drivers/net/wireless/libertas/main.c | 9 ++++++++- | ||
15 | 1 files changed, 8 insertions(+), 1 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c | ||
18 | index fa09585..7eaf992 100644 | ||
19 | --- a/drivers/net/wireless/libertas/main.c | ||
20 | +++ b/drivers/net/wireless/libertas/main.c | ||
21 | @@ -1033,7 +1033,9 @@ void lbs_remove_card(struct lbs_private *priv) | ||
22 | lbs_deb_enter(LBS_DEB_MAIN); | ||
23 | |||
24 | lbs_remove_mesh(priv); | ||
25 | - lbs_scan_deinit(priv); | ||
26 | + | ||
27 | + if (priv->wiphy_registered) | ||
28 | + lbs_scan_deinit(priv); | ||
29 | |||
30 | /* worker thread destruction blocks on the in-flight command which | ||
31 | * should have been cleared already in lbs_stop_card(). | ||
32 | @@ -1128,6 +1130,11 @@ void lbs_stop_card(struct lbs_private *priv) | ||
33 | goto out; | ||
34 | dev = priv->dev; | ||
35 | |||
36 | + /* If the netdev isn't registered, it means that lbs_start_card() was | ||
37 | + * never called so we have nothing to do here. */ | ||
38 | + if (dev->reg_state != NETREG_REGISTERED) | ||
39 | + goto out; | ||
40 | + | ||
41 | netif_stop_queue(dev); | ||
42 | netif_carrier_off(dev); | ||
43 | |||
44 | -- | ||
45 | 1.7.4.4 | ||
46 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0012-libertas-add-asynchronous-firmware-loading-capabilit.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0012-libertas-add-asynchronous-firmware-loading-capabilit.patch new file mode 100644 index 00000000..58963b3e --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0012-libertas-add-asynchronous-firmware-loading-capabilit.patch | |||
@@ -0,0 +1,269 @@ | |||
1 | From 534111c78c59a8db89c570fd07489243dc366a05 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Mon, 16 Apr 2012 23:53:26 +0100 | ||
4 | Subject: [PATCH 12/17] libertas: add asynchronous firmware loading capability | ||
5 | |||
6 | As described at | ||
7 | http://article.gmane.org/gmane.linux.kernel.wireless.general/86084 | ||
8 | libertas is taking a long time to load because it loads firmware | ||
9 | during module loading. | ||
10 | |||
11 | Add a new API for interface drivers to load their firmware | ||
12 | asynchronously. The same semantics of the firmware table are followed | ||
13 | like before. | ||
14 | |||
15 | Interface drivers will be converted in follow-up patches, then we can | ||
16 | remove the old, synchronous firmware loading function. | ||
17 | |||
18 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
19 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
20 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
21 | --- | ||
22 | drivers/net/wireless/libertas/decl.h | 8 ++ | ||
23 | drivers/net/wireless/libertas/dev.h | 10 ++ | ||
24 | drivers/net/wireless/libertas/firmware.c | 143 ++++++++++++++++++++++++++++++ | ||
25 | drivers/net/wireless/libertas/main.c | 3 + | ||
26 | 4 files changed, 164 insertions(+), 0 deletions(-) | ||
27 | |||
28 | diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h | ||
29 | index 2fb2e31..84a3aa7 100644 | ||
30 | --- a/drivers/net/wireless/libertas/decl.h | ||
31 | +++ b/drivers/net/wireless/libertas/decl.h | ||
32 | @@ -19,6 +19,10 @@ struct lbs_fw_table { | ||
33 | }; | ||
34 | |||
35 | struct lbs_private; | ||
36 | +typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret, | ||
37 | + const struct firmware *helper, const struct firmware *mainfw); | ||
38 | + | ||
39 | +struct lbs_private; | ||
40 | struct sk_buff; | ||
41 | struct net_device; | ||
42 | struct cmd_ds_command; | ||
43 | @@ -70,5 +74,9 @@ int lbs_get_firmware(struct device *dev, u32 card_model, | ||
44 | const struct lbs_fw_table *fw_table, | ||
45 | const struct firmware **helper, | ||
46 | const struct firmware **mainfw); | ||
47 | +int lbs_get_firmware_async(struct lbs_private *priv, struct device *device, | ||
48 | + u32 card_model, const struct lbs_fw_table *fw_table, | ||
49 | + lbs_fw_cb callback); | ||
50 | +void lbs_wait_for_firmware_load(struct lbs_private *priv); | ||
51 | |||
52 | #endif | ||
53 | diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h | ||
54 | index f3fd447..6720054 100644 | ||
55 | --- a/drivers/net/wireless/libertas/dev.h | ||
56 | +++ b/drivers/net/wireless/libertas/dev.h | ||
57 | @@ -7,6 +7,7 @@ | ||
58 | #define _LBS_DEV_H_ | ||
59 | |||
60 | #include "defs.h" | ||
61 | +#include "decl.h" | ||
62 | #include "host.h" | ||
63 | |||
64 | #include <linux/kfifo.h> | ||
65 | @@ -180,6 +181,15 @@ struct lbs_private { | ||
66 | wait_queue_head_t scan_q; | ||
67 | /* Whether the scan was initiated internally and not by cfg80211 */ | ||
68 | bool internal_scan; | ||
69 | + | ||
70 | + /* Firmware load */ | ||
71 | + u32 fw_model; | ||
72 | + wait_queue_head_t fw_waitq; | ||
73 | + struct device *fw_device; | ||
74 | + const struct firmware *helper_fw; | ||
75 | + const struct lbs_fw_table *fw_table; | ||
76 | + const struct lbs_fw_table *fw_iter; | ||
77 | + lbs_fw_cb fw_callback; | ||
78 | }; | ||
79 | |||
80 | extern struct cmd_confirm_sleep confirm_sleep; | ||
81 | diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c | ||
82 | index 0c8c845..cd23f1a 100644 | ||
83 | --- a/drivers/net/wireless/libertas/firmware.c | ||
84 | +++ b/drivers/net/wireless/libertas/firmware.c | ||
85 | @@ -3,10 +3,151 @@ | ||
86 | */ | ||
87 | |||
88 | #include <linux/firmware.h> | ||
89 | +#include <linux/firmware.h> | ||
90 | #include <linux/module.h> | ||
91 | |||
92 | +#include "dev.h" | ||
93 | #include "decl.h" | ||
94 | |||
95 | +static void load_next_firmware_from_table(struct lbs_private *private); | ||
96 | + | ||
97 | +static void lbs_fw_loaded(struct lbs_private *priv, int ret, | ||
98 | + const struct firmware *helper, const struct firmware *mainfw) | ||
99 | +{ | ||
100 | + unsigned long flags; | ||
101 | + | ||
102 | + lbs_deb_fw("firmware load complete, code %d\n", ret); | ||
103 | + | ||
104 | + /* User must free helper/mainfw */ | ||
105 | + priv->fw_callback(priv, ret, helper, mainfw); | ||
106 | + | ||
107 | + spin_lock_irqsave(&priv->driver_lock, flags); | ||
108 | + priv->fw_callback = NULL; | ||
109 | + wake_up(&priv->fw_waitq); | ||
110 | + spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
111 | +} | ||
112 | + | ||
113 | +static void do_load_firmware(struct lbs_private *priv, const char *name, | ||
114 | + void (*cb)(const struct firmware *fw, void *context)) | ||
115 | +{ | ||
116 | + int ret; | ||
117 | + | ||
118 | + lbs_deb_fw("Requesting %s\n", name); | ||
119 | + ret = request_firmware_nowait(THIS_MODULE, true, name, | ||
120 | + priv->fw_device, GFP_KERNEL, priv, cb); | ||
121 | + if (ret) { | ||
122 | + lbs_deb_fw("request_firmware_nowait error %d\n", ret); | ||
123 | + lbs_fw_loaded(priv, ret, NULL, NULL); | ||
124 | + } | ||
125 | +} | ||
126 | + | ||
127 | +static void main_firmware_cb(const struct firmware *firmware, void *context) | ||
128 | +{ | ||
129 | + struct lbs_private *priv = context; | ||
130 | + | ||
131 | + if (!firmware) { | ||
132 | + /* Failed to find firmware: try next table entry */ | ||
133 | + load_next_firmware_from_table(priv); | ||
134 | + return; | ||
135 | + } | ||
136 | + | ||
137 | + /* Firmware found! */ | ||
138 | + lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); | ||
139 | +} | ||
140 | + | ||
141 | +static void helper_firmware_cb(const struct firmware *firmware, void *context) | ||
142 | +{ | ||
143 | + struct lbs_private *priv = context; | ||
144 | + | ||
145 | + if (!firmware) { | ||
146 | + /* Failed to find firmware: try next table entry */ | ||
147 | + load_next_firmware_from_table(priv); | ||
148 | + return; | ||
149 | + } | ||
150 | + | ||
151 | + /* Firmware found! */ | ||
152 | + if (priv->fw_iter->fwname) { | ||
153 | + priv->helper_fw = firmware; | ||
154 | + do_load_firmware(priv, priv->fw_iter->fwname, main_firmware_cb); | ||
155 | + } else { | ||
156 | + /* No main firmware needed for this helper --> success! */ | ||
157 | + lbs_fw_loaded(priv, 0, firmware, NULL); | ||
158 | + } | ||
159 | +} | ||
160 | + | ||
161 | +static void load_next_firmware_from_table(struct lbs_private *priv) | ||
162 | +{ | ||
163 | + const struct lbs_fw_table *iter; | ||
164 | + | ||
165 | + if (!priv->fw_iter) | ||
166 | + iter = priv->fw_table; | ||
167 | + else | ||
168 | + iter = ++priv->fw_iter; | ||
169 | + | ||
170 | + if (priv->helper_fw) { | ||
171 | + release_firmware(priv->helper_fw); | ||
172 | + priv->helper_fw = NULL; | ||
173 | + } | ||
174 | + | ||
175 | +next: | ||
176 | + if (!iter->helper) { | ||
177 | + /* End of table hit. */ | ||
178 | + lbs_fw_loaded(priv, -ENOENT, NULL, NULL); | ||
179 | + return; | ||
180 | + } | ||
181 | + | ||
182 | + if (iter->model != priv->fw_model) { | ||
183 | + iter++; | ||
184 | + goto next; | ||
185 | + } | ||
186 | + | ||
187 | + priv->fw_iter = iter; | ||
188 | + do_load_firmware(priv, iter->helper, helper_firmware_cb); | ||
189 | +} | ||
190 | + | ||
191 | +void lbs_wait_for_firmware_load(struct lbs_private *priv) | ||
192 | +{ | ||
193 | + wait_event(priv->fw_waitq, priv->fw_callback == NULL); | ||
194 | +} | ||
195 | + | ||
196 | +/** | ||
197 | + * lbs_get_firmware_async - Retrieves firmware asynchronously. Can load | ||
198 | + * either a helper firmware and a main firmware (2-stage), or just the helper. | ||
199 | + * | ||
200 | + * @priv: Pointer to lbs_private instance | ||
201 | + * @dev: A pointer to &device structure | ||
202 | + * @card_model: Bus-specific card model ID used to filter firmware table | ||
203 | + * elements | ||
204 | + * @fw_table: Table of firmware file names and device model numbers | ||
205 | + * terminated by an entry with a NULL helper name | ||
206 | + * @callback: User callback to invoke when firmware load succeeds or fails. | ||
207 | + */ | ||
208 | +int lbs_get_firmware_async(struct lbs_private *priv, struct device *device, | ||
209 | + u32 card_model, const struct lbs_fw_table *fw_table, | ||
210 | + lbs_fw_cb callback) | ||
211 | +{ | ||
212 | + unsigned long flags; | ||
213 | + | ||
214 | + spin_lock_irqsave(&priv->driver_lock, flags); | ||
215 | + if (priv->fw_callback) { | ||
216 | + lbs_deb_fw("firmware load already in progress\n"); | ||
217 | + spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
218 | + return -EBUSY; | ||
219 | + } | ||
220 | + | ||
221 | + priv->fw_device = device; | ||
222 | + priv->fw_callback = callback; | ||
223 | + priv->fw_table = fw_table; | ||
224 | + priv->fw_iter = NULL; | ||
225 | + priv->fw_model = card_model; | ||
226 | + spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
227 | + | ||
228 | + lbs_deb_fw("Starting async firmware load\n"); | ||
229 | + load_next_firmware_from_table(priv); | ||
230 | + return 0; | ||
231 | +} | ||
232 | +EXPORT_SYMBOL_GPL(lbs_get_firmware_async); | ||
233 | + | ||
234 | /** | ||
235 | * lbs_get_firmware - Retrieves two-stage firmware | ||
236 | * | ||
237 | @@ -18,6 +159,8 @@ | ||
238 | * @helper: On success, the helper firmware; caller must free | ||
239 | * @mainfw: On success, the main firmware; caller must free | ||
240 | * | ||
241 | + * Deprecated: use lbs_get_firmware_async() instead. | ||
242 | + * | ||
243 | * returns: 0 on success, non-zero on failure | ||
244 | */ | ||
245 | int lbs_get_firmware(struct device *dev, u32 card_model, | ||
246 | diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c | ||
247 | index 7eaf992..e96ee0a 100644 | ||
248 | --- a/drivers/net/wireless/libertas/main.c | ||
249 | +++ b/drivers/net/wireless/libertas/main.c | ||
250 | @@ -878,6 +878,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | ||
251 | priv->is_host_sleep_configured = 0; | ||
252 | priv->is_host_sleep_activated = 0; | ||
253 | init_waitqueue_head(&priv->host_sleep_q); | ||
254 | + init_waitqueue_head(&priv->fw_waitq); | ||
255 | mutex_init(&priv->lock); | ||
256 | |||
257 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, | ||
258 | @@ -1037,6 +1038,8 @@ void lbs_remove_card(struct lbs_private *priv) | ||
259 | if (priv->wiphy_registered) | ||
260 | lbs_scan_deinit(priv); | ||
261 | |||
262 | + lbs_wait_for_firmware_load(priv); | ||
263 | + | ||
264 | /* worker thread destruction blocks on the in-flight command which | ||
265 | * should have been cleared already in lbs_stop_card(). | ||
266 | */ | ||
267 | -- | ||
268 | 1.7.4.4 | ||
269 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0013-libertas-SDIO-convert-to-asynchronous-firmware-loadi.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0013-libertas-SDIO-convert-to-asynchronous-firmware-loadi.patch new file mode 100644 index 00000000..545ea889 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0013-libertas-SDIO-convert-to-asynchronous-firmware-loadi.patch | |||
@@ -0,0 +1,320 @@ | |||
1 | From 66d647efe5e845c77f745478480c5e96218b7f3d Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Mon, 16 Apr 2012 23:53:43 +0100 | ||
4 | Subject: [PATCH 13/17] libertas SDIO: convert to asynchronous firmware | ||
5 | loading | ||
6 | |||
7 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
8 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
9 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
10 | --- | ||
11 | drivers/net/wireless/libertas/if_sdio.c | 206 ++++++++++++++++++------------- | ||
12 | 1 files changed, 121 insertions(+), 85 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c | ||
15 | index 6590feb..76caeba 100644 | ||
16 | --- a/drivers/net/wireless/libertas/if_sdio.c | ||
17 | +++ b/drivers/net/wireless/libertas/if_sdio.c | ||
18 | @@ -117,6 +117,8 @@ struct if_sdio_card { | ||
19 | int model; | ||
20 | unsigned long ioport; | ||
21 | unsigned int scratch_reg; | ||
22 | + bool started; | ||
23 | + wait_queue_head_t pwron_waitq; | ||
24 | |||
25 | u8 buffer[65536] __attribute__((aligned(4))); | ||
26 | |||
27 | @@ -129,6 +131,9 @@ struct if_sdio_card { | ||
28 | u8 rx_unit; | ||
29 | }; | ||
30 | |||
31 | +static void if_sdio_finish_power_on(struct if_sdio_card *card); | ||
32 | +static int if_sdio_power_off(struct if_sdio_card *card); | ||
33 | + | ||
34 | /********************************************************************/ | ||
35 | /* I/O */ | ||
36 | /********************************************************************/ | ||
37 | @@ -669,12 +674,39 @@ out: | ||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | +static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret, | ||
42 | + const struct firmware *helper, | ||
43 | + const struct firmware *mainfw) | ||
44 | +{ | ||
45 | + struct if_sdio_card *card = priv->card; | ||
46 | + | ||
47 | + if (ret) { | ||
48 | + pr_err("failed to find firmware (%d)\n", ret); | ||
49 | + return; | ||
50 | + } | ||
51 | + | ||
52 | + ret = if_sdio_prog_helper(card, helper); | ||
53 | + if (ret) | ||
54 | + goto out; | ||
55 | + | ||
56 | + lbs_deb_sdio("Helper firmware loaded\n"); | ||
57 | + | ||
58 | + ret = if_sdio_prog_real(card, mainfw); | ||
59 | + if (ret) | ||
60 | + goto out; | ||
61 | + | ||
62 | + lbs_deb_sdio("Firmware loaded\n"); | ||
63 | + if_sdio_finish_power_on(card); | ||
64 | + | ||
65 | +out: | ||
66 | + release_firmware(helper); | ||
67 | + release_firmware(mainfw); | ||
68 | +} | ||
69 | + | ||
70 | static int if_sdio_prog_firmware(struct if_sdio_card *card) | ||
71 | { | ||
72 | int ret; | ||
73 | u16 scratch; | ||
74 | - const struct firmware *helper = NULL; | ||
75 | - const struct firmware *mainfw = NULL; | ||
76 | |||
77 | lbs_deb_enter(LBS_DEB_SDIO); | ||
78 | |||
79 | @@ -708,41 +740,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | ||
80 | */ | ||
81 | if (scratch == IF_SDIO_FIRMWARE_OK) { | ||
82 | lbs_deb_sdio("firmware already loaded\n"); | ||
83 | - goto success; | ||
84 | + if_sdio_finish_power_on(card); | ||
85 | + return 0; | ||
86 | } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) { | ||
87 | lbs_deb_sdio("firmware may be running\n"); | ||
88 | - goto success; | ||
89 | - } | ||
90 | - | ||
91 | - ret = lbs_get_firmware(&card->func->dev, card->model, &fw_table[0], | ||
92 | - &helper, &mainfw); | ||
93 | - if (ret) { | ||
94 | - pr_err("failed to find firmware (%d)\n", ret); | ||
95 | - goto out; | ||
96 | + if_sdio_finish_power_on(card); | ||
97 | + return 0; | ||
98 | } | ||
99 | |||
100 | - ret = if_sdio_prog_helper(card, helper); | ||
101 | - if (ret) | ||
102 | - goto out; | ||
103 | - | ||
104 | - lbs_deb_sdio("Helper firmware loaded\n"); | ||
105 | - | ||
106 | - ret = if_sdio_prog_real(card, mainfw); | ||
107 | - if (ret) | ||
108 | - goto out; | ||
109 | - | ||
110 | - lbs_deb_sdio("Firmware loaded\n"); | ||
111 | - | ||
112 | -success: | ||
113 | - sdio_claim_host(card->func); | ||
114 | - sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
115 | - sdio_release_host(card->func); | ||
116 | - ret = 0; | ||
117 | + ret = lbs_get_firmware_async(card->priv, &card->func->dev, card->model, | ||
118 | + fw_table, if_sdio_do_prog_firmware); | ||
119 | |||
120 | out: | ||
121 | - release_firmware(helper); | ||
122 | - release_firmware(mainfw); | ||
123 | - | ||
124 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
125 | return ret; | ||
126 | } | ||
127 | @@ -751,55 +760,15 @@ out: | ||
128 | /* Power management */ | ||
129 | /********************************************************************/ | ||
130 | |||
131 | -static int if_sdio_power_on(struct if_sdio_card *card) | ||
132 | +/* Finish power on sequence (after firmware is loaded) */ | ||
133 | +static void if_sdio_finish_power_on(struct if_sdio_card *card) | ||
134 | { | ||
135 | struct sdio_func *func = card->func; | ||
136 | struct lbs_private *priv = card->priv; | ||
137 | - struct mmc_host *host = func->card->host; | ||
138 | int ret; | ||
139 | |||
140 | sdio_claim_host(func); | ||
141 | - | ||
142 | - ret = sdio_enable_func(func); | ||
143 | - if (ret) | ||
144 | - goto release; | ||
145 | - | ||
146 | - /* For 1-bit transfers to the 8686 model, we need to enable the | ||
147 | - * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
148 | - * bit to allow access to non-vendor registers. */ | ||
149 | - if ((card->model == MODEL_8686) && | ||
150 | - (host->caps & MMC_CAP_SDIO_IRQ) && | ||
151 | - (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
152 | - u8 reg; | ||
153 | - | ||
154 | - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
155 | - reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
156 | - if (ret) | ||
157 | - goto disable; | ||
158 | - | ||
159 | - reg |= SDIO_BUS_ECSI; | ||
160 | - sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
161 | - if (ret) | ||
162 | - goto disable; | ||
163 | - } | ||
164 | - | ||
165 | - card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | ||
166 | - if (ret) | ||
167 | - goto disable; | ||
168 | - | ||
169 | - card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; | ||
170 | - if (ret) | ||
171 | - goto disable; | ||
172 | - | ||
173 | - card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; | ||
174 | - if (ret) | ||
175 | - goto disable; | ||
176 | - | ||
177 | - sdio_release_host(func); | ||
178 | - ret = if_sdio_prog_firmware(card); | ||
179 | - sdio_claim_host(func); | ||
180 | - if (ret) | ||
181 | - goto disable; | ||
182 | + sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
183 | |||
184 | /* | ||
185 | * Get rx_unit if the chip is SD8688 or newer. | ||
186 | @@ -824,7 +793,7 @@ static int if_sdio_power_on(struct if_sdio_card *card) | ||
187 | */ | ||
188 | ret = sdio_claim_irq(func, if_sdio_interrupt); | ||
189 | if (ret) | ||
190 | - goto disable; | ||
191 | + goto release; | ||
192 | |||
193 | /* | ||
194 | * Enable interrupts now that everything is set up | ||
195 | @@ -850,11 +819,79 @@ static int if_sdio_power_on(struct if_sdio_card *card) | ||
196 | } | ||
197 | |||
198 | priv->fw_ready = 1; | ||
199 | + wake_up(&card->pwron_waitq); | ||
200 | |||
201 | - return 0; | ||
202 | + if (!card->started) { | ||
203 | + ret = lbs_start_card(priv); | ||
204 | + if_sdio_power_off(card); | ||
205 | + if (ret == 0) { | ||
206 | + card->started = true; | ||
207 | + /* Tell PM core that we don't need the card to be | ||
208 | + * powered now */ | ||
209 | + pm_runtime_put_noidle(&func->dev); | ||
210 | + } | ||
211 | + } | ||
212 | + | ||
213 | + return; | ||
214 | |||
215 | release_irq: | ||
216 | sdio_release_irq(func); | ||
217 | +release: | ||
218 | + sdio_release_host(func); | ||
219 | +} | ||
220 | + | ||
221 | +static int if_sdio_power_on(struct if_sdio_card *card) | ||
222 | +{ | ||
223 | + struct sdio_func *func = card->func; | ||
224 | + struct mmc_host *host = func->card->host; | ||
225 | + int ret; | ||
226 | + | ||
227 | + sdio_claim_host(func); | ||
228 | + | ||
229 | + ret = sdio_enable_func(func); | ||
230 | + if (ret) | ||
231 | + goto release; | ||
232 | + | ||
233 | + /* For 1-bit transfers to the 8686 model, we need to enable the | ||
234 | + * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
235 | + * bit to allow access to non-vendor registers. */ | ||
236 | + if ((card->model == MODEL_8686) && | ||
237 | + (host->caps & MMC_CAP_SDIO_IRQ) && | ||
238 | + (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
239 | + u8 reg; | ||
240 | + | ||
241 | + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
242 | + reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
243 | + if (ret) | ||
244 | + goto disable; | ||
245 | + | ||
246 | + reg |= SDIO_BUS_ECSI; | ||
247 | + sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
248 | + if (ret) | ||
249 | + goto disable; | ||
250 | + } | ||
251 | + | ||
252 | + card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | ||
253 | + if (ret) | ||
254 | + goto disable; | ||
255 | + | ||
256 | + card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; | ||
257 | + if (ret) | ||
258 | + goto disable; | ||
259 | + | ||
260 | + card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; | ||
261 | + if (ret) | ||
262 | + goto disable; | ||
263 | + | ||
264 | + sdio_release_host(func); | ||
265 | + ret = if_sdio_prog_firmware(card); | ||
266 | + if (ret) { | ||
267 | + sdio_disable_func(func); | ||
268 | + return ret; | ||
269 | + } | ||
270 | + | ||
271 | + return 0; | ||
272 | + | ||
273 | disable: | ||
274 | sdio_disable_func(func); | ||
275 | release: | ||
276 | @@ -1061,11 +1098,17 @@ static int if_sdio_power_save(struct lbs_private *priv) | ||
277 | static int if_sdio_power_restore(struct lbs_private *priv) | ||
278 | { | ||
279 | struct if_sdio_card *card = priv->card; | ||
280 | + int r; | ||
281 | |||
282 | /* Make sure the card will not be powered off by runtime PM */ | ||
283 | pm_runtime_get_sync(&card->func->dev); | ||
284 | |||
285 | - return if_sdio_power_on(card); | ||
286 | + r = if_sdio_power_on(card); | ||
287 | + if (r) | ||
288 | + return r; | ||
289 | + | ||
290 | + wait_event(card->pwron_waitq, priv->fw_ready); | ||
291 | + return 0; | ||
292 | } | ||
293 | |||
294 | |||
295 | @@ -1166,6 +1209,7 @@ static int if_sdio_probe(struct sdio_func *func, | ||
296 | spin_lock_init(&card->lock); | ||
297 | card->workqueue = create_workqueue("libertas_sdio"); | ||
298 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); | ||
299 | + init_waitqueue_head(&card->pwron_waitq); | ||
300 | |||
301 | /* Check if we support this card */ | ||
302 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
303 | @@ -1207,14 +1251,6 @@ static int if_sdio_probe(struct sdio_func *func, | ||
304 | if (ret) | ||
305 | goto err_activate_card; | ||
306 | |||
307 | - ret = lbs_start_card(priv); | ||
308 | - if_sdio_power_off(card); | ||
309 | - if (ret) | ||
310 | - goto err_activate_card; | ||
311 | - | ||
312 | - /* Tell PM core that we don't need the card to be powered now */ | ||
313 | - pm_runtime_put_noidle(&func->dev); | ||
314 | - | ||
315 | out: | ||
316 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
317 | |||
318 | -- | ||
319 | 1.7.4.4 | ||
320 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0014-libertas-USB-convert-to-asynchronous-firmware-loadin.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0014-libertas-USB-convert-to-asynchronous-firmware-loadin.patch new file mode 100644 index 00000000..9952cd3b --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0014-libertas-USB-convert-to-asynchronous-firmware-loadin.patch | |||
@@ -0,0 +1,201 @@ | |||
1 | From ce84bb69f50e6f6cfeabc9b965365290f4184417 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Mon, 16 Apr 2012 23:53:55 +0100 | ||
4 | Subject: [PATCH 14/17] libertas USB: convert to asynchronous firmware loading | ||
5 | |||
6 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
7 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
8 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
9 | --- | ||
10 | drivers/net/wireless/libertas/if_usb.c | 102 +++++++++++++------------------ | ||
11 | 1 files changed, 43 insertions(+), 59 deletions(-) | ||
12 | |||
13 | diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c | ||
14 | index f29471b..75403e6 100644 | ||
15 | --- a/drivers/net/wireless/libertas/if_usb.c | ||
16 | +++ b/drivers/net/wireless/libertas/if_usb.c | ||
17 | @@ -41,6 +41,16 @@ enum { | ||
18 | MODEL_8682 = 0x2 | ||
19 | }; | ||
20 | |||
21 | +/* table of firmware file names */ | ||
22 | +static const struct lbs_fw_table fw_table[] = { | ||
23 | + { MODEL_8388, "libertas/usb8388_olpc.bin", NULL }, | ||
24 | + { MODEL_8388, "libertas/usb8388_v9.bin", NULL }, | ||
25 | + { MODEL_8388, "libertas/usb8388_v5.bin", NULL }, | ||
26 | + { MODEL_8388, "libertas/usb8388.bin", NULL }, | ||
27 | + { MODEL_8388, "usb8388.bin", NULL }, | ||
28 | + { MODEL_8682, "libertas/usb8682.bin", NULL } | ||
29 | +}; | ||
30 | + | ||
31 | static struct usb_device_id if_usb_table[] = { | ||
32 | /* Enter the device signature inside */ | ||
33 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, | ||
34 | @@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); | ||
35 | |||
36 | static void if_usb_receive(struct urb *urb); | ||
37 | static void if_usb_receive_fwload(struct urb *urb); | ||
38 | -static int if_usb_prog_firmware(struct if_usb_card *cardp); | ||
39 | +static void if_usb_prog_firmware(struct lbs_private *priv, int ret, | ||
40 | + const struct firmware *fw, | ||
41 | + const struct firmware *unused); | ||
42 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | ||
43 | uint8_t *payload, uint16_t nb); | ||
44 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | ||
45 | @@ -187,6 +199,7 @@ static int if_usb_probe(struct usb_interface *intf, | ||
46 | struct usb_endpoint_descriptor *endpoint; | ||
47 | struct lbs_private *priv; | ||
48 | struct if_usb_card *cardp; | ||
49 | + int r = -ENOMEM; | ||
50 | int i; | ||
51 | |||
52 | udev = interface_to_usbdev(intf); | ||
53 | @@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf, | ||
54 | goto dealloc; | ||
55 | } | ||
56 | |||
57 | - /* Upload firmware */ | ||
58 | - if (if_usb_prog_firmware(cardp)) { | ||
59 | - lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | ||
60 | - goto err_prog_firmware; | ||
61 | - } | ||
62 | - | ||
63 | if (!(priv = lbs_add_card(cardp, &intf->dev))) | ||
64 | - goto err_prog_firmware; | ||
65 | + goto err_add_card; | ||
66 | |||
67 | cardp->priv = priv; | ||
68 | - cardp->priv->fw_ready = 1; | ||
69 | |||
70 | priv->hw_host_to_card = if_usb_host_to_card; | ||
71 | priv->enter_deep_sleep = NULL; | ||
72 | @@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf, | ||
73 | |||
74 | cardp->boot2_version = udev->descriptor.bcdDevice; | ||
75 | |||
76 | - if_usb_submit_rx_urb(cardp); | ||
77 | - | ||
78 | - if (lbs_start_card(priv)) | ||
79 | - goto err_start_card; | ||
80 | - | ||
81 | - if_usb_setup_firmware(priv); | ||
82 | - | ||
83 | usb_get_dev(udev); | ||
84 | usb_set_intfdata(intf, cardp); | ||
85 | |||
86 | - /* | ||
87 | - * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | ||
88 | - */ | ||
89 | - priv->wol_criteria = EHS_REMOVE_WAKEUP; | ||
90 | - if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | ||
91 | - priv->ehs_remove_supported = false; | ||
92 | + r = lbs_get_firmware_async(priv, &udev->dev, cardp->model, | ||
93 | + fw_table, if_usb_prog_firmware); | ||
94 | + if (r) | ||
95 | + goto err_get_fw; | ||
96 | |||
97 | return 0; | ||
98 | |||
99 | -err_start_card: | ||
100 | +err_get_fw: | ||
101 | lbs_remove_card(priv); | ||
102 | -err_prog_firmware: | ||
103 | +err_add_card: | ||
104 | if_usb_reset_device(cardp); | ||
105 | dealloc: | ||
106 | if_usb_free(cardp); | ||
107 | |||
108 | error: | ||
109 | - return -ENOMEM; | ||
110 | + return r; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | @@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | -/* table of firmware file names */ | ||
119 | -static const struct { | ||
120 | - u32 model; | ||
121 | - const char *fwname; | ||
122 | -} fw_table[] = { | ||
123 | - { MODEL_8388, "libertas/usb8388_olpc.bin" }, | ||
124 | - { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
125 | - { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
126 | - { MODEL_8388, "libertas/usb8388.bin" }, | ||
127 | - { MODEL_8388, "usb8388.bin" }, | ||
128 | - { MODEL_8682, "libertas/usb8682.bin" } | ||
129 | -}; | ||
130 | - | ||
131 | -static int get_fw(struct if_usb_card *cardp) | ||
132 | -{ | ||
133 | - int i; | ||
134 | - | ||
135 | - /* Otherwise search for firmware to use */ | ||
136 | - for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
137 | - if (fw_table[i].model != cardp->model) | ||
138 | - continue; | ||
139 | - if (request_firmware(&cardp->fw, fw_table[i].fwname, | ||
140 | - &cardp->udev->dev) == 0) | ||
141 | - return 0; | ||
142 | - } | ||
143 | - | ||
144 | - return -ENOENT; | ||
145 | -} | ||
146 | - | ||
147 | -static int if_usb_prog_firmware(struct if_usb_card *cardp) | ||
148 | +static void if_usb_prog_firmware(struct lbs_private *priv, int ret, | ||
149 | + const struct firmware *fw, | ||
150 | + const struct firmware *unused) | ||
151 | { | ||
152 | + struct if_usb_card *cardp = priv->card; | ||
153 | int i = 0; | ||
154 | static int reset_count = 10; | ||
155 | - int ret = 0; | ||
156 | |||
157 | lbs_deb_enter(LBS_DEB_USB); | ||
158 | |||
159 | - ret = get_fw(cardp); | ||
160 | if (ret) { | ||
161 | pr_err("failed to find firmware (%d)\n", ret); | ||
162 | goto done; | ||
163 | } | ||
164 | |||
165 | + cardp->fw = fw; | ||
166 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { | ||
167 | ret = -EINVAL; | ||
168 | goto release_fw; | ||
169 | @@ -954,13 +924,27 @@ restart: | ||
170 | goto release_fw; | ||
171 | } | ||
172 | |||
173 | + cardp->priv->fw_ready = 1; | ||
174 | + if_usb_submit_rx_urb(cardp); | ||
175 | + | ||
176 | + if (lbs_start_card(priv)) | ||
177 | + goto release_fw; | ||
178 | + | ||
179 | + if_usb_setup_firmware(priv); | ||
180 | + | ||
181 | + /* | ||
182 | + * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | ||
183 | + */ | ||
184 | + priv->wol_criteria = EHS_REMOVE_WAKEUP; | ||
185 | + if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | ||
186 | + priv->ehs_remove_supported = false; | ||
187 | + | ||
188 | release_fw: | ||
189 | release_firmware(cardp->fw); | ||
190 | cardp->fw = NULL; | ||
191 | |||
192 | done: | ||
193 | - lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); | ||
194 | - return ret; | ||
195 | + lbs_deb_leave(LBS_DEB_USB); | ||
196 | } | ||
197 | |||
198 | |||
199 | -- | ||
200 | 1.7.4.4 | ||
201 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0015-libertas-CS-convert-to-asynchronous-firmware-loading.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0015-libertas-CS-convert-to-asynchronous-firmware-loading.patch new file mode 100644 index 00000000..79aafdcf --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0015-libertas-CS-convert-to-asynchronous-firmware-loading.patch | |||
@@ -0,0 +1,154 @@ | |||
1 | From 488c3ee77ea0e63c9ae4736b1610aaf39c6527ee Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Drake <dsd@laptop.org> | ||
3 | Date: Wed, 18 Apr 2012 20:09:44 +0100 | ||
4 | Subject: [PATCH 15/17] libertas CS: convert to asynchronous firmware loading | ||
5 | |||
6 | Signed-off-by: Daniel Drake <dsd@laptop.org> | ||
7 | Tested-by: Dan Williams <dcbw@redhat.com> | ||
8 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
9 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
10 | --- | ||
11 | drivers/net/wireless/libertas/if_cs.c | 88 ++++++++++++++++++-------------- | ||
12 | 1 files changed, 49 insertions(+), 39 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c | ||
15 | index cee5052..16beaf3 100644 | ||
16 | --- a/drivers/net/wireless/libertas/if_cs.c | ||
17 | +++ b/drivers/net/wireless/libertas/if_cs.c | ||
18 | @@ -738,6 +738,50 @@ done: | ||
19 | return ret; | ||
20 | } | ||
21 | |||
22 | +static void if_cs_prog_firmware(struct lbs_private *priv, int ret, | ||
23 | + const struct firmware *helper, | ||
24 | + const struct firmware *mainfw) | ||
25 | +{ | ||
26 | + struct if_cs_card *card = priv->card; | ||
27 | + | ||
28 | + if (ret) { | ||
29 | + pr_err("failed to find firmware (%d)\n", ret); | ||
30 | + return; | ||
31 | + } | ||
32 | + | ||
33 | + /* Load the firmware */ | ||
34 | + ret = if_cs_prog_helper(card, helper); | ||
35 | + if (ret == 0 && (card->model != MODEL_8305)) | ||
36 | + ret = if_cs_prog_real(card, mainfw); | ||
37 | + if (ret) | ||
38 | + goto out; | ||
39 | + | ||
40 | + /* Now actually get the IRQ */ | ||
41 | + ret = request_irq(card->p_dev->irq, if_cs_interrupt, | ||
42 | + IRQF_SHARED, DRV_NAME, card); | ||
43 | + if (ret) { | ||
44 | + pr_err("error in request_irq\n"); | ||
45 | + goto out; | ||
46 | + } | ||
47 | + | ||
48 | + /* | ||
49 | + * Clear any interrupt cause that happened while sending | ||
50 | + * firmware/initializing card | ||
51 | + */ | ||
52 | + if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); | ||
53 | + if_cs_enable_ints(card); | ||
54 | + | ||
55 | + /* And finally bring the card up */ | ||
56 | + priv->fw_ready = 1; | ||
57 | + if (lbs_start_card(priv) != 0) { | ||
58 | + pr_err("could not activate card\n"); | ||
59 | + free_irq(card->p_dev->irq, card); | ||
60 | + } | ||
61 | + | ||
62 | +out: | ||
63 | + release_firmware(helper); | ||
64 | + release_firmware(mainfw); | ||
65 | +} | ||
66 | |||
67 | |||
68 | /********************************************************************/ | ||
69 | @@ -809,8 +853,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
70 | unsigned int prod_id; | ||
71 | struct lbs_private *priv; | ||
72 | struct if_cs_card *card; | ||
73 | - const struct firmware *helper = NULL; | ||
74 | - const struct firmware *mainfw = NULL; | ||
75 | |||
76 | lbs_deb_enter(LBS_DEB_CS); | ||
77 | |||
78 | @@ -890,20 +932,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
79 | goto out2; | ||
80 | } | ||
81 | |||
82 | - ret = lbs_get_firmware(&p_dev->dev, card->model, &fw_table[0], | ||
83 | - &helper, &mainfw); | ||
84 | - if (ret) { | ||
85 | - pr_err("failed to find firmware (%d)\n", ret); | ||
86 | - goto out2; | ||
87 | - } | ||
88 | - | ||
89 | - /* Load the firmware early, before calling into libertas.ko */ | ||
90 | - ret = if_cs_prog_helper(card, helper); | ||
91 | - if (ret == 0 && (card->model != MODEL_8305)) | ||
92 | - ret = if_cs_prog_real(card, mainfw); | ||
93 | - if (ret) | ||
94 | - goto out2; | ||
95 | - | ||
96 | /* Make this card known to the libertas driver */ | ||
97 | priv = lbs_add_card(card, &p_dev->dev); | ||
98 | if (!priv) { | ||
99 | @@ -911,37 +939,22 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | ||
100 | goto out2; | ||
101 | } | ||
102 | |||
103 | - /* Finish setting up fields in lbs_private */ | ||
104 | + /* Set up fields in lbs_private */ | ||
105 | card->priv = priv; | ||
106 | priv->card = card; | ||
107 | priv->hw_host_to_card = if_cs_host_to_card; | ||
108 | priv->enter_deep_sleep = NULL; | ||
109 | priv->exit_deep_sleep = NULL; | ||
110 | priv->reset_deep_sleep_wakeup = NULL; | ||
111 | - priv->fw_ready = 1; | ||
112 | |||
113 | - /* Now actually get the IRQ */ | ||
114 | - ret = request_irq(p_dev->irq, if_cs_interrupt, | ||
115 | - IRQF_SHARED, DRV_NAME, card); | ||
116 | + /* Get firmware */ | ||
117 | + ret = lbs_get_firmware_async(priv, &p_dev->dev, card->model, fw_table, | ||
118 | + if_cs_prog_firmware); | ||
119 | if (ret) { | ||
120 | - pr_err("error in request_irq\n"); | ||
121 | - goto out3; | ||
122 | - } | ||
123 | - | ||
124 | - /* | ||
125 | - * Clear any interrupt cause that happened while sending | ||
126 | - * firmware/initializing card | ||
127 | - */ | ||
128 | - if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); | ||
129 | - if_cs_enable_ints(card); | ||
130 | - | ||
131 | - /* And finally bring the card up */ | ||
132 | - if (lbs_start_card(priv) != 0) { | ||
133 | - pr_err("could not activate card\n"); | ||
134 | + pr_err("failed to find firmware (%d)\n", ret); | ||
135 | goto out3; | ||
136 | } | ||
137 | |||
138 | - ret = 0; | ||
139 | goto out; | ||
140 | |||
141 | out3: | ||
142 | @@ -951,9 +964,6 @@ out2: | ||
143 | out1: | ||
144 | pcmcia_disable_device(p_dev); | ||
145 | out: | ||
146 | - release_firmware(helper); | ||
147 | - release_firmware(mainfw); | ||
148 | - | ||
149 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | ||
150 | return ret; | ||
151 | } | ||
152 | -- | ||
153 | 1.7.4.4 | ||
154 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0016-libertas-add-missing-include.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0016-libertas-add-missing-include.patch new file mode 100644 index 00000000..1a898165 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0016-libertas-add-missing-include.patch | |||
@@ -0,0 +1,30 @@ | |||
1 | From 7608f165734eaeb530ba2442c0413e6e9630ad83 Mon Sep 17 00:00:00 2001 | ||
2 | From: Felix Fietkau <nbd@openwrt.org> | ||
3 | Date: Thu, 19 Apr 2012 13:54:12 +0200 | ||
4 | Subject: [PATCH 16/17] libertas: add missing include | ||
5 | |||
6 | Without it, I get compile errors due to missing TASK_NORMAL, | ||
7 | TASK_UNINTERRUPTIBLE and schedule. | ||
8 | |||
9 | Signed-off-by: Felix Fietkau <nbd@openwrt.org> | ||
10 | Acked-by: Dan Williams <dcbw@redhat.com> | ||
11 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
12 | --- | ||
13 | drivers/net/wireless/libertas/firmware.c | 1 + | ||
14 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
15 | |||
16 | diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c | ||
17 | index cd23f1a..77f6504 100644 | ||
18 | --- a/drivers/net/wireless/libertas/firmware.c | ||
19 | +++ b/drivers/net/wireless/libertas/firmware.c | ||
20 | @@ -5,6 +5,7 @@ | ||
21 | #include <linux/firmware.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <linux/module.h> | ||
24 | +#include <linux/sched.h> | ||
25 | |||
26 | #include "dev.h" | ||
27 | #include "decl.h" | ||
28 | -- | ||
29 | 1.7.4.4 | ||
30 | |||
diff --git a/recipes-kernel/linux/linux-mainline-3.2/libertas/0017-remove-debug-msgs-due-to-missing-in_interrupt.patch b/recipes-kernel/linux/linux-mainline-3.2/libertas/0017-remove-debug-msgs-due-to-missing-in_interrupt.patch new file mode 100644 index 00000000..e46ae14d --- /dev/null +++ b/recipes-kernel/linux/linux-mainline-3.2/libertas/0017-remove-debug-msgs-due-to-missing-in_interrupt.patch | |||
@@ -0,0 +1,36 @@ | |||
1 | From 94938a2b8b1db241843abfe98168b81bf9273165 Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@googlemail.com> | ||
3 | Date: Mon, 21 May 2012 17:01:23 +0200 | ||
4 | Subject: [PATCH] remove debug msgs due to missing in_interrupt | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | |||
10 | Signed-off-by: Andreas M??ller <schnitzeltony@googlemail.com> | ||
11 | --- | ||
12 | drivers/net/wireless/libertas/defs.h | 7 ------- | ||
13 | 1 files changed, 0 insertions(+), 7 deletions(-) | ||
14 | |||
15 | diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h | ||
16 | index ab966f0..a80b40e 100644 | ||
17 | --- a/drivers/net/wireless/libertas/defs.h | ||
18 | +++ b/drivers/net/wireless/libertas/defs.h | ||
19 | @@ -46,14 +46,7 @@ | ||
20 | |||
21 | extern unsigned int lbs_debug; | ||
22 | |||
23 | -#ifdef DEBUG | ||
24 | -#define LBS_DEB_LL(grp, grpnam, fmt, args...) \ | ||
25 | -do { if ((lbs_debug & (grp)) == (grp)) \ | ||
26 | - printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \ | ||
27 | - in_interrupt() ? " (INT)" : "", ## args); } while (0) | ||
28 | -#else | ||
29 | #define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0) | ||
30 | -#endif | ||
31 | |||
32 | #define lbs_deb_enter(grp) \ | ||
33 | LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__); | ||
34 | -- | ||
35 | 1.7.4.4 | ||
36 | |||
diff --git a/recipes-kernel/linux/linux-mainline_3.2.bb b/recipes-kernel/linux/linux-mainline_3.2.bb index 69eb7e5f..69344ff8 100644 --- a/recipes-kernel/linux/linux-mainline_3.2.bb +++ b/recipes-kernel/linux/linux-mainline_3.2.bb | |||
@@ -10,7 +10,7 @@ PV = "3.2.18" | |||
10 | SRCREV_pn-${PN} = "52c6b95f8a2edaff98b779f15b2f4d69b61b18b9" | 10 | SRCREV_pn-${PN} = "52c6b95f8a2edaff98b779f15b2f4d69b61b18b9" |
11 | 11 | ||
12 | # The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc | 12 | # The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc |
13 | MACHINE_KERNEL_PR_append = "a" | 13 | MACHINE_KERNEL_PR_append = "b" |
14 | 14 | ||
15 | FILESPATH =. "${FILE_DIRNAME}/linux-mainline-3.2:${FILE_DIRNAME}/linux-mainline-3.2/${MACHINE}:" | 15 | FILESPATH =. "${FILE_DIRNAME}/linux-mainline-3.2:${FILE_DIRNAME}/linux-mainline-3.2/${MACHINE}:" |
16 | 16 | ||
@@ -74,7 +74,23 @@ SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.gi | |||
74 | file://omap_fixes/0006-OMAP-HWMOD-add-es3plus-to-am36xx-am35xx.patch \ | 74 | file://omap_fixes/0006-OMAP-HWMOD-add-es3plus-to-am36xx-am35xx.patch \ |
75 | file://sgx/0001-Revert-OMAP-DSS2-remove-update_mode-from-omapdss-v3.2.patch \ | 75 | file://sgx/0001-Revert-OMAP-DSS2-remove-update_mode-from-omapdss-v3.2.patch \ |
76 | file://led/0001-leds-heartbeat-stop-on-shutdown-reboot-or-panic.patch \ | 76 | file://led/0001-leds-heartbeat-stop-on-shutdown-reboot-or-panic.patch \ |
77 | \ | 77 | file://libertas/0001-USB-convert-drivers-net-to-use-module_usb_driver.patch \ |
78 | file://libertas/0002-net-fix-assignment-of-0-1-to-bool-variables.patch \ | ||
79 | file://libertas/0003-switch-debugfs-to-umode_t.patch \ | ||
80 | file://libertas/0004-drivers-net-Remove-unnecessary-k.alloc-v.alloc-OOM-m.patch \ | ||
81 | file://libertas/0005-libertas-remove-dump_survey-implementation.patch \ | ||
82 | file://libertas/0007-wireless-libertas-remove-redundant-NULL-tests-before.patch \ | ||
83 | file://libertas/0008-libertas-fix-signedness-bug-in-lbs_auth_to_authtype.patch \ | ||
84 | file://libertas/0009-drivers-net-wireless-libertas-if_usb.c-add-missing-d.patch \ | ||
85 | file://libertas/0010-libertas-Firmware-loading-simplifications.patch \ | ||
86 | file://libertas/0011-libertas-harden-up-exit-paths.patch \ | ||
87 | file://libertas/0012-libertas-add-asynchronous-firmware-loading-capabilit.patch \ | ||
88 | file://libertas/0013-libertas-SDIO-convert-to-asynchronous-firmware-loadi.patch \ | ||
89 | file://libertas/0014-libertas-USB-convert-to-asynchronous-firmware-loadin.patch \ | ||
90 | file://libertas/0015-libertas-CS-convert-to-asynchronous-firmware-loading.patch \ | ||
91 | file://libertas/0016-libertas-add-missing-include.patch \ | ||
92 | file://libertas/0017-remove-debug-msgs-due-to-missing-in_interrupt.patch \ | ||
93 | \ | ||
78 | file://defconfig" | 94 | file://defconfig" |
79 | 95 | ||
80 | SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \ | 96 | SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \ |