summaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorTobias Powalowski <tobias@T-POWA-LX.(none)>2010-11-23 12:56:39 +0100
committerTobias Powalowski <tobias@T-POWA-LX.(none)>2010-11-23 12:56:39 +0100
commit98f7ba20a2661bb6e663264e9ac4e7c2333172d0 (patch)
treed178afe34f2cb4eb138745dd37768f251a3e54c4 /patches
parentfe8521995cac38f3a2b10101f444de447aa7020a (diff)
add pre patches and add r8169 regression patch
Diffstat (limited to 'patches')
-rw-r--r--patches/kernel-2.6.36.2-pre-20101123.patch6384
-rw-r--r--patches/r8169-regression.patch49
2 files changed, 6433 insertions, 0 deletions
diff --git a/patches/kernel-2.6.36.2-pre-20101123.patch b/patches/kernel-2.6.36.2-pre-20101123.patch
new file mode 100644
index 0000000..8d536d6
--- /dev/null
+++ b/patches/kernel-2.6.36.2-pre-20101123.patch
@@ -0,0 +1,6384 @@
+From 892b6f90db81cccb723d5d92f4fddc2d68b206e1 Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen@oracle.com>
+Date: Wed, 13 Oct 2010 21:18:03 +0200
+Subject: block: Ensure physical block size is unsigned int
+
+From: Martin K. Petersen <martin.petersen@oracle.com>
+
+commit 892b6f90db81cccb723d5d92f4fddc2d68b206e1 upstream.
+
+Physical block size was declared unsigned int to accomodate the maximum
+size reported by READ CAPACITY(16). Make sure we use the right type in
+the related functions.
+
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-settings.c | 2 +-
+ include/linux/blkdev.h | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -343,7 +343,7 @@ EXPORT_SYMBOL(blk_queue_logical_block_si
+ * hardware can operate on without reverting to read-modify-write
+ * operations.
+ */
+-void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
++void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
+ {
+ q->limits.physical_block_size = size;
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -851,7 +851,7 @@ extern void blk_queue_max_segment_size(s
+ extern void blk_queue_max_discard_sectors(struct request_queue *q,
+ unsigned int max_discard_sectors);
+ extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
+-extern void blk_queue_physical_block_size(struct request_queue *, unsigned short);
++extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
+ extern void blk_queue_alignment_offset(struct request_queue *q,
+ unsigned int alignment);
+ extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
+@@ -1004,7 +1004,7 @@ static inline unsigned int queue_physica
+ return q->limits.physical_block_size;
+ }
+
+-static inline int bdev_physical_block_size(struct block_device *bdev)
++static inline unsigned int bdev_physical_block_size(struct block_device *bdev)
+ {
+ return queue_physical_block_size(bdev_get_queue(bdev));
+ }
+From 7681bfeeccff5efa9eb29bf09249a3c400b15327 Mon Sep 17 00:00:00 2001
+From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+Date: Tue, 19 Oct 2010 09:05:00 +0200
+Subject: block: fix accounting bug on cross partition merges
+
+From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+
+commit 7681bfeeccff5efa9eb29bf09249a3c400b15327 upstream.
+
+/proc/diskstats would display a strange output as follows.
+
+$ cat /proc/diskstats |grep sda
+ 8 0 sda 90524 7579 102154 20464 0 0 0 0 0 14096 20089
+ 8 1 sda1 19085 1352 21841 4209 0 0 0 0 4294967064 15689 4293424691
+ ~~~~~~~~~~
+ 8 2 sda2 71252 3624 74891 15950 0 0 0 0 232 23995 1562390
+ 8 3 sda3 54 487 2188 92 0 0 0 0 0 88 92
+ 8 4 sda4 4 0 8 0 0 0 0 0 0 0 0
+ 8 5 sda5 81 2027 2130 138 0 0 0 0 0 87 137
+
+Its reason is the wrong way of accounting hd_struct->in_flight. When a bio is
+merged into a request belongs to different partition by ELEVATOR_FRONT_MERGE.
+
+The detailed root cause is as follows.
+
+Assuming that there are two partition, sda1 and sda2.
+
+1. A request for sda2 is in request_queue. Hence sda1's hd_struct->in_flight
+ is 0 and sda2's one is 1.
+
+ | hd_struct->in_flight
+ ---------------------------
+ sda1 | 0
+ sda2 | 1
+ ---------------------------
+
+2. A bio belongs to sda1 is issued and is merged into the request mentioned on
+ step1 by ELEVATOR_BACK_MERGE. The first sector of the request is changed
+ from sda2 region to sda1 region. However the two partition's
+ hd_struct->in_flight are not changed.
+
+ | hd_struct->in_flight
+ ---------------------------
+ sda1 | 0
+ sda2 | 1
+ ---------------------------
+
+3. The request is finished and blk_account_io_done() is called. In this case,
+ sda2's hd_struct->in_flight, not a sda1's one, is decremented.
+
+ | hd_struct->in_flight
+ ---------------------------
+ sda1 | -1
+ sda2 | 1
+ ---------------------------
+
+The patch fixes the problem by caching the partition lookup
+inside the request structure, hence making sure that the increment
+and decrement will always happen on the same partition struct. This
+also speeds up IO with accounting enabled, since it cuts down on
+the number of lookups we have to do.
+
+When reloading partition tables, quiesce IO to ensure that no
+request references to the partition struct exists. When it is safe
+to free the partition table, the IO for that device is restarted
+again.
+
+Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-core.c | 24 ++++++++++++++++--------
+ block/blk-merge.c | 2 +-
+ block/blk.h | 4 ----
+ block/genhd.c | 14 ++++++++++++++
+ fs/partitions/check.c | 12 ++++++++++++
+ include/linux/blkdev.h | 1 +
+ include/linux/elevator.h | 2 ++
+ include/linux/genhd.h | 1 +
+ 8 files changed, 47 insertions(+), 13 deletions(-)
+
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -64,13 +64,15 @@ static void drive_stat_acct(struct reque
+ return;
+
+ cpu = part_stat_lock();
+- part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
+
+- if (!new_io)
++ if (!new_io) {
++ part = rq->part;
+ part_stat_inc(cpu, part, merges[rw]);
+- else {
++ } else {
++ part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
+ part_round_stats(cpu, part);
+ part_inc_in_flight(part, rw);
++ rq->part = part;
+ }
+
+ part_stat_unlock();
+@@ -128,6 +130,7 @@ void blk_rq_init(struct request_queue *q
+ rq->ref_count = 1;
+ rq->start_time = jiffies;
+ set_start_time_ns(rq);
++ rq->part = NULL;
+ }
+ EXPORT_SYMBOL(blk_rq_init);
+
+@@ -796,11 +799,16 @@ static struct request *get_request(struc
+ rl->starved[is_sync] = 0;
+
+ priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+- if (priv)
++ if (priv) {
+ rl->elvpriv++;
+
+- if (blk_queue_io_stat(q))
+- rw_flags |= REQ_IO_STAT;
++ /*
++ * Don't do stats for non-priv requests
++ */
++ if (blk_queue_io_stat(q))
++ rw_flags |= REQ_IO_STAT;
++ }
++
+ spin_unlock_irq(q->queue_lock);
+
+ rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
+@@ -1759,7 +1767,7 @@ static void blk_account_io_completion(st
+ int cpu;
+
+ cpu = part_stat_lock();
+- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
++ part = req->part;
+ part_stat_add(cpu, part, sectors[rw], bytes >> 9);
+ part_stat_unlock();
+ }
+@@ -1779,7 +1787,7 @@ static void blk_account_io_done(struct r
+ int cpu;
+
+ cpu = part_stat_lock();
+- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
++ part = req->part;
+
+ part_stat_inc(cpu, part, ios[rw]);
+ part_stat_add(cpu, part, ticks[rw], duration);
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -343,7 +343,7 @@ static void blk_account_io_merge(struct
+ int cpu;
+
+ cpu = part_stat_lock();
+- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
++ part = req->part;
+
+ part_round_stats(cpu, part);
+ part_dec_in_flight(part, rq_data_dir(req));
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -110,10 +110,6 @@ void blk_queue_congestion_threshold(stru
+
+ int blk_dev_init(void);
+
+-void elv_quiesce_start(struct request_queue *q);
+-void elv_quiesce_end(struct request_queue *q);
+-
+-
+ /*
+ * Return the threshold (number of used requests) at which the queue is
+ * considered to be congested. It include a little hysteresis to keep the
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -925,8 +925,15 @@ static void disk_free_ptbl_rcu_cb(struct
+ {
+ struct disk_part_tbl *ptbl =
+ container_of(head, struct disk_part_tbl, rcu_head);
++ struct gendisk *disk = ptbl->disk;
++ struct request_queue *q = disk->queue;
++ unsigned long flags;
+
+ kfree(ptbl);
++
++ spin_lock_irqsave(q->queue_lock, flags);
++ elv_quiesce_end(q);
++ spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+
+ /**
+@@ -944,11 +951,17 @@ static void disk_replace_part_tbl(struct
+ struct disk_part_tbl *new_ptbl)
+ {
+ struct disk_part_tbl *old_ptbl = disk->part_tbl;
++ struct request_queue *q = disk->queue;
+
+ rcu_assign_pointer(disk->part_tbl, new_ptbl);
+
+ if (old_ptbl) {
+ rcu_assign_pointer(old_ptbl->last_lookup, NULL);
++
++ spin_lock_irq(q->queue_lock);
++ elv_quiesce_start(q);
++ spin_unlock_irq(q->queue_lock);
++
+ call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
+ }
+ }
+@@ -989,6 +1002,7 @@ int disk_expand_part_tbl(struct gendisk
+ return -ENOMEM;
+
+ new_ptbl->len = target;
++ new_ptbl->disk = disk;
+
+ for (i = 0; i < len; i++)
+ rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
+--- a/fs/partitions/check.c
++++ b/fs/partitions/check.c
+@@ -364,17 +364,25 @@ struct device_type part_type = {
+ static void delete_partition_rcu_cb(struct rcu_head *head)
+ {
+ struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
++ struct gendisk *disk = part_to_disk(part);
++ struct request_queue *q = disk->queue;
++ unsigned long flags;
+
+ part->start_sect = 0;
+ part->nr_sects = 0;
+ part_stat_set_all(part, 0);
+ put_device(part_to_dev(part));
++
++ spin_lock_irqsave(q->queue_lock, flags);
++ elv_quiesce_end(q);
++ spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+
+ void delete_partition(struct gendisk *disk, int partno)
+ {
+ struct disk_part_tbl *ptbl = disk->part_tbl;
+ struct hd_struct *part;
++ struct request_queue *q = disk->queue;
+
+ if (partno >= ptbl->len)
+ return;
+@@ -389,6 +397,10 @@ void delete_partition(struct gendisk *di
+ kobject_put(part->holder_dir);
+ device_del(part_to_dev(part));
+
++ spin_lock_irq(q->queue_lock);
++ elv_quiesce_start(q);
++ spin_unlock_irq(q->queue_lock);
++
+ call_rcu(&part->rcu_head, delete_partition_rcu_cb);
+ }
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -115,6 +115,7 @@ struct request {
+ void *elevator_private3;
+
+ struct gendisk *rq_disk;
++ struct hd_struct *part;
+ unsigned long start_time;
+ #ifdef CONFIG_BLK_CGROUP
+ unsigned long long start_time_ns;
+--- a/include/linux/elevator.h
++++ b/include/linux/elevator.h
+@@ -122,6 +122,8 @@ extern void elv_completed_request(struct
+ extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
+ extern void elv_put_request(struct request_queue *, struct request *);
+ extern void elv_drain_elevator(struct request_queue *);
++extern void elv_quiesce_start(struct request_queue *);
++extern void elv_quiesce_end(struct request_queue *);
+
+ /*
+ * io scheduler registration
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -130,6 +130,7 @@ struct disk_part_tbl {
+ struct rcu_head rcu_head;
+ int len;
+ struct hd_struct *last_lookup;
++ struct gendisk *disk;
+ struct hd_struct *part[];
+ };
+
+From 01ea50638bc04ca5259f5711fcdedefcdde1cf43 Mon Sep 17 00:00:00 2001
+From: Signed-off-by: Jan Kara <jack@suse.cz>
+Date: Thu, 16 Sep 2010 20:36:36 +0200
+Subject: block: Fix race during disk initialization
+
+From: Signed-off-by: Jan Kara <jack@suse.cz>
+
+commit 01ea50638bc04ca5259f5711fcdedefcdde1cf43 upstream.
+
+When a new disk is being discovered, add_disk() first ties the bdev to gendisk
+(via register_disk()->blkdev_get()) and only after that calls
+bdi_register_bdev(). Because register_disk() also creates disk's kobject, it
+can happen that userspace manages to open and modify the device's data (or
+inode) before its BDI is properly initialized leading to a warning in
+__mark_inode_dirty().
+
+Fix the problem by registering BDI early enough.
+
+This patch addresses https://bugzilla.kernel.org/show_bug.cgi?id=16312
+
+Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/genhd.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -541,13 +541,15 @@ void add_disk(struct gendisk *disk)
+ disk->major = MAJOR(devt);
+ disk->first_minor = MINOR(devt);
+
++ /* Register BDI before referencing it from bdev */
++ bdi = &disk->queue->backing_dev_info;
++ bdi_register_dev(bdi, disk_devt(disk));
++
+ blk_register_region(disk_devt(disk), disk->minors, NULL,
+ exact_match, exact_lock, disk);
+ register_disk(disk);
+ blk_register_queue(disk);
+
+- bdi = &disk->queue->backing_dev_info;
+- bdi_register_dev(bdi, disk_devt(disk));
+ retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
+ "bdi");
+ WARN_ON(retval);
+From f3f63c1c28bc861a931fac283b5bc3585efb8967 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <jaxboe@fusionio.com>
+Date: Fri, 29 Oct 2010 11:46:56 -0600
+Subject: block: limit vec count in bio_kmalloc() and bio_alloc_map_data()
+
+From: Jens Axboe <jaxboe@fusionio.com>
+
+commit f3f63c1c28bc861a931fac283b5bc3585efb8967 upstream.
+
+Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/bio.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -370,6 +370,9 @@ struct bio *bio_kmalloc(gfp_t gfp_mask,
+ {
+ struct bio *bio;
+
++ if (nr_iovecs > UIO_MAXIOV)
++ return NULL;
++
+ bio = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec),
+ gfp_mask);
+ if (unlikely(!bio))
+@@ -697,8 +700,12 @@ static void bio_free_map_data(struct bio
+ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
+ gfp_t gfp_mask)
+ {
+- struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask);
++ struct bio_map_data *bmd;
++
++ if (iov_count > UIO_MAXIOV)
++ return NULL;
+
++ bmd = kmalloc(sizeof(*bmd), gfp_mask);
+ if (!bmd)
+ return NULL;
+
+From 9f864c80913467312c7b8690e41fb5ebd1b50e92 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <jaxboe@fusionio.com>
+Date: Fri, 29 Oct 2010 11:31:42 -0600
+Subject: block: take care not to overflow when calculating total iov length
+
+From: Jens Axboe <jaxboe@fusionio.com>
+
+commit 9f864c80913467312c7b8690e41fb5ebd1b50e92 upstream.
+
+Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/scsi_ioctl.c | 34 ++++++++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 10 deletions(-)
+
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q
+ if (hdr->iovec_count) {
+ const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+ size_t iov_data_len;
+- struct sg_iovec *iov;
++ struct sg_iovec *sg_iov;
++ struct iovec *iov;
++ int i;
+
+- iov = kmalloc(size, GFP_KERNEL);
+- if (!iov) {
++ sg_iov = kmalloc(size, GFP_KERNEL);
++ if (!sg_iov) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+- if (copy_from_user(iov, hdr->dxferp, size)) {
+- kfree(iov);
++ if (copy_from_user(sg_iov, hdr->dxferp, size)) {
++ kfree(sg_iov);
+ ret = -EFAULT;
+ goto out;
+ }
+
++ /*
++ * Sum up the vecs, making sure they don't overflow
++ */
++ iov = (struct iovec *) sg_iov;
++ iov_data_len = 0;
++ for (i = 0; i < hdr->iovec_count; i++) {
++ if (iov_data_len + iov[i].iov_len < iov_data_len) {
++ kfree(sg_iov);
++ ret = -EINVAL;
++ goto out;
++ }
++ iov_data_len += iov[i].iov_len;
++ }
++
+ /* SG_IO howto says that the shorter of the two wins */
+- iov_data_len = iov_length((struct iovec *)iov,
+- hdr->iovec_count);
+ if (hdr->dxfer_len < iov_data_len) {
+- hdr->iovec_count = iov_shorten((struct iovec *)iov,
++ hdr->iovec_count = iov_shorten(iov,
+ hdr->iovec_count,
+ hdr->dxfer_len);
+ iov_data_len = hdr->dxfer_len;
+ }
+
+- ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count,
++ ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count,
+ iov_data_len, GFP_KERNEL);
+- kfree(iov);
++ kfree(sg_iov);
+ } else if (hdr->dxfer_len)
+ ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
+ GFP_KERNEL);
+From 9284bcf4e335e5f18a8bc7b26461c33ab60d0689 Mon Sep 17 00:00:00 2001
+From: Jens Axboe <jaxboe@fusionio.com>
+Date: Fri, 29 Oct 2010 08:10:18 -0600
+Subject: block: check for proper length of iov entries in blk_rq_map_user_iov()
+
+From: Jens Axboe <jaxboe@fusionio.com>
+
+commit 9284bcf4e335e5f18a8bc7b26461c33ab60d0689 upstream.
+
+Ensure that we pass down properly validated iov segments before
+calling into the mapping or copy functions.
+
+Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-map.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/block/blk-map.c
++++ b/block/blk-map.c
+@@ -205,6 +205,8 @@ int blk_rq_map_user_iov(struct request_q
+ unaligned = 1;
+ break;
+ }
++ if (!iov[i].iov_len)
++ return -EINVAL;
+ }
+
+ if (unaligned || (q->dma_pad_mask & len) || map_data)
+From a0ae5864d42b41c411368bd689462bf063c029c8 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Tue, 2 Nov 2010 05:26:48 +0000
+Subject: drm/radeon/kms: don't disable shared encoders on pre-DCE3 display blocks
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit a0ae5864d42b41c411368bd689462bf063c029c8 upstream.
+
+The A/B links aren't independantly useable on these blocks so when
+we disable the encoders, make sure to only disable the encoder when
+there is no connector using it.
+
+Should fix:
+https://bugs.freedesktop.org/show_bug.cgi?id=18564
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/radeon_encoders.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_encoders.c
++++ b/drivers/gpu/drm/radeon/radeon_encoders.c
+@@ -1547,6 +1547,23 @@ static void radeon_atom_encoder_disable(
+ struct radeon_device *rdev = dev->dev_private;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig;
++
++ /* check for pre-DCE3 cards with shared encoders;
++ * can't really use the links individually, so don't disable
++ * the encoder if it's in use by another connector
++ */
++ if (!ASIC_IS_DCE3(rdev)) {
++ struct drm_encoder *other_encoder;
++ struct radeon_encoder *other_radeon_encoder;
++
++ list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
++ other_radeon_encoder = to_radeon_encoder(other_encoder);
++ if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
++ drm_helper_encoder_in_use(other_encoder))
++ goto disable_done;
++ }
++ }
++
+ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+ switch (radeon_encoder->encoder_id) {
+@@ -1586,6 +1603,7 @@ static void radeon_atom_encoder_disable(
+ break;
+ }
+
++disable_done:
+ if (radeon_encoder_is_digital(encoder)) {
+ if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+ r600_hdmi_disable(encoder);
+From c8a8684d5cfb0f110a962c93586630c0bf91ebc1 Mon Sep 17 00:00:00 2001
+From: Guo-Fu Tseng <cooldavid@cooldavid.org>
+Date: Mon, 18 Oct 2010 14:10:40 +0000
+Subject: jme: Fix PHY power-off error
+
+From: Guo-Fu Tseng <cooldavid@cooldavid.org>
+
+commit c8a8684d5cfb0f110a962c93586630c0bf91ebc1 upstream.
+
+Adding phy_on in opposition to phy_off.
+
+Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/jme.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/jme.c
++++ b/drivers/net/jme.c
+@@ -1575,6 +1575,16 @@ jme_free_irq(struct jme_adapter *jme)
+ }
+ }
+
++static inline void
++jme_phy_on(struct jme_adapter *jme)
++{
++ u32 bmcr;
++
++ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
++ bmcr &= ~BMCR_PDOWN;
++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
++}
++
+ static int
+ jme_open(struct net_device *netdev)
+ {
+@@ -1595,10 +1605,12 @@ jme_open(struct net_device *netdev)
+
+ jme_start_irq(jme);
+
+- if (test_bit(JME_FLAG_SSET, &jme->flags))
++ if (test_bit(JME_FLAG_SSET, &jme->flags)) {
++ jme_phy_on(jme);
+ jme_set_settings(netdev, &jme->old_ecmd);
+- else
++ } else {
+ jme_reset_phy_processor(jme);
++ }
+
+ jme_reset_link(jme);
+
+@@ -3006,10 +3018,12 @@ jme_resume(struct pci_dev *pdev)
+ jme_clear_pm(jme);
+ pci_restore_state(pdev);
+
+- if (test_bit(JME_FLAG_SSET, &jme->flags))
++ if (test_bit(JME_FLAG_SSET, &jme->flags)) {
++ jme_phy_on(jme);
+ jme_set_settings(netdev, &jme->old_ecmd);
+- else
++ } else {
+ jme_reset_phy_processor(jme);
++ }
+
+ jme_start_irq(jme);
+ netif_device_attach(netdev);
+From efc463eb508798da4243625b08c7396462cabf9f Mon Sep 17 00:00:00 2001
+From: Samuel Ortiz <samuel@sortiz.org>
+Date: Mon, 11 Oct 2010 01:17:56 +0200
+Subject: irda: Fix parameter extraction stack overflow
+
+From: Samuel Ortiz <samuel@sortiz.org>
+
+commit efc463eb508798da4243625b08c7396462cabf9f upstream.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/irda/parameters.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/irda/parameters.c
++++ b/net/irda/parameters.c
+@@ -298,6 +298,8 @@ static int irda_extract_string(void *sel
+
+ p.pi = pi; /* In case handler needs to know */
+ p.pl = buf[1]; /* Extract length of value */
++ if (p.pl > 32)
++ p.pl = 32;
+
+ IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
+ p.pi, p.pl);
+@@ -318,7 +320,7 @@ static int irda_extract_string(void *sel
+ (__u8) str[0], (__u8) str[1]);
+
+ /* Null terminate string */
+- str[p.pl+1] = '\0';
++ str[p.pl] = '\0';
+
+ p.pv.c = str; /* Handler will need to take a copy */
+
+From 37f9fc452d138dfc4da2ee1ce5ae85094efc3606 Mon Sep 17 00:00:00 2001
+From: Samuel Ortiz <samuel@sortiz.org>
+Date: Wed, 6 Oct 2010 01:03:12 +0200
+Subject: irda: Fix heap memory corruption in iriap.c
+
+From: Samuel Ortiz <samuel@sortiz.org>
+
+commit 37f9fc452d138dfc4da2ee1ce5ae85094efc3606 upstream.
+
+While parsing the GetValuebyClass command frame, we could potentially write
+passed the skb->data pointer.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/irda/iriap.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/irda/iriap.c
++++ b/net/irda/iriap.c
+@@ -502,7 +502,8 @@ static void iriap_getvaluebyclass_confir
+ IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
+
+ /* Make sure the string is null-terminated */
+- fp[n+value_len] = 0x00;
++ if (n + value_len < skb->len)
++ fp[n + value_len] = 0x00;
+ IRDA_DEBUG(4, "Got string %s\n", fp+n);
+
+ /* Will truncate to IAS_MAX_STRING bytes */
+From e2269308359d5863b6aa1fcb95a425a2ab255f1f Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 14 Oct 2010 17:41:53 +0000
+Subject: r6040: Fix multicast filter some more
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit e2269308359d5863b6aa1fcb95a425a2ab255f1f upstream.
+
+This code has been broken forever, but in several different and
+creative ways.
+
+So far as I can work out, the R6040 MAC filter has 4 exact-match
+entries, the first of which the driver uses for its assigned unicast
+address, plus a 64-entry hash-based filter for multicast addresses
+(maybe unicast as well?).
+
+The original version of this code would write the first 4 multicast
+addresses as exact-match entries from offset 1 (bug #1: there is no
+entry 4 so this could write to some PHY registers). It would fill the
+remainder of the exact-match entries with the broadcast address (bug #2:
+this would overwrite the last used entry). If more than 4 multicast
+addresses were configured, it would set up the hash table, write some
+random crap to the MAC control register (bug #3) and finally walk off
+the end of the list when filling the exact-match entries (bug #4).
+
+All of this seems to be pointless, since it sets the promiscuous bit
+when the interface is made promiscuous or if >4 multicast addresses
+are enabled, and never clears it (bug #5, masking bug #2).
+
+The recent(ish) changes to the multicast list fixed bug #4, but
+completely removed the limit on iteration over the exact-match entries
+(bug #6).
+
+Bug #4 was reported as
+<https://bugzilla.kernel.org/show_bug.cgi?id=15355> and more recently
+as <http://bugs.debian.org/600155>. Florian Fainelli attempted to fix
+these in commit 3bcf8229a8c49769e48d3e0bd1e20d8e003f8106, but that
+actually dealt with bugs #1-3, bug #4 having been fixed in mainline at
+that point.
+
+That commit fixes the most important current bug #6.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/r6040.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/r6040.c
++++ b/drivers/net/r6040.c
+@@ -893,16 +893,18 @@ static void r6040_multicast_list(struct
+ /* Multicast Address 1~4 case */
+ i = 0;
+ netdev_for_each_mc_addr(ha, dev) {
+- if (i < MCAST_MAX) {
+- adrp = (u16 *) ha->addr;
+- iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+- iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+- iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+- } else {
+- iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
+- iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
+- iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
+- }
++ if (i >= MCAST_MAX)
++ break;
++ adrp = (u16 *) ha->addr;
++ iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
++ iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
++ iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
++ i++;
++ }
++ while (i < MCAST_MAX) {
++ iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
++ iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
++ iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
+ i++;
+ }
+ }
+From 354da653233898ed1e51f20cebac9705456bf9b1 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Mon, 18 Oct 2010 23:45:39 -0400
+Subject: drm/radeon/kms: fix 2D tile height alignment in the r600 CS checker
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit 354da653233898ed1e51f20cebac9705456bf9b1 upstream.
+
+macro tile heights are aligned to num channels, not num banks.
+
+Noticed by Dave Airlie.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600_cs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/r600_cs.c
++++ b/drivers/gpu/drm/radeon/r600_cs.c
+@@ -228,7 +228,7 @@ static inline int r600_cs_track_validate
+ __func__, __LINE__, pitch);
+ return -EINVAL;
+ }
+- if (!IS_ALIGNED((height / 8), track->nbanks)) {
++ if (!IS_ALIGNED((height / 8), track->npipes)) {
+ dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
+ __func__, __LINE__, height);
+ return -EINVAL;
+@@ -367,7 +367,7 @@ static int r600_cs_track_check(struct ra
+ __func__, __LINE__, pitch);
+ return -EINVAL;
+ }
+- if ((height / 8) & (track->nbanks - 1)) {
++ if (!IS_ALIGNED((height / 8), track->npipes)) {
+ dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
+ __func__, __LINE__, height);
+ return -EINVAL;
+From a8909cfb1832ac623142898df2a9374722cfe68f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+Date: Sun, 10 Oct 2010 22:51:54 +0200
+Subject: ath9k: built-in rate control A-MPDU fix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+
+commit a8909cfb1832ac623142898df2a9374722cfe68f upstream.
+
+This patch attempts to ensure that ath9k's built-in rate control algorithm
+does not rely on the value of the ampdu_len and ampdu_ack_len tx status
+fields unless the IEEE80211_TX_STAT_AMPDU flag is set.
+
+This patch has not been tested.
+
+Signed-off-by: Björn Smedman <bjorn.smedman@venatech.se>
+Acked-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/rc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -1359,6 +1359,12 @@ static void ath_tx_status(void *priv, st
+ if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
+ return;
+
++ if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
++ tx_info->status.ampdu_ack_len =
++ (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
++ tx_info->status.ampdu_len = 1;
++ }
++
+ /*
+ * If an underrun error is seen assume it as an excessive retry only
+ * if max frame trigger level has been reached (2 KB for singel stream,
+From f209f5298217cf54cd5a9163e18b08d093faf8d9 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Fri, 1 Oct 2010 01:06:53 +0200
+Subject: ath9k: fix channel flag / regd issues with multiple cards
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit f209f5298217cf54cd5a9163e18b08d093faf8d9 upstream.
+
+Since the regulatory code touches the channel array, it needs to be
+copied for each device instance. That way the original channel array
+can also be made const.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/init.c | 37 ++++++++++++++++++++++++++++------
+ 1 file changed, 31 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blin
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
++static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
+ CHAN2G(2412, 0), /* Channel 1 */
+ CHAN2G(2417, 1), /* Channel 2 */
+ CHAN2G(2422, 2), /* Channel 3 */
+@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2g
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
++static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
+ /* _We_ call this UNII 1 */
+ CHAN5G(5180, 14), /* Channel 36 */
+ CHAN5G(5200, 15), /* Channel 40 */
+@@ -477,10 +477,17 @@ err:
+ return -EIO;
+ }
+
+-static void ath9k_init_channels_rates(struct ath_softc *sc)
++static int ath9k_init_channels_rates(struct ath_softc *sc)
+ {
++ void *channels;
++
+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
+- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
++ channels = kmemdup(ath9k_2ghz_chantable,
++ sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
++ if (!channels)
++ return -ENOMEM;
++
++ sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
+ sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+ sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+ ARRAY_SIZE(ath9k_2ghz_chantable);
+@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(st
+ }
+
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
+- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
++ channels = kmemdup(ath9k_5ghz_chantable,
++ sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
++ if (!channels) {
++ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
++ return -ENOMEM;
++ }
++
++ sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
+ sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+ sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
+ ARRAY_SIZE(ath9k_5ghz_chantable);
+@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(st
+ sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
+ ARRAY_SIZE(ath9k_legacy_rates) - 4;
+ }
++ return 0;
+ }
+
+ static void ath9k_init_misc(struct ath_softc *sc)
+@@ -593,8 +609,11 @@ static int ath9k_init_softc(u16 devid, s
+ if (ret)
+ goto err_btcoex;
+
++ ret = ath9k_init_channels_rates(sc);
++ if (ret)
++ goto err_btcoex;
++
+ ath9k_init_crypto(sc);
+- ath9k_init_channels_rates(sc);
+ ath9k_init_misc(sc);
+
+ return 0;
+@@ -751,6 +770,12 @@ static void ath9k_deinit_softc(struct at
+ {
+ int i = 0;
+
++ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
++
++ if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
++
+ if ((sc->btcoex.no_stomp_timer) &&
+ sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+ ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+From ebd022873aa61937603d2c4dfea19ce63ea1a3c8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+Date: Sun, 10 Oct 2010 22:44:39 +0200
+Subject: ath9k: A-MPDU rate control info fix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+
+commit ebd022873aa61937603d2c4dfea19ce63ea1a3c8 upstream.
+
+This patch fixes the following problems with the rate control feedback
+generated by ath9k for A-MPDU frames:
+
+1. Rate control feedback is carried on the first frame of an aggregate
+that is either ACKed, or has execeeded the software retry count and is
+considered failed. However, ath9k would incorrectly assume the aggregate
+had the length 1 if one of these conditions did not apply to the first
+frame of the aggregate, but instead a later frame. This fix therefor
+copies the bf_nframes field of the buffer in the same manner as the rates
+field of the tx status.
+
+2. Sometimes the ampdu_len and ampdu_ack_len fields of the tx status was
+left uninitialized eventhough the IEEE80211_TX_STAT_AMPDU flag was set.
+This is now avoid by setting flag and fields in the same place.
+
+3. Even if a frame has been selected for aggregation by mac80211 and
+marked with the IEEE80211_TX_CTL_AMPDU flag it can sometimes happen that
+ath9k transmits the frame without aggregation. In these cases the
+ampdu_ack_len field could be incorrectly computed because the nbad
+parameter to ath_tx_rc_status was incorrect.
+
+Signed-off-by: Björn Smedman <bjorn.smedman@venatech.se>
+Acked-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -312,6 +312,7 @@ static void ath_tx_complete_aggr(struct
+ int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+ bool rc_update = true;
+ struct ieee80211_tx_rate rates[4];
++ int nframes;
+
+ skb = bf->bf_mpdu;
+ hdr = (struct ieee80211_hdr *)skb->data;
+@@ -320,6 +321,7 @@ static void ath_tx_complete_aggr(struct
+ hw = bf->aphy->hw;
+
+ memcpy(rates, tx_info->control.rates, sizeof(rates));
++ nframes = bf->bf_nframes;
+
+ rcu_read_lock();
+
+@@ -337,7 +339,7 @@ static void ath_tx_complete_aggr(struct
+ !bf->bf_stale || bf_next != NULL)
+ list_move_tail(&bf->list, &bf_head);
+
+- ath_tx_rc_status(bf, ts, 0, 0, false);
++ ath_tx_rc_status(bf, ts, 1, 0, false);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+ 0, 0);
+
+@@ -442,6 +444,7 @@ static void ath_tx_complete_aggr(struct
+
+ if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+ memcpy(tx_info->control.rates, rates, sizeof(rates));
++ bf->bf_nframes = nframes;
+ ath_tx_rc_status(bf, ts, nbad, txok, true);
+ rc_update = false;
+ } else {
+@@ -2024,9 +2027,15 @@ static void ath_tx_rc_status(struct ath_
+
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+
++ BUG_ON(nbad > bf->bf_nframes);
++
++ tx_info->status.ampdu_len = bf->bf_nframes;
++ tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
++ }
++
+ if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+ (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+ if (ieee80211_is_data(hdr->frame_control)) {
+@@ -2036,8 +2045,6 @@ static void ath_tx_rc_status(struct ath_
+ if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
+ (ts->ts_status & ATH9K_TXERR_FIFO))
+ tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
+- tx_info->status.ampdu_len = bf->bf_nframes;
+- tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+ }
+ }
+
+@@ -2159,7 +2166,7 @@ static void ath_tx_processq(struct ath_s
+ */
+ if (ts.ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+- ath_tx_rc_status(bf, &ts, 0, txok, true);
++ ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
+ }
+
+ if (bf_isampdu(bf))
+@@ -2288,7 +2295,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+ if (!bf_isampdu(bf)) {
+ if (txs.ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+- ath_tx_rc_status(bf, &txs, 0, txok, true);
++ ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
+ }
+
+ if (bf_isampdu(bf))
+From 9094537c3a9ef9e127e844254a74186735c9a90b Mon Sep 17 00:00:00 2001
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Date: Mon, 20 Sep 2010 22:54:46 -0700
+Subject: ath9k: Fix tx struck state with paprd
+
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+
+commit 9094537c3a9ef9e127e844254a74186735c9a90b upstream.
+
+Paprd needs to be done only on active chains(not for all the chains
+that hw can support). The paprd training frames which are sent
+for inactive chains would be hanging on the hw queue without
+getting transmitted and would make the connection so unstable.
+This issue happens only with the hw which supports paprd cal(ar9003).
+
+Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -269,6 +269,7 @@ static void ath_paprd_activate(struct at
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
++ struct ath_common *common = ath9k_hw_common(ah);
+ int chain;
+
+ if (!caldata || !caldata->paprd_done)
+@@ -277,7 +278,7 @@ static void ath_paprd_activate(struct at
+ ath9k_ps_wakeup(sc);
+ ar9003_paprd_enable(ah, false);
+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+- if (!(ah->caps.tx_chainmask & BIT(chain)))
++ if (!(common->tx_chainmask & BIT(chain)))
+ continue;
+
+ ar9003_paprd_populate_single_table(ah, caldata, chain);
+@@ -299,6 +300,7 @@ void ath_paprd_calibrate(struct work_str
+ struct ieee80211_supported_band *sband = &sc->sbands[band];
+ struct ath_tx_control txctl;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
++ struct ath_common *common = ath9k_hw_common(ah);
+ int qnum, ftype;
+ int chain_ok = 0;
+ int chain;
+@@ -332,7 +334,7 @@ void ath_paprd_calibrate(struct work_str
+ ath9k_ps_wakeup(sc);
+ ar9003_paprd_init_table(ah);
+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+- if (!(ah->caps.tx_chainmask & BIT(chain)))
++ if (!(common->tx_chainmask & BIT(chain)))
+ continue;
+
+ chain_ok = 0;
+From 90fa539ca3f07323da5a90f5c8f4e5cd952875e7 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 20 Sep 2010 13:45:38 +0200
+Subject: ath9k: clean up / fix aggregation session flush
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 90fa539ca3f07323da5a90f5c8f4e5cd952875e7 upstream.
+
+The tid aggregation cleanup is a bit fragile, as it discards failed
+subframes in some places, and retransmits them in others. This could
+block the cleanup of an existing aggregation session, if a retransmission
+for a tid is issued, yet the tid is never scheduled again because of
+the cleanup state.
+
+Fix this by getting rid of as many subframes as possible, as early
+as possible, and immediately transmitting pending subframes as regular
+HT frames instead of waiting for the cleanup to complete.
+
+Drop all pending subframes while keeping track of the Block ACK window
+during aggregate tx completion to prevent sending out stale subframes,
+which could confuse the receiver side.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 63 ++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 37 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath
+ struct ath_tx_status *ts, int txok);
+ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
+ int nbad, int txok, bool update_rc);
++static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
++ int seqno);
+
+ enum {
+ MCS_HT20,
+@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_
+ struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+ struct ath_buf *bf;
+ struct list_head bf_head;
+- INIT_LIST_HEAD(&bf_head);
++ struct ath_tx_status ts;
+
+- WARN_ON(!tid->paused);
++ INIT_LIST_HEAD(&bf_head);
+
++ memset(&ts, 0, sizeof(ts));
+ spin_lock_bh(&txq->axq_lock);
+- tid->paused = false;
+
+ while (!list_empty(&tid->buf_q)) {
+ bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+- BUG_ON(bf_isretried(bf));
+ list_move_tail(&bf->list, &bf_head);
+- ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
++
++ if (bf_isretried(bf)) {
++ ath_tx_update_baw(sc, tid, bf->bf_seqno);
++ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++ } else {
++ ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
++ }
+ }
+
+ spin_unlock_bh(&txq->axq_lock);
+@@ -433,7 +440,7 @@ static void ath_tx_complete_aggr(struct
+ list_move_tail(&bf->list, &bf_head);
+ }
+
+- if (!txpending) {
++ if (!txpending || (tid->state & AGGR_CLEANUP)) {
+ /*
+ * complete the acked-ones/xretried ones; update
+ * block-ack window
+@@ -513,15 +520,12 @@ static void ath_tx_complete_aggr(struct
+ }
+
+ if (tid->state & AGGR_CLEANUP) {
++ ath_tx_flush_tid(sc, tid);
++
+ if (tid->baw_head == tid->baw_tail) {
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
+ tid->state &= ~AGGR_CLEANUP;
+-
+- /* send buffered frames as singles */
+- ath_tx_flush_tid(sc, tid);
+ }
+- rcu_read_unlock();
+- return;
+ }
+
+ rcu_read_unlock();
+@@ -806,12 +810,6 @@ void ath_tx_aggr_stop(struct ath_softc *
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+ struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
+ struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+- struct ath_tx_status ts;
+- struct ath_buf *bf;
+- struct list_head bf_head;
+-
+- memset(&ts, 0, sizeof(ts));
+- INIT_LIST_HEAD(&bf_head);
+
+ if (txtid->state & AGGR_CLEANUP)
+ return;
+@@ -821,31 +819,22 @@ void ath_tx_aggr_stop(struct ath_softc *
+ return;
+ }
+
+- /* drop all software retried frames and mark this TID */
+ spin_lock_bh(&txq->axq_lock);
+ txtid->paused = true;
+- while (!list_empty(&txtid->buf_q)) {
+- bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
+- if (!bf_isretried(bf)) {
+- /*
+- * NB: it's based on the assumption that
+- * software retried frame will always stay
+- * at the head of software queue.
+- */
+- break;
+- }
+- list_move_tail(&bf->list, &bf_head);
+- ath_tx_update_baw(sc, txtid, bf->bf_seqno);
+- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+- }
+- spin_unlock_bh(&txq->axq_lock);
+
+- if (txtid->baw_head != txtid->baw_tail) {
++ /*
++ * If frames are still being transmitted for this TID, they will be
++ * cleaned up during tx completion. To prevent race conditions, this
++ * TID can only be reused after all in-progress subframes have been
++ * completed.
++ */
++ if (txtid->baw_head != txtid->baw_tail)
+ txtid->state |= AGGR_CLEANUP;
+- } else {
++ else
+ txtid->state &= ~AGGR_ADDBA_COMPLETE;
+- ath_tx_flush_tid(sc, txtid);
+- }
++ spin_unlock_bh(&txq->axq_lock);
++
++ ath_tx_flush_tid(sc, txtid);
+ }
+
+ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+From 8ab2cd09fecc8819bbaee2d0fd8f3a092d866ce3 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:26 -0400
+Subject: ath9k: fix power save race conditions
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 8ab2cd09fecc8819bbaee2d0fd8f3a092d866ce3 upstream.
+
+ath9k has a race on putting the chip into network sleep and
+having registers read from hardware. The race occurs because
+although ath9k_ps_restore() locks its own callers it makes use
+of some variables which get altered in the driver at different
+code paths. The variables are the ps_enabled and ps_flags.
+
+This is easily reprodicible in large network environments when
+roaming with the wpa_supplicant simple bgscan. You'd get some
+0xdeadbeef read out on certain registers such as:
+
+ath: timeout (100000 us) on reg 0x806c: 0xdeadbeef & 0x01f00000 != 0x00000000
+ath: RX failed to go idle in 10 ms RXSM=0xdeadbeef
+
+ath: timeout (100000 us) on reg 0x7000: 0xdeadbeef & 0x00000003 != 0x00000000
+ath: Chip reset failed
+
+The fix is to protect the ath9k_config(hw, IEEE80211_CONF_CHANGE_PS)
+calls with a spin_lock_irqsave() which will disable contendors for
+these variables from interrupt context, timers, re-entry from mac80211
+on the same callback, and most importantly from ath9k_ps_restore()
+which is the only call which will put the device into network sleep.
+
+There are quite a few threads and bug reports on these a few of them are:
+
+https://bugs.launchpad.net/ubuntu/karmic/+source/linux/+bug/407040
+http://code.google.com/p/chromium-os/issues/detail?id=5709
+http://code.google.com/p/chromium-os/issues/detail?id=5943
+
+Stable fixes apply to [2.6.32+]
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 5 ++++-
+ drivers/net/wireless/ath/ath9k/recv.c | 3 +++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1558,6 +1558,8 @@ static int ath9k_config(struct ieee80211
+ * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
+ */
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
++ unsigned long flags;
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (conf->flags & IEEE80211_CONF_PS) {
+ sc->ps_flags |= PS_ENABLED;
+ /*
+@@ -1572,7 +1574,7 @@ static int ath9k_config(struct ieee80211
+ sc->ps_enabled = false;
+ sc->ps_flags &= ~(PS_ENABLED |
+ PS_NULLFUNC_COMPLETED);
+- ath9k_setpower(sc, ATH9K_PM_AWAKE);
++ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+ if (!(ah->caps.hw_caps &
+ ATH9K_HW_CAP_AUTOSLEEP)) {
+ ath9k_hw_setrxabort(sc->sc_ah, 0);
+@@ -1587,6 +1589,7 @@ static int ath9k_config(struct ieee80211
+ }
+ }
+ }
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1096,6 +1096,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
+ u8 rx_status_len = ah->caps.rx_status_len;
+ u64 tsf = 0;
+ u32 tsf_lower = 0;
++ unsigned long flags;
+
+ if (edma)
+ dma_type = DMA_BIDIRECTIONAL;
+@@ -1204,11 +1205,13 @@ int ath_rx_tasklet(struct ath_softc *sc,
+ sc->rx.rxotherant = 0;
+ }
+
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (unlikely(ath9k_check_auto_sleep(sc) ||
+ (sc->ps_flags & (PS_WAIT_FOR_BEACON |
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA))))
+ ath_rx_ps(sc, skb);
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+ ath_rx_send_to_mac80211(hw, sc, skb, rxs);
+
+From 231c3a1f0630c07a584905507a1cb7b705a56ab7 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 20 Sep 2010 19:35:28 +0200
+Subject: ath9k: fix an aggregation start related race condition
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 231c3a1f0630c07a584905507a1cb7b705a56ab7 upstream.
+
+A new aggregation session start can be issued by mac80211, even when the
+cleanup of the previous session has not completed yet. Since the data structure
+for the session is not recreated, this could corrupt the block ack window
+and lock up the aggregation session. Fix this by delaying the new session
+until the old one has been cleaned up.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++--
+ drivers/net/wireless/ath/ath9k/main.c | 5 +++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 10 ++++++++--
+ 3 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -346,8 +346,8 @@ void ath_tx_tasklet(struct ath_softc *sc
+ void ath_tx_edma_tasklet(struct ath_softc *sc);
+ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
+ bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
+-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+- u16 tid, u16 *ssn);
++int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
++ u16 tid, u16 *ssn);
+ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+ void ath9k_enable_ps(struct ath_softc *sc);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1973,8 +1973,9 @@ static int ath9k_ampdu_action(struct iee
+ break;
+ case IEEE80211_AMPDU_TX_START:
+ ath9k_ps_wakeup(sc);
+- ath_tx_aggr_start(sc, sta, tid, ssn);
+- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
++ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
++ if (!ret)
++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ ath9k_ps_restore(sc);
+ break;
+ case IEEE80211_AMPDU_TX_STOP:
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -792,17 +792,23 @@ static void ath_tx_sched_aggr(struct ath
+ status != ATH_AGGR_BAW_CLOSED);
+ }
+
+-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+- u16 tid, u16 *ssn)
++int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
++ u16 tid, u16 *ssn)
+ {
+ struct ath_atx_tid *txtid;
+ struct ath_node *an;
+
+ an = (struct ath_node *)sta->drv_priv;
+ txtid = ATH_AN_2_TID(an, tid);
++
++ if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
++ return -EAGAIN;
++
+ txtid->state |= AGGR_ADDBA_PROGRESS;
+ txtid->paused = true;
+ *ssn = txtid->seq_start;
++
++ return 0;
+ }
+
+ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+From 3fac6dfdcd2b893c22b20a03dd1bf1af8b627c4b Mon Sep 17 00:00:00 2001
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:35 -0400
+Subject: ath9k: fix regression which prevents chip sleep after CAB data
+
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+
+commit 3fac6dfdcd2b893c22b20a03dd1bf1af8b627c4b upstream.
+
+The patch:
+
+commit 293dc5dfdbcc16cde06e40a688394cc8ab083e48
+Author: Gabor Juhos <juhosg@openwrt.org>
+Date: Fri Jun 19 12:17:48 2009 +0200
+
+ ath9k: remove ath_rx_ps_back_to_sleep helper
+
+ This helper only clears the SC_OP_WAIT_FOR_{BEACON,CAB} flags.
+ Remove it and clear these flags directly in the approptiate
+ places instead.
+
+ Changes-licensed-under: ISC
+ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+introduced a regression which forgot to lift the beacon flag
+after we received all broadcast and multicast data. This meant
+we never went to sleep consuming about ~650mW on idle. This pretty
+much broke power save completely.
+
+This patch has fixes for stable kernels [2.6.32+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Sameer Nanda <snanda@google.com>
+Cc: Gabor Juhos <juhosg@openwrt.org>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -631,7 +631,7 @@ static void ath_rx_ps(struct ath_softc *
+ * No more broadcast/multicast frames to be received at this
+ * point.
+ */
+- sc->ps_flags &= ~PS_WAIT_FOR_CAB;
++ sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
+ ath_print(common, ATH_DBG_PS,
+ "All PS CAB frames received, back to sleep\n");
+ } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
+From 3ae74c33c4f799f6bf6d67240a94a0814a8f1944 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Tue, 14 Sep 2010 18:38:26 +0200
+Subject: ath9k_hw: handle rx key miss
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 3ae74c33c4f799f6bf6d67240a94a0814a8f1944 upstream.
+
+If AR_KeyMiss is set in the rx descriptor and AR_RxFrameOK is unset,
+the hardware could not locate a valid key during a decryption attempt.
+
+In this case, the frame must not be reported as decrypted, otherwise
+mac80211 sees only random garbage.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 ++-
+ drivers/net/wireless/ath/ath9k/mac.c | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -616,7 +616,8 @@ int ath9k_hw_process_rxdesc_edma(struct
+ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ } else if (rxsp->status11 & AR_MichaelErr) {
+ rxs->rs_status |= ATH9K_RXERR_MIC;
+- }
++ } else if (rxsp->status11 & AR_KeyMiss)
++ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -713,6 +713,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ rs->rs_status |= ATH9K_RXERR_MIC;
++ else if (ads.ds_rxstatus8 & AR_KeyMiss)
++ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
+From 008443def34db1dcc8016763587a288254ea5735 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:36 -0400
+Subject: ath9k: fix regression which disabled ps on ath9k
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 008443def34db1dcc8016763587a288254ea5735 upstream.
+
+The patch titled "ath9k: Add new file init.c" shuffled some code
+around but in dong so for some reason also removed the revision
+check for disablign power save. Add this revision check again
+so we can get power save re-enabled again by default on cards
+newer than AR5416 and AR5418.
+
+$ git describe --contains 556242049cc3992d0ee625e9f15c4b00ea4baac8
+v2.6.34-rc1~233^2~49^2~343
+
+This patch has fixes for stable kernels [2.6.34+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/init.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -660,7 +660,8 @@ void ath9k_set_hw_capab(struct ath_softc
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
++ if (AR_SREV_5416(sc->sc_ah))
++ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+ hw->queues = 4;
+ hw->max_rates = 4;
+From 52b8ac92496e03d6b5619204d7f3bae6ce6eae45 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:27 -0400
+Subject: ath9k: fix regression on beacon loss after bgscan
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 52b8ac92496e03d6b5619204d7f3bae6ce6eae45 upstream.
+
+When we return to the home channel we were never reseting our beacon
+timers, this was casued by the fact that the scanning flag was still
+on even after we returned to our home channel. There are also other
+reasons why we would get a reset and if we are not off channel
+we always need to resynch our beacon timers, because a reset will
+clear them.
+
+This bug is a regression introduced on 2.6.36. The order of the
+changes are as follows:
+
+5ee08656 - Sat Jul 31 - ath9k: prevent calibration during off-channel activity
+a0daa0e7 - Tue Jul 27 - Revert "mac80211: fix sw scan bracketing"
+543708be - Fri Jun 18 - mac80211: fix sw scan bracketing
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains 5ee0865615f65f84e6ee9174771a6716c29e08e1
+v2.6.36-rc1~43^2~34^2~22
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains a0daa0e7592ada797d6835f11529097aabc27ad2
+v2.6.36-rc1~571^2~64^2~13
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains 543708be320d7df692d24b349ca01a947b340764
+v2.6.36-rc1~571^2~107^2~187
+
+So 5ee08656 would have worked if a0daa0e7 was not committed but
+it was so this means 5ee08656 was broken since it assumed that
+when we were in the channel change routine the scan flag would
+be lifted. As it turns out the scan flag will be set when we
+are already on the home channel.
+
+For more details refer to:
+
+http://code.google.com/p/chromium-os/issues/detail?id=5715
+
+These issues will need to be considered for our solution on
+reshifting the scan complete callback location on mac80211 on
+current development kernel work.
+
+This patch has stable fixes which apply down to [2.6.36+]
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -257,9 +257,11 @@ int ath_set_channel(struct ath_softc *sc
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
+ ath_start_ani(common);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+- ath_beacon_config(sc, NULL);
+ }
+
++ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)))
++ ath_beacon_config(sc, NULL);
++
+ ps_restore:
+ ath9k_ps_restore(sc);
+ return r;
+@@ -953,7 +955,7 @@ int ath_reset(struct ath_softc *sc, bool
+
+ ath_update_txpow(sc);
+
+- if (sc->sc_flags & SC_OP_BEACONS)
++ if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+ ath_beacon_config(sc, NULL); /* restart beacons */
+
+ ath9k_hw_set_interrupts(ah, ah->imask);
+From 56363ddeeed3afc5277ca227209773bc1042cc7b Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 28 Aug 2010 18:21:21 +0200
+Subject: ath9k: fix spurious MIC failure reports
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 56363ddeeed3afc5277ca227209773bc1042cc7b upstream.
+
+According to the hardware documentation, the MIC failure bit is only
+valid if the frame was decrypted using a valid TKIP key and is not a
+fragment.
+In some setups I've seen hardware-reported MIC failures on an AP that
+was configured for CCMP only, so it's clear that additional checks are
+necessary.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath.h | 1 +
+ drivers/net/wireless/ath/ath9k/common.c | 11 +++++++++++
+ drivers/net/wireless/ath/ath9k/mac.c | 3 ++-
+ drivers/net/wireless/ath/ath9k/recv.c | 19 +++++++++++--------
+ 4 files changed, 25 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -119,6 +119,7 @@ struct ath_common {
+
+ u32 keymax;
+ DECLARE_BITMAP(keymap, ATH_KEYMAX);
++ DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
+ u8 splitmic;
+
+ struct ath_regulatory regulatory;
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -366,9 +366,13 @@ int ath9k_cmn_key_config(struct ath_comm
+ set_bit(idx, common->keymap);
+ if (key->alg == ALG_TKIP) {
+ set_bit(idx + 64, common->keymap);
++ set_bit(idx, common->tkip_keymap);
++ set_bit(idx + 64, common->tkip_keymap);
+ if (common->splitmic) {
+ set_bit(idx + 32, common->keymap);
+ set_bit(idx + 64 + 32, common->keymap);
++ set_bit(idx + 32, common->tkip_keymap);
++ set_bit(idx + 64 + 32, common->tkip_keymap);
+ }
+ }
+
+@@ -393,10 +397,17 @@ void ath9k_cmn_key_delete(struct ath_com
+ return;
+
+ clear_bit(key->hw_key_idx + 64, common->keymap);
++
++ clear_bit(key->hw_key_idx, common->tkip_keymap);
++ clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
++
+ if (common->splitmic) {
+ ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
+ clear_bit(key->hw_key_idx + 32, common->keymap);
+ clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
++
++ clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
++ clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
+ }
+ }
+ EXPORT_SYMBOL(ath9k_cmn_key_delete);
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -711,7 +711,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ rs->rs_phyerr = phyerr;
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+- else if (ads.ds_rxstatus8 & AR_MichaelErr)
++ else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
++ rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+ rs->rs_status |= ATH9K_RXERR_MIC;
+ else if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -870,15 +870,18 @@ static bool ath9k_rx_accept(struct ath_c
+ if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+ *decrypt_error = true;
+ } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+- if (ieee80211_is_ctl(fc))
+- /*
+- * Sometimes, we get invalid
+- * MIC failures on valid control frames.
+- * Remove these mic errors.
+- */
+- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+- else
++ /*
++ * The MIC error bit is only valid if the frame
++ * is not a control frame or fragment, and it was
++ * decrypted using a valid TKIP key.
++ */
++ if (!ieee80211_is_ctl(fc) &&
++ !ieee80211_has_morefrags(fc) &&
++ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
++ test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+ rxs->flag |= RX_FLAG_MMIC_ERROR;
++ else
++ rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+ }
+ /*
+ * Reject error frames with the exception of
+From fac6b6a065da42f826088c58bddad82e1b1ccb40 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 23 Oct 2010 17:45:38 +0200
+Subject: ath9k: resume aggregation immediately after a hardware reset
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit fac6b6a065da42f826088c58bddad82e1b1ccb40 upstream.
+
+Since aggregation is usually triggered by tx completion, a hardware
+reset (because of beacon stuck, tx hang or baseband hang) can
+significantly delay the transmission of the next AMPDU (until the next
+tx completion event).
+Fix this by rescheduling aggregation after such a reset.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/beacon.c | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -366,7 +366,7 @@ void ath_beacon_tasklet(unsigned long da
+ ath_print(common, ATH_DBG_BEACON,
+ "beacon is officially stuck\n");
+ sc->sc_flags |= SC_OP_TSF_RESET;
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ }
+
+ return;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -554,7 +554,7 @@ void ath_hw_check(struct work_struct *wo
+
+ msleep(1);
+ }
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+
+ out:
+ ath9k_ps_restore(sc);
+@@ -572,7 +572,7 @@ void ath9k_tasklet(unsigned long data)
+ ath9k_ps_wakeup(sc);
+
+ if (status & ATH9K_INT_FATAL) {
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ return;
+ }
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2206,7 +2206,7 @@ static void ath_tx_complete_poll_work(st
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+ "tx hung, resetting the chip\n");
+ ath9k_ps_wakeup(sc);
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ }
+
+From 2d3fca180710c6832de22c44155ce6a3a4953c6b Mon Sep 17 00:00:00 2001
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+Date: Tue, 19 Oct 2010 20:01:41 +0530
+Subject: ath9k_hw: Fix divide by zero cases in paprd.
+
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+
+commit 2d3fca180710c6832de22c44155ce6a3a4953c6b upstream.
+
+We are not handling all divide by zero cases in paprd.
+Add additional checks for divide by zero cases in papard.
+
+This patch has fixes intended for kernel 2.6.36.
+
+Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -347,6 +347,10 @@ static bool create_pa_curve(u32 *data_L,
+ (((Y[6] - Y[3]) * 1 << scale_factor) +
+ (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]);
+
++ /* prevent division by zero */
++ if (G_fxp == 0)
++ return false;
++
+ Y_intercept =
+ (G_fxp * (x_est[0] - x_est[3]) +
+ (1 << scale_factor)) / (1 << scale_factor) + Y[3];
+@@ -356,14 +360,12 @@ static bool create_pa_curve(u32 *data_L,
+
+ for (i = 0; i <= 3; i++) {
+ y_est[i] = i * 32;
+-
+- /* prevent division by zero */
+- if (G_fxp == 0)
+- return false;
+-
+ x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp;
+ }
+
++ if (y_est[max_index] == 0)
++ return false;
++
+ x_est_fxp1_nonlin =
+ x_est[max_index] - ((1 << scale_factor) * y_est[max_index] +
+ G_fxp) / G_fxp;
+@@ -457,6 +459,8 @@ static bool create_pa_curve(u32 *data_L,
+
+ Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10);
+ scale_B = scale_B / (1 << Q_scale_B);
++ if (scale_B == 0)
++ return false;
+ Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
+ Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
+ beta_raw = beta_raw / (1 << Q_beta);
+From 0dfa6dbb7372e581d3beb38b11772152114796b8 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Mon, 18 Oct 2010 22:47:54 -0700
+Subject: ath9k_hw: Fix TX carrier leakage for IEEE compliance on AR9003 2.2
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 0dfa6dbb7372e581d3beb38b11772152114796b8 upstream.
+
+This updates the initvals for the AR9003 2.2 chipsets. The initvals
+are the initial register values we use for our registers upon hardware
+reset. This synchs up the initvals to match what our latest recommendation
+from our systems engineering team.
+
+The description of changes in this update:
+
+ Improves ability to support very strong Rx conditions.
+ Enhances DFS support for AP-mode.
+ Improves performance of Tx carrier leak calibration.
+ Adds support for Japan channel 14 Tx filtering requirements.
+ Improves Tx power accuracy.
+
+Impact:
+
+ Update required to address degraded throughput at very short range.
+ Update required for AP-mode DFS certification.
+ Update required to comply to IEEE Tx carrier leak specification.
+ May not meet expected +/- 2 dB Tx power accuracy without update.
+
+The most important fix here would be the TX carrier leakage required
+to comply with IEEE 802.11 specifications. The group of changes have
+been tested all together in one release.
+
+References:
+
+ Osprey 2.2 header file ver #33
+
+Checksums:
+
+$ ./initvals -f ar9003-2p2
+0x000000004a488fc7 ar9300_2p2_radio_postamble
+0x0000000046cb1300 ar9300Modes_lowest_ob_db_tx_gain_table_2p2
+0x00000000e912711f ar9300Modes_fast_clock_2p2
+0x0000000037ac0ee8 ar9300_2p2_radio_core
+0x00000000047a7700 ar9300Common_rx_gain_table_merlin_2p2
+0x0000000003f783bb ar9300_2p2_mac_postamble
+0x00000000301fc841 ar9300_2p2_soc_postamble
+0x000000005ec8075f ar9200_merlin_2p2_radio_core
+0x0000000083372ffa ar9300_2p2_baseband_postamble
+0x00000000c4f59974 ar9300_2p2_baseband_core
+0x00000000e20d2e72 ar9300Modes_high_power_tx_gain_table_2p2
+0x000000007fd55c70 ar9300Modes_high_ob_db_tx_gain_table_2p2
+0x0000000029495000 ar9300Common_rx_gain_table_2p2
+0x0000000042cb1300 ar9300Modes_low_ob_db_tx_gain_table_2p2
+0x00000000c4739cd6 ar9300_2p2_mac_core
+0x000000003521a300 ar9300Common_wo_xlna_rx_gain_table_2p2
+0x00000000a15ccf1b ar9300_2p2_soc_preamble
+0x0000000029734396 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2
+0x000000002d834396 ar9300PciePhy_clkreq_enable_L1_2p2
+0x0000000029834396 ar9300PciePhy_clkreq_disable_L1_2p2
+
+$ ./initvals -f ar9003-2p2 | sha1sum
+0ceddb5cf66737610fb51f04cf3e9ff71870c7b4 -
+
+Cc: Yixiang Li <yixiang.li@atheros.com>
+Cc: Don Breslin <don.breslin@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 191 +++++++++++++------
+ 1 file changed, 135 insertions(+), 56 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+@@ -34,6 +34,10 @@ static const u32 ar9300_2p2_radio_postam
+
+ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+@@ -99,6 +103,30 @@ static const u32 ar9300Modes_lowest_ob_d
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
++ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
++ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
++ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -118,7 +146,7 @@ static const u32 ar9300Modes_fast_clock_
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+- {0x00009e00, 0x03721821, 0x03721821},
++ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+ };
+@@ -595,15 +623,16 @@ static const u32 ar9300_2p2_baseband_pos
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+- {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
++ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
++ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
++ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+@@ -624,16 +653,16 @@ static const u32 ar9300_2p2_baseband_pos
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
+- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
++ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+- {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
++ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+- {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
++ {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+@@ -649,13 +678,13 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+- {0x00009834, 0x5f3ca3de},
++ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+- {0x000098b0, 0x52440bbe},
++ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+@@ -681,7 +710,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+- {0x00009e3c, 0xcf946222},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+@@ -694,7 +722,7 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+- {0x0000a22c, 0x01036a1e},
++ {0x0000a22c, 0x01036a27},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+@@ -702,10 +730,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+- {0x0000a2dc, 0x00000000},
+- {0x0000a2e0, 0x00000000},
+- {0x0000a2e4, 0x00000000},
+- {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+@@ -753,33 +777,17 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+- {0x0000a43c, 0x00000000},
++ {0x0000a43c, 0x00100000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x06000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+- {0x0000a600, 0x00000000},
+- {0x0000a604, 0x00000000},
+- {0x0000a608, 0x00000000},
+- {0x0000a60c, 0x00000000},
+- {0x0000a610, 0x00000000},
+- {0x0000a614, 0x00000000},
+- {0x0000a618, 0x00000000},
+- {0x0000a61c, 0x00000000},
+- {0x0000a620, 0x00000000},
+- {0x0000a624, 0x00000000},
+- {0x0000a628, 0x00000000},
+- {0x0000a62c, 0x00000000},
+- {0x0000a630, 0x00000000},
+- {0x0000a634, 0x00000000},
+- {0x0000a638, 0x00000000},
+- {0x0000a63c, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+- {0x0000a64c, 0x00000637},
++ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+@@ -802,10 +810,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+- {0x0000b2dc, 0x00000000},
+- {0x0000b2e0, 0x00000000},
+- {0x0000b2e4, 0x00000000},
+- {0x0000b2e8, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+@@ -820,10 +824,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000b8f4, 0x00000000},
+ {0x0000c2d0, 0x00000080},
+ {0x0000c2d4, 0x00000000},
+- {0x0000c2dc, 0x00000000},
+- {0x0000c2e0, 0x00000000},
+- {0x0000c2e4, 0x00000000},
+- {0x0000c2e8, 0x00000000},
+ {0x0000c2ec, 0x00000000},
+ {0x0000c2f0, 0x00000000},
+ {0x0000c2f4, 0x00000000},
+@@ -835,6 +835,10 @@ static const u32 ar9300_2p2_baseband_cor
+
+ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+@@ -855,7 +859,7 @@ static const u32 ar9300Modes_high_power_
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+@@ -900,6 +904,30 @@ static const u32 ar9300Modes_high_power_
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
+ {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
+ {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+@@ -913,6 +941,10 @@ static const u32 ar9300Modes_high_power_
+
+ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+@@ -933,7 +965,7 @@ static const u32 ar9300Modes_high_ob_db_
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+@@ -978,6 +1010,30 @@ static const u32 ar9300Modes_high_ob_db_
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -1151,14 +1207,14 @@ static const u32 ar9300Common_rx_gain_ta
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+- {0x0000b080, 0x32323232},
+- {0x0000b084, 0x2f2f3232},
+- {0x0000b088, 0x23282a2d},
+- {0x0000b08c, 0x1c1e2123},
+- {0x0000b090, 0x14171919},
+- {0x0000b094, 0x0e0e1214},
+- {0x0000b098, 0x03050707},
+- {0x0000b09c, 0x00030303},
++ {0x0000b080, 0x2a2d2f32},
++ {0x0000b084, 0x21232328},
++ {0x0000b088, 0x19191c1e},
++ {0x0000b08c, 0x12141417},
++ {0x0000b090, 0x07070e0e},
++ {0x0000b094, 0x03030305},
++ {0x0000b098, 0x00000003},
++ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+@@ -1251,6 +1307,10 @@ static const u32 ar9300Common_rx_gain_ta
+
+ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+@@ -1316,6 +1376,30 @@ static const u32 ar9300Modes_low_ob_db_t
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
++ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
++ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
++ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -1414,15 +1498,10 @@ static const u32 ar9300_2p2_mac_core[][2
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+- {0x00008170, 0x18486200},
+- {0x00008174, 0x33332210},
+- {0x00008178, 0x00000000},
+- {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+- {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+From d654567dec75782d6fd9add4b7b9c50e0926d369 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 27 Oct 2010 12:02:54 +0530
+Subject: ath9k_htc: Set proper firmware offset for Netgear WNDA3200
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit d654567dec75782d6fd9add4b7b9c50e0926d369 upstream.
+
+Netgear WNDA3200 device uses ar7010 firmware but it is failed to set
+correct firmware offset on firmware download which causes device initialization
+failure.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -799,10 +799,16 @@ static int ath9k_hif_usb_download_fw(str
+ }
+ kfree(buf);
+
+- if ((hif_dev->device_id == 0x7010) || (hif_dev->device_id == 0x7015))
++ switch (hif_dev->device_id) {
++ case 0x7010:
++ case 0x7015:
++ case 0x9018:
+ firm_offset = AR7010_FIRMWARE_TEXT;
+- else
++ break;
++ default:
+ firm_offset = AR9271_FIRMWARE_TEXT;
++ break;
++ }
+
+ /*
+ * Issue FW download complete command to firmware.
+From 4fc4fbd1d9a05fa4f348b499aca3a6f8d3c9bbe6 Mon Sep 17 00:00:00 2001
+From: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+Date: Thu, 28 Oct 2010 19:51:47 +0530
+Subject: ath9k: Fix incorrect access of rate flags in RC
+
+From: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+
+commit 4fc4fbd1d9a05fa4f348b499aca3a6f8d3c9bbe6 upstream.
+
+The index variable to access the rate flags should be obtained from the
+inner loop counter which corresponds to the rate table structure.This
+fixes the invalid rate selection i.e when the supported basic rate is
+invalid on a particular band and also the following warning message.
+Thanks to Raj for finding this out.
+
+Call Trace:
+
+ [<ffffffff8104ee4a>] warn_slowpath_common+0x7a/0xb0
+
+ [<ffffffff8104ee95>] warn_slowpath_null+0x15/0x20
+
+ [<ffffffffa0583c45>] ath_get_rate+0x595/0x5b0 [ath9k]
+
+ [<ffffffff811a0636>] ? cpumask_next_and+0x36/0x50
+
+ [<ffffffffa0405186>] rate_control_get_rate+0x86/0x160 [mac80211]
+
+ [<ffffffffa040dfac>] invoke_tx_handlers+0x81c/0x12d0 [mac80211]
+
+ [<ffffffffa040eae9>] ieee80211_tx+0x89/0x2b0 [mac80211]
+
+ [<ffffffff812891bc>] ? pskb_expand_head+0x1cc/0x1f0
+
+ [<ffffffffa040edc5>] ieee80211_xmit+0xb5/0x1c0 [mac80211]
+
+ [<ffffffffa041026f>] ieee80211_tx_skb+0x4f/0x60 [mac80211]
+
+ [<ffffffffa03fe016>] ieee80211_send_nullfunc+0x46/0x60 [mac80211]
+
+ [<ffffffffa03f91d7>] ieee80211_offchannel_stop_station+0x107/0x150
+[mac80211]
+
+ [<ffffffff812891bc>] ? pskb_expand_head+0x1cc/0x1f0
+
+ [<ffffffffa040edc5>] ieee80211_xmit+0xb5/0x1c0 [mac80211]
+
+ [<ffffffffa041026f>] ieee80211_tx_skb+0x4f/0x60 [mac80211]
+
+ [<ffffffffa03fe016>] ieee80211_send_nullfunc+0x46/0x60 [mac80211]
+
+ [<ffffffffa03f91d7>] ieee80211_offchannel_stop_station+0x107/0x150
+[mac80211]
+
+ [<ffffffffa03f8896>] ieee80211_scan_work+0x146/0x600 [mac80211]
+
+ [<ffffffff8133a375>] ? schedule+0x2f5/0x8e0
+
+ [<ffffffffa03f8750>] ? ieee80211_scan_work+0x0/0x600 [mac80211]
+
+ [<ffffffff81064fcf>] process_one_work+0x10f/0x380
+
+ [<ffffffff81066bc2>] worker_thread+0x162/0x340
+
+ [<ffffffff81066a60>] ? worker_thread+0x0/0x340
+
+Signed-off-by: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/rc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -538,7 +538,7 @@ static u8 ath_rc_setvalid_rates(struct a
+ for (i = 0; i < rateset->rs_nrates; i++) {
+ for (j = 0; j < rate_table->rate_cnt; j++) {
+ u32 phy = rate_table->info[j].phy;
+- u16 rate_flags = rate_table->info[i].rate_flags;
++ u16 rate_flags = rate_table->info[j].rate_flags;
+ u8 rate = rateset->rs_rates[i];
+ u8 dot11rate = rate_table->info[j].dot11rate;
+
+From b79b33c4baf2532aac2c0924dce5a738099b888c Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:05 -0700
+Subject: ath9k: rename rxflushlock to pcu_lock
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit b79b33c4baf2532aac2c0924dce5a738099b888c upstream.
+
+The real way to lock RX is to contend on the PCU
+and reset, this will be fixed in the next patch but for
+now just do the renames so that the next patch which changes
+the locking order is crystal clear.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/recv.c | 6 +++---
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -312,7 +312,7 @@ struct ath_rx {
+ u8 rxotherant;
+ u32 *rxlink;
+ unsigned int rxfilter;
+- spinlock_t rxflushlock;
++ spinlock_t pcu_lock;
+ spinlock_t rxbuflock;
+ struct list_head rxbuf;
+ struct ath_descdma rxdma;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -587,7 +587,7 @@ void ath9k_tasklet(unsigned long data)
+ rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+
+ if (status & rxmask) {
+- spin_lock_bh(&sc->rx.rxflushlock);
++ spin_lock_bh(&sc->rx.pcu_lock);
+
+ /* Check for high priority Rx first */
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+@@ -595,7 +595,7 @@ void ath9k_tasklet(unsigned long data)
+ ath_rx_tasklet(sc, 0, true);
+
+ ath_rx_tasklet(sc, 0, false);
+- spin_unlock_bh(&sc->rx.rxflushlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ if (status & ATH9K_INT_TX) {
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -310,7 +310,7 @@ int ath_rx_init(struct ath_softc *sc, in
+ struct ath_buf *bf;
+ int error = 0;
+
+- spin_lock_init(&sc->rx.rxflushlock);
++ spin_lock_init(&sc->rx.pcu_lock);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+ spin_lock_init(&sc->rx.rxbuflock);
+
+@@ -522,13 +522,13 @@ bool ath_stoprecv(struct ath_softc *sc)
+
+ void ath_flushrecv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxflushlock);
++ spin_lock_bh(&sc->rx.pcu_lock);
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+- spin_unlock_bh(&sc->rx.rxflushlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
+From e609e2ea2cdb3448e7849703179cd792a28dcc55 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 27 Oct 2010 02:15:05 +0200
+Subject: ath9k: fix tx aggregation flush on AR9003
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit e609e2ea2cdb3448e7849703179cd792a28dcc55 upstream.
+
+Completing aggregate frames can lead to new buffers being pushed into
+the tid queues due to software retransmission.
+When the tx queues are being drained, all pending aggregates must be
+completed before the tid queues get drained, otherwise buffers might be
+leaked.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1101,15 +1101,6 @@ void ath_draintxq(struct ath_softc *sc,
+ txq->axq_tx_inprogress = false;
+ spin_unlock_bh(&txq->axq_lock);
+
+- /* flush any pending frames if aggregation is enabled */
+- if (sc->sc_flags & SC_OP_TXAGGR) {
+- if (!retry_tx) {
+- spin_lock_bh(&txq->axq_lock);
+- ath_txq_drain_pending_buffers(sc, txq);
+- spin_unlock_bh(&txq->axq_lock);
+- }
+- }
+-
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(&txq->txq_fifo_pending)) {
+@@ -1130,6 +1121,15 @@ void ath_draintxq(struct ath_softc *sc,
+ }
+ spin_unlock_bh(&txq->axq_lock);
+ }
++
++ /* flush any pending frames if aggregation is enabled */
++ if (sc->sc_flags & SC_OP_TXAGGR) {
++ if (!retry_tx) {
++ spin_lock_bh(&txq->axq_lock);
++ ath_txq_drain_pending_buffers(sc, txq);
++ spin_unlock_bh(&txq->axq_lock);
++ }
++ }
+ }
+
+ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+From 1e450285281bdf766272c181ecd43d4f2f0711ce Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:03 -0700
+Subject: ath9k: add locking for stopping RX
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 1e450285281bdf766272c181ecd43d4f2f0711ce upstream.
+
+ath9k locks for starting RX but not for stopping RX. We could
+potentially run into a situation where tried to stop RX
+but immediately started RX. This allows for races on the
+the RX engine deciding what buffer we last left off on
+and could potentially cause ath9k to DMA into already
+free'd memory or in the worst case at a later time to
+already given memory to other drivers.
+
+Fix this by locking stopping RX.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -297,10 +297,8 @@ static void ath_edma_start_recv(struct a
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxbuflock);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ int ath_rx_init(struct ath_softc *sc, int nbufs)
+@@ -508,6 +506,7 @@ bool ath_stoprecv(struct ath_softc *sc)
+ struct ath_hw *ah = sc->sc_ah;
+ bool stopped;
+
++ spin_lock_bh(&sc->rx.rxbuflock);
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah);
+@@ -516,6 +515,7 @@ bool ath_stoprecv(struct ath_softc *sc)
+ ath_edma_stop_recv(sc);
+ else
+ sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->rx.rxbuflock);
+
+ return stopped;
+ }
+From 48a6a468198aadb54bc5d3fdd065364d43ff5197 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:28 -0400
+Subject: ath9k: fix enabling ANI / tx monitor after bg scan
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 48a6a468198aadb54bc5d3fdd065364d43ff5197 upstream.
+
+ath9k's entire logic with SC_OP_SCANNING is incorrect due to the
+way mac80211 currently implements the scan complete callback and
+we handle it in ath9k. This patch removes the flag completely in
+preference for the SC_OP_OFFCHANNEL which is really what we wanted.
+
+The scanning flag was used to ensure we reset ANI to the old values
+when we go back to the home channel, but if we are offchannel we
+use some defaults. The flag was also used to re-enable the TX monitor.
+
+Without this patch we simply never re-enabled ANI and the TX monitor
+after going offchannel. This means that after one background
+scan we are prone to noise issues and if we had a TX hang we would
+not recover. To get this to work properly we must enable ANI after
+we have configured the beacon timers, otherwise hardware acts really
+oddly.
+
+This patch has stable fixes which apply down to [2.6.36+], there
+*may* be a to fix this on older kernels but requires a bit of
+work since this patch relies on the new mac80211 flag
+IEEE80211_CONF_OFFCHANNEL which was introduced as of 2.6.36.
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
+ drivers/net/wireless/ath/ath9k/main.c | 10 +++-------
+ drivers/net/wireless/ath/ath9k/recv.c | 4 ++--
+ 3 files changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -516,7 +516,6 @@ void ath_deinit_leds(struct ath_softc *s
+ #define SC_OP_RXFLUSH BIT(7)
+ #define SC_OP_LED_ASSOCIATED BIT(8)
+ #define SC_OP_LED_ON BIT(9)
+-#define SC_OP_SCANNING BIT(10)
+ #define SC_OP_TSF_RESET BIT(11)
+ #define SC_OP_BT_PRIORITY_DETECTED BIT(12)
+ #define SC_OP_BT_SCAN BIT(13)
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -254,14 +254,12 @@ int ath_set_channel(struct ath_softc *sc
+ ath_update_txpow(sc);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+
+- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
+- ath_start_ani(common);
++ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
++ ath_beacon_config(sc, NULL);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
++ ath_start_ani(common);
+ }
+
+- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+- ath_beacon_config(sc, NULL);
+-
+ ps_restore:
+ ath9k_ps_restore(sc);
+ return r;
+@@ -2040,7 +2038,6 @@ static void ath9k_sw_scan_start(struct i
+
+ aphy->state = ATH_WIPHY_SCAN;
+ ath9k_wiphy_pause_all_forced(sc, aphy);
+- sc->sc_flags |= SC_OP_SCANNING;
+ mutex_unlock(&sc->mutex);
+ }
+
+@@ -2055,7 +2052,6 @@ static void ath9k_sw_scan_complete(struc
+
+ mutex_lock(&sc->mutex);
+ aphy->state = ATH_WIPHY_ACTIVE;
+- sc->sc_flags &= ~SC_OP_SCANNING;
+ mutex_unlock(&sc->mutex);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -292,7 +292,7 @@ static void ath_edma_start_recv(struct a
+
+ ath_opmode_init(sc);
+
+- ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING));
++ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+ }
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+@@ -496,7 +496,7 @@ int ath_startrecv(struct ath_softc *sc)
+ start_recv:
+ spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+- ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING));
++ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
+ return 0;
+ }
+From 48a7c3df14d0cda850337a9b3f9e667a0b12a996 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Mon, 8 Nov 2010 20:40:53 +0530
+Subject: ath9k_hw: Fix memory leak on ath9k_hw_rf_alloc_ext_banks failure
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 48a7c3df14d0cda850337a9b3f9e667a0b12a996 upstream.
+
+The allocated externel radio banks have to be freed in
+case of ath9k_hw_rf_alloc_ext_banks failure.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -486,6 +486,7 @@ static int ath9k_hw_post_init(struct ath
+ ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
+ "Failed allocating banks for "
+ "external radio\n");
++ ath9k_hw_rf_free_ext_banks(ah);
+ return ecode;
+ }
+
+From f119da3015712dc32bdf1c311652479e02dcb49a Mon Sep 17 00:00:00 2001
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Date: Thu, 4 Nov 2010 17:41:25 -0700
+Subject: ath9k_hw: Fix AR9280 surprise removal during frequent idle on/off
+
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+
+commit f119da3015712dc32bdf1c311652479e02dcb49a upstream.
+
+Bit 22 of AR_WA should be set to fix the situation where chip reset
+is asynchronous to clock of analog shift registers, such that when
+reset is released, it could mess up the values of analog shift registers
+and cause some hw issue on AR9280.
+
+This bit is write only, but the driver does a read-modify-write
+on AR_WA without setting bit 22 in ar9002_hw_configpcipowersave()
+during radio disable. This causes surprise removal of hw. It can
+never recover from this state and the hw will become usable only
+after a power on/off cycle, and sometimes only during a cold reboot.
+
+This issue can be triggered by doing frequent roaming with the
+simple/test-roam script available from the wifi-test project [1]
+when roaming between APs quickly. When roaming there is a is a high
+possibility that the device being put into idle (radio disable) state
+by mac80211 during AUTH->ASSOC. A device hardware reset would fail
+and the kernel would output:
+
+[40251.363799] ath: AWAKE -> FULL-SLEEP
+[40251.363815] ieee80211 phy17: device no longer idle - working
+[40251.363817] ath: Marking phy17 as not-idle
+[40251.363819] ath: FULL-SLEEP -> AWAKE
+[40251.415978] pciehp 0000:00:1c.3:pcie04: Card not present on Slot(3)
+[40251.419896] ath: ah->misc_mode 0x4
+[40251.428138] pciehp 0000:00:1c.3:pcie04: Card present on Slot(3)
+[40251.532247] ath: timeout (100000 us) on reg 0x9860: 0xffffffff & 0x00000001 != 0x00000000
+[40251.532250] ath: Unable to reset channel (2462 MHz), reset status -5
+[40251.532422] ath: Set channel: 5745 MHz
+[40251.540639] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.548826] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.557023] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.565211] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.573415] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.581603] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.581606] ath: Failed to stop TX DMA. Resetting hardware!
+[40251.592679] ath: DMA failed to stop in 10 ms AR_CR=0xffffffff AR_DIAG_SW=0xffffffff
+[40251.703330] ath: timeout (100000 us) on reg 0x7000: 0xffffffff & 0x00000003 != 0x00000000
+[40251.703333] ath: RTC stuck in MAC reset
+[40251.703334] ath: Chip reset failed
+[40251.703335] ath: Unable to reset hardware; reset status -22
+
+This is currently only reproducible with some HB92 (Half Mini-PCIE)
+cards but the fix applies to all AR9280 cards. This patch fixes this
+issue by setting bit 22 during radio disable.
+
+This patch has fixes for all kernels that has ath9k.
+
+[1] http://wireless.kernel.org/en/developers/Testing/wifi-test
+
+Cc: kyungwan.nam@atheros.com
+Cc: amod.bodas@atheros.com
+Cc: david.quan@atheros.com
+Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9002_hw.c | 3 +++
+ drivers/net/wireless/ath/ath9k/reg.h | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+@@ -411,6 +411,9 @@ static void ar9002_hw_configpcipowersave
+ val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
+ }
+
++ if (AR_SREV_9280(ah))
++ val |= AR_WA_BIT22;
++
+ if (AR_SREV_9285E_20(ah))
+ val |= AR_WA_BIT23;
+
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -709,6 +709,7 @@
+ #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
+ #define AR_WA_ANALOG_SHIFT (1 << 20)
+ #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
++#define AR_WA_BIT22 (1 << 22)
+ #define AR9285_WA_DEFAULT 0x004a050b
+ #define AR9280_WA_DEFAULT 0x0040073b
+ #define AR_WA_DEFAULT 0x0000073f
+From 3bf30b56c4f0a1c4fae34050b7db4527c92891e8 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Thu, 18 Nov 2010 12:19:52 +0530
+Subject: ath9k_htc: Avoid setting QoS control for non-QoS frames
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 3bf30b56c4f0a1c4fae34050b7db4527c92891e8 upstream.
+
+Setting tid information in the TX header is required only for QoS
+frames. Not handling this case causes severe data loss with some APs.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+@@ -121,7 +121,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_
+ tx_hdr.data_type = ATH9K_HTC_NORMAL;
+ }
+
+- if (ieee80211_is_data(fc)) {
++ if (ieee80211_is_data_qos(fc)) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+ }
+From 7583c550c3e635dcc61ab127c36ecefd59fb8dc8 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:04 -0700
+Subject: ath9k: add locking for starting the PCU on RX
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 7583c550c3e635dcc61ab127c36ecefd59fb8dc8 upstream.
+
+There was some locking for starting some parts of
+RX but not for starting the PCU. Include this otherwise
+we can content against stopping the PCU.
+
+This can potentially lead to races against different
+buffers on the PCU which can lead to to the DMA RX
+engine writing to buffers which are already freed.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+index e581b1f..b3c9baf 100644
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -288,11 +288,11 @@ static void ath_edma_start_recv(struct a
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
+ sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
+
+- spin_unlock_bh(&sc->rx.rxbuflock);
+-
+ ath_opmode_init(sc);
+
+ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
++
++ spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+@@ -494,10 +494,11 @@ int ath_startrecv(struct ath_softc *sc)
+ ath9k_hw_rxena(ah);
+
+ start_recv:
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
++ spin_unlock_bh(&sc->rx.rxbuflock);
++
+ return 0;
+ }
+
+From b5261cf4f3860bd772346a3e692683b6144dd44c Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:26 +0530
+Subject: ath9k_hw: Set proper eeprom offset for AR9287 HTC devices
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit b5261cf4f3860bd772346a3e692683b6144dd44c upstream.
+
+AR9287 based PCI & USB devices are differed in eeprom start offset.
+So set proper the offset for HTC devices to read nvram correctly.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/eeprom_9287.c | 2 +-
+ drivers/net/wireless/ath/ath9k/reg.h | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -37,7 +37,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(
+ int addr, eep_start_loc;
+ eep_data = (u16 *)eep;
+
+- if (ah->hw_version.devid == 0x7015)
++ if (AR9287_HTC_DEVID(ah))
+ eep_start_loc = AR9287_HTC_EEP_START_LOC;
+ else
+ eep_start_loc = AR9287_EEP_START_LOC;
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -903,6 +903,10 @@
+ ((_ah)->hw_version.devid == 0x7015) || \
+ ((_ah)->hw_version.devid == 0x9018))
+
++#define AR9287_HTC_DEVID(_ah) \
++ (((_ah)->hw_version.devid == 0x7015) || \
++ ((_ah)->hw_version.devid == 0x1200))
++
+ #define AR_RADIO_SREV_MAJOR 0xf0
+ #define AR_RAD5133_SREV_MAJOR 0xc0
+ #define AR_RAD2133_SREV_MAJOR 0xd0
+From 7cbf2611dac8d5f76fe64795a9426b8c97e6c3f8 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:25 +0530
+Subject: ath9k_htc: Add new devices into AR7010
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 7cbf2611dac8d5f76fe64795a9426b8c97e6c3f8 upstream.
+
+Treat new PIDs (0xA704, 0x1200) as AR7010 devices.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ++++
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 ++
+ drivers/net/wireless/ath/ath9k/reg.h | 4 +++-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -803,6 +803,8 @@ static int ath9k_hif_usb_download_fw(str
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ firm_offset = AR7010_FIRMWARE_TEXT;
+ break;
+ default:
+@@ -909,6 +911,8 @@ static int ath9k_hif_usb_probe(struct us
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
+ hif_dev->fw_name = FIRMWARE_AR7010_1_1;
+ else
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -247,6 +247,8 @@ static int ath9k_init_htc_services(struc
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ priv->htc->credits = 45;
+ break;
+ default:
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -901,7 +901,9 @@
+ #define AR_DEVID_7010(_ah) \
+ (((_ah)->hw_version.devid == 0x7010) || \
+ ((_ah)->hw_version.devid == 0x7015) || \
+- ((_ah)->hw_version.devid == 0x9018))
++ ((_ah)->hw_version.devid == 0x9018) || \
++ ((_ah)->hw_version.devid == 0xA704) || \
++ ((_ah)->hw_version.devid == 0x1200))
+
+ #define AR9287_HTC_DEVID(_ah) \
+ (((_ah)->hw_version.devid == 0x7015) || \
+From ac618d70aeb681df7b77c1107fdf26f3249f855f Mon Sep 17 00:00:00 2001
+From: Haitao Zhang <minipanda@linuxrobot.org>
+Date: Sun, 7 Nov 2010 12:50:24 +0800
+Subject: ath9k_htc: Add support for device ID 3346
+
+From: Haitao Zhang <minipanda@linuxrobot.org>
+
+commit ac618d70aeb681df7b77c1107fdf26f3249f855f upstream.
+
+This patch adds support for USB dongle with device ID 3346 from IMC Networks.
+
+Signed-off-by: Haitao Zhang <minipanda@linuxrobot.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -35,6 +35,7 @@ static struct usb_device_id ath9k_hif_us
+ { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
+ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
+ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
+ { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
+ { },
+From 32b089558c54792028f14ae830ca7c0a8d9ac9a3 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:24 +0530
+Subject: ath9k_htc: Update usb device ID list
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 32b089558c54792028f14ae830ca7c0a8d9ac9a3 upstream.
+
+Added new VID/PIDs into supported devices list
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -36,8 +36,13 @@ static struct usb_device_id ath9k_hif_us
+ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
++ { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
+ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
+ { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
++ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
++ { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */
+ { },
+ };
+
+From 5e848f789d60000d39d9a5f26ab02dbdd963f6cd Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:06 -0700
+Subject: ath9k: lock reset and PCU start/stopping
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 5e848f789d60000d39d9a5f26ab02dbdd963f6cd upstream.
+
+Apart from locking the start and stop PCU we need
+to ensure we also content starting and stopping the PCU
+between hardware resets.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 27 +++++++++++++++++++++++++++
+ drivers/net/wireless/ath/ath9k/recv.c | 2 --
+ 2 files changed, 27 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -213,6 +213,9 @@ int ath_set_channel(struct ath_softc *sc
+ */
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_drain_all_txq(sc, false);
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ stopped = ath_stoprecv(sc);
+
+ /* XXX: do not flush receive queue here. We don't want
+@@ -239,6 +242,7 @@ int ath_set_channel(struct ath_softc *sc
+ "reset status %d\n",
+ channel->center_freq, r);
+ spin_unlock_bh(&sc->sc_resetlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto ps_restore;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+@@ -247,9 +251,12 @@ int ath_set_channel(struct ath_softc *sc
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
+ r = -EIO;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto ps_restore;
+ }
+
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ ath_cache_conf_rate(sc, &hw->conf);
+ ath_update_txpow(sc);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+@@ -840,6 +847,7 @@ void ath_radio_enable(struct ath_softc *
+ if (!ah->curchan)
+ ah->curchan = ath_get_curchannel(sc, sc->hw);
+
++ spin_lock_bh(&sc->rx.pcu_lock);
+ spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (r) {
+@@ -854,8 +862,10 @@ void ath_radio_enable(struct ath_softc *
+ if (ath_startrecv(sc) != 0) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ return;
+ }
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ if (sc->sc_flags & SC_OP_BEACONS)
+ ath_beacon_config(sc, NULL); /* restart beacons */
+@@ -894,6 +904,9 @@ void ath_radio_disable(struct ath_softc
+ ath9k_hw_set_interrupts(ah, 0);
+
+ ath_drain_all_txq(sc, false); /* clear pending tx frames */
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ ath_stoprecv(sc); /* turn off frame recv */
+ ath_flushrecv(sc); /* flush recv queue */
+
+@@ -911,6 +924,9 @@ void ath_radio_disable(struct ath_softc
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ ath9k_hw_phy_disable(ah);
++
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ ath9k_hw_configpcipowersave(ah, 1, 1);
+ ath9k_ps_restore(sc);
+ ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
+@@ -930,6 +946,9 @@ int ath_reset(struct ath_softc *sc, bool
+
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_drain_all_txq(sc, retry_tx);
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ ath_stoprecv(sc);
+ ath_flushrecv(sc);
+
+@@ -944,6 +963,8 @@ int ath_reset(struct ath_softc *sc, bool
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ /*
+ * We may be doing a reset in response to a request
+ * that changes the channel so update any state that
+@@ -1108,6 +1129,7 @@ static int ath9k_start(struct ieee80211_
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
++ spin_lock_bh(&sc->rx.pcu_lock);
+ spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
+ if (r) {
+@@ -1116,6 +1138,7 @@ static int ath9k_start(struct ieee80211_
+ "(freq %u MHz)\n", r,
+ curchan->center_freq);
+ spin_unlock_bh(&sc->sc_resetlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto mutex_unlock;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+@@ -1137,8 +1160,10 @@ static int ath9k_start(struct ieee80211_
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+ r = -EIO;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto mutex_unlock;
+ }
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ /* Setup our intr mask. */
+ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+@@ -1340,12 +1365,14 @@ static void ath9k_stop(struct ieee80211_
+ * before setting the invalid flag. */
+ ath9k_hw_set_interrupts(ah, 0);
+
++ spin_lock_bh(&sc->rx.pcu_lock);
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ath_drain_all_txq(sc, false);
+ ath_stoprecv(sc);
+ ath9k_hw_phy_disable(ah);
+ } else
+ sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ /* disable HAL and put h/w to sleep */
+ ath9k_hw_disable(ah);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -523,13 +523,11 @@ bool ath_stoprecv(struct ath_softc *sc)
+
+ void ath_flushrecv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.pcu_lock);
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+- spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
+From 3207390a8b58bfc1335750f91cf6783c48ca19ca Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Wed, 6 Oct 2010 21:18:04 +0200
+Subject: cfg80211: fix BSS double-unlinking
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 3207390a8b58bfc1335750f91cf6783c48ca19ca upstream.
+
+When multiple interfaces are actively trying
+to associate with the same BSS, they may both
+find that the BSS isn't there and then try to
+unlink it. This can cause errors since the
+unlinking code can't currently deal with items
+that have already been unlinked.
+
+Normally this doesn't happen as most people
+don't try to use multiple station interfaces
+that associate at the same time too.
+
+Fix this by using the list entry as a flag to
+see if the item is still on a list.
+
+Reported-by: Ben Greear <greearb@candelatech.com>
+Tested-by: Hun-Kyi Wynn <hkwynn@candelatech.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/wireless/scan.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -650,14 +650,14 @@ void cfg80211_unlink_bss(struct wiphy *w
+ bss = container_of(pub, struct cfg80211_internal_bss, pub);
+
+ spin_lock_bh(&dev->bss_lock);
++ if (!list_empty(&bss->list)) {
++ list_del_init(&bss->list);
++ dev->bss_generation++;
++ rb_erase(&bss->rbn, &dev->bss_tree);
+
+- list_del(&bss->list);
+- dev->bss_generation++;
+- rb_erase(&bss->rbn, &dev->bss_tree);
+-
++ kref_put(&bss->ref, bss_release);
++ }
+ spin_unlock_bh(&dev->bss_lock);
+-
+- kref_put(&bss->ref, bss_release);
+ }
+ EXPORT_SYMBOL(cfg80211_unlink_bss);
+
+From 2234362c427e2ef667595b9b81c0125003ac5607 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 30 Sep 2010 22:17:43 +0200
+Subject: cfg80211: fix locking
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 2234362c427e2ef667595b9b81c0125003ac5607 upstream.
+
+Add missing unlocking of the wiphy in set_channel,
+and don't try to unlock a non-existing wiphy in
+set_cqm.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/wireless/nl80211.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -761,11 +761,13 @@ static int nl80211_set_channel(struct sk
+
+ result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+ if (result)
+- goto unlock;
++ goto unlock_rtnl;
+
+ result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
+
+- unlock:
++ dev_put(netdev);
++ cfg80211_unlock_rdev(rdev);
++ unlock_rtnl:
+ rtnl_unlock();
+
+ return result;
+@@ -4996,7 +4998,7 @@ static int nl80211_set_cqm_rssi(struct g
+
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+ if (err)
+- goto unlock_rdev;
++ goto unlock_rtnl;
+
+ wdev = dev->ieee80211_ptr;
+
+@@ -5013,9 +5015,10 @@ static int nl80211_set_cqm_rssi(struct g
+ err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
+ threshold, hysteresis);
+
+-unlock_rdev:
++ unlock_rdev:
+ cfg80211_unlock_rdev(rdev);
+ dev_put(dev);
++ unlock_rtnl:
+ rtnl_unlock();
+
+ return err;
+From a171fba491f54216e356efa46096171a7ed01d10 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Mon, 18 Oct 2010 17:44:51 -0700
+Subject: cfg80211: fix regression on processing country IEs
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit a171fba491f54216e356efa46096171a7ed01d10 upstream.
+
+The patch 4f366c5:
+
+ wireless: only use alpha2 regulatory information from country IE
+
+removed some complex intersection we were always doing between the AP's
+country IE info and what we got from CRDA. When CRDA sent us back a
+regulatory domain we would do some sanity checks on that regulatory
+domain response we just got. Part of these sanity checks included
+checking that we already had performed an intersection for the
+request of NL80211_REGDOM_SET_BY_COUNTRY_IE type.
+
+This mean that cfg80211 was only processing country IEs for cases
+where we already had an intersection, but since we removed enforcing
+this this is no longer required, we should just apply the country
+IE country hint with the data received from CRDA.
+
+This patch has fixes intended for kernels >= 2.6.36.
+
+Reported-by: Easwar Krishnan <easwar.krishnan@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/wireless/reg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -1170,7 +1170,7 @@ static int ignore_request(struct wiphy *
+ return 0;
+ return -EALREADY;
+ }
+- return REG_INTERSECT;
++ return 0;
+ case NL80211_REGDOM_SET_BY_DRIVER:
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
+ if (regdom_changes(pending_request->alpha2))
+From 15d46f38df87f89242e470f5797120fa384c1fc3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+Date: Sun, 10 Oct 2010 22:14:25 +0200
+Subject: mac80211: minstrel_ht A-MPDU fix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+
+commit 15d46f38df87f89242e470f5797120fa384c1fc3 upstream.
+
+This patch fixes two problems with the minstrel_ht rate control
+algorithms handling of A-MPDU frames:
+
+1. The ampdu_len field of the tx status is not always initialized for
+non-HT frames (and it would probably be unreasonable to require all
+drivers to do so). This could cause rate control statistics to be
+corrupted. We now trust the ampdu_len and ampdu_ack_len fields only when
+the frame is marked with the IEEE80211_TX_STAT_AMPDU flag.
+
+2. Successful transmission attempts where only recognized when the A-MPDU
+subframe carrying the rate control status information was marked with the
+IEEE80211_TX_STAT_ACK flag. If this information happed to be carried on a
+frame that failed to be ACKed then the other subframes (which may have
+succeeded) where not correctly registered. We now update rate control
+statistics regardless of whether the subframe carrying the information was
+ACKed or not.
+
+Signed-off-by: Björn Smedman <bjorn.smedman@venatech.se>
+Acked-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/rc80211_minstrel_ht.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -397,8 +397,9 @@ minstrel_ht_tx_status(void *priv, struct
+ !(info->flags & IEEE80211_TX_STAT_AMPDU))
+ return;
+
+- if (!info->status.ampdu_len) {
+- info->status.ampdu_ack_len = 1;
++ if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) {
++ info->status.ampdu_ack_len =
++ (info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
+ info->status.ampdu_len = 1;
+ }
+
+@@ -426,7 +427,7 @@ minstrel_ht_tx_status(void *priv, struct
+ group = minstrel_ht_get_group_idx(&ar[i]);
+ rate = &mi->groups[group].rates[ar[i].idx % 8];
+
+- if (last && (info->flags & IEEE80211_TX_STAT_ACK))
++ if (last)
+ rate->success += info->status.ampdu_ack_len;
+
+ rate->attempts += ar[i].count * info->status.ampdu_len;
+From d12c74528e3065c90df70fbc06ec6ffd6e804738 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 8 Oct 2010 22:27:07 +0200
+Subject: mac80211: fix possible null-pointer de-reference
+
+From: Christian Lamparter <chunkeey@googlemail.com>
+
+commit d12c74528e3065c90df70fbc06ec6ffd6e804738 upstream.
+
+This patch not only fixes a null-pointer de-reference
+that would be triggered by a PLINK_OPEN frame with mis-
+matching/incompatible mesh configuration, but also
+responds correctly to non-compatible PLINK_OPEN frames
+by generating a PLINK_CLOSE with the right reason code.
+
+The original bug was detected by smatch.
+( http://repo.or.cz/w/smatch.git )
+
+net/mac80211/mesh_plink.c +574 mesh_rx_plink_frame(168)
+error: we previously assumed 'sta' could be null.
+
+Reviewed-and-Tested-by: Steve deRosier <steve@cozybit.com>
+Reviewed-and-Tested-by: Javier Cardona <javier@cozybit.com>
+Acked-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/mesh_plink.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/net/mac80211/mesh_plink.c
++++ b/net/mac80211/mesh_plink.c
+@@ -412,7 +412,7 @@ void mesh_rx_plink_frame(struct ieee8021
+ enum plink_event event;
+ enum plink_frame_type ftype;
+ size_t baselen;
+- bool deactivated;
++ bool deactivated, matches_local = true;
+ u8 ie_len;
+ u8 *baseaddr;
+ __le16 plid, llid, reason;
+@@ -487,6 +487,7 @@ void mesh_rx_plink_frame(struct ieee8021
+ /* Now we will figure out the appropriate event... */
+ event = PLINK_UNDEFINED;
+ if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {
++ matches_local = false;
+ switch (ftype) {
+ case PLINK_OPEN:
+ event = OPN_RJCT;
+@@ -498,7 +499,15 @@ void mesh_rx_plink_frame(struct ieee8021
+ /* avoid warning */
+ break;
+ }
+- spin_lock_bh(&sta->lock);
++ }
++
++ if (!sta && !matches_local) {
++ rcu_read_unlock();
++ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++ llid = 0;
++ mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid,
++ plid, reason);
++ return;
+ } else if (!sta) {
+ /* ftype == PLINK_OPEN */
+ u32 rates;
+@@ -522,7 +531,7 @@ void mesh_rx_plink_frame(struct ieee8021
+ }
+ event = OPN_ACPT;
+ spin_lock_bh(&sta->lock);
+- } else {
++ } else if (matches_local) {
+ spin_lock_bh(&sta->lock);
+ switch (ftype) {
+ case PLINK_OPEN:
+@@ -564,6 +573,8 @@ void mesh_rx_plink_frame(struct ieee8021
+ rcu_read_unlock();
+ return;
+ }
++ } else {
++ spin_lock_bh(&sta->lock);
+ }
+
+ mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
+From e7480bbb926c5816e4fbfca70748096bbe0e4978 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Fri, 1 Oct 2010 17:05:19 -0400
+Subject: mac80211: fix channel assumption for association done work
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit e7480bbb926c5816e4fbfca70748096bbe0e4978 upstream.
+
+Be consistent and use the wk->chan instead of the
+local->hw.conf.channel for the association done work.
+This prevents any possible races against channel changes
+while we run this work.
+
+In the case that the race did happen we would be initializing
+the bit rates for the new AP under the assumption of a wrong
+channel and in the worst case, wrong band. This could lead
+to trying to assuming we could use CCK frames on 5 GHz, for
+example.
+
+This patch has a fix for kernels >= v2.6.34
+
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/mlme.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1262,7 +1262,7 @@ static bool ieee80211_assoc_success(stru
+
+ rates = 0;
+ basic_rates = 0;
+- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ sband = local->hw.wiphy->bands[wk->chan->band];
+
+ for (i = 0; i < elems.supp_rates_len; i++) {
+ int rate = (elems.supp_rates[i] & 0x7f) * 5;
+@@ -1298,11 +1298,11 @@ static bool ieee80211_assoc_success(stru
+ }
+ }
+
+- sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
++ sta->sta.supp_rates[wk->chan->band] = rates;
+ sdata->vif.bss_conf.basic_rates = basic_rates;
+
+ /* cf. IEEE 802.11 9.2.12 */
+- if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++ if (wk->chan->band == IEEE80211_BAND_2GHZ &&
+ have_higher_than_11mbit)
+ sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
+ else
+From 8d4780eb1ece4e8109b4f6b2e5e61f7fc593c3f4 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Fri, 24 Sep 2010 21:59:57 -0400
+Subject: mac80211: fix offchannel assumption upon association
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 8d4780eb1ece4e8109b4f6b2e5e61f7fc593c3f4 upstream.
+
+Association is dealt with as an atomic offchannel operation,
+we do this because we don't know we are associated until we
+get the associatin response from the AP. When we do get the
+associatin response though we were never clearing the offchannel
+state. This has a few implications, we told drivers we were
+still offchannel, and the first configured TX power for the
+channel does not take into account any power constraints.
+
+For ath9k this meant ANI calibration would not start upon
+association, and we'd have to wait until the first bgscan
+to be triggered. There may be other issues this resolves
+but I'm too lazy to comb the code to check.
+
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Cc: Vasanth Thiagarajan <vasanth.thiagarajan@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -108,7 +108,8 @@ int ieee80211_hw_config(struct ieee80211
+ chan = scan_chan;
+ channel_type = NL80211_CHAN_NO_HT;
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+- } else if (local->tmp_channel) {
++ } else if (local->tmp_channel &&
++ local->oper_channel != local->tmp_channel) {
+ chan = scan_chan = local->tmp_channel;
+ channel_type = local->tmp_channel_type;
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+From 3ba06c6fbd651ed3377e584026d1c112b492cc8b Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <j@w1.fi>
+Date: Fri, 27 Aug 2010 22:21:13 +0300
+Subject: mac80211: Fix signal strength average initialization for CQM events
+
+From: Jouni Malinen <j@w1.fi>
+
+commit 3ba06c6fbd651ed3377e584026d1c112b492cc8b upstream.
+
+The ave_beacon_signal value uses 1/16 dB unit and as such, must be
+initialized with the signal level of the first Beacon frame multiplied
+by 16. This fixes an issue where the initial CQM events are reported
+incorrectly with a burst of events while the running average
+approaches the correct value after the incorrect initialization. This
+could cause user space -based roaming decision process to get quite
+confused at the moment when we would like to go through authentication
+and DHCP.
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/mlme.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1540,7 +1540,7 @@ static void ieee80211_rx_mgmt_beacon(str
+ ifmgd->last_beacon_signal = rx_status->signal;
+ if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
+ ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
+- ifmgd->ave_beacon_signal = rx_status->signal;
++ ifmgd->ave_beacon_signal = rx_status->signal * 16;
+ ifmgd->last_cqm_event_signal = 0;
+ } else {
+ ifmgd->ave_beacon_signal =
+From 4730d5977f3e12b828d354f7752cffd94bdf39e5 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:31 -0400
+Subject: mac80211: reset connection idle when going offchannel
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 4730d5977f3e12b828d354f7752cffd94bdf39e5 upstream.
+
+When we go offchannel mac80211 currently leaves alive the
+connection idle monitor. This should be instead postponed
+until we come back to our home channel, otherwise by the
+time we get back to the home channel we could be triggering
+unecesary probe requests. For APs that do not respond to
+unicast probe requests (Nexus One is a simple example) this
+means we essentially get disconnected after the probes
+fails.
+
+This patch has stable fixes for kernels [2.6.35+]
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/offchannel.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -22,12 +22,15 @@
+ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
+ {
+ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ local->offchannel_ps_enabled = false;
+
+ /* FIXME: what to do when local->pspolling is true? */
+
+ del_timer_sync(&local->dynamic_ps_timer);
++ del_timer_sync(&ifmgd->conn_mon_timer);
++
+ cancel_work_sync(&local->dynamic_ps_enable_work);
+
+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+@@ -85,6 +88,8 @@ static void ieee80211_offchannel_ps_disa
+ mod_timer(&local->dynamic_ps_timer, jiffies +
+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+ }
++
++ ieee80211_sta_reset_conn_monitor(sdata);
+ }
+
+ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
+From be099e82e9cf6d5d65d044e9ef6fc8bee3c7a113 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:29 -0400
+Subject: mac80211: add helper for reseting the connection monitor
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit be099e82e9cf6d5d65d044e9ef6fc8bee3c7a113 upstream.
+
+This will be used in another place later. The connection
+monitor was added as of 2.6.35 so these fixes will be
+applicable to >= 2.6.35.
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/ieee80211_i.h | 1 +
+ net/mac80211/mlme.c | 15 ++++++++++-----
+ 2 files changed, 11 insertions(+), 5 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1003,6 +1003,7 @@ void ieee80211_sta_restart(struct ieee80
+ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
++void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
+
+ /* IBSS code */
+ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -118,6 +118,15 @@ static void mod_beacon_timer(struct ieee
+ round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
+ }
+
++void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
++{
++ if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
++ return;
++
++ mod_timer(&sdata->u.mgd.conn_mon_timer,
++ round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
++}
++
+ static int ecw2cw(int ecw)
+ {
+ return (1 << ecw) - 1;
+@@ -1006,11 +1015,7 @@ void ieee80211_sta_rx_notify(struct ieee
+ if (is_multicast_ether_addr(hdr->addr1))
+ return;
+
+- if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+- return;
+-
+- mod_timer(&sdata->u.mgd.conn_mon_timer,
+- round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
++ ieee80211_sta_reset_conn_monitor(sdata);
+ }
+
+ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
+From d3a910a8e4e846b9a767d35483f4dc7c6de7af82 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:32 -0400
+Subject: mac80211: make the beacon monitor available externally
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit d3a910a8e4e846b9a767d35483f4dc7c6de7af82 upstream.
+
+This will be used by other components next. The beacon
+monitor was added as of 2.6.34 so these fixes are applicable
+only to kernels >= 2.6.34.
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/ieee80211_i.h | 1 +
+ net/mac80211/mlme.c | 8 ++++----
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1003,6 +1003,7 @@ void ieee80211_sta_restart(struct ieee80
+ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
++void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
+
+ /* IBSS code */
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -109,7 +109,7 @@ static void run_again(struct ieee80211_i
+ mod_timer(&ifmgd->timer, timeout);
+ }
+
+-static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
++void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
+ {
+ if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
+ return;
+@@ -1367,7 +1367,7 @@ static bool ieee80211_assoc_success(stru
+ * Also start the timer that will detect beacon loss.
+ */
+ ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
+- mod_beacon_timer(sdata);
++ ieee80211_sta_reset_beacon_monitor(sdata);
+
+ return true;
+ }
+@@ -1470,7 +1470,7 @@ static void ieee80211_rx_mgmt_probe_resp
+ * we have or will be receiving any beacons or data, so let's
+ * schedule the timers again, just in case.
+ */
+- mod_beacon_timer(sdata);
++ ieee80211_sta_reset_beacon_monitor(sdata);
+
+ mod_timer(&ifmgd->conn_mon_timer,
+ round_jiffies_up(jiffies +
+@@ -1593,7 +1593,7 @@ static void ieee80211_rx_mgmt_beacon(str
+ * Push the beacon loss detection into the future since
+ * we are processing a beacon from the AP just now.
+ */
+- mod_beacon_timer(sdata);
++ ieee80211_sta_reset_beacon_monitor(sdata);
+
+ ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
+ ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
+From f01a067d9e4598c71e3c9ee3a84859d2e8af4f8e Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:34 -0400
+Subject: mac80211: send last 3/5 probe requests as unicast
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit f01a067d9e4598c71e3c9ee3a84859d2e8af4f8e upstream.
+
+Some buggy APs do not respond to unicast probe requests
+or send unicast probe requests very delayed so in the
+worst case we should try to send broadcast probe requests,
+otherwise we can get disconnected from these APs.
+
+Even if drivers do not have filters to disregard probe
+responses from foreign APs mac80211 will only process
+probe responses from our associated AP for re-arming
+connection monitoring.
+
+We need to do this since the beacon monitor does not
+push back the connection monitor by design so even if we
+are getting beacons from these type of APs our connection
+monitor currently relies heavily on the way the probe
+requests are received on the AP. An example of an AP
+affected by this is the Nexus One, but this has also been
+observed with random APs.
+
+We can probably optimize this later by using null funcs
+instead of probe requests.
+
+For more details refer to:
+
+http://code.google.com/p/chromium-os/issues/detail?id=5715
+
+This patch has fixes for stable kernels [2.6.35+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/mlme.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1022,10 +1022,19 @@ static void ieee80211_mgd_probe_ap_send(
+ {
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ const u8 *ssid;
++ u8 *dst = ifmgd->associated->bssid;
++ u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3);
++
++ /*
++ * Try sending broadcast probe requests for the last three
++ * probe requests after the first ones failed since some
++ * buggy APs only support broadcast probe requests.
++ */
++ if (ifmgd->probe_send_count >= unicast_limit)
++ dst = NULL;
+
+ ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
+- ieee80211_send_probe_req(sdata, ifmgd->associated->bssid,
+- ssid + 2, ssid[1], NULL, 0);
++ ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
+
+ ifmgd->probe_send_count++;
+ ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
+From 3bc3c0d748402e8c1f31b8569f5924d25d7b8e30 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:33 -0400
+Subject: mac80211: disable beacon monitor while going offchannel
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 3bc3c0d748402e8c1f31b8569f5924d25d7b8e30 upstream.
+
+The beacon monitor should be disabled when going off channel
+to prevent spurious warnings and triggering connection
+deterioration work such as sending probe requests. Re-enable
+the beacon monitor once we come back to the home channel.
+
+This patch has fixes for stable kernels [2.6.34+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/offchannel.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -29,6 +29,7 @@ static void ieee80211_offchannel_ps_enab
+ /* FIXME: what to do when local->pspolling is true? */
+
+ del_timer_sync(&local->dynamic_ps_timer);
++ del_timer_sync(&ifmgd->bcn_mon_timer);
+ del_timer_sync(&ifmgd->conn_mon_timer);
+
+ cancel_work_sync(&local->dynamic_ps_enable_work);
+@@ -89,6 +90,7 @@ static void ieee80211_offchannel_ps_disa
+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+ }
+
++ ieee80211_sta_reset_beacon_monitor(sdata);
+ ieee80211_sta_reset_conn_monitor(sdata);
+ }
+
+From f5521b13880f4f4f612e1d20dd4f565122d16e04 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 14 Sep 2010 22:06:53 +0200
+Subject: mac80211: use correct station flags lock
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit f5521b13880f4f4f612e1d20dd4f565122d16e04 upstream.
+
+This code is modifying the station flags, and
+as such should hold the flags lock so it can
+do so atomically vs. other flags modifications
+and readers. This issue was introduced when
+this code was added in eccb8e8f, as it used
+the wrong lock (thus not fixing the race that
+was previously documented in a comment.)
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/cfg.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -634,6 +634,7 @@ static void sta_apply_parameters(struct
+ struct sta_info *sta,
+ struct station_parameters *params)
+ {
++ unsigned long flags;
+ u32 rates;
+ int i, j;
+ struct ieee80211_supported_band *sband;
+@@ -642,7 +643,7 @@ static void sta_apply_parameters(struct
+
+ sband = local->hw.wiphy->bands[local->oper_channel->band];
+
+- spin_lock_bh(&sta->lock);
++ spin_lock_irqsave(&sta->flaglock, flags);
+ mask = params->sta_flags_mask;
+ set = params->sta_flags_set;
+
+@@ -669,7 +670,7 @@ static void sta_apply_parameters(struct
+ if (set & BIT(NL80211_STA_FLAG_MFP))
+ sta->flags |= WLAN_STA_MFP;
+ }
+- spin_unlock_bh(&sta->lock);
++ spin_unlock_irqrestore(&sta->flaglock, flags);
+
+ /*
+ * cfg80211 validates this (1-2007) and allows setting the AID
+From eb7d3066cf864342e8ae6a5c1126a1602c4d06c0 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Tue, 21 Sep 2010 21:36:18 +0200
+Subject: mac80211: clear txflags for ps-filtered frames
+
+From: Christian Lamparter <chunkeey@googlemail.com>
+
+commit eb7d3066cf864342e8ae6a5c1126a1602c4d06c0 upstream.
+
+This patch fixes stale mac80211_tx_control_flags for
+filtered / retried frames.
+
+Because ieee80211_handle_filtered_frame feeds skbs back
+into the tx path, they have to be stripped of some tx
+flags so they won't confuse the stack, driver or device.
+
+Acked-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/net/mac80211.h | 16 ++++++++++++++++
+ net/mac80211/status.c | 1 +
+ 2 files changed, 17 insertions(+)
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -315,6 +315,9 @@ struct ieee80211_bss_conf {
+ * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
+ * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
+ * frame and selects the maximum number of streams that it can use.
++ *
++ * Note: If you have to add new flags to the enumeration, then don't
++ * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
+ */
+ enum mac80211_tx_control_flags {
+ IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
+@@ -344,6 +347,19 @@ enum mac80211_tx_control_flags {
+
+ #define IEEE80211_TX_CTL_STBC_SHIFT 23
+
++/*
++ * This definition is used as a mask to clear all temporary flags, which are
++ * set by the tx handlers for each transmission attempt by the mac80211 stack.
++ */
++#define IEEE80211_TX_TEMPORARY_FLAGS (IEEE80211_TX_CTL_NO_ACK | \
++ IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT | \
++ IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \
++ IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \
++ IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \
++ IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \
++ IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \
++ IEEE80211_TX_CTL_STBC)
++
+ /**
+ * enum mac80211_rate_control_flags - per-rate flags set by the
+ * Rate Control algorithm.
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -58,6 +58,7 @@ static void ieee80211_handle_filtered_fr
+ info->control.vif = &sta->sdata->vif;
+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
+ IEEE80211_TX_INTFL_RETRANSMISSION;
++ info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+
+ sta->tx_filtered_count++;
+
+From 0c699c3a75d4e8d0d2c317f83048d8fd3ffe692a Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:30 -0400
+Subject: mac80211: reset probe send counter upon connection timer reset
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 0c699c3a75d4e8d0d2c317f83048d8fd3ffe692a upstream.
+
+Upon beacon loss we send probe requests after 30 seconds of idle
+time and we wait for each probe response 1/2 second. We send a
+total of 3 probe requests before giving up on the AP. In the case
+that we reset the connection idle monitor we should reset the probe
+requests count to 0. Right now this won't help in any way but
+the next patch will.
+
+This patch has fixes for stable kernel [2.6.35+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/mlme.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -120,11 +120,15 @@ void ieee80211_sta_reset_beacon_monitor(
+
+ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
+ {
++ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
++
+ if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+ return;
+
+ mod_timer(&sdata->u.mgd.conn_mon_timer,
+ round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
++
++ ifmgd->probe_send_count = 0;
+ }
+
+ static int ecw2cw(int ecw)
+From c8716d9dc13c7f6ee92f2bfc6cc3b723b417bff8 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Sat, 23 Oct 2010 10:59:57 +0530
+Subject: mac80211: Fix ibss station got expired immediately
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit c8716d9dc13c7f6ee92f2bfc6cc3b723b417bff8 upstream.
+
+Station addition in ieee80211_ibss_rx_queued_mgmt is not updating
+sta->last_rx which is causing station expiry in ieee80211_ibss_work
+path. So sta addition and deletion happens repeatedly.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/ibss.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -435,6 +435,7 @@ struct sta_info *ieee80211_ibss_add_sta(
+ if (!sta)
+ return NULL;
+
++ sta->last_rx = jiffies;
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+
+ /* make sure mandatory rates are always added */
+From 5f4e6b2d3c74c1adda1cbfd9d9d30da22c7484fc Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Sat, 16 Oct 2010 18:49:15 +0200
+Subject: mac80211: don't sanitize invalid rates
+
+From: Christian Lamparter <chunkeey@googlemail.com>
+
+commit 5f4e6b2d3c74c1adda1cbfd9d9d30da22c7484fc upstream.
+
+I found this bug while poking around with a pure-gn AP.
+
+Commit:
+cfg80211/mac80211: Use more generic bitrate mask for rate control
+
+Added some sanity checks to ensure that each tx rate index
+is included in the configured mask and it would change any
+rate indexes if it wasn't.
+
+But, the current implementation doesn't take into account
+that the invalid rate index "-1" has a special meaning
+(= no further attempts) and it should not be "changed".
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/rate.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -328,6 +328,9 @@ void rate_control_get_rate(struct ieee80
+ * if needed.
+ */
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
++ /* Skip invalid rates */
++ if (info->control.rates[i].idx < 0)
++ break;
+ /* Rate masking supports only legacy rates for now */
+ if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
+ continue;
+From 44271488b91c9eecf249e075a1805dd887e222d2 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 5 Oct 2010 21:40:33 +0200
+Subject: mac80211: delete AddBA response timer
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 44271488b91c9eecf249e075a1805dd887e222d2 upstream.
+
+We never delete the addBA response timer, which
+is typically fine, but if the station it belongs
+to is deleted very quickly after starting the BA
+session, before the peer had a chance to reply,
+the timer may fire after the station struct has
+been freed already. Therefore, we need to delete
+the timer in a suitable spot -- best when the
+session is being stopped (which will happen even
+then) in which case the delete will be a no-op
+most of the time.
+
+I've reproduced the scenario and tested the fix.
+
+This fixes the crash reported at
+http://mid.gmane.org/4CAB6F96.6090701@candelatech.com
+
+Reported-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/agg-tx.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -177,6 +177,8 @@ int ___ieee80211_stop_tx_ba_session(stru
+
+ del_timer_sync(&tid_tx->addba_resp_timer);
+
++ del_timer_sync(&tid_tx->addba_resp_timer);
++
+ /*
+ * After this packets are no longer handed right through
+ * to the driver but are put onto tid_tx->pending instead,
+From c8701a08d6a4efeae45d84d0aa87172f23b14e3c Mon Sep 17 00:00:00 2001
+From: Tilman Schmidt <tilman@imap.cc>
+Date: Thu, 30 Sep 2010 13:34:40 +0000
+Subject: isdn/gigaset: fix bas_gigaset AT read error handling
+
+From: Tilman Schmidt <tilman@imap.cc>
+
+commit c8701a08d6a4efeae45d84d0aa87172f23b14e3c upstream.
+
+Rework the handling of USB errors in AT response reads
+to fix a possible infinite retry loop and a memory leak,
+and silence a few overly verbose kernel messages.
+
+Signed-off-by: Tilman Schmidt <tilman@imap.cc>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/isdn/gigaset/bas-gigaset.c | 83 ++++++++++++++-----------------------
+ 1 file changed, 33 insertions(+), 50 deletions(-)
+
+--- a/drivers/isdn/gigaset/bas-gigaset.c
++++ b/drivers/isdn/gigaset/bas-gigaset.c
+@@ -438,23 +438,27 @@ static void cmd_in_timeout(unsigned long
+ return;
+ }
+
+- if (ucs->retry_cmd_in++ < BAS_RETRY) {
+- dev_notice(cs->dev, "control read: timeout, retry %d\n",
+- ucs->retry_cmd_in);
+- rc = atread_submit(cs, BAS_TIMEOUT);
+- if (rc >= 0 || rc == -ENODEV)
+- /* resubmitted or disconnected */
+- /* - bypass regular exit block */
+- return;
+- } else {
++ if (ucs->retry_cmd_in++ >= BAS_RETRY) {
+ dev_err(cs->dev,
+ "control read: timeout, giving up after %d tries\n",
+ ucs->retry_cmd_in);
++ kfree(ucs->rcvbuf);
++ ucs->rcvbuf = NULL;
++ ucs->rcvbuf_size = 0;
++ error_reset(cs);
++ return;
++ }
++
++ gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d",
++ __func__, ucs->retry_cmd_in);
++ rc = atread_submit(cs, BAS_TIMEOUT);
++ if (rc < 0) {
++ kfree(ucs->rcvbuf);
++ ucs->rcvbuf = NULL;
++ ucs->rcvbuf_size = 0;
++ if (rc != -ENODEV)
++ error_reset(cs);
+ }
+- kfree(ucs->rcvbuf);
+- ucs->rcvbuf = NULL;
+- ucs->rcvbuf_size = 0;
+- error_reset(cs);
+ }
+
+ /* read_ctrl_callback
+@@ -470,18 +474,11 @@ static void read_ctrl_callback(struct ur
+ struct cardstate *cs = inbuf->cs;
+ struct bas_cardstate *ucs = cs->hw.bas;
+ int status = urb->status;
+- int have_data = 0;
+ unsigned numbytes;
+ int rc;
+
+ update_basstate(ucs, 0, BS_ATRDPEND);
+ wake_up(&ucs->waitqueue);
+-
+- if (!ucs->rcvbuf_size) {
+- dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
+- return;
+- }
+-
+ del_timer(&ucs->timer_cmd_in);
+
+ switch (status) {
+@@ -495,19 +492,10 @@ static void read_ctrl_callback(struct ur
+ numbytes = ucs->rcvbuf_size;
+ }
+
+- /* copy received bytes to inbuf */
+- have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
+-
+- if (unlikely(numbytes < ucs->rcvbuf_size)) {
+- /* incomplete - resubmit for remaining bytes */
+- ucs->rcvbuf_size -= numbytes;
+- ucs->retry_cmd_in = 0;
+- rc = atread_submit(cs, BAS_TIMEOUT);
+- if (rc >= 0 || rc == -ENODEV)
+- /* resubmitted or disconnected */
+- /* - bypass regular exit block */
+- return;
+- error_reset(cs);
++ /* copy received bytes to inbuf, notify event layer */
++ if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) {
++ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
++ gigaset_schedule_event(cs);
+ }
+ break;
+
+@@ -516,37 +504,32 @@ static void read_ctrl_callback(struct ur
+ case -EINPROGRESS: /* pending */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
+- /* no action necessary */
++ /* no further action necessary */
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(status));
+ break;
+
+- default: /* severe trouble */
+- dev_warn(cs->dev, "control read: %s\n",
+- get_usb_statmsg(status));
++ default: /* other errors: retry */
+ if (ucs->retry_cmd_in++ < BAS_RETRY) {
+- dev_notice(cs->dev, "control read: retry %d\n",
+- ucs->retry_cmd_in);
++ gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__,
++ get_usb_statmsg(status), ucs->retry_cmd_in);
+ rc = atread_submit(cs, BAS_TIMEOUT);
+- if (rc >= 0 || rc == -ENODEV)
+- /* resubmitted or disconnected */
+- /* - bypass regular exit block */
++ if (rc >= 0)
++ /* successfully resubmitted, skip freeing */
+ return;
+- } else {
+- dev_err(cs->dev,
+- "control read: giving up after %d tries\n",
+- ucs->retry_cmd_in);
++ if (rc == -ENODEV)
++ /* disconnect, no further action necessary */
++ break;
+ }
++ dev_err(cs->dev, "control read: %s, giving up after %d tries\n",
++ get_usb_statmsg(status), ucs->retry_cmd_in);
+ error_reset(cs);
+ }
+
++ /* read finished, free buffer */
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+- if (have_data) {
+- gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+- gigaset_schedule_event(cs);
+- }
+ }
+
+ /* atread_submit
+From f3d531b99fb30945b4a64d6e2e86e1e62605aca5 Mon Sep 17 00:00:00 2001
+From: Tilman Schmidt <tilman@imap.cc>
+Date: Thu, 30 Sep 2010 13:34:51 +0000
+Subject: isdn/gigaset: correct bas_gigaset rx buffer handling
+
+From: Tilman Schmidt <tilman@imap.cc>
+
+commit f3d531b99fb30945b4a64d6e2e86e1e62605aca5 upstream.
+
+In transparent data reception, avoid a NULL pointer dereference
+in case an skbuff cannot be allocated, remove an inappropriate
+call to the HDLC flush routine, and correct the accounting of
+received bytes for continued buffers.
+
+Signed-off-by: Tilman Schmidt <tilman@imap.cc>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/isdn/gigaset/isocdata.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/isdn/gigaset/isocdata.c
++++ b/drivers/isdn/gigaset/isocdata.c
+@@ -842,13 +842,14 @@ static inline void trans_receive(unsigne
+
+ if (unlikely(bcs->ignore)) {
+ bcs->ignore--;
+- hdlc_flush(bcs);
+ return;
+ }
+ skb = bcs->rx_skb;
+- if (skb == NULL)
++ if (skb == NULL) {
+ skb = gigaset_new_rx_skb(bcs);
+- bcs->hw.bas->goodbytes += skb->len;
++ if (skb == NULL)
++ return;
++ }
+ dobytes = bcs->rx_bufsize - skb->len;
+ while (count > 0) {
+ dst = skb_put(skb, count < dobytes ? count : dobytes);
+@@ -860,6 +861,7 @@ static inline void trans_receive(unsigne
+ if (dobytes == 0) {
+ dump_bytes(DEBUG_STREAM_DUMP,
+ "rcv data", skb->data, skb->len);
++ bcs->hw.bas->goodbytes += skb->len;
+ gigaset_skb_rcvd(bcs, skb);
+ skb = gigaset_new_rx_skb(bcs);
+ if (skb == NULL)
+From b33ffa5cbf52ee751bb8068218ebb3c742c5a515 Mon Sep 17 00:00:00 2001
+From: Tilman Schmidt <tilman@imap.cc>
+Date: Thu, 30 Sep 2010 13:34:30 +0000
+Subject: isdn/gigaset: bas_gigaset locking fix
+
+From: Tilman Schmidt <tilman@imap.cc>
+
+commit b33ffa5cbf52ee751bb8068218ebb3c742c5a515 upstream.
+
+Unlock cs->lock before calling error_hangup() which is marked
+"cs->lock must not be held".
+
+Signed-off-by: Tilman Schmidt <tilman@imap.cc>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/isdn/gigaset/bas-gigaset.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/isdn/gigaset/bas-gigaset.c
++++ b/drivers/isdn/gigaset/bas-gigaset.c
+@@ -1581,13 +1581,13 @@ static int gigaset_init_bchannel(struct
+
+ ret = starturbs(bcs);
+ if (ret < 0) {
++ spin_unlock_irqrestore(&cs->lock, flags);
+ dev_err(cs->dev,
+ "could not start isochronous I/O for channel B%d: %s\n",
+ bcs->channel + 1,
+ ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
+ if (ret != -ENODEV)
+ error_hangup(bcs);
+- spin_unlock_irqrestore(&cs->lock, flags);
+ return ret;
+ }
+
+@@ -1597,11 +1597,11 @@ static int gigaset_init_bchannel(struct
+ dev_err(cs->dev, "could not open channel B%d\n",
+ bcs->channel + 1);
+ stopurbs(bcs->hw.bas);
+- if (ret != -ENODEV)
+- error_hangup(bcs);
+ }
+
+ spin_unlock_irqrestore(&cs->lock, flags);
++ if (ret < 0 && ret != -ENODEV)
++ error_hangup(bcs);
+ return ret;
+ }
+
+From 323584436db0cb05286425d4dfd9516fce88487f Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Sun, 24 Oct 2010 18:16:57 +0200
+Subject: i2c-pca-platform: Change device name of request_irq
+
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+
+commit 323584436db0cb05286425d4dfd9516fce88487f upstream.
+
+i2c->adap.name shouldn't be used in request_irq.
+Instead the driver name "i2c-pca-platform" should be used.
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Acked-by: Wolfram Sang <w.sang@pengutronix.de>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/i2c/busses/i2c-pca-platform.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-pca-platform.c
++++ b/drivers/i2c/busses/i2c-pca-platform.c
+@@ -224,7 +224,7 @@ static int __devinit i2c_pca_pf_probe(st
+
+ if (irq) {
+ ret = request_irq(irq, i2c_pca_pf_handler,
+- IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
++ IRQF_TRIGGER_FALLING, pdev->name, i2c);
+ if (ret)
+ goto e_reqirq;
+ }
+From 85c5702ac046b14713f776d59768252d8ed8018f Mon Sep 17 00:00:00 2001
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Date: Fri, 17 Sep 2010 01:16:25 +0000
+Subject: viafb: fix i2c_transfer error handling
+
+From: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+
+commit 85c5702ac046b14713f776d59768252d8ed8018f upstream.
+
+i2c_transfer returns negative errno on error and number of messages
+processed on success. Just returning this value would give a poor
+interface as it is not obvious that you must compare with 2 after reading
+1 or n bytes and with 1 after writing 1 byte to determine if it was
+successful. To avoid this error prone interface convert the error code
+of a successful read/write to zero and all other non-negative values to
+an negative error code.
+This fixes a regression introduced by
+ via: Rationalize vt1636 detection
+which resulted in no longer detecting a VT1636 chip and therefore has
+broken the output in configurations which contain this chip.
+
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+Acked-by: Jonathan Corbet <corbet@lwn.net>
+Cc: Joseph Chan <JosephChan@via.com.tw>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/video/via/via_i2c.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+--- a/drivers/video/via/via_i2c.c
++++ b/drivers/video/via/via_i2c.c
+@@ -114,6 +114,7 @@ static void via_i2c_setsda(void *data, i
+
+ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
+ {
++ int ret;
+ u8 mm1[] = {0x00};
+ struct i2c_msg msgs[2];
+
+@@ -126,11 +127,18 @@ int viafb_i2c_readbyte(u8 adap, u8 slave
+ mm1[0] = index;
+ msgs[0].len = 1; msgs[1].len = 1;
+ msgs[0].buf = mm1; msgs[1].buf = pdata;
+- return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
++ ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
++ if (ret == 2)
++ ret = 0;
++ else if (ret >= 0)
++ ret = -EIO;
++
++ return ret;
+ }
+
+ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
+ {
++ int ret;
+ u8 msg[2] = { index, data };
+ struct i2c_msg msgs;
+
+@@ -140,11 +148,18 @@ int viafb_i2c_writebyte(u8 adap, u8 slav
+ msgs.addr = slave_addr / 2;
+ msgs.len = 2;
+ msgs.buf = msg;
+- return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
++ ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
++ if (ret == 1)
++ ret = 0;
++ else if (ret >= 0)
++ ret = -EIO;
++
++ return ret;
+ }
+
+ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
+ {
++ int ret;
+ u8 mm1[] = {0x00};
+ struct i2c_msg msgs[2];
+
+@@ -156,7 +171,13 @@ int viafb_i2c_readbytes(u8 adap, u8 slav
+ mm1[0] = index;
+ msgs[0].len = 1; msgs[1].len = buff_len;
+ msgs[0].buf = mm1; msgs[1].buf = buff;
+- return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
++ ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
++ if (ret == 2)
++ ret = 0;
++ else if (ret >= 0)
++ ret = -EIO;
++
++ return ret;
+ }
+
+ /*
+From a5193fe50e7f21c26d22c17c8196420fac1a3ca7 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Wed, 17 Nov 2010 17:56:49 -0500
+Subject: drm/radeon/kms: register an i2c adapter name for the dp aux bus
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit a5193fe50e7f21c26d22c17c8196420fac1a3ca7 upstream.
+
+This causes the connector to not be added since i2c init fails
+for the adapter. Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=31688
+
+Noticed by Ari Savolainen.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Cc: Ari Savolainen <ari.m.savolainen@gmail.com>
+Cc: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/radeon_i2c.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_i2c.c
++++ b/drivers/gpu/drm/radeon/radeon_i2c.c
+@@ -946,6 +946,7 @@ struct radeon_i2c_chan *radeon_i2c_creat
+ i2c->rec = *rec;
+ i2c->adapter.owner = THIS_MODULE;
+ i2c->dev = dev;
++ sprintf(i2c->adapter.name, "Radeon aux bus %s", name);
+ i2c_set_adapdata(&i2c->adapter, i2c);
+ i2c->adapter.algo_data = &i2c->algo.dp;
+ i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch;
+From 0e7adbe263f89ea2ef15b5af5e80a812b2a85025 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Oct 2010 10:37:11 +0200
+Subject: ALSA: hda - Disable sticky PCM stream assignment for AD codecs
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 0e7adbe263f89ea2ef15b5af5e80a812b2a85025 upstream.
+
+The sticky PCM stream assignment introduced in 2.6.36 kernel seems
+causing problems on AD codecs. At some time later, the streaming no
+longer works by unknown reason. A simple workaround is to disable
+sticky-assignment for these codecs.
+
+Tested-by: Vasily Khoruzhick <anarsoul@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/hda_codec.c | 3 +++
+ sound/pci/hda/hda_codec.h | 1 +
+ sound/pci/hda/patch_analog.c | 7 +++++++
+ 3 files changed, 11 insertions(+)
+
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -1281,6 +1281,9 @@ void __snd_hda_codec_cleanup_stream(stru
+ if (!nid)
+ return;
+
++ if (codec->no_sticky_stream)
++ do_now = 1;
++
+ snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
+ p = get_hda_cvt_setup(codec, nid);
+ if (p) {
+--- a/sound/pci/hda/hda_codec.h
++++ b/sound/pci/hda/hda_codec.h
+@@ -850,6 +850,7 @@ struct hda_codec {
+ unsigned int pin_amp_workaround:1; /* pin out-amp takes index
+ * (e.g. Conexant codecs)
+ */
++ unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
+ unsigned int pins_shutup:1; /* pins are shut up */
+ unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -1276,6 +1276,7 @@ static int patch_ad1986a(struct hda_code
+ spec->multiout.no_share_stream = 1;
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -1463,6 +1464,7 @@ static int patch_ad1983(struct hda_codec
+ codec->patch_ops = ad198x_patch_ops;
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -1917,6 +1919,7 @@ static int patch_ad1981(struct hda_codec
+ }
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -3235,6 +3238,7 @@ static int patch_ad1988(struct hda_codec
+ spec->vmaster_nid = 0x04;
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -3449,6 +3453,7 @@ static int patch_ad1884(struct hda_codec
+ codec->patch_ops = ad198x_patch_ops;
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -4422,6 +4427,7 @@ static int patch_ad1884a(struct hda_code
+ }
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+@@ -4761,6 +4767,7 @@ static int patch_ad1882(struct hda_codec
+ }
+
+ codec->no_trigger_sense = 1;
++ codec->no_sticky_stream = 1;
+
+ return 0;
+ }
+From 62b7e5e09bcb854ff05e6ee1aa161f8283dc36ee Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 22 Oct 2010 17:15:47 +0200
+Subject: ALSA: hda - Add workarounds for CT-IBG controllers
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 62b7e5e09bcb854ff05e6ee1aa161f8283dc36ee upstream.
+
+Creative IBG controllers require the playback stream-tags to be started
+from 1, instead of capture+1. Otherwise the stream stalls.
+
+Reported-by: Wai Yew CHAY <wychay@ctl.creative.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/hda_codec.c | 5 ++++-
+ sound/pci/hda/hda_intel.c | 9 +++++++--
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct h
+ struct hda_codec *c;
+ struct hda_cvt_setup *p;
+ unsigned int oldval, newval;
++ int type;
+ int i;
+
+ if (!nid)
+@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct h
+ p->dirty = 0;
+
+ /* make other inactive cvts with the same stream-tag dirty */
++ type = get_wcaps_type(get_wcaps(codec, nid));
+ list_for_each_entry(c, &codec->bus->codec_list, list) {
+ for (i = 0; i < c->cvt_setups.used; i++) {
+ p = snd_array_elem(&c->cvt_setups, i);
+- if (!p->active && p->stream_tag == stream_tag)
++ if (!p->active && p->stream_tag == stream_tag &&
++ get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+ p->dirty = 1;
+ }
+ }
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -1647,7 +1647,7 @@ static int azx_pcm_prepare(struct snd_pc
+ struct azx_dev *azx_dev = get_azx_dev(substream);
+ struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+ struct snd_pcm_runtime *runtime = substream->runtime;
+- unsigned int bufsize, period_bytes, format_val;
++ unsigned int bufsize, period_bytes, format_val, stream_tag;
+ int err;
+
+ azx_stream_reset(chip, azx_dev);
+@@ -1689,7 +1689,12 @@ static int azx_pcm_prepare(struct snd_pc
+ else
+ azx_dev->fifo_size = 0;
+
+- return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag,
++ stream_tag = azx_dev->stream_tag;
++ /* CA-IBG chips need the playback stream starting from 1 */
++ if (chip->driver_type == AZX_DRIVER_CTX &&
++ stream_tag > chip->capture_streams)
++ stream_tag -= chip->capture_streams;
++ return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
+ azx_dev->format_val, substream);
+ }
+
+From 24b55c69b66eb2a122842820ec14ab215fc8572f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 21 Oct 2010 08:55:13 +0200
+Subject: ALSA: hda - Fix wrong SPDIF NID assignment for CA0110
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 24b55c69b66eb2a122842820ec14ab215fc8572f upstream.
+
+The dig_out_nid field must take a digital-converter widget, but the current
+ca0110 parser passed the pin wrongly instead.
+
+Reported-by: Wai Yew CHAY <wychay@ctl.creative.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_ca0110.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/pci/hda/patch_ca0110.c
++++ b/sound/pci/hda/patch_ca0110.c
+@@ -489,7 +489,7 @@ static void parse_digital(struct hda_cod
+ if (cfg->dig_outs &&
+ snd_hda_get_connections(codec, cfg->dig_out_pins[0],
+ &spec->dig_out, 1) == 1)
+- spec->multiout.dig_out_nid = cfg->dig_out_pins[0];
++ spec->multiout.dig_out_nid = spec->dig_out;
+ }
+
+ static int ca0110_parse_auto_config(struct hda_codec *codec)
+From 14d34f166c57e77e3d7f9bc8b43d349186d922c1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 21 Oct 2010 09:03:25 +0200
+Subject: ALSA: hda - Add some workarounds for Creative IBG
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 14d34f166c57e77e3d7f9bc8b43d349186d922c1 upstream.
+
+Creative HD-audio controller chips require some workarounds:
+ - Additional delay before RIRB response
+ - Set the initial RIRB counter to 0xc0
+
+The latter seems to be done in general in Windows driver, so we may
+use this value later for all types if it's confirmed to work better.
+
+Reported-by: Wai Yew CHAY <wychay@ctl.creative.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/hda_intel.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -458,6 +458,7 @@ enum {
+ AZX_DRIVER_ULI,
+ AZX_DRIVER_NVIDIA,
+ AZX_DRIVER_TERA,
++ AZX_DRIVER_CTX,
+ AZX_DRIVER_GENERIC,
+ AZX_NUM_DRIVERS, /* keep this as last entry */
+ };
+@@ -473,6 +474,7 @@ static char *driver_short_names[] __devi
+ [AZX_DRIVER_ULI] = "HDA ULI M5461",
+ [AZX_DRIVER_NVIDIA] = "HDA NVidia",
+ [AZX_DRIVER_TERA] = "HDA Teradici",
++ [AZX_DRIVER_CTX] = "HDA Creative",
+ [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
+ };
+
+@@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *
+ /* reset the rirb hw write pointer */
+ azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
+ /* set N=1, get RIRB response interrupt for new entry */
+- azx_writew(chip, RINTCNT, 1);
++ if (chip->driver_type == AZX_DRIVER_CTX)
++ azx_writew(chip, RINTCNT, 0xc0);
++ else
++ azx_writew(chip, RINTCNT, 1);
+ /* enable rirb dma and response irq */
+ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+ spin_unlock_irq(&chip->reg_lock);
+@@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq
+ /* clear rirb int */
+ status = azx_readb(chip, RIRBSTS);
+ if (status & RIRB_INT_MASK) {
+- if (status & RIRB_INT_RESPONSE)
++ if (status & RIRB_INT_RESPONSE) {
++ if (chip->driver_type == AZX_DRIVER_CTX)
++ udelay(80);
+ azx_update_rirb(chip);
++ }
+ azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
+ }
+
+@@ -2799,10 +2807,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids)
+ { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
+ .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+ .class_mask = 0xffffff,
+- .driver_data = AZX_DRIVER_GENERIC },
++ .driver_data = AZX_DRIVER_CTX },
+ #else
+ /* this entry seems still valid -- i.e. without emu20kx chip */
+- { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC },
++ { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX },
+ #endif
+ /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
+From 838c364ff05c143fd1810e8ad1469935d6c23a7a Mon Sep 17 00:00:00 2001
+From: Jaroslav Kysela <perex@perex.cz>
+Date: Fri, 8 Oct 2010 10:48:50 +0200
+Subject: ALSA: OSS mixer emulation - fix locking
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+commit 838c364ff05c143fd1810e8ad1469935d6c23a7a upstream.
+
+Fix mutex release and cleanup some locking code.
+
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/core/oss/mixer_oss.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/sound/core/oss/mixer_oss.c
++++ b/sound/core/oss/mixer_oss.c
+@@ -618,8 +618,10 @@ static void snd_mixer_oss_put_volume1_vo
+ if (numid == ID_UNKNOWN)
+ return;
+ down_read(&card->controls_rwsem);
+- if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
++ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
++ up_read(&card->controls_rwsem);
+ return;
++ }
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (uinfo == NULL || uctl == NULL)
+@@ -658,7 +660,7 @@ static void snd_mixer_oss_put_volume1_sw
+ return;
+ down_read(&card->controls_rwsem);
+ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
+- up_read(&fmixer->card->controls_rwsem);
++ up_read(&card->controls_rwsem);
+ return;
+ }
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+@@ -797,7 +799,7 @@ static int snd_mixer_oss_get_recsrc2(str
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (uinfo == NULL || uctl == NULL) {
+ err = -ENOMEM;
+- goto __unlock;
++ goto __free_only;
+ }
+ down_read(&card->controls_rwsem);
+ kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
+@@ -826,6 +828,7 @@ static int snd_mixer_oss_get_recsrc2(str
+ err = 0;
+ __unlock:
+ up_read(&card->controls_rwsem);
++ __free_only:
+ kfree(uctl);
+ kfree(uinfo);
+ return err;
+@@ -847,7 +850,7 @@ static int snd_mixer_oss_put_recsrc2(str
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (uinfo == NULL || uctl == NULL) {
+ err = -ENOMEM;
+- goto __unlock;
++ goto __free_only;
+ }
+ down_read(&card->controls_rwsem);
+ kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
+@@ -880,6 +883,7 @@ static int snd_mixer_oss_put_recsrc2(str
+ err = 0;
+ __unlock:
+ up_read(&card->controls_rwsem);
++ __free_only:
+ kfree(uctl);
+ kfree(uinfo);
+ return err;
+From flameeyes@gmail.com Mon Nov 22 16:18:17 2010
+From: David Henningsson <david.henningsson@canonical.com>
+Date: Mon, 25 Oct 2010 23:52:04 +0200
+Subject: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510
+To: stable@kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, David Henningsson <david.henningsson@canonical.com>
+Message-ID: <1288043524-31436-2-git-send-email-flameeyes@gmail.com>
+
+From: David Henningsson <david.henningsson@canonical.com>
+
+[Not upstream as .37 fixes this differently in a much more complete way
+that is not able to be backported easily.]
+
+(Ported on top of 2.6.36)
+
+BugLink: http://launchpad.net/bugs/628961
+BugLink: http://launchpad.net/bugs/605047
+
+Signed-off-by: David Henningsson <david.henningsson@canonical.com>
+Signed-off-by: Diego Elio Pettenò <flameeyes@gmail.com>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_sigmatel.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -93,6 +93,7 @@ enum {
+ STAC_92HD83XXX_REF,
+ STAC_92HD83XXX_PWR_REF,
+ STAC_DELL_S14,
++ STAC_DELL_E6410,
+ STAC_92HD83XXX_HP,
+ STAC_HP_DV7_4000,
+ STAC_92HD83XXX_MODELS
+@@ -1633,6 +1634,13 @@ static unsigned int dell_s14_pin_configs
+ 0x40f000f0, 0x40f000f0,
+ };
+
++/* Deliberately turn off 0x0f (Dock Mic) to make it choose Int Mic instead */
++static unsigned int dell_e6410_pin_configs[10] = {
++ 0x04a11020, 0x0421101f, 0x400000f0, 0x90170110,
++ 0x23011050, 0x40f000f0, 0x400000f0, 0x90a60130,
++ 0x40f000f0, 0x40f000f0,
++};
++
+ static unsigned int hp_dv7_4000_pin_configs[10] = {
+ 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
+ 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140,
+@@ -1643,6 +1651,7 @@ static unsigned int *stac92hd83xxx_brd_t
+ [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
+ [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
+ [STAC_DELL_S14] = dell_s14_pin_configs,
++ [STAC_DELL_E6410] = dell_e6410_pin_configs,
+ [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
+ };
+
+@@ -1651,6 +1660,7 @@ static const char *stac92hd83xxx_models[
+ [STAC_92HD83XXX_REF] = "ref",
+ [STAC_92HD83XXX_PWR_REF] = "mic-ref",
+ [STAC_DELL_S14] = "dell-s14",
++ [STAC_DELL_E6410] = "dell-e6410",
+ [STAC_92HD83XXX_HP] = "hp",
+ [STAC_HP_DV7_4000] = "hp-dv7-4000",
+ };
+@@ -1663,6 +1673,10 @@ static struct snd_pci_quirk stac92hd83xx
+ "DFI LanParty", STAC_92HD83XXX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
+ "unknown Dell", STAC_DELL_S14),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x040a,
++ "Dell E6410", STAC_DELL_E6410),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x040b,
++ "Dell E6510", STAC_DELL_E6410),
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
+ "HP", STAC_92HD83XXX_HP),
+ {} /* terminator */
+From 1c2c25c78740b2796c7c06640784cb6732fa4907 Mon Sep 17 00:00:00 2001
+From: Michael Neuling <mikey@neuling.org>
+Date: Wed, 17 Nov 2010 16:32:59 +0000
+Subject: powerpc: Fix call to subpage_protection()
+
+From: Michael Neuling <mikey@neuling.org>
+
+commit 1c2c25c78740b2796c7c06640784cb6732fa4907 upstream.
+
+In:
+ powerpc/mm: Fix pgtable cache cleanup with CONFIG_PPC_SUBPAGE_PROT
+ commit d28513bc7f675d28b479db666d572e078ecf182d
+ Author: David Gibson <david@gibson.dropbear.id.au>
+
+subpage_protection() was changed to to take an mm rather a pgdir but it
+didn't change calling site in hashpage_preload(). The change wasn't
+noticed at compile time since hashpage_preload() used a void* as the
+parameter to subpage_protection().
+
+This is obviously wrong and can trigger the following crash when
+CONFIG_SLAB, CONFIG_DEBUG_SLAB, CONFIG_PPC_64K_PAGES
+CONFIG_PPC_SUBPAGE_PROT are enabled.
+
+Freeing unused kernel memory: 704k freed
+Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6c49b7
+Faulting instruction address: 0xc0000000000410f4
+cpu 0x2: Vector: 300 (Data Access) at [c00000004233f590]
+ pc: c0000000000410f4: .hash_preload+0x258/0x338
+ lr: c000000000041054: .hash_preload+0x1b8/0x338
+ sp: c00000004233f810
+ msr: 8000000000009032
+ dar: 6b6b6b6b6b6c49b7
+ dsisr: 40000000
+ current = 0xc00000007e2c0070
+ paca = 0xc000000007fe0500
+ pid = 1, comm = init
+enter ? for help
+[c00000004233f810] c000000000041020 .hash_preload+0x184/0x338 (unreliable)
+[c00000004233f8f0] c00000000003ed98 .update_mmu_cache+0xb0/0xd0
+[c00000004233f990] c000000000157754 .__do_fault+0x48c/0x5dc
+[c00000004233faa0] c000000000158fd0 .handle_mm_fault+0x508/0xa8c
+[c00000004233fb90] c0000000006acdd4 .do_page_fault+0x428/0x6ac
+[c00000004233fe30] c000000000005260 handle_page_fault+0x20/0x74
+
+Reported-by: Jim Keniston <jkenisto@linux.vnet.ibm.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+cc: David Gibson <david@gibson.dropbear.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
+index 83f534d..5e95844 100644
+--- a/arch/powerpc/mm/hash_utils_64.c
++++ b/arch/powerpc/mm/hash_utils_64.c
+@@ -1123,7 +1123,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
+ else
+ #endif /* CONFIG_PPC_HAS_HASH_64K */
+ rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
+- subpage_protection(pgdir, ea));
++ subpage_protection(mm, ea));
+
+ /* Dump some info in case of hash insertion failure, they should
+ * never happen so it is really useful to know if/when they do
+From 118df3d17f11733b294ea2cd988d56ee376ef9fd Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Sun, 24 Oct 2010 17:17:31 -0400
+Subject: SUNRPC: After calling xprt_release(), we must restart from call_reserve
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 118df3d17f11733b294ea2cd988d56ee376ef9fd upstream.
+
+Rob Leslie reports seeing the following Oops after his Kerberos session
+expired.
+
+BUG: unable to handle kernel NULL pointer dereference at 00000058
+IP: [<e186ed94>] rpcauth_refreshcred+0x11/0x12c [sunrpc]
+*pde = 00000000
+Oops: 0000 [#1]
+last sysfs file: /sys/devices/platform/pc87360.26144/temp3_input
+Modules linked in: autofs4 authenc esp4 xfrm4_mode_transport ipt_LOG ipt_REJECT xt_limit xt_state ipt_REDIRECT xt_owner xt_HL xt_hl xt_tcpudp xt_mark cls_u32 cls_tcindex sch_sfq sch_htb sch_dsmark geodewdt deflate ctr twofish_generic twofish_i586 twofish_common camellia serpent blowfish cast5 cbc xcbc rmd160 sha512_generic sha1_generic hmac crypto_null af_key rpcsec_gss_krb5 nfsd exportfs nfs lockd fscache nfs_acl auth_rpcgss sunrpc ip_gre sit tunnel4 dummy ext3 jbd nf_nat_irc nf_conntrack_irc nf_nat_ftp nf_conntrack_ftp iptable_mangle iptable_nat nf_nat nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 iptable_filter ip_tables x_tables pc8736x_gpio nsc_gpio pc87360 hwmon_vid loop aes_i586 aes_generic sha256_generic dm_crypt cs5535_gpio serio_raw cs5535_mfgpt hifn_795x des_generic geode_rng rng_core led_class ext4 mbcache jbd2 crc16 dm_mirror dm_region_hash dm_log dm_snapshot dm_mod sd_mod crc_t10dif ide_pci_generic cs5536 amd74xx ide_core pata_cs5536 ata_generic libata usb_storage via_rhine mii scsi_mod btrfs zlib_deflate crc32c libcrc32c [last unloaded: scsi_wait_scan]
+
+Pid: 12875, comm: sudo Not tainted 2.6.36-net5501 #1 /
+EIP: 0060:[<e186ed94>] EFLAGS: 00010292 CPU: 0
+EIP is at rpcauth_refreshcred+0x11/0x12c [sunrpc]
+EAX: 00000000 EBX: defb13a0 ECX: 00000006 EDX: e18683b8
+ESI: defb13a0 EDI: 00000000 EBP: 00000000 ESP: de571d58
+ DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
+Process sudo (pid: 12875, ti=de570000 task=decd1430 task.ti=de570000)
+Stack:
+ e186e008 00000000 defb13a0 0000000d deda6000 e1868f22 e196f12b defb13a0
+<0> defb13d8 00000000 00000000 e186e0aa 00000000 defb13a0 de571dac 00000000
+<0> e186956c de571e34 debea5c0 de571dc8 e186967a 00000000 debea5c0 de571e34
+Call Trace:
+ [<e186e008>] ? rpc_wake_up_next+0x114/0x11b [sunrpc]
+ [<e1868f22>] ? call_decode+0x24a/0x5af [sunrpc]
+ [<e196f12b>] ? nfs4_xdr_dec_access+0x0/0xa2 [nfs]
+ [<e186e0aa>] ? __rpc_execute+0x62/0x17b [sunrpc]
+ [<e186956c>] ? rpc_run_task+0x91/0x97 [sunrpc]
+ [<e186967a>] ? rpc_call_sync+0x40/0x5b [sunrpc]
+ [<e1969ca2>] ? nfs4_proc_access+0x10a/0x176 [nfs]
+ [<e19572fa>] ? nfs_do_access+0x2b1/0x2c0 [nfs]
+ [<e186ed61>] ? rpcauth_lookupcred+0x62/0x84 [sunrpc]
+ [<e19573b6>] ? nfs_permission+0xad/0x13b [nfs]
+ [<c0177824>] ? exec_permission+0x15/0x4b
+ [<c0177fbd>] ? link_path_walk+0x4f/0x456
+ [<c017867d>] ? path_walk+0x4c/0xa8
+ [<c0179678>] ? do_path_lookup+0x1f/0x68
+ [<c017a3fb>] ? user_path_at+0x37/0x5f
+ [<c016359c>] ? handle_mm_fault+0x229/0x55b
+ [<c0170a2d>] ? sys_faccessat+0x93/0x146
+ [<c0170aef>] ? sys_access+0xf/0x13
+ [<c02cf615>] ? syscall_call+0x7/0xb
+Code: 0f 94 c2 84 d2 74 09 8b 44 24 0c e8 6a e9 8b de 83 c4 14 89 d8 5b 5e 5f 5d c3 55 57 56 53 83 ec 1c fc 89 c6 8b 40 10 89 44 24 04 <8b> 58 58 85 db 0f 85 d4 00 00 00 0f b7 46 70 8b 56 20 89 c5 83
+EIP: [<e186ed94>] rpcauth_refreshcred+0x11/0x12c [sunrpc] SS:ESP 0068:de571d58
+CR2: 0000000000000058
+
+This appears to be caused by the function rpc_verify_header() first
+calling xprt_release(), then doing a call_refresh. If we release the
+transport slot, we should _always_ jump back to call_reserve before
+calling anything else.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/sunrpc/clnt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -1675,7 +1675,7 @@ rpc_verify_header(struct rpc_task *task)
+ rpcauth_invalcred(task);
+ /* Ensure we obtain a new XID! */
+ xprt_release(task);
+- task->tk_action = call_refresh;
++ task->tk_action = call_reserve;
+ goto out_retry;
+ case RPC_AUTH_BADCRED:
+ case RPC_AUTH_BADVERF:
+From b843e4ec01991a386a9e0e9030703524446e03da Mon Sep 17 00:00:00 2001
+From: Thomas Backlund <tmb@mandriva.org>
+Date: Thu, 21 Oct 2010 13:19:10 +0300
+Subject: microblaze: Fix build with make 3.82
+
+From: Thomas Backlund <tmb@mandriva.org>
+
+commit b843e4ec01991a386a9e0e9030703524446e03da upstream.
+
+When running make headers_install_all on x86_64 and make 3.82 I hit this:
+
+arch/microblaze/Makefile:80: *** mixed implicit and normal rules. Stop.
+make: *** [headers_install_all] Error 2
+
+So split the rules to satisfy make 3.82.
+
+Signed-off-by: Thomas Backlund <tmb@mandriva.org>
+Signed-off-by: Michal Simek <monstr@monstr.eu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/microblaze/Makefile | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/arch/microblaze/Makefile
++++ b/arch/microblaze/Makefile
+@@ -72,12 +72,16 @@ export MMU DTB
+
+ all: linux.bin
+
+-BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.%
++# With make 3.82 we cannot mix normal and wildcard targets
++BOOT_TARGETS1 = linux.bin linux.bin.gz
++BOOT_TARGETS2 = simpleImage.%
+
+ archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
+-$(BOOT_TARGETS): vmlinux
++$(BOOT_TARGETS1): vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
++$(BOOT_TARGETS2): vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+ define archhelp
+From be8c648051048bc66fbca590d00f3e8543ec32af Mon Sep 17 00:00:00 2001
+From: Arnaud Patard <arnaud.patard@rtp-net.org>
+Date: Thu, 21 Oct 2010 03:59:57 -0700
+Subject: phy/marvell: fix 88e1121 support
+
+From: Arnaud Patard <arnaud.patard@rtp-net.org>
+
+commit be8c648051048bc66fbca590d00f3e8543ec32af upstream.
+
+Commit c477d0447db08068a497e7beb892b2b2a7bff64b added support for RGMII
+rx/tx delays except that it ends up clearing rx/tx delays bit for modes
+differents that RGMII*ID. Due to this, ethernet is not working anymore
+on my guruplug server +. This patch is fixing that.
+
+Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/phy/marvell.c | 31 +++++++++++++++++++------------
+ 1 file changed, 19 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -196,20 +196,27 @@ static int m88e1121_config_aneg(struct p
+ MII_88E1121_PHY_MSCR_PAGE);
+ if (err < 0)
+ return err;
+- mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
+- MII_88E1121_PHY_MSCR_DELAY_MASK;
+
+- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+- mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
+- MII_88E1121_PHY_MSCR_TX_DELAY);
+- else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+- mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
+- else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+- mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
++ if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
++ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
++ (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
++ (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+
+- err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
+- if (err < 0)
+- return err;
++ mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
++ MII_88E1121_PHY_MSCR_DELAY_MASK;
++
++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
++ mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
++ MII_88E1121_PHY_MSCR_TX_DELAY);
++ else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
++ mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
++ else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
++ mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
++
++ err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
++ if (err < 0)
++ return err;
++ }
+
+ phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
+
+From 6eaa61496fb3b93cceface7a296415fc4c030bce Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Mon, 4 Oct 2010 17:59:08 -0400
+Subject: NFSv4: Don't call nfs4_reclaim_complete() on receiving NFS4ERR_STALE_CLIENTID
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 6eaa61496fb3b93cceface7a296415fc4c030bce upstream.
+
+If the server sends us an NFS4ERR_STALE_CLIENTID while the state management
+thread is busy reclaiming state, we do want to treat all state that wasn't
+reclaimed before the STALE_CLIENTID as if a network partition occurred (see
+the edge conditions described in RFC3530 and RFC5661).
+What we do not want to do is to send an nfs4_reclaim_complete(), since we
+haven't yet even started reclaiming state after the server rebooted.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nfs/nfs4state.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -1138,16 +1138,14 @@ static void nfs4_reclaim_complete(struct
+ (void)ops->reclaim_complete(clp);
+ }
+
+-static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
++static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
+ {
+ struct nfs4_state_owner *sp;
+ struct rb_node *pos;
+ struct nfs4_state *state;
+
+ if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
+- return;
+-
+- nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
++ return 0;
+
+ for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
+@@ -1161,6 +1159,14 @@ static void nfs4_state_end_reclaim_reboo
+ }
+
+ nfs_delegation_reap_unclaimed(clp);
++ return 1;
++}
++
++static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
++{
++ if (!nfs4_state_clear_reclaim_reboot(clp))
++ return;
++ nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
+ }
+
+ static void nfs_delegation_clear_all(struct nfs_client *clp)
+@@ -1187,7 +1193,7 @@ static int nfs4_recovery_handle_error(st
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+- nfs4_state_end_reclaim_reboot(clp);
++ nfs4_state_clear_reclaim_reboot(clp);
+ nfs4_state_start_reclaim_reboot(clp);
+ break;
+ case -NFS4ERR_EXPIRED:
+From ae1007d37e00144b72906a4bdc47d517ae91bcc1 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Mon, 4 Oct 2010 17:59:08 -0400
+Subject: NFSv4: Don't call nfs4_state_mark_reclaim_reboot() from error handlers
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit ae1007d37e00144b72906a4bdc47d517ae91bcc1 upstream.
+
+In the case of a server reboot, the state recovery thread starts by calling
+nfs4_state_end_reclaim_reboot() in order to avoid edge conditions when
+the server reboots while the client is in the middle of recovery.
+
+However, if the client has already marked the nfs4_state as requiring
+reboot recovery, then the above behaviour will cause the recovery thread to
+treat the open as if it was part of such an edge condition: the open will
+be recovered as if it was part of a lease expiration (and all the locks
+will be lost).
+Fix is to remove the call to nfs4_state_mark_reclaim_reboot from
+nfs4_async_handle_error(), and nfs4_handle_exception(). Instead we leave it
+to the recovery thread to do this for us.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nfs/nfs4proc.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -255,9 +255,6 @@ static int nfs4_handle_exception(const s
+ nfs4_state_mark_reclaim_nograce(clp, state);
+ goto do_state_recovery;
+ case -NFS4ERR_STALE_STATEID:
+- if (state == NULL)
+- break;
+- nfs4_state_mark_reclaim_reboot(clp, state);
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_EXPIRED:
+ goto do_state_recovery;
+@@ -3490,9 +3487,6 @@ nfs4_async_handle_error(struct rpc_task
+ nfs4_state_mark_reclaim_nograce(clp, state);
+ goto do_state_recovery;
+ case -NFS4ERR_STALE_STATEID:
+- if (state == NULL)
+- break;
+- nfs4_state_mark_reclaim_reboot(clp, state);
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_EXPIRED:
+ goto do_state_recovery;
+From b0ed9dbc24f1fd912b2dd08b995153cafc1d5b1c Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Mon, 4 Oct 2010 17:59:08 -0400
+Subject: NFSv4: Fix open recovery
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit b0ed9dbc24f1fd912b2dd08b995153cafc1d5b1c upstream.
+
+NFSv4 open recovery is currently broken: since we do not clear the
+state->flags states before attempting recovery, we end up with the
+'can_open_cached()' function triggering. This again leads to no OPEN call
+being put on the wire.
+
+Reported-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nfs/nfs4proc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1117,6 +1117,7 @@ static int nfs4_open_recover(struct nfs4
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+ smp_rmb();
+ if (state->n_rdwr != 0) {
++ clear_bit(NFS_O_RDWR_STATE, &state->flags);
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
+ if (ret != 0)
+ return ret;
+@@ -1124,6 +1125,7 @@ static int nfs4_open_recover(struct nfs4
+ return -ESTALE;
+ }
+ if (state->n_wronly != 0) {
++ clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+ ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
+ if (ret != 0)
+ return ret;
+@@ -1131,6 +1133,7 @@ static int nfs4_open_recover(struct nfs4
+ return -ESTALE;
+ }
+ if (state->n_rdonly != 0) {
++ clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
+ if (ret != 0)
+ return ret;
+From bc4866b6e0b44f8ea0df22a16e5927714beb4983 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Mon, 4 Oct 2010 17:59:08 -0400
+Subject: NFS: Don't SIGBUS if nfs_vm_page_mkwrite races with a cache invalidation
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit bc4866b6e0b44f8ea0df22a16e5927714beb4983 upstream.
+
+In the case where we lock the page, and then find out that the page has
+been thrown out of the page cache, we should just return VM_FAULT_NOPAGE.
+This is what block_page_mkwrite() does in these situations.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nfs/file.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -551,7 +551,7 @@ static int nfs_vm_page_mkwrite(struct vm
+ struct file *filp = vma->vm_file;
+ struct dentry *dentry = filp->f_path.dentry;
+ unsigned pagelen;
+- int ret = -EINVAL;
++ int ret = VM_FAULT_NOPAGE;
+ struct address_space *mapping;
+
+ dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
+@@ -567,21 +567,20 @@ static int nfs_vm_page_mkwrite(struct vm
+ if (mapping != dentry->d_inode->i_mapping)
+ goto out_unlock;
+
+- ret = 0;
+ pagelen = nfs_page_length(page);
+ if (pagelen == 0)
+ goto out_unlock;
+
+- ret = nfs_flush_incompatible(filp, page);
+- if (ret != 0)
+- goto out_unlock;
++ ret = VM_FAULT_LOCKED;
++ if (nfs_flush_incompatible(filp, page) == 0 &&
++ nfs_updatepage(filp, page, 0, pagelen) == 0)
++ goto out;
+
+- ret = nfs_updatepage(filp, page, 0, pagelen);
++ ret = VM_FAULT_SIGBUS;
+ out_unlock:
+- if (!ret)
+- return VM_FAULT_LOCKED;
+ unlock_page(page);
+- return VM_FAULT_SIGBUS;
++out:
++ return ret;
+ }
+
+ static const struct vm_operations_struct nfs_file_vm_ops = {
+From b7d8cce5b558e0c0aa6898c9865356481598b46d Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Mon, 25 Oct 2010 19:44:00 -0400
+Subject: drm/radeon/kms: MC vram map needs to be >= pci aperture size
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit b7d8cce5b558e0c0aa6898c9865356481598b46d upstream.
+
+The vram map in the radeon memory controller needs to be
+>= the pci aperture size. Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=28402
+
+The problematic cards in the above bug have 64 MB of vram,
+but the pci aperture is 128 MB and the MC vram map was only
+64 MB. This can lead to hangs.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r100.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -2318,6 +2318,9 @@ void r100_vram_init_sizes(struct radeon_
+ /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM -
+ * Novell bug 204882 + along with lots of ubuntu ones
+ */
++ if (rdev->mc.aper_size > config_aper_size)
++ config_aper_size = rdev->mc.aper_size;
++
+ if (config_aper_size > rdev->mc.real_vram_size)
+ rdev->mc.mc_vram_size = config_aper_size;
+ else
+From 881fe6c1d06bf49f4ab7aef212cdaf66bd059614 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Mon, 18 Oct 2010 23:54:56 -0400
+Subject: drm/radeon/kms: properly compute group_size on 6xx/7xx
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit 881fe6c1d06bf49f4ab7aef212cdaf66bd059614 upstream.
+
+Needed for tiled surfaces.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600.c | 7 +++++--
+ drivers/gpu/drm/radeon/rv770.c | 9 +++++----
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -1608,8 +1608,11 @@ void r600_gpu_init(struct radeon_device
+ rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes;
+ rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
+ tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
+- tiling_config |= GROUP_SIZE(0);
+- rdev->config.r600.tiling_group_size = 256;
++ tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT);
++ if ((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT)
++ rdev->config.r600.tiling_group_size = 512;
++ else
++ rdev->config.r600.tiling_group_size = 256;
+ tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
+ if (tmp > 3) {
+ tiling_config |= ROW_TILING(3);
+--- a/drivers/gpu/drm/radeon/rv770.c
++++ b/drivers/gpu/drm/radeon/rv770.c
+@@ -643,10 +643,11 @@ static void rv770_gpu_init(struct radeon
+ else
+ gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
+ rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);
+-
+- gb_tiling_config |= GROUP_SIZE(0);
+- rdev->config.rv770.tiling_group_size = 256;
+-
++ gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT);
++ if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT)
++ rdev->config.rv770.tiling_group_size = 512;
++ else
++ rdev->config.rv770.tiling_group_size = 256;
+ if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
+ gb_tiling_config |= ROW_TILING(3);
+ gb_tiling_config |= SAMPLE_SPLIT(3);
+From 2d7b8366ae4a9ec2183c30e432a4a9a495c82bcd Mon Sep 17 00:00:00 2001
+From: Yuanhan Liu <yuanhan.liu@intel.com>
+Date: Fri, 8 Oct 2010 10:21:06 +0100
+Subject: drm/i915: Update hotplug interrupts register definitions for Sandybridge
+
+From: Yuanhan Liu <yuanhan.liu@intel.com>
+
+commit 2d7b8366ae4a9ec2183c30e432a4a9a495c82bcd upstream.
+
+On Sandybridge, the bit definition for hotplug on SDE has changed, so
+update the code to new definition.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30378
+Signed-off-by: Yuanhan Liu <yuanhan.liu@intel.com>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++-----
+ drivers/gpu/drm/i915/i915_reg.h | 4 ++++
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -310,6 +310,7 @@ irqreturn_t ironlake_irq_handler(struct
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int ret = IRQ_NONE;
+ u32 de_iir, gt_iir, de_ier, pch_iir;
++ u32 hotplug_mask;
+ struct drm_i915_master_private *master_priv;
+ struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+
+@@ -325,6 +326,11 @@ irqreturn_t ironlake_irq_handler(struct
+ if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
+ goto done;
+
++ if (HAS_PCH_CPT(dev))
++ hotplug_mask = SDE_HOTPLUG_MASK_CPT;
++ else
++ hotplug_mask = SDE_HOTPLUG_MASK;
++
+ ret = IRQ_HANDLED;
+
+ if (dev->primary->master) {
+@@ -366,10 +372,8 @@ irqreturn_t ironlake_irq_handler(struct
+ drm_handle_vblank(dev, 1);
+
+ /* check event from PCH */
+- if ((de_iir & DE_PCH_EVENT) &&
+- (pch_iir & SDE_HOTPLUG_MASK)) {
++ if ((de_iir & DE_PCH_EVENT) && (pch_iir & hotplug_mask))
+ queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+- }
+
+ if (de_iir & DE_PCU_EVENT) {
+ I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
+@@ -1424,8 +1428,7 @@ static int ironlake_irq_postinstall(stru
+ u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
+ DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
+ u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT;
+- u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
+- SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
++ u32 hotplug_mask;
+
+ dev_priv->irq_mask_reg = ~display_mask;
+ dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK;
+@@ -1450,6 +1453,14 @@ static int ironlake_irq_postinstall(stru
+ I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
+ (void) I915_READ(GTIER);
+
++ if (HAS_PCH_CPT(dev)) {
++ hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT |
++ SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ;
++ } else {
++ hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
++ SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
++ }
++
+ dev_priv->pch_irq_mask_reg = ~hotplug_mask;
+ dev_priv->pch_irq_enable_reg = hotplug_mask;
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2551,6 +2551,10 @@
+ #define SDE_PORTD_HOTPLUG_CPT (1 << 23)
+ #define SDE_PORTC_HOTPLUG_CPT (1 << 22)
+ #define SDE_PORTB_HOTPLUG_CPT (1 << 21)
++#define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \
++ SDE_PORTD_HOTPLUG_CPT | \
++ SDE_PORTC_HOTPLUG_CPT | \
++ SDE_PORTB_HOTPLUG_CPT)
+
+ #define SDEISR 0xc4000
+ #define SDEIMR 0xc4004
+From 2126d0a4a205e2d6b763434f892524cd60f74228 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Wed, 6 Oct 2010 00:13:04 -0400
+Subject: drm/radeon/kms: make sure blit addr masks are 64 bit
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit 2126d0a4a205e2d6b763434f892524cd60f74228 upstream.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600_blit_kms.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
++++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
+@@ -650,8 +650,8 @@ void r600_kms_blit_copy(struct radeon_de
+ int src_x = src_gpu_addr & 255;
+ int dst_x = dst_gpu_addr & 255;
+ int h = 1;
+- src_gpu_addr = src_gpu_addr & ~255;
+- dst_gpu_addr = dst_gpu_addr & ~255;
++ src_gpu_addr = src_gpu_addr & ~255ULL;
++ dst_gpu_addr = dst_gpu_addr & ~255ULL;
+
+ if (!src_x && !dst_x) {
+ h = (cur_size / max_bytes);
+@@ -744,8 +744,8 @@ void r600_kms_blit_copy(struct radeon_de
+ int src_x = (src_gpu_addr & 255);
+ int dst_x = (dst_gpu_addr & 255);
+ int h = 1;
+- src_gpu_addr = src_gpu_addr & ~255;
+- dst_gpu_addr = dst_gpu_addr & ~255;
++ src_gpu_addr = src_gpu_addr & ~255ULL;
++ dst_gpu_addr = dst_gpu_addr & ~255ULL;
+
+ if (!src_x && !dst_x) {
+ h = (cur_size / max_bytes);
+From 43b93fbffc2c080dba2e84df6fce8d7e6c0a2581 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Wed, 27 Oct 2010 01:02:35 -0400
+Subject: drm/radeon/kms: fix handling of tex lookup disable in cs checker on r2xx
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit 43b93fbffc2c080dba2e84df6fce8d7e6c0a2581 upstream.
+
+There are cases when multiple texture units have to be enabled,
+but not actually used to sample. This patch checks to see if
+the lookup_disable bit is set and if so, skips the texture check.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=25544
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r100.c | 3 +++
+ drivers/gpu/drm/radeon/r100_track.h | 1 +
+ drivers/gpu/drm/radeon/r200.c | 2 ++
+ drivers/gpu/drm/radeon/radeon_reg.h | 1 +
+ 4 files changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -3228,6 +3228,8 @@ static int r100_cs_track_texture_check(s
+ for (u = 0; u < track->num_texture; u++) {
+ if (!track->textures[u].enabled)
+ continue;
++ if (track->textures[u].lookup_disable)
++ continue;
+ robj = track->textures[u].robj;
+ if (robj == NULL) {
+ DRM_ERROR("No texture bound to unit %u\n", u);
+@@ -3462,6 +3464,7 @@ void r100_cs_track_clear(struct radeon_d
+ track->textures[i].robj = NULL;
+ /* CS IB emission code makes sure texture unit are disabled */
+ track->textures[i].enabled = false;
++ track->textures[i].lookup_disable = false;
+ track->textures[i].roundup_w = true;
+ track->textures[i].roundup_h = true;
+ if (track->separate_cube)
+--- a/drivers/gpu/drm/radeon/r100_track.h
++++ b/drivers/gpu/drm/radeon/r100_track.h
+@@ -46,6 +46,7 @@ struct r100_cs_track_texture {
+ unsigned height_11;
+ bool use_pitch;
+ bool enabled;
++ bool lookup_disable;
+ bool roundup_w;
+ bool roundup_h;
+ unsigned compress_format;
+--- a/drivers/gpu/drm/radeon/r200.c
++++ b/drivers/gpu/drm/radeon/r200.c
+@@ -447,6 +447,8 @@ int r200_packet0_check(struct radeon_cs_
+ track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
+ track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+ }
++ if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
++ track->textures[i].lookup_disable = true;
+ switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
+ case R200_TXFORMAT_I8:
+ case R200_TXFORMAT_RGB332:
+--- a/drivers/gpu/drm/radeon/radeon_reg.h
++++ b/drivers/gpu/drm/radeon/radeon_reg.h
+@@ -2836,6 +2836,7 @@
+ # define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24)
+ # define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24)
+ # define R200_TXFORMAT_ST_ROUTE_SHIFT 24
++# define R200_TXFORMAT_LOOKUP_DISABLE (1 << 27)
+ # define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28)
+ # define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29)
+ # define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30)
+From 1510a97182b4ddb5fe3c4e8d05240f7cd6fd13e7 Mon Sep 17 00:00:00 2001
+From: Yuanhan Liu <yuanhan.liu@intel.com>
+Date: Fri, 8 Oct 2010 10:18:01 +0100
+Subject: drm/i915/crt: Make sure the hotplug interrupt is enabled
+
+From: Yuanhan Liu <yuanhan.liu@intel.com>
+
+commit 1510a97182b4ddb5fe3c4e8d05240f7cd6fd13e7 upstream.
+
+After disabling the hotplug interrupts for VGA detection on Ironlake, be
+sure to re-enable them again afterwards.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30378
+Signed-off-by: Yuanhan Liu <yuanhan.liu@intel.com>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_crt.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_crt.c
++++ b/drivers/gpu/drm/i915/intel_crt.c
+@@ -191,7 +191,8 @@ static bool intel_ironlake_crt_detect_ho
+ DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
+
+ if (turn_off_dac) {
+- I915_WRITE(PCH_ADPA, temp);
++ /* Make sure hotplug is enabled */
++ I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE);
+ (void)I915_READ(PCH_ADPA);
+ }
+
+From c2873e9633fe908dccd36dbb1d370e9c59a1ca62 Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Thu, 7 Oct 2010 09:20:12 +0100
+Subject: drm/i915: Free hardware status page on unload when physically mapped
+
+From: Keith Packard <keithp@keithp.com>
+
+commit c2873e9633fe908dccd36dbb1d370e9c59a1ca62 upstream.
+
+A physically mapped hardware status page is allocated at driver load
+time but was never freed. Call the existing code to free this page at
+driver unload time on hardware which uses this kind.
+
+Signed-off-by: Keith Packard <keithp@keithp.com>
+[ickle: call before tearing down registers on KMS-only path, as pointed
+out by Dave Airlie]
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_dma.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_dma.c
++++ b/drivers/gpu/drm/i915/i915_dma.c
+@@ -2306,6 +2306,9 @@ int i915_driver_unload(struct drm_device
+ i915_gem_lastclose(dev);
+
+ intel_cleanup_overlay(dev);
++
++ if (!I915_NEED_GFX_HWS(dev))
++ i915_free_hws(dev);
+ }
+
+ intel_teardown_mchbar(dev);
+From 382b09362711d7d03272230a33767015a277926e Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 7 Oct 2010 16:01:25 -0700
+Subject: drm/i915: diasable clock gating for the panel power sequencer
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 382b09362711d7d03272230a33767015a277926e upstream.
+
+Needed on Ibex Peak and Cougar Point or the panel won't always come on.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_reg.h | 3 +++
+ drivers/gpu/drm/i915/intel_display.c | 7 +++++++
+ 2 files changed, 10 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2726,6 +2726,9 @@
+ #define FDI_RXB_CHICKEN 0xc2010
+ #define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1)
+
++#define SOUTH_DSPCLK_GATE_D 0xc2020
++#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
++
+ /* CPU: FDI_TX */
+ #define FDI_TXA_CTL 0x60100
+ #define FDI_TXB_CTL 0x61100
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -5674,6 +5674,13 @@ void intel_init_clock_gating(struct drm_
+ I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+ /*
++ * On Ibex Peak and Cougar Point, we need to disable clock
++ * gating for the panel power sequencer or it will fail to
++ * start up when no ports are active.
++ */
++ I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
++
++ /*
+ * According to the spec the following bits should be set in
+ * order to enable memory self-refresh
+ * The bit 22/21 of 0x42004
+From 0ddc1289f3ffd779779ddd3922f26ae7d0a21604 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 12 Aug 2010 09:35:00 +0100
+Subject: drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to writing.
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 0ddc1289f3ffd779779ddd3922f26ae7d0a21604 upstream.
+
+Just makes sure that writes are not being aliased by the CPU cache and
+do make it out to main memory.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=24977
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_overlay.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/i915/intel_overlay.c
++++ b/drivers/gpu/drm/i915/intel_overlay.c
+@@ -1367,6 +1367,12 @@ void intel_setup_overlay(struct drm_devi
+ goto out_free_bo;
+ }
+ overlay->flip_addr = overlay->reg_bo->gtt_offset;
++
++ ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
++ if (ret) {
++ DRM_ERROR("failed to move overlay register bo into the GTT\n");
++ goto out_unpin_bo;
++ }
+ } else {
+ ret = i915_gem_attach_phys_object(dev, reg_bo,
+ I915_GEM_PHYS_OVERLAY_REGS,
+@@ -1399,6 +1405,8 @@ void intel_setup_overlay(struct drm_devi
+ DRM_INFO("initialized overlay support\n");
+ return;
+
++out_unpin_bo:
++ i915_gem_object_unpin(reg_bo);
+ out_free_bo:
+ drm_gem_object_unreference(reg_bo);
+ out_free:
+From 62391f97babb7fe0c769830b6f0e0bd184bd0704 Mon Sep 17 00:00:00 2001
+From: Ken Kawasaki <ken_kawasaki@spring.nifty.jp>
+Date: Fri, 29 Oct 2010 12:17:51 +0000
+Subject: pcnet_cs: add new_id
+
+From: Ken Kawasaki <ken_kawasaki@spring.nifty.jp>
+
+commit 62391f97babb7fe0c769830b6f0e0bd184bd0704 upstream.
+
+pcnet_cs:
+ add new_id: "corega Ether CF-TD" 10Base-T PCMCIA card.
+
+Signed-off-by: Ken Kawasaki <ken_kawasaki@spring.nifty.jp>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/pcmcia/pcnet_cs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/pcmcia/pcnet_cs.c
++++ b/drivers/net/pcmcia/pcnet_cs.c
+@@ -1622,6 +1622,7 @@ static struct pcmcia_device_id pcnet_ids
+ PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
+ PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
+ PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
++ PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
+ PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
+From d8b5fc01683c66060edc202d6bb5635365822181 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 7 Oct 2010 14:08:52 +0100
+Subject: SH: Add missing consts to sys_execve() declaration
+
+From: David Howells <dhowells@redhat.com>
+
+commit d8b5fc01683c66060edc202d6bb5635365822181 upstream.
+
+Add missing consts to the sys_execve() declaration which result in the
+following error:
+
+arch/sh/kernel/process_32.c:303: error: conflicting types for 'sys_execve'
+/warthog/nfs/linux-2.6-fscache/arch/sh/include/asm/syscalls_32.h:24: error: previous declaration of 'sys_execve' was here
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sh/include/asm/syscalls_32.h | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/arch/sh/include/asm/syscalls_32.h
++++ b/arch/sh/include/asm/syscalls_32.h
+@@ -19,9 +19,10 @@ asmlinkage int sys_clone(unsigned long c
+ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs);
+-asmlinkage int sys_execve(const char __user *ufilename, char __user * __user *uargv,
+- char __user * __user *uenvp, unsigned long r7,
+- struct pt_regs __regs);
++asmlinkage int sys_execve(const char __user *ufilename,
++ const char __user *const __user *uargv,
++ const char __user *const __user *uenvp,
++ unsigned long r7, struct pt_regs __regs);
+ asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs);
diff --git a/patches/r8169-regression.patch b/patches/r8169-regression.patch
new file mode 100644
index 0000000..ae93bc2
--- /dev/null
+++ b/patches/r8169-regression.patch
@@ -0,0 +1,49 @@
+From 53f57357ff0afc37804f4e82ee3123e0c0a2cad6 Mon Sep 17 00:00:00 2001
+From: =?utf8?q?fran=C3=A7ois=20romieu?= <romieu@fr.zoreil.com>
+Date: Mon, 8 Nov 2010 13:23:05 +0000
+Subject: [PATCH] r8169: revert "Handle rxfifo errors on 8168 chips"
+
+The original patch helps under obscure conditions (no pun) but
+some 8168 do not like it. The change needs to be tightened with
+a specific 8168 version.
+
+This reverts commit 801e147cde02f04b5c2f42764cd43a89fc7400a2
+("r8169: Handle rxfifo errors on 8168 chips").
+
+Regression at https://bugzilla.kernel.org/show_bug.cgi?id=20882
+
+Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
+Tested-by: Andreas Radke <a.radke@arcor.de>
+Cc: Matthew Garrett <mjg@redhat.com>
+Cc: Daniel J Blueman <daniel.blueman@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/r8169.c | 5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
+index d88ce9f..3a0877e 100644
+--- a/drivers/net/r8169.c
++++ b/drivers/net/r8169.c
+@@ -2931,7 +2931,7 @@ static const struct rtl_cfg_info {
+ .hw_start = rtl_hw_start_8168,
+ .region = 2,
+ .align = 8,
+- .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow |
++ .intr_event = SYSErr | LinkChg | RxOverflow |
+ TxErr | TxOK | RxOK | RxErr,
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow,
+ .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
+@@ -4588,7 +4588,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
+ }
+
+ /* Work around for rx fifo overflow */
+- if (unlikely(status & RxFIFOOver)) {
++ if (unlikely(status & RxFIFOOver) &&
++ (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+ netif_stop_queue(dev);
+ rtl8169_tx_timeout(dev);
+ break;
+--
+1.7.3.2
+