--- /dev/null
+From 78f18df4b323d2ac14d6c82e2fc3c8dc4556bccc Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 10 Dec 2012 17:40:21 +0100
+Subject: b43: fix tx path skb leaks
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 78f18df4b323d2ac14d6c82e2fc3c8dc4556bccc upstream.
+
+ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for
+tx packets passed to the driver from mac80211
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43/dma.c | 7 +++++--
+ drivers/net/wireless/b43/main.c | 12 ++++++++----
+ drivers/net/wireless/b43/pio.c | 4 ++--
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -409,7 +409,10 @@ static inline
+ struct b43_dmadesc_meta *meta)
+ {
+ if (meta->skb) {
+- dev_kfree_skb_any(meta->skb);
++ if (ring->tx)
++ ieee80211_free_txskb(ring->dev->wl->hw, meta->skb);
++ else
++ dev_kfree_skb_any(meta->skb);
+ meta->skb = NULL;
+ }
+ }
+@@ -1454,7 +1457,7 @@ int b43_dma_tx(struct b43_wldev *dev, st
+ if (unlikely(err == -ENOKEY)) {
+ /* Drop this packet, as we don't have the encryption key
+ * anymore and must not transmit it unencrypted. */
+- dev_kfree_skb_any(skb);
++ ieee80211_free_txskb(dev->wl->hw, skb);
+ err = 0;
+ goto out;
+ }
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -3397,7 +3397,7 @@ static void b43_tx_work(struct work_stru
+ break;
+ }
+ if (unlikely(err))
+- dev_kfree_skb(skb); /* Drop it */
++ ieee80211_free_txskb(wl->hw, skb);
+ err = 0;
+ }
+
+@@ -3419,7 +3419,7 @@ static void b43_op_tx(struct ieee80211_h
+
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
+- dev_kfree_skb_any(skb);
++ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+ B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+@@ -4229,8 +4229,12 @@ redo:
+
+ /* Drain all TX queues. */
+ for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+- while (skb_queue_len(&wl->tx_queue[queue_num]))
+- dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
++ while (skb_queue_len(&wl->tx_queue[queue_num])) {
++ struct sk_buff *skb;
++
++ skb = skb_dequeue(&wl->tx_queue[queue_num]);
++ ieee80211_free_txskb(wl->hw, skb);
++ }
+ }
+
+ b43_mac_suspend(dev);
+--- a/drivers/net/wireless/b43/pio.c
++++ b/drivers/net/wireless/b43/pio.c
+@@ -196,7 +196,7 @@ static void b43_pio_cancel_tx_packets(st
+ for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
+ pack = &(q->packets[i]);
+ if (pack->skb) {
+- dev_kfree_skb_any(pack->skb);
++ ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
+ pack->skb = NULL;
+ }
+ }
+@@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, st
+ if (unlikely(err == -ENOKEY)) {
+ /* Drop this packet, as we don't have the encryption key
+ * anymore and must not transmit it unencrypted. */
+- dev_kfree_skb_any(skb);
++ ieee80211_free_txskb(dev->wl->hw, skb);
+ err = 0;
+ goto out;
+ }
--- /dev/null
+From 576d28a7c73013717311cfcb514dbcae27c82eeb Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Thu, 6 Dec 2012 21:55:16 -0600
+Subject: b43legacy: Fix firmware loading when driver is built into the kernel
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit 576d28a7c73013717311cfcb514dbcae27c82eeb upstream.
+
+Recent versions of udev cause synchronous firmware loading from the
+probe routine to fail because the request to user space times out.
+The original fix for b43legacy (commit a3ea2c7) moved the firmware
+load from the probe routine to a work queue, but it still used synchronous
+firmware loading. This method is OK when b43legacy is built as a module;
+however, it fails when the driver is compiled into the kernel.
+
+This version changes the code to load the initial firmware file
+using request_firmware_nowait(). A completion event is used to
+hold the work queue until that file is available. The remaining
+firmware files are read synchronously.
+
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43legacy/b43legacy.h | 5 +++
+ drivers/net/wireless/b43legacy/main.c | 37 ++++++++++++++++++++++++-----
+ 2 files changed, 36 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/b43legacy/b43legacy.h
++++ b/drivers/net/wireless/b43legacy/b43legacy.h
+@@ -13,6 +13,7 @@
+
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_driver_chipcommon.h>
++#include <linux/completion.h>
+
+ #include <net/mac80211.h>
+
+@@ -733,6 +734,10 @@ struct b43legacy_wldev {
+
+ /* Firmware data */
+ struct b43legacy_firmware fw;
++ const struct firmware *fwp; /* needed to pass fw pointer */
++
++ /* completion struct for firmware loading */
++ struct completion fw_load_complete;
+
+ /* Devicelist in struct b43legacy_wl (all 802.11 cores) */
+ struct list_head list;
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -1513,9 +1513,17 @@ static void b43legacy_print_fw_helptext(
+ "and download the correct firmware (version 3).\n");
+ }
+
++static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
++{
++ struct b43legacy_wldev *dev = context;
++
++ dev->fwp = firmware;
++ complete(&dev->fw_load_complete);
++}
++
+ static int do_request_fw(struct b43legacy_wldev *dev,
+ const char *name,
+- const struct firmware **fw)
++ const struct firmware **fw, bool async)
+ {
+ char path[sizeof(modparam_fwpostfix) + 32];
+ struct b43legacy_fw_header *hdr;
+@@ -1528,7 +1536,24 @@ static int do_request_fw(struct b43legac
+ snprintf(path, ARRAY_SIZE(path),
+ "b43legacy%s/%s.fw",
+ modparam_fwpostfix, name);
+- err = request_firmware(fw, path, dev->dev->dev);
++ b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
++ if (async) {
++ init_completion(&dev->fw_load_complete);
++ err = request_firmware_nowait(THIS_MODULE, 1, path,
++ dev->dev->dev, GFP_KERNEL,
++ dev, b43legacy_fw_cb);
++ if (err) {
++ b43legacyerr(dev->wl, "Unable to load firmware\n");
++ return err;
++ }
++ /* stall here until fw ready */
++ wait_for_completion(&dev->fw_load_complete);
++ if (!dev->fwp)
++ err = -EINVAL;
++ *fw = dev->fwp;
++ } else {
++ err = request_firmware(fw, path, dev->dev->dev);
++ }
+ if (err) {
+ b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
+ "or load failed.\n", path);
+@@ -1580,7 +1605,7 @@ static void b43legacy_request_firmware(s
+ filename = "ucode4";
+ else
+ filename = "ucode5";
+- err = do_request_fw(dev, filename, &fw->ucode);
++ err = do_request_fw(dev, filename, &fw->ucode, true);
+ if (err)
+ goto err_load;
+ }
+@@ -1589,7 +1614,7 @@ static void b43legacy_request_firmware(s
+ filename = "pcm4";
+ else
+ filename = "pcm5";
+- err = do_request_fw(dev, filename, &fw->pcm);
++ err = do_request_fw(dev, filename, &fw->pcm, false);
+ if (err)
+ goto err_load;
+ }
+@@ -1607,7 +1632,7 @@ static void b43legacy_request_firmware(s
+ default:
+ goto err_no_initvals;
+ }
+- err = do_request_fw(dev, filename, &fw->initvals);
++ err = do_request_fw(dev, filename, &fw->initvals, false);
+ if (err)
+ goto err_load;
+ }
+@@ -1627,7 +1652,7 @@ static void b43legacy_request_firmware(s
+ default:
+ goto err_no_initvals;
+ }
+- err = do_request_fw(dev, filename, &fw->initvals_band);
++ err = do_request_fw(dev, filename, &fw->initvals_band, false);
+ if (err)
+ goto err_load;
+ }
--- /dev/null
+From bd9eb7fbe69111ea0ff1f999ef4a5f26d223d1d5 Mon Sep 17 00:00:00 2001
+From: Chuansheng Liu <chuansheng.liu@intel.com>
+Date: Sat, 10 Nov 2012 01:27:22 +0800
+Subject: firmware loader: Fix the concurrent request_firmware() race for kref_get/put
+
+From: Chuansheng Liu <chuansheng.liu@intel.com>
+
+commit bd9eb7fbe69111ea0ff1f999ef4a5f26d223d1d5 upstream.
+
+There is one race that both request_firmware() with the same
+firmware name.
+
+The race scenerio is as below:
+CPU1 CPU2
+request_firmware() -->
+_request_firmware_load() return err another request_firmware() is coming -->
+_request_firmware_cleanup is called --> _request_firmware_prepare -->
+release_firmware ---> fw_lookup_and_allocate_buf -->
+ spin_lock(&fwc->lock)
+... __fw_lookup_buf() return true
+fw_free_buf() will be called --> ...
+kref_put -->
+decrease the refcount to 0
+ kref_get(&tmp->ref) ==> it will trigger warning
+ due to refcount == 0
+__fw_free_buf() -->
+... spin_unlock(&fwc->lock)
+spin_lock(&fwc->lock)
+list_del(&buf->list)
+spin_unlock(&fwc->lock)
+kfree(buf)
+ After that, the freed buf will be used.
+
+The key race is decreasing refcount to 0 and list_del is not protected together by
+fwc->lock, and it is possible another thread try to get it between refcount==0
+and list_del.
+
+Fix it here to protect it together.
+
+Acked-by: Ming Lei <ming.lei@canonical.com>
+Signed-off-by: liu chuansheng <chuansheng.liu@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/firmware_class.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *r
+ __func__, buf->fw_id, buf, buf->data,
+ (unsigned int)buf->size);
+
+- spin_lock(&fwc->lock);
+ list_del(&buf->list);
+ spin_unlock(&fwc->lock);
+
+@@ -263,7 +262,10 @@ static void __fw_free_buf(struct kref *r
+
+ static void fw_free_buf(struct firmware_buf *buf)
+ {
+- kref_put(&buf->ref, __fw_free_buf);
++ struct firmware_cache *fwc = buf->fwc;
++ spin_lock(&fwc->lock);
++ if (!kref_put(&buf->ref, __fw_free_buf))
++ spin_unlock(&fwc->lock);
+ }
+
+ /* direct firmware loading support */
--- /dev/null
+From ce2fcbd99cef580623116bb33531dbc3e6f690b0 Mon Sep 17 00:00:00 2001
+From: Chuansheng Liu <chuansheng.liu@intel.com>
+Date: Thu, 8 Nov 2012 19:14:40 +0800
+Subject: firmware loader: Fix the race FW_STATUS_DONE is followed by class_timeout
+
+From: Chuansheng Liu <chuansheng.liu@intel.com>
+
+commit ce2fcbd99cef580623116bb33531dbc3e6f690b0 upstream.
+
+There is a race as below when calling request_firmware():
+CPU1 CPU2
+write 0 > loading
+mutex_lock(&fw_lock)
+...
+set_bit FW_STATUS_DONE class_timeout is coming
+ set_bit FW_STATUS_ABORT
+complete_all &completion
+...
+mutex_unlock(&fw_lock)
+
+In this time, the bit FW_STATUS_DONE and FW_STATUS_ABORT are set,
+and request_firmware() will return failure due to condition in
+_request_firmware_load():
+ if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
+ retval = -ENOENT;
+
+But from the above scenerio, it should be a successful requesting.
+So we need judge if the bit FW_STATUS_DONE is already set before
+calling fw_load_abort() in timeout function.
+
+As Ming's proposal, we need change the timer into sched_work to
+benefit from using &fw_lock mutex also.
+
+Signed-off-by: liu chuansheng <chuansheng.liu@intel.com>
+Acked-by: Ming Lei <ming.lei@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/firmware_class.c | 24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -143,7 +143,7 @@ struct fw_cache_entry {
+ };
+
+ struct firmware_priv {
+- struct timer_list timeout;
++ struct delayed_work timeout_work;
+ bool nowait;
+ struct device dev;
+ struct firmware_buf *buf;
+@@ -667,11 +667,18 @@ static struct bin_attribute firmware_att
+ .write = firmware_data_write,
+ };
+
+-static void firmware_class_timeout(u_long data)
++static void firmware_class_timeout_work(struct work_struct *work)
+ {
+- struct firmware_priv *fw_priv = (struct firmware_priv *) data;
++ struct firmware_priv *fw_priv = container_of(work,
++ struct firmware_priv, timeout_work.work);
+
++ mutex_lock(&fw_lock);
++ if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
++ mutex_unlock(&fw_lock);
++ return;
++ }
+ fw_load_abort(fw_priv);
++ mutex_unlock(&fw_lock);
+ }
+
+ static struct firmware_priv *
+@@ -690,8 +697,8 @@ fw_create_instance(struct firmware *firm
+
+ fw_priv->nowait = nowait;
+ fw_priv->fw = firmware;
+- setup_timer(&fw_priv->timeout,
+- firmware_class_timeout, (u_long) fw_priv);
++ INIT_DELAYED_WORK(&fw_priv->timeout_work,
++ firmware_class_timeout_work);
+
+ f_dev = &fw_priv->dev;
+
+@@ -858,7 +865,9 @@ static int _request_firmware_load(struct
+ dev_dbg(f_dev->parent, "firmware: direct-loading"
+ " firmware %s\n", buf->fw_id);
+
++ mutex_lock(&fw_lock);
+ set_bit(FW_STATUS_DONE, &buf->status);
++ mutex_unlock(&fw_lock);
+ complete_all(&buf->completion);
+ direct_load = 1;
+ goto handle_fw;
+@@ -894,15 +903,14 @@ static int _request_firmware_load(struct
+ dev_set_uevent_suppress(f_dev, false);
+ dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
+ if (timeout != MAX_SCHEDULE_TIMEOUT)
+- mod_timer(&fw_priv->timeout,
+- round_jiffies_up(jiffies + timeout));
++ schedule_delayed_work(&fw_priv->timeout_work, timeout);
+
+ kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
+ }
+
+ wait_for_completion(&buf->completion);
+
+- del_timer_sync(&fw_priv->timeout);
++ cancel_delayed_work_sync(&fw_priv->timeout_work);
+
+ handle_fw:
+ mutex_lock(&fw_lock);
--- /dev/null
+From cdc87c5a30f407ed1ce43d8a22261116873d5ef1 Mon Sep 17 00:00:00 2001
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Date: Fri, 7 Dec 2012 23:11:14 +0100
+Subject: pnpacpi: fix incorrect TEST_ALPHA() test
+
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+commit cdc87c5a30f407ed1ce43d8a22261116873d5ef1 upstream.
+
+TEST_ALPHA() is broken and always returns 0.
+
+[akpm@linux-foundation.org: return false for '@' as well, per Bjorn]
+Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pnp/pnpacpi/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pnp/pnpacpi/core.c
++++ b/drivers/pnp/pnpacpi/core.c
+@@ -58,7 +58,7 @@ static inline int __init is_exclusive_de
+ if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
+ return 0
+ #define TEST_ALPHA(c) \
+- if (!('@' <= (c) || (c) <= 'Z')) \
++ if (!('A' <= (c) && (c) <= 'Z')) \
+ return 0
+ static int __init ispnpidacpi(const char *id)
+ {
net-fix-a-race-in-gro_cell_poll.patch
+firmware-loader-fix-the-race-fw_status_done-is-followed-by-class_timeout.patch
+firmware-loader-fix-the-concurrent-request_firmware-race-for-kref_get-put.patch
+b43legacy-fix-firmware-loading-when-driver-is-built-into-the-kernel.patch
+b43-fix-tx-path-skb-leaks.patch
+pnpacpi-fix-incorrect-test_alpha-test.patch