From 98f7ba20a2661bb6e663264e9ac4e7c2333172d0 Mon Sep 17 00:00:00 2001 From: Tobias Powalowski Date: Tue, 23 Nov 2010 12:56:39 +0100 Subject: add pre patches and add r8169 regression patch --- patches/kernel-2.6.36.2-pre-20101123.patch | 6384 ++++++++++++++++++++++++++++ 1 file changed, 6384 insertions(+) create mode 100644 patches/kernel-2.6.36.2-pre-20101123.patch (limited to 'patches/kernel-2.6.36.2-pre-20101123.patch') 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 +Date: Wed, 13 Oct 2010 21:18:03 +0200 +Subject: block: Ensure physical block size is unsigned int + +From: Martin K. Petersen + +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 +Acked-by: Mike Snitzer +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 19 Oct 2010 09:05:00 +0200 +Subject: block: fix accounting bug on cross partition merges + +From: Yasuaki Ishimatsu + +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 +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 20:36:36 +0200 +Subject: block: Fix race during disk initialization + +From: Signed-off-by: Jan Kara + +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 +Signed-off-by: Jan Kara +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +commit f3f63c1c28bc861a931fac283b5bc3585efb8967 upstream. + +Reported-by: Dan Rosenberg +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 29 Oct 2010 11:31:42 -0600 +Subject: block: take care not to overflow when calculating total iov length + +From: Jens Axboe + +commit 9f864c80913467312c7b8690e41fb5ebd1b50e92 upstream. + +Reported-by: Dan Rosenberg +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +commit 9284bcf4e335e5f18a8bc7b26461c33ab60d0689 upstream. + +Ensure that we pass down properly validated iov segments before +calling into the mapping or copy functions. + +Reported-by: Dan Rosenberg +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 18 Oct 2010 14:10:40 +0000 +Subject: jme: Fix PHY power-off error + +From: Guo-Fu Tseng + +commit c8a8684d5cfb0f110a962c93586630c0bf91ebc1 upstream. + +Adding phy_on in opposition to phy_off. + +Signed-off-by: Guo-Fu Tseng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 11 Oct 2010 01:17:56 +0200 +Subject: irda: Fix parameter extraction stack overflow + +From: Samuel Ortiz + +commit efc463eb508798da4243625b08c7396462cabf9f upstream. + +Reported-by: Ilja Van Sprundel +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 6 Oct 2010 01:03:12 +0200 +Subject: irda: Fix heap memory corruption in iriap.c + +From: Samuel Ortiz + +commit 37f9fc452d138dfc4da2ee1ce5ae85094efc3606 upstream. + +While parsing the GetValuebyClass command frame, we could potentially write +passed the skb->data pointer. + +Reported-by: Ilja Van Sprundel +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 14 Oct 2010 17:41:53 +0000 +Subject: r6040: Fix multicast filter some more + +From: Ben Hutchings + +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 + and more recently +as . 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +commit 354da653233898ed1e51f20cebac9705456bf9b1 upstream. + +macro tile heights are aligned to num channels, not num banks. + +Noticed by Dave Airlie. + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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?= +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?= + +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 +Acked-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 1 Oct 2010 01:06:53 +0200 +Subject: ath9k: fix channel flag / regd issues with multiple cards + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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?= +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?= + +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 +Acked-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 20 Sep 2010 22:54:46 -0700 +Subject: ath9k: Fix tx struck state with paprd + +From: Vasanthakumar Thiagarajan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 20 Sep 2010 13:45:38 +0200 +Subject: ath9k: clean up / fix aggregation session flush + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:26 -0400 +Subject: ath9k: fix power save race conditions + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 20 Sep 2010 19:35:28 +0200 +Subject: ath9k: fix an aggregation start related race condition + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:35 -0400 +Subject: ath9k: fix regression which prevents chip sleep after CAB data + +From: Senthil Balasubramanian + +commit 3fac6dfdcd2b893c22b20a03dd1bf1af8b627c4b upstream. + +The patch: + +commit 293dc5dfdbcc16cde06e40a688394cc8ab083e48 +Author: Gabor Juhos +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 + Signed-off-by: John W. Linville + +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 +Cc: Sameer Nanda +Cc: Gabor Juhos +Cc: Amod Bodas +Signed-off-by: Senthil Balasubramanian +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 14 Sep 2010 18:38:26 +0200 +Subject: ath9k_hw: handle rx key miss + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:36 -0400 +Subject: ath9k: fix regression which disabled ps on ath9k + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:27 -0400 +Subject: ath9k: fix regression on beacon loss after bgscan + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 28 Aug 2010 18:21:21 +0200 +Subject: ath9k: fix spurious MIC failure reports + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 23 Oct 2010 17:45:38 +0200 +Subject: ath9k: resume aggregation immediately after a hardware reset + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 19 Oct 2010 20:01:41 +0530 +Subject: ath9k_hw: Fix divide by zero cases in paprd. + +From: Senthil Balasubramanian + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Cc: Don Breslin +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 27 Oct 2010 12:02:54 +0530 +Subject: ath9k_htc: Set proper firmware offset for Netgear WNDA3200 + +From: Rajkumar Manoharan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 28 Oct 2010 19:51:47 +0530 +Subject: ath9k: Fix incorrect access of rate flags in RC + +From: Mohammed Shafi Shajakhan + +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: + + [] warn_slowpath_common+0x7a/0xb0 + + [] warn_slowpath_null+0x15/0x20 + + [] ath_get_rate+0x595/0x5b0 [ath9k] + + [] ? cpumask_next_and+0x36/0x50 + + [] rate_control_get_rate+0x86/0x160 [mac80211] + + [] invoke_tx_handlers+0x81c/0x12d0 [mac80211] + + [] ieee80211_tx+0x89/0x2b0 [mac80211] + + [] ? pskb_expand_head+0x1cc/0x1f0 + + [] ieee80211_xmit+0xb5/0x1c0 [mac80211] + + [] ieee80211_tx_skb+0x4f/0x60 [mac80211] + + [] ieee80211_send_nullfunc+0x46/0x60 [mac80211] + + [] ieee80211_offchannel_stop_station+0x107/0x150 +[mac80211] + + [] ? pskb_expand_head+0x1cc/0x1f0 + + [] ieee80211_xmit+0xb5/0x1c0 [mac80211] + + [] ieee80211_tx_skb+0x4f/0x60 [mac80211] + + [] ieee80211_send_nullfunc+0x46/0x60 [mac80211] + + [] ieee80211_offchannel_stop_station+0x107/0x150 +[mac80211] + + [] ieee80211_scan_work+0x146/0x600 [mac80211] + + [] ? schedule+0x2f5/0x8e0 + + [] ? ieee80211_scan_work+0x0/0x600 [mac80211] + + [] process_one_work+0x10f/0x380 + + [] worker_thread+0x162/0x340 + + [] ? worker_thread+0x0/0x340 + +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 20 Oct 2010 16:07:05 -0700 +Subject: ath9k: rename rxflushlock to pcu_lock + +From: Luis R. Rodriguez + +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 +Cc: Kyungwan Nam +Signed-off-by: Luis R. Rodriguez +Tested-by: Ben Greear +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 27 Oct 2010 02:15:05 +0200 +Subject: ath9k: fix tx aggregation flush on AR9003 + +From: Felix Fietkau + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 20 Oct 2010 16:07:03 -0700 +Subject: ath9k: add locking for stopping RX + +From: Luis R. Rodriguez + +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 +Cc: Kyungwan Nam +Signed-off-by: Luis R. Rodriguez +Tested-by: Ben Greear +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:28 -0400 +Subject: ath9k: fix enabling ANI / tx monitor after bg scan + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 4 Nov 2010 17:41:25 -0700 +Subject: ath9k_hw: Fix AR9280 surprise removal during frequent idle on/off + +From: Vasanthakumar Thiagarajan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 18 Nov 2010 12:19:52 +0530 +Subject: ath9k_htc: Avoid setting QoS control for non-QoS frames + +From: Rajkumar Manoharan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 20 Oct 2010 16:07:04 -0700 +Subject: ath9k: add locking for starting the PCU on RX + +From: Luis R. Rodriguez + +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 +Cc: Kyungwan Nam +Signed-off-by: Luis R. Rodriguez +Tested-by: Ben Greear +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +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 +Date: Wed, 10 Nov 2010 17:51:26 +0530 +Subject: ath9k_hw: Set proper eeprom offset for AR9287 HTC devices + +From: Rajkumar Manoharan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 10 Nov 2010 17:51:25 +0530 +Subject: ath9k_htc: Add new devices into AR7010 + +From: Rajkumar Manoharan + +commit 7cbf2611dac8d5f76fe64795a9426b8c97e6c3f8 upstream. + +Treat new PIDs (0xA704, 0x1200) as AR7010 devices. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sun, 7 Nov 2010 12:50:24 +0800 +Subject: ath9k_htc: Add support for device ID 3346 + +From: Haitao Zhang + +commit ac618d70aeb681df7b77c1107fdf26f3249f855f upstream. + +This patch adds support for USB dongle with device ID 3346 from IMC Networks. + +Signed-off-by: Haitao Zhang +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 10 Nov 2010 17:51:24 +0530 +Subject: ath9k_htc: Update usb device ID list + +From: Rajkumar Manoharan + +commit 32b089558c54792028f14ae830ca7c0a8d9ac9a3 upstream. + +Added new VID/PIDs into supported devices list + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 20 Oct 2010 16:07:06 -0700 +Subject: ath9k: lock reset and PCU start/stopping + +From: Luis R. Rodriguez + +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 +Cc: Kyungwan Nam +Signed-off-by: Luis R. Rodriguez +Tested-by: Ben Greear +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 6 Oct 2010 21:18:04 +0200 +Subject: cfg80211: fix BSS double-unlinking + +From: Johannes Berg + +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 +Tested-by: Hun-Kyi Wynn +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 30 Sep 2010 22:17:43 +0200 +Subject: cfg80211: fix locking + +From: Johannes Berg + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 18 Oct 2010 17:44:51 -0700 +Subject: cfg80211: fix regression on processing country IEs + +From: Luis R. Rodriguez + +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 +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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?= +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?= + +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 +Acked-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 8 Oct 2010 22:27:07 +0200 +Subject: mac80211: fix possible null-pointer de-reference + +From: Christian Lamparter + +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 +Reviewed-and-Tested-by: Javier Cardona +Acked-by: Johannes Berg +Signed-off-by: Christian Lamparter +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 1 Oct 2010 17:05:19 -0400 +Subject: mac80211: fix channel assumption for association done work + +From: Luis R. Rodriguez + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 24 Sep 2010 21:59:57 -0400 +Subject: mac80211: fix offchannel assumption upon association + +From: Luis R. Rodriguez + +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 +Cc: Vasanth Thiagarajan +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 27 Aug 2010 22:21:13 +0300 +Subject: mac80211: Fix signal strength average initialization for CQM events + +From: Jouni Malinen + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:31 -0400 +Subject: mac80211: reset connection idle when going offchannel + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:29 -0400 +Subject: mac80211: add helper for reseting the connection monitor + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:32 -0400 +Subject: mac80211: make the beacon monitor available externally + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:34 -0400 +Subject: mac80211: send last 3/5 probe requests as unicast + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:33 -0400 +Subject: mac80211: disable beacon monitor while going offchannel + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 14 Sep 2010 22:06:53 +0200 +Subject: mac80211: use correct station flags lock + +From: Johannes Berg + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 21 Sep 2010 21:36:18 +0200 +Subject: mac80211: clear txflags for ps-filtered frames + +From: Christian Lamparter + +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 +Signed-off-by: Christian Lamparter +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 Sep 2010 15:12:30 -0400 +Subject: mac80211: reset probe send counter upon connection timer reset + +From: Luis R. Rodriguez + +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 +Cc: Amod Bodas +Signed-off-by: Luis R. Rodriguez +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 23 Oct 2010 10:59:57 +0530 +Subject: mac80211: Fix ibss station got expired immediately + +From: Rajkumar Manoharan + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 16 Oct 2010 18:49:15 +0200 +Subject: mac80211: don't sanitize invalid rates + +From: Christian Lamparter + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Tue, 5 Oct 2010 21:40:33 +0200 +Subject: mac80211: delete AddBA response timer + +From: Johannes Berg + +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 +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 30 Sep 2010 13:34:40 +0000 +Subject: isdn/gigaset: fix bas_gigaset AT read error handling + +From: Tilman Schmidt + +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 30 Sep 2010 13:34:51 +0000 +Subject: isdn/gigaset: correct bas_gigaset rx buffer handling + +From: Tilman Schmidt + +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 30 Sep 2010 13:34:30 +0000 +Subject: isdn/gigaset: bas_gigaset locking fix + +From: Tilman Schmidt + +commit b33ffa5cbf52ee751bb8068218ebb3c742c5a515 upstream. + +Unlock cs->lock before calling error_hangup() which is marked +"cs->lock must not be held". + +Signed-off-by: Tilman Schmidt +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sun, 24 Oct 2010 18:16:57 +0200 +Subject: i2c-pca-platform: Change device name of request_irq + +From: Nobuhiro Iwamatsu + +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 +Acked-by: Wolfram Sang +Signed-off-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 17 Sep 2010 01:16:25 +0000 +Subject: viafb: fix i2c_transfer error handling + +From: Florian Tobias Schandinat + +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 +Acked-by: Jonathan Corbet +Cc: Joseph Chan +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Cc: Ari Savolainen +Cc: Jean Delvare +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 25 Oct 2010 10:37:11 +0200 +Subject: ALSA: hda - Disable sticky PCM stream assignment for AD codecs + +From: Takashi Iwai + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 22 Oct 2010 17:15:47 +0200 +Subject: ALSA: hda - Add workarounds for CT-IBG controllers + +From: Takashi Iwai + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 21 Oct 2010 08:55:13 +0200 +Subject: ALSA: hda - Fix wrong SPDIF NID assignment for CA0110 + +From: Takashi Iwai + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 21 Oct 2010 09:03:25 +0200 +Subject: ALSA: hda - Add some workarounds for Creative IBG + +From: Takashi Iwai + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 8 Oct 2010 10:48:50 +0200 +Subject: ALSA: OSS mixer emulation - fix locking + +From: Jaroslav Kysela + +commit 838c364ff05c143fd1810e8ad1469935d6c23a7a upstream. + +Fix mutex release and cleanup some locking code. + +Signed-off-by: Jaroslav Kysela +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 , David Henningsson +Message-ID: <1288043524-31436-2-git-send-email-flameeyes@gmail.com> + +From: David Henningsson + +[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 +Signed-off-by: Diego Elio Pettenò +Acked-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 17 Nov 2010 16:32:59 +0000 +Subject: powerpc: Fix call to subpage_protection() + +From: Michael Neuling + +commit 1c2c25c78740b2796c7c06640784cb6732fa4907 upstream. + +In: + powerpc/mm: Fix pgtable cache cleanup with CONFIG_PPC_SUBPAGE_PROT + commit d28513bc7f675d28b479db666d572e078ecf182d + Author: David Gibson + +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 +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Michael Neuling +cc: David Gibson +Signed-off-by: Greg Kroah-Hartman + +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 +Date: Sun, 24 Oct 2010 17:17:31 -0400 +Subject: SUNRPC: After calling xprt_release(), we must restart from call_reserve + +From: Trond Myklebust + +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: [] 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:[] 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: + [] ? rpc_wake_up_next+0x114/0x11b [sunrpc] + [] ? call_decode+0x24a/0x5af [sunrpc] + [] ? nfs4_xdr_dec_access+0x0/0xa2 [nfs] + [] ? __rpc_execute+0x62/0x17b [sunrpc] + [] ? rpc_run_task+0x91/0x97 [sunrpc] + [] ? rpc_call_sync+0x40/0x5b [sunrpc] + [] ? nfs4_proc_access+0x10a/0x176 [nfs] + [] ? nfs_do_access+0x2b1/0x2c0 [nfs] + [] ? rpcauth_lookupcred+0x62/0x84 [sunrpc] + [] ? nfs_permission+0xad/0x13b [nfs] + [] ? exec_permission+0x15/0x4b + [] ? link_path_walk+0x4f/0x456 + [] ? path_walk+0x4c/0xa8 + [] ? do_path_lookup+0x1f/0x68 + [] ? user_path_at+0x37/0x5f + [] ? handle_mm_fault+0x229/0x55b + [] ? sys_faccessat+0x93/0x146 + [] ? sys_access+0xf/0x13 + [] ? 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: [] 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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 21 Oct 2010 13:19:10 +0300 +Subject: microblaze: Fix build with make 3.82 + +From: Thomas Backlund + +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 +Signed-off-by: Michal Simek +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 21 Oct 2010 03:59:57 -0700 +Subject: phy/marvell: fix 88e1121 support + +From: Arnaud Patard + +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 4 Oct 2010 17:59:08 -0400 +Subject: NFSv4: Fix open recovery + +From: Trond Myklebust + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Mon, 18 Oct 2010 23:54:56 -0400 +Subject: drm/radeon/kms: properly compute group_size on 6xx/7xx + +From: Alex Deucher + +commit 881fe6c1d06bf49f4ab7aef212cdaf66bd059614 upstream. + +Needed for tiled surfaces. + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 8 Oct 2010 10:21:06 +0100 +Subject: drm/i915: Update hotplug interrupts register definitions for Sandybridge + +From: Yuanhan Liu + +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 +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Wed, 6 Oct 2010 00:13:04 -0400 +Subject: drm/radeon/kms: make sure blit addr masks are 64 bit + +From: Alex Deucher + +commit 2126d0a4a205e2d6b763434f892524cd60f74228 upstream. + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 8 Oct 2010 10:18:01 +0100 +Subject: drm/i915/crt: Make sure the hotplug interrupt is enabled + +From: Yuanhan Liu + +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 +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 7 Oct 2010 09:20:12 +0100 +Subject: drm/i915: Free hardware status page on unload when physically mapped + +From: Keith Packard + +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 +[ickle: call before tearing down registers on KMS-only path, as pointed +out by Dave Airlie] +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 7 Oct 2010 16:01:25 -0700 +Subject: drm/i915: diasable clock gating for the panel power sequencer + +From: Jesse Barnes + +commit 382b09362711d7d03272230a33767015a277926e upstream. + +Needed on Ibex Peak and Cougar Point or the panel won't always come on. + +Signed-off-by: Jesse Barnes +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 + +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 +Reviewed-by: Daniel Vetter +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=24977 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 29 Oct 2010 12:17:51 +0000 +Subject: pcnet_cs: add new_id + +From: Ken Kawasaki + +commit 62391f97babb7fe0c769830b6f0e0bd184bd0704 upstream. + +pcnet_cs: + add new_id: "corega Ether CF-TD" 10Base-T PCMCIA card. + +Signed-off-by: Ken Kawasaki +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 7 Oct 2010 14:08:52 +0100 +Subject: SH: Add missing consts to sys_execve() declaration + +From: David Howells + +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 +Cc: Nobuhiro Iwamatsu +Signed-off-by: Greg Kroah-Hartman + +--- + 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); -- cgit v1.2.3-54-g00ecf